Тщательно понимать события в Kubernetes

Go облачный носитель Kubernetes
Тщательно понимать события в Kubernetes

Всем привет, меня зовут Чжан Цзиньтао.

я написал«Более элегантная схема измерения событий кластера Kubernetes», и используйте Jaeger для использования трассировки для сбора событий в кластере Kubernetes и их отображения. Окончательный эффект выглядит следующим образом:

Когда я писал ту статью, я поставил флажок, чтобы подробно представить принцип.Я был голубем в течение долгого времени, и теперь это конец года, пришло время отправить его.

Обзор объектов

Давайте начнем с простого примера, чтобы увидеть, какие события происходят в кластере Kubernetes.

Создайте новое пространство имен с именем moelove и создайте в нем развертывание с именем redis. Затем просмотрите все события в этом пространстве имен.

(MoeLove) ➜ kubectl create ns moelove
namespace/moelove created
(MoeLove) ➜ kubectl -n moelove create deployment redis --image=ghcr.io/moelove/redis:alpine 
deployment.apps/redis created
(MoeLove) ➜ kubectl -n moelove get deploy
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
redis   1/1     1            1           11s
(MoeLove) ➜ kubectl -n moelove get events
LAST SEEN   TYPE     REASON              OBJECT                        MESSAGE
21s         Normal   Scheduled           pod/redis-687967dbc5-27vmr    Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3
21s         Normal   Pulling             pod/redis-687967dbc5-27vmr    Pulling image "ghcr.io/moelove/redis:alpine"
15s         Normal   Pulled              pod/redis-687967dbc5-27vmr    Successfully pulled image "ghcr.io/moelove/redis:alpine" in 6.814310968s
14s         Normal   Created             pod/redis-687967dbc5-27vmr    Created container redis
14s         Normal   Started             pod/redis-687967dbc5-27vmr    Started container redis
22s         Normal   SuccessfulCreate    replicaset/redis-687967dbc5   Created pod: redis-687967dbc5-27vmr
22s         Normal   ScalingReplicaSet   deployment/redis              Scaled up replica set redis-687967dbc5 to 1

Но мы обнаружим, что по умолчаниюkubectl get eventsОн расположен не в том порядке, в котором происходят события, поэтому нам часто нужно добавить к нему--sort-by='{.metadata.creationTimestamp}'параметр, позволяющий организовать его вывод во времени.

Вот почему версия Kubernetes v1.23 добавитkubectl alpha eventsПричина заказа. я был раньшеСтатья «K8S Ecological Weekly | Официальный выпуск Kubernetes v1.23.0, список новых функций»Подробно он был представлен в , и здесь не будет останавливаться.

После сортировки по времени можно увидеть следующие результаты:

(MoeLove) ➜ kubectl -n moelove get events --sort-by='{.metadata.creationTimestamp}'
LAST SEEN   TYPE     REASON              OBJECT                        MESSAGE
2m12s       Normal   Scheduled           pod/redis-687967dbc5-27vmr    Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3
2m13s       Normal   SuccessfulCreate    replicaset/redis-687967dbc5   Created pod: redis-687967dbc5-27vmr
2m13s       Normal   ScalingReplicaSet   deployment/redis              Scaled up replica set redis-687967dbc5 to 1
2m12s       Normal   Pulling             pod/redis-687967dbc5-27vmr    Pulling image "ghcr.io/moelove/redis:alpine"
2m6s        Normal   Pulled              pod/redis-687967dbc5-27vmr    Successfully pulled image "ghcr.io/moelove/redis:alpine" in 6.814310968s
2m5s        Normal   Created             pod/redis-687967dbc5-27vmr    Created container redis
2m5s        Normal   Started             pod/redis-687967dbc5-27vmr    Started container redis

С помощью вышеуказанных операций мы можем найти, чтоСобытия на самом деле являются ресурсом в кластере Kubernetes. При изменении состояния ресурсов в кластере Kubernetes могут генерироваться новые события..

Погрузитесь в события

один объект события

Поскольку события являются ресурсом в кластере Kubernetes, обычно оно должно содержать свое имя в своем metadata.name для отдельных операций. Таким образом, мы можем вывести его имя с помощью следующей команды:

(MoeLove) ➜ kubectl -n moelove get events --sort-by='{.metadata.creationTimestamp}' -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'
redis-687967dbc5-27vmr.16c4fb7bde8c69d2
redis-687967dbc5.16c4fb7bde6b54c4
redis.16c4fb7bde1bf769
redis-687967dbc5-27vmr.16c4fb7bf8a0ab35
redis-687967dbc5-27vmr.16c4fb7d8ecaeff8
redis-687967dbc5-27vmr.16c4fb7d99709da9
redis-687967dbc5-27vmr.16c4fb7d9be30c06

Выберите любую из записей событий и выведите ее в формате YAML для просмотра:

(MoeLove) ➜ kubectl -n moelove get events redis-687967dbc5-27vmr.16c4fb7bde8c69d2 -o yaml
action: Binding
apiVersion: v1
eventTime: "2021-12-28T19:31:13.702987Z"
firstTimestamp: null
involvedObject:
  apiVersion: v1
  kind: Pod
  name: redis-687967dbc5-27vmr
  namespace: moelove
  resourceVersion: "330230"
  uid: 71b97182-5593-47b2-88cc-b3f59618c7aa
kind: Event
lastTimestamp: null
message: Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3
metadata:
  creationTimestamp: "2021-12-28T19:31:13Z"
  name: redis-687967dbc5-27vmr.16c4fb7bde8c69d2
  namespace: moelove
  resourceVersion: "330235"
  uid: e5c03126-33b9-4559-9585-5e82adcd96b0
reason: Scheduled
reportingComponent: default-scheduler
reportingInstance: default-scheduler-kind-control-plane
source: {}
type: Normal

Вы видите, что он содержит много информации, мы не будем ее здесь раскрывать. Давайте посмотрим на другой пример.

kubectl describeСобытия в

Мы можем выполнять объект Deployment и объект Pod отдельно.describeоперации можно получить следующие результаты (опуская промежуточный вывод):

  • Операции с развертываниями
(MoeLove) ➜ kubectl -n moelove describe deploy/redis                
Name:                   redis
Namespace:              moelove
...
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  15m   deployment-controller  Scaled up replica set redis-687967dbc5 to 1
  • Операции над модулями
(MoeLove) ➜ kubectl -n moelove describe pods redis-687967dbc5-27vmr
Name:         redis-687967dbc5-27vmr                                                                 
Namespace:    moelove
Priority:     0
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  18m   default-scheduler  Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3
  Normal  Pulling    18m   kubelet            Pulling image "ghcr.io/moelove/redis:alpine"
  Normal  Pulled     17m   kubelet            Successfully pulled image "ghcr.io/moelove/redis:alpine" in 6.814310968s
  Normal  Created    17m   kubelet            Created container redis
  Normal  Started    17m   kubelet            Started container redis

мы можем узнатьПри описании различных объектов ресурсов содержание событий, которые вы видите, напрямую связано с вами. При описании развертывания я не вижу событий, связанных с подом.

это означает,Объект Event содержит информацию об объекте ресурса, который он описывает., они имеют прямое отношение.

Объединив один объект Event, который мы видели ранее, мы находим, чтоinvolvedObjectСодержимое поля представляет собой информацию об объекте ресурса, связанном с событием..

Узнать больше о событиях

Давайте рассмотрим следующий пример, в котором создается Deployment, но используется несуществующий образ:

(MoeLove) ➜ kubectl -n moelove create deployment non-exist --image=ghcr.io/moelove/non-exist
deployment.apps/non-exist created
(MoeLove) ➜ kubectl -n moelove get pods
NAME                        READY   STATUS         RESTARTS   AGE
non-exist-d9ddbdd84-tnrhd   0/1     ErrImagePull   0          11s
redis-687967dbc5-27vmr      1/1     Running        0          26m

Мы видим, что текущий Pod находится вErrImagePullстатус. Просмотр событий в текущем пространстве имен (предыдущие записи deploy/redis я пропустил)

(MoeLove) ➜ kubectl -n moelove get events --sort-by='{.metadata.creationTimestamp}'                                                           
LAST SEEN   TYPE      REASON              OBJECT                           MESSAGE
35s         Normal    SuccessfulCreate    replicaset/non-exist-d9ddbdd84   Created pod: non-exist-d9ddbdd84-tnrhd
35s         Normal    ScalingReplicaSet   deployment/non-exist             Scaled up replica set non-exist-d9ddbdd84 to 1
35s         Normal    Scheduled           pod/non-exist-d9ddbdd84-tnrhd    Successfully assigned moelove/non-exist-d9ddbdd84-tnrhd to kind-worker3
17s         Warning   Failed              pod/non-exist-d9ddbdd84-tnrhd    Error: ErrImagePull
17s         Warning   Failed              pod/non-exist-d9ddbdd84-tnrhd    Failed to pull image "ghcr.io/moelove/non-exist": rpc error: code = Unknown desc = failed to pull and unpack image "ghcr.io/moelove/non-exist:latest": failed to resolve reference "ghcr.io/moelove/non-exist:latest": failed to authorize: failed to fetch anonymous token: unexpected status: 403 Forbidden
18s         Normal    Pulling             pod/non-exist-d9ddbdd84-tnrhd    Pulling image "ghcr.io/moelove/non-exist"
4s          Warning   Failed              pod/non-exist-d9ddbdd84-tnrhd    Error: ImagePullBackOff
4s          Normal    BackOff             pod/non-exist-d9ddbdd84-tnrhd    Back-off pulling image "ghcr.io/moelove/non-exist"

Выполнить на этом подеdescribeработать:

(MoeLove) ➜ kubectl -n moelove describe pods non-exist-d9ddbdd84-tnrhd
...
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  4m                     default-scheduler  Successfully assigned moelove/non-exist-d9ddbdd84-tnrhd to kind-worker3
  Normal   Pulling    2m22s (x4 over 3m59s)  kubelet            Pulling image "ghcr.io/moelove/non-exist"
  Warning  Failed     2m21s (x4 over 3m59s)  kubelet            Failed to pull image "ghcr.io/moelove/non-exist": rpc error: code = Unknown desc = failed to pull and unpack image "ghcr.io/moelove/non-exist:latest": failed to resolve reference "ghcr.io/moelove/non-exist:latest": failed to authorize: failed to fetch anonymous token: unexpected status: 403 Forbidden
  Warning  Failed     2m21s (x4 over 3m59s)  kubelet            Error: ErrImagePull
  Warning  Failed     2m9s (x6 over 3m58s)   kubelet            Error: ImagePullBackOff
  Normal   BackOff    115s (x7 over 3m58s)   kubelet            Back-off pulling image "ghcr.io/moelove/non-exist"

Мы видим, что вывод здесь не такой, как когда модуль работал правильно раньше. Основное отличие сAgeСписок. Здесь мы видим что-то вроде115s (x7 over 3m58s)такой выход.

Его значение означает:Событие такого типа произошло 7 раз за 3 минуты 58 секунд, последнее произошло до 115 секунд.

Но когда мы идем прямоkubectl get events, мы не видим событие с 7 повторениями. это означаетKubernetes автоматически объединяет повторяющиеся события.

Выбираем последние Events (метод уже описан ранее) и выводим его содержимое в формате YAML:

(MoeLove) ➜ kubectl -n moelove get events non-exist-d9ddbdd84-tnrhd.16c4fce570cfba46 -o yaml
apiVersion: v1
count: 43
eventTime: null
firstTimestamp: "2021-12-28T19:57:06Z"
involvedObject:
  apiVersion: v1
  fieldPath: spec.containers{non-exist}
  kind: Pod
  name: non-exist-d9ddbdd84-tnrhd
  namespace: moelove
  resourceVersion: "333366"
  uid: 33045163-146e-4282-b559-fec19a189a10
kind: Event
lastTimestamp: "2021-12-28T18:07:14Z"
message: Back-off pulling image "ghcr.io/moelove/non-exist"
metadata:
  creationTimestamp: "2021-12-28T19:57:06Z"
  name: non-exist-d9ddbdd84-tnrhd.16c4fce570cfba46
  namespace: moelove
  resourceVersion: "334638"
  uid: 60708be0-23b9-481b-a290-dd208fed6d47
reason: BackOff
reportingComponent: ""
reportingInstance: ""
source:
  component: kubelet
  host: kind-worker3
type: Normal

Здесь мы видим, что его поля включаютcountПоле, указывающее, сколько раз происходит одно и то же событие. а такжеfirstTimestampиlastTimestampСоответственно представляют время, когда событие впервые появилось в последний раз. Это также объясняет продолжительность событий в предыдущем выводе.

Полностью понимать События

Ниже приведен случайный выбор из Events, и мы можем увидеть некоторую информацию о полях, которую он содержит:

apiVersion: v1
count: 1
eventTime: null
firstTimestamp: "2021-12-28T19:31:13Z"
involvedObject:
  apiVersion: apps/v1
  kind: ReplicaSet
  name: redis-687967dbc5
  namespace: moelove
  resourceVersion: "330227"
  uid: 11e98a9d-9062-4ccb-92cb-f51cc74d4c1d
kind: Event
lastTimestamp: "2021-12-28T19:31:13Z"
message: 'Created pod: redis-687967dbc5-27vmr'
metadata:
  creationTimestamp: "2021-12-28T19:31:13Z"
  name: redis-687967dbc5.16c4fb7bde6b54c4
  namespace: moelove
  resourceVersion: "330231"
  uid: 8e37ec1e-b3a1-420c-96d4-3b3b2995c300
reason: SuccessfulCreate
reportingComponent: ""
reportingInstance: ""
source:
  component: replicaset-controller
type: Normal

Значения основных полей следующие:

  • count: Указывает, сколько раз произошло текущее событие того же типа (описано ранее)
  • вовлеченный объект: объект ресурса, непосредственно связанный с этим событием (представленным ранее), имеет следующую структуру:
type ObjectReference struct {
	Kind string
	Namespace string
	Name string
	UID types.UID
	APIVersion string
	ResourceVersion string
	FieldPath string
}
  • источник: Непосредственно связанные компоненты, структура следующая:
type EventSource struct {
	Component string
	Host string
}
  • причина: простая сводка (или фиксированный код), которая больше подходит для условий фильтрации, в основном для того, чтобы сделать ее читаемой машинами, таких кодов на данный момент более 50;
  • сообщение: дайте более удобочитаемое подробное описание
  • тип: пока толькоNormalиWarningЕсть два типа, и их значения также прописаны в исходном коде:
// staging/src/k8s.io/api/core/v1/types.go
const (
	// Information only and will not cause any problems
	EventTypeNormal string = "Normal"
	// These events are to warn that something might go wrong
	EventTypeWarning string = "Warning"
)

Поэтому, когда мы собираем эти события как диапазоны трассировки, мы можем следить за ихsourceСортировать поinvolvedObjectСопоставьте и отсортируйте по времени.

Суммировать

В этой статье я в основном представляю фактическую роль объекта Events и значение его различных полей с помощью двух примеров: развертывание, развернутое правильно, и развертывание, развернутое с использованием несуществующего образа.

Для Kubernetes события содержат много полезной информации, но эта информация не оказывает никакого влияния на Kubernetes, и они не являются реальными журналами Kubernetes. По умолчанию журналы в Kubernetes очищаются через 1 час, чтобы освободить ресурсы etcd.

Поэтому, чтобы лучше сообщить администратору кластера о том, что произошло, в производственной среде мы обычно также собираем события кластера Kubernetes. Лично я рекомендую следующие инструменты:GitHub.com/op с IE/crying…

Конечно, вы также можете следить за моей предыдущей статьей«Более элегантная схема измерения событий кластера Kubernetes», и используйте Jaeger для использования трассировки для сбора событий в кластере Kubernetes и их отображения.


Добро пожаловать, чтобы подписаться на мой публичный аккаунт статьи [MoeLove]

TheMoeLove