K8s kubectl Глубокое погружение

В моей предыдущей статье kubectl я показал вам, как использовать его для получения информации о кластере, apiVersion, а также информации о API-ресурсах. В этой статье давайте продолжим работу с узлами.

Для данного узла K8s обычно работают три компонента:

  • kubelet: агент, который регистрирует/отменяет регистрацию узла с помощью API Kubernetes.
  • Среда выполнения контейнера: механизм выполнения контейнера.
  • kube-proxy: процесс сетевого прокси K8s.

Как администратор K8s, вам много раз нужно устранять неполадки, почему определенный узел не может запускать модули, получать информацию об узле в кластере, добавлять новый узел, заменять существующий узел и т. д. В этой статье позвольте мне показать вам все операции узла с помощью инструмента kubectl.

Список узлов

$ kubectl get nodes
NAME                             STATUS   ROLES    AGE   VERSION
ip-192-168-62-238.ec2.internal   Ready    <none>   85m   v1.24.7-eks-fb459a0

Описать узел

$ kubectl describe node ip-192-168-62-238.ec2.internal
Name:               ip-192-168-62-238.ec2.internal
Roles:              <none>
Labels:             alpha.eksctl.io/cluster-name=dev-cluster
                    alpha.eksctl.io/nodegroup-name=standard-workers
                    beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=t3.medium
                    beta.kubernetes.io/os=linux
                    eks.amazonaws.com/capacityType=ON_DEMAND
                    eks.amazonaws.com/nodegroup=standard-workers
                    eks.amazonaws.com/nodegroup-image=ami-0c84934009677b6d5
                    eks.amazonaws.com/sourceLaunchTemplateId=lt-0768d4e5bac8456db
                    eks.amazonaws.com/sourceLaunchTemplateVersion=1
                    failure-domain.beta.kubernetes.io/region=us-east-1
                    failure-domain.beta.kubernetes.io/zone=us-east-1c
                    k8s.io/cloud-provider-aws=494fdbb3e67643238cbc864a5ef9986c
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ip-192-168-62-238.ec2.internal
                    kubernetes.io/os=linux
                    node.kubernetes.io/instance-type=t3.medium
                    topology.kubernetes.io/region=us-east-1
                    topology.kubernetes.io/zone=us-east-1c
Annotations:        alpha.kubernetes.io/provided-node-ip: 192.168.62.238
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Mon, 19 Dec 2022 00:36:51 +0000
Taints:             <none>
Unschedulable:      false
Lease:
  HolderIdentity:  ip-192-168-62-238.ec2.internal
...
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                    Requests    Limits
  --------                    --------    ------
  cpu                         325m (16%)  0 (0%)
  memory                      140Mi (4%)  340Mi (10%)
  ephemeral-storage           0 (0%)      0 (0%)
  hugepages-1Gi               0 (0%)      0 (0%)
  hugepages-2Mi               0 (0%)      0 (0%)
  attachable-volumes-aws-ebs  0           0
Events:                       <none>

Показать использование узла

Иногда полезно знать, какие ресурсы потребляются узлами. Чтобы отобразить ресурсы, используемые узлами, выполните следующую команду:

$ kubectl top node
NAME                             CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
ip-192-168-23-112.ec2.internal   39m          2%     484Mi           14%
ip-192-168-40-6.ec2.internal     39m          2%     503Mi           15%

Команда kubectl top показывает метрики узла по использованию ЦП и памяти. Вы также можете использовать команду watch для просмотра и мониторинга узлов в режиме реального времени, если вам нужно:

$ watch kubectl top nodes
Every 2.0s: kubectl top nodes                                                                                                           Sat Dec 24 19:35:53 2022

NAME                             CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
ip-192-168-23-112.ec2.internal   39m          2%     486Mi           14%
ip-192-168-40-6.ec2.internal     37m          1%     503Mi           15%

Отключить планирование узлов

Иногда мы хотим временно предотвратить назначение новых модулей на определенный узел, вы можете использовать параметр cordon. Параметр cordon позволяет пометить узел K8s как незапланированный.

$ kubectl cordon -h
Mark node as unschedulable.

Examples:
  # Mark node "foo" as unschedulable
  kubectl cordon foo

Options:
      --dry-run='none': Must be "none", "server", or "client". If client strategy, only print the object that would be
sent, without sending it. If server strategy, submit server-side request without persisting the resource.
  -l, --selector='': Selector (label query) to filter on

Usage:
  kubectl cordon NODE [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

Давайте попробуем, мы видим, что кластер K8s в настоящее время имеет два доступных узла:

$ kubectl get nodes
NAME                             STATUS   ROLES    AGE   VERSION
ip-192-168-23-112.ec2.internal   Ready    <none>   10m   v1.23.13-eks-fb459a0
ip-192-168-40-6.ec2.internal     Ready    <none>   10m   v1.23.13-eks-fb459a0

Давайте отметим узел ip-192–168–40–6.ec2.internal с помощью cordon :

$ $ kubectl cordon ip-192-168-40-6.ec2.internal
node/ip-192-168-40-6.ec2.internal cordoned

Теперь, если мы снова проверим доступность узлов:

$ kubectl get nodes
NAME                             STATUS                     ROLES    AGE   VERSION
ip-192-168-23-112.ec2.internal   Ready                      <none>   12m   v1.23.13-eks-fb459a0
ip-192-168-40-6.ec2.internal     Ready,SchedulingDisabled   <none>   12m   v1.23.13-eks-fb459a0

Обратите внимание, что теперь статус узла ip-192–168–40–6.ec2.internal показывает «Готово, расписание отключено». Этот переключатель cordon удобен, когда вы хотите быстро запустить некоторые тесты в своем кластере K8s, но не хотите влиять на критические узлы.

Примечание. Если заблокированный узел будет перезагружен, все запланированные на нем модули будут перенесены на другие узлы.

Чтобы возобновить его, вы можете использовать команду kubectl uncordon:

$ kubectl uncordon ip-192-168-40-6.ec2.internal
node/ip-192-168-40-6.ec2.internal uncordoned
$ kubectl get nodes
NAME                             STATUS   ROLES    AGE   VERSION
ip-192-168-23-112.ec2.internal   Ready    <none>   14m   v1.23.13-eks-fb459a0
ip-192-168-40-6.ec2.internal     Ready    <none>   14m   v1.23.13-eks-fb459a0

Сливные узлы

Если вы хотите переместить все запущенные поды с узла для обслуживания узла, вы можете использовать команду drain. kubectl drain истощит заданный узел в рамках подготовки к обслуживанию.

drain ожидает корректного завершения. Вы не должны работать на машине, пока команда не завершится. Когда вы будете готовы вернуть узел в эксплуатацию, используйте kubectl uncordon, что снова сделает узел планируемым.

Давайте создадим несколько Nginx подов в нашем кластере:

$ kubectl get po -owide
NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE                             NOMINATED NODE   READINESS GATES
nginx-74d589986c-2h98c   1/1     Running   0          7s    192.168.62.163   ip-192-168-40-6.ec2.internal     <none>           <none>
nginx-74d589986c-2tnfc   1/1     Running   0          7s    192.168.22.109   ip-192-168-23-112.ec2.internal   <none>           <none>
nginx-74d589986c-5bs67   1/1     Running   0          7s    192.168.53.226   ip-192-168-40-6.ec2.internal     <none>           <none>
nginx-74d589986c-65cxz   1/1     Running   0          7s    192.168.11.223   ip-192-168-23-112.ec2.internal   <none>           <none>
nginx-74d589986c-bjd2d   1/1     Running   0          7s    192.168.58.226   ip-192-168-40-6.ec2.internal     <none>           <none>
nginx-74d589986c-q8kn4   1/1     Running   0          7s    192.168.25.25    ip-192-168-23-112.ec2.internal   <none>           <none>

У нас есть 6 Nginx подов, работающих на двух разных узлах, давайте возьмем один из узлов:

$ kubectl drain ip-192-168-40-6.ec2.internal --dry-run='client'
node/ip-192-168-40-6.ec2.internal cordoned (dry run)
error: unable to drain node "ip-192-168-40-6.ec2.internal" due to error:[cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/aws-node-hh78n, kube-system/kube-proxy-xq4kl, cannot delete Pods with local storage (use --delete-emptydir-data to override): kube-system/coredns-d5b9bfc4-bcb97, kube-system/coredns-d5b9bfc4-f4w9w], continuing command...
There are pending nodes to be drained:
 ip-192-168-40-6.ec2.internal
cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/aws-node-hh78n, kube-system/kube-proxy-xq4kl
cannot delete Pods with local storage (use --delete-emptydir-data to override): kube-system/coredns-d5b9bfc4-bcb97, kube-system/coredns-d5b9bfc4-f4w9w

Как видите, поскольку на узле работает DaemonSet, мы не можем его слить.

$ kubectl get po kube-proxy-xq4kl -n kube-system -owide
NAME               READY   STATUS    RESTARTS   AGE   IP             NODE                           NOMINATED NODE   READINESS GATES
kube-proxy-xq4kl   1/1     Running   0          24m   192.168.40.6   ip-192-168-40-6.ec2.internal   <none>           <none>

В этом случае мы должны использовать флаг --ignore-daemonsets:

$ kubectl drain ip-192-168-40-6.ec2.internal  --dry-run='client' --ignore-daemonsets 
node/ip-192-168-40-6.ec2.internal already cordoned (dry run)
WARNING: ignoring DaemonSet-managed Pods: kube-system/aws-node-hh78n, kube-system/kube-proxy-xq4kl
evicting pod default/nginx-74d589986c-2h98c (dry run)
evicting pod default/nginx-74d589986c-5bs67 (dry run)
evicting pod default/nginx-74d589986c-bjd2d (dry run)
evicting pod kube-system/coredns-d5b9bfc4-bcb97 (dry run)
evicting pod kube-system/coredns-d5b9bfc4-f4w9w (dry run)
node/ip-192-168-40-6.ec2.internal drained (dry run)

Теперь давайте удалим флаг --dry-run и фактически истощим его:

$ $ kubectl drain ip-192-168-40-6.ec2.internal  --ignore-daemonsets
node/ip-192-168-40-6.ec2.internal already cordoned
WARNING: ignoring DaemonSet-managed Pods: kube-system/aws-node-hh78n, kube-system/kube-proxy-xq4kl
evicting pod kube-system/coredns-d5b9bfc4-f4w9w
evicting pod default/nginx-74d589986c-5bs67
evicting pod default/nginx-74d589986c-bjd2d
evicting pod kube-system/coredns-d5b9bfc4-bcb97
evicting pod default/nginx-74d589986c-2h98c
pod/nginx-74d589986c-bjd2d evicted
pod/nginx-74d589986c-5bs67 evicted
pod/coredns-d5b9bfc4-bcb97 evicted
pod/nginx-74d589986c-2h98c evicted
pod/coredns-d5b9bfc4-f4w9w evicted
node/ip-192-168-40-6.ec2.internal drained

$ kubectl get nodes
NAME                             STATUS                     ROLES    AGE   VERSION
ip-192-168-23-112.ec2.internal   Ready                      <none>   27m   v1.23.13-eks-fb459a0
ip-192-168-40-6.ec2.internal     Ready,SchedulingDisabled   <none>   27m   v1.23.13-eks-fb459a0

Теперь вы можете начать обслуживание этого узла.

Удалить узлы

Вы можете использовать команду kubectl delete для удаления узла из кластера K8s.

$ kubectl delete node ip-192-168-40-6.ec2.internal
node "ip-192-168-40-6.ec2.internal" deleted

$ kubectl get node
NAME                             STATUS   ROLES    AGE   VERSION
ip-192-168-23-112.ec2.internal   Ready    <none>   30m   v1.23.13-eks-fb459a0