Розвʼязання проблем kubeadm
Так само як і з будь-якою іншою технологією, ви можете зіткнутися з проблемами під час встановлення або використання kubeadm. Цей документ містить список найпоширеніших проблем та їх рішень, пропонуючи вам кроки, які допоможуть зʼясувати та розвʼязати проблеми.
Якщо вашої проблеми немає в переліку нижче, будь ласка, скористайтесь настпуним:
Ви вважаєте, що це помилка в kubeadm:
- Відвідайте github.com/kubernetes/kubeadm, пошукайте в списку наявних повідомлень.
- Якщо ви не знайшли свою проблему, створіть нове повідомлення про проблему використовуючи готовий шаблон.
Ви не впевнені, що це проблема в роботі kubeadm, ви можете запитати в Slack в каналі
#kubeadm
, або поставити питання на Stack Overflow. Будь ласка, додайте теґи#kubeadm
та#kubernetes
.
Неможливо приєднати вузол v1.18 до кластера v1.17 через відсутність RBAC
У версії v1.18 kubeadm додав запобігання приєднання вузла до кластера, якщо вузол з таким самим імʼям вже існує. Це вимагало додавання RBAC для користувача bootstrap-token для можливості виконання операції GET обʼєкта Node.
Однак це викликає проблему, коли kubeadm join
з v1.18 не може приєднатися до кластера, створеного за допомогою kubeadm v1.17.
Для того, щоб оминути цю проблему у вас є два варіанти:
Виконайте kubeadm init phase bootstrap-token
на вузлі панелі управління за допомогою kubeadm v1.18. Зауважте, що це дозволяє інші дозволи bootstrap-token.
або
Застосуйте наступний RBAC вручну за допомогою kubectl apply -f ...
:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubeadm:get-nodes
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeadm:get-nodes
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeadm:get-nodes
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:bootstrappers:kubeadm:default-node-token
ebtables
або подібний виконавчий файл не знайдений під час встановлення
Якщо ви бачите наступні попередження під час виконання kubeadm init
:
[preflight] WARNING: ebtables not found in system path
[preflight] WARNING: ethtool not found in system path
Тоді вам може бракувати ebtables
, ethtool
або подібного виконавчого файлу на вашому вузлі. Ви можете встановити їх за допомогою наступних команд:
- Для користувачів Ubuntu/Debian виконайте
apt install ebtables ethtool
. - Для користувачів CentOS/Fedora виконайте
yum install ebtables ethtool
.
kubeadm
блокується під час очікування на панель управління під час встановлення
Якщо ви помічаєте, що kubeadm init
зупиняється після виведення наступного рядка:
[apiclient] Created API client, waiting for the control plane to become ready
Це може бути спричинено кількома проблемами. Найбільш поширеними є:
- проблеми з мережевим підключенням. Перш ніж продовжувати, перевірте, чи ваша машина має повне підключення до мережі.
- драйвер cgroup контейнера відрізняється від драйвера kubelet cgroup. Щоб зрозуміти, як правильно налаштувати це, див. Налаштування драйвера cgroup.
- контейнери панелі управління впадають в цикл або зупиняються. Ви можете перевірити це, використовуючи
docker ps
та вивчаючи кожен контейнер за допомогоюdocker logs
. Для інших середовищ виконання контейнерів, див. Налагодження вузлів Kubernetes за допомогою crictl.
kubeadm
блокується під час видалення керованих контейнерів
Наступне може трапитися, якщо середовище виконання контейнерів зупиняється і не видаляє жодних керованих контейнерів Kubernetes:
sudo kubeadm reset
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
(block)
Можливий варіант вирішення — перезапустити середовище виконання контейнерів, а потім знову запустити kubeadm reset
. Ви також можете використовувати crictl
для налагодження стану середовища виконання контейнерів. Див. Налагодження вузлів Kubernetes за допомогою crictl.
Podʼи у стані RunContainerError
, CrashLoopBackOff
або Error
Відразу після виконання kubeadm init
не повинно бути жодних контейнерів у таких станах.
- Якщо є контейнери в одному з цих станів відразу після
kubeadm init
, будь ласка, створіть тікет в репозиторії kubeadm.coredns
(абоkube-dns
) повинен перебувати у станіPending
до моменту розгортання додатка для мережі. - Якщо ви бачите контейнери у стані
RunContainerError
,CrashLoopBackOff
абоError
після розгортання додатка для мережі та нічого не відбувається зcoredns
(абоkube-dns
), дуже ймовірно, що додаток Pod Network, який ви встановили, є пошкодженим. Можливо, вам потрібно надати йому більше привілеїв RBAC або використовувати новішу версію. Будь ласка, створіть тікет в системі відстеження проблем постачальника Pod Network та очікуйте розвʼязання проблеми там.
coredns
застрягає у стані Pending
Це очікувано і є частиною дизайну. kubeadm є агностичним до мережі, тому адміністратор повинен встановити вибраний додаток для мережі за власним вибором. Вам потрібно встановити Pod Network, перш ніж coredns
може бути повністю розгорнутим. Таким чином, стан Pending
перед налаштуванням мережі є нормальним.
Сервіси HostPort
не працюють
Функціональність HostPort
та HostIP
доступна залежно від вашого провайдера Pod Network. Будь ласка, звʼяжіться з автором додатка Pod Network, щоб дізнатися, чи
функціональність HostPort
та HostIP
доступна.
Перевірено, що Calico, Canal та Flannel CNI підтримують HostPort.
Для отримання додаткової інформації перегляньте документацію CNI portmap.
Якщо ваш постачальник мережі не підтримує втулок CNI portmap, можливо, вам доведеться використовувати функцію NodePort для сервісів або використовуйте HostNetwork=true
.
До Podʼів неможливо отримати доступ за їх Service IP
Багато додатків для мережі ще не увімкнули режим hairpin, який дозволяє Podʼам звертатися до себе за їх Service IP. Це повʼязано з CNI. Будь ласка, звʼяжіться з постачальником додатка для мережі, щоб дізнатися про останній статус підтримки режиму hairpin.
Якщо ви використовуєте VirtualBox (безпосередньо, або через Vagrant), вам слід переконатися, що
hostname -i
повертає маршрутизовану IP-адресу. Типово перший інтерфейс підключений до немаршрутизованої мережі тільки для хосту. Як тимчасовий варіант, ви можете змінити/etc/hosts
, подивіться цей Vagrantfile для прикладу.
Помилки сертифіката TLS
Наступна помилка вказує на можливу несумісність сертифікатів.
# kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
Перевірте, що файл
$HOME/.kube/config
містить дійсний сертифікат, та перегенеруйте сертифікат за необхідності. Сертифікати у файлі конфігурації kubeconfig закодовані у форматі base64. Командаbase64 --decode
може бути використана для декодування сертифіката, аopenssl x509 -text -noout
може бути використано для перегляду інформації про сертифікат.Скасуйте змінну середовища
KUBECONFIG
за допомогою:unset KUBECONFIG
Або встановіть його в типове розташування
KUBECONFIG
:export KUBECONFIG=/etc/kubernetes/admin.conf
Іншим обхідним методом є перезапис наявного
kubeconfig
для користувача "admin":mv $HOME/.kube $HOME/.kube.bak mkdir $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
Помилка ротації сертифіката клієнта Kubelet
Стандартно kubeadm
налаштовує kubelet
на автоматичну ротацію сертифікатів клієнта за допомогою символічного посилання /var/lib/kubelet/pki/kubelet-client-current.pem
, вказаного в /etc/kubernetes/kubelet.conf
. Якщо цей процес ротації завершиться невдачею, ви можете побачити помилки, такі як x509: certificate has expired or is not yet valid
в журналах kube-apiserver
. Щоб виправити цю проблему, слід виконати наступні кроки:
Зробіть резервну копію та видаліть файли
/etc/kubernetes/kubelet.conf
та/var/lib/kubelet/pki/kubelet-client*
з несправного вузла.З робочого вузла контрольної площини кластера, де є
/etc/kubernetes/pki/ca.key
, виконайтеkubeadm kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf
.$NODE
повинно бути встановлено на імʼя наявного несправного вузла в кластері. Вручну змініть отриманийkubelet.conf
, щоб відкоригувати імʼя та endpoint сервера, або передайтеkubeconfig user --config
(див. see Створення файлів kubeconfig для додаткових користувачів). Якщо в у вашому кластері немаєca.key
, ви повинні вручну підписати вбудовані сертифікати вkubelet.conf
.Скопіюйте цей отриманий
kubelet.conf
в/etc/kubernetes/kubelet.conf
на несправному вузлі.Перезапустіть
kubelet
(systemctl restart kubelet
) на несправному вузлі та зачекайте, доки/var/lib/kubelet/pki/kubelet-client-current.pem
буде відновлено.Вручну відредагуйте
kubelet.conf
, щоб вказати на обертані сертифікати клієнтаkubelet
, замінившиclient-certificate-data
таclient-key-data
на:client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
Перезапустіть
kubelet
.Переконайтеся, що вузол стає
Ready
.
Типовий мережевий інтерфейс NIC при використанні Flannel як мережі для Podʼів у Vagrant
Наступна помилка може свідчити про те, що щось пішло не так у мережі Podʼів:
Error from server (NotFound): the server could not find the requested resource
Якщо ви використовуєте Flannel як мережу для Podʼів у Vagrant, тоді вам доведеться вказати типове імʼя інтерфейсу для Flannel.
Зазвичай Vagrant призначає два інтерфейси всім віртуальним машинам. Перший, для якого всі хости мають IP-адресу
10.0.2.15
, призначено для зовнішнього трафіку, який проходить через NAT.Це може призвести до проблем із Flannel, яка стандартно він обирає перший інтерфейс на хості. Це призводить до того, що всі хости вважають, що у них однакова публічна IP-адреса. Щоб цього уникнути, передайте прапорець
--iface eth1
для Flannel, щоб обрати другий інтерфейс.
Непублічні IP-адреси для контейнерів
У деяких ситуаціях команди kubectl logs
та kubectl run
можуть повертати помилки на функціональному кластері:
Error from server: Get https://10.19.0.41:10250/containerLogs/default/mysql-ddc65b868-glc5m/mysql: dial tcp 10.19.0.41:10250: getsockopt: no route to host
Це може бути викликано використанням Kubernetes IP-адреси, яка не може взаємодіяти з іншими IP-адресами на одній підмережі, можливо, через політику провайдера машин.
DigitalOcean призначає публічний IP для
eth0
, а також приватний IP для внутрішнього використання як анкера для їхньої функції змінного IP. Однак,kubelet
вибере останній якInternalIP
вузла замість першого.Використовуйте
ip addr show
для перевірки цього сценарію, а неifconfig
, оскількиifconfig
не показує обрану адресу IP для аліаса. Альтернативно, API-точка, специфічна для DigitalOcean, дозволяє запитувати анкер IP-адресу з машини:curl http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address
Обхідним рішенням є повідомлення
kubelet
, яку IP використовувати за допомогою--node-ip
. Коли використовується DigitalOcean, це може бути публічний IP (призначенийeth0
) або приватний IP (призначенийeth1
), якщо ви хочете використовувати додаткову приватну мережу. РозділkubeletExtraArgs
структури kubeadmNodeRegistrationOptions
може бути використаний для цього.Потім перезапустіть
kubelet
:systemctl daemon-reload systemctl restart kubelet
Podʼи coredns
перебувають у стані CrashLoopBackOff
або Error
Якщо у вас є вузли, які працюють із SELinux та старішою версією Docker, ви можете стикнутися зі сценарієм, де Podʼи coredns
не запускаються. Щоб вирішити це, ви можете спробувати один з наступних варіантів:
Оновіться до новішої версії Docker.
Змініть розгортання
coredns
, встановившиallowPrivilegeEscalation
вtrue
:
kubectl -n kube-system get deployment coredns -o yaml | \
sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
kubectl apply -f -
Іншою причиною того, що CoreDNS має CrashLoopBackOff
, є те, що Pod CoreDNS, розгорнутий в Kubernetes, виявляє цикл. Існують різні обхідні варіанти, щоб уникнути спроб перезапуску Podʼа CoreDNS кожного разу, коли CoreDNS виявляє цикл та виходить.
Попередження:
Вимкнення SELinux або встановленняallowPrivilegeEscalation
в true
може піддавати ризику безпеку вашого кластера.Podʼі etcd постійно перезапускаються
Якщо ви стикаєтеся з такою помилкою:
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "process_linux.go:110: decoding init error from pipe caused \"read parent: connection reset by peer\""
Ця проблема виникає, якщо ви використовуєте CentOS 7 з Docker 1.13.1.84. Ця версія Docker може завадити kubelet виконуватися в контейнері etcd.
Для усунення цієї проблеми виберіть один з наступних варіантів:
Поверніться до попередньої версії Docker, наприклад, 1.13.1-75
yum downgrade docker-1.13.1-75.git8633870.el7.centos.x86_64 docker-client-1.13.1-75.git8633870.el7.centos.x86_64 docker-common-1.13.1-75.git8633870.el7.centos.x86_64
Встановіть одну з новіших рекомендованих версій, наприклад 18.06:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install docker-ce-18.06.1.ce-3.el7.x86_64
Неможливо передати розділений комою список значень аргументів під прапорцем --component-extra-args
Прапорці kubeadm init
, такі як --component-extra-args
, дозволяють передавати власні аргументи компоненту панелі управління, наприклад, kube-apiserver. Однак цей механізм обмежений через тип, який використовується для розбору значень (mapStringString
).
Якщо ви вирішите передати аргумент, який підтримує кілька значень, розділених комами, такий як --apiserver-extra-args "enable-admission-plugins=LimitRanger,NamespaceExists"
, цей прапорець видасть помилку flag: malformed pair, expect string=string
. Це відбувається через те, що список аргументів для --apiserver-extra-args
очікує пари key=value
, і в цьому випадку NamespacesExists
розглядається як ключ, якому не вистачає значення.
У іншому випадку ви можете спробувати розділити пари key=value
так: --apiserver-extra-args "enable-admission-plugins=LimitRanger,enable-admission-plugins=NamespaceExists"
, але це призведе до того, що ключ enable-admission-plugins
матиме лише значення NamespaceExists
.
Відомий обхід цього — використання файлу конфігурації kubeadm.
kube-proxy плануєтья до того, як вузол ініціалізовано cloud-controller-manager
У сценаріях хмарних провайдерів kube-proxy може виявитися запланованим на нових робочих вузлах до того, як cloud-controller-manager ініціалізує адреси вузла. Це призводить до того, що kube-proxy не може належним чином отримати IP-адресу вузла, і це має негативний вплив на функцію проксі, що керує балансуванням навантаження.
У kube-proxy Pods можна побачити наступну помилку:
server.go:610] Failed to retrieve node IP: host IP unknown; known addresses: []
proxier.go:340] invalid nodeIP, initializing kube-proxy with 127.0.0.1 as nodeIP
Відомий варіант рішення — виправлення DaemonSet kube-proxy, щоб дозволити його планування на вузлах панелі управління незалежно від їхніх умов, утримуючи його подальше від інших вузлів, доки їхні початкові умови зберігаються:
kubectl -n kube-system patch ds kube-proxy -p='{
"spec": {
"template": {
"spec": {
"tolerations": [
{
"key": "CriticalAddonsOnly",
"operator": "Exists"
},
{
"effect": "NoSchedule",
"key": "node-role.kubernetes.io/control-plane"
}
]
}
}
}
}'
Тікет, що відстежує цю проблему, розташовано тут.
/usr
монтується тільки для читання на вузлах
У дистрибутивах Linux, таких як Fedora CoreOS або Flatcar Container Linux, тека /usr
монтується як файлова система тільки для читання. Для підтримки flex-volume компоненти Kubernetes, такі як kubelet і kube-controller-manager, використовують типовий шлях /usr/libexec/kubernetes/kubelet-plugins/volume/exec/
, проте тека flex-volume має бути доступною для запису, щоб ця функція працювала.
Примітка:
У випуску Kubernetes v1.23 функцію FlexVolume було визнано застарілою.Для усунення цієї проблеми ви можете налаштувати теку flex-volume, використовуючи файл конфігурації kubeadm.
На основному вузлі панелі управління (створеному за допомогою kubeadm init
) передайте наступний файл, використовуючи параметр --config
:
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
- name: "volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
controllerManager:
extraArgs:
- name: "flex-volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
При долученні вузлів:
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
- name: "volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
Альтернативно ви можете змінити файл /etc/fstab
, щоб зробити монтування /usr
доступним для запису, проте будьте обізнані, що це змінює принцип дизайну дистрибутиву Linux.
kubeadm upgrade plan
виводить повідомлення про помилку context deadline exceeded
Це повідомлення про помилку виводиться при оновленні кластера Kubernetes за допомогою kubeadm
у випадку використання зовнішнього etcd. Це не критична помилка і виникає через те, що старі версії kubeadm
виконують перевірку версії зовнішнього кластера etcd. Ви можете продовжити з kubeadm upgrade apply ...
.
Цю проблему виправлено у версії 1.19.
kubeadm reset
відмонтовує /var/lib/kubelet
Якщо /var/lib/kubelet
має точку монтування, виконання kubeadm reset
фактично відмонтує його.
Для уникнення цієї проблеми повторно замонтуйте каталог /var/lib/kubelet
після виконання операції kubeadm reset
.
Це вдосконалення було введено в kubeadm 1.15. Проблема виправлена в 1.20.
Неможливо безпечно використовувати metrics-server в кластері kubeadm
У кластері kubeadm metrics-server може бути використаний в небезпечний спосіб, передаючи йому параметр --kubelet-insecure-tls
. Це не рекомендується для промислових кластерів.
Якщо ви хочете використовувати TLS між metrics-server та kubelet, виникає проблема, оскільки kubeadm розгортає самопідписний службовий сертифікат для kubelet. Це може призвести до наступних помилок з боку metrics-server:
x509: certificate signed by unknown authority
x509: certificate is valid for IP-foo not IP-bar
Дивіться Увімкнення підписаних службових сертифікатів kubelet, щоб зрозуміти, як налаштувати kubelet в кластері kubeadm для отримання належно підписаних службових сертифікатів.
Також перегляньте Як запустити metrics-server безпечно.
Оновлення не вдається через незмінність хешу etcd
Це стосується лише оновлення вузла панелі управління за допомогою бінарного файлу kubeadm v1.28.3 або пізніше, при умові, що вузол в цей час керується версіями kubeadm v1.28.0, v1.28.1 або v1.28.2.
Ось повідомлення про помилку, яке може виникнути:
[upgrade/etcd] Failed to upgrade etcd: couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced: static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
[upgrade/etcd] Waiting for previous etcd to become available
I0907 10:10:09.109104 3704 etcd.go:588] [etcd] attempting to see if all cluster endpoints ([https://172.17.0.6:2379/ https://172.17.0.4:2379/ https://172.17.0.3:2379/]) are available 1/10
[upgrade/etcd] Etcd was rolled back and is now available
static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.rollbackOldManifests
cmd/kubeadm/app/phases/upgrade/staticpods.go:525
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.upgradeComponent
cmd/kubeadm/app/phases/upgrade/staticpods.go:254
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.performEtcdStaticPodUpgrade
cmd/kubeadm/app/phases/upgrade/staticpods.go:338
...
Причина цієї помилки полягає в тому, що пошкоджені версії генерують файл маніфесту etcd із небажаними стандартними в PodSpec. Це призводить до різниці в порівнянні маніфестів, і kubeadm буде очікувати зміни хешу в Pod, але kubelet ніколи не оновить хеш.
Є два способи обійти цю проблему, якщо ви бачите її у своєму кластері:
Оновлення etcd може бути пропущено між пошкодженими версіями та v1.28.3 (або пізніше) за допомогою:
kubeadm upgrade {apply|node} [version] --etcd-upgrade=false
Це не рекомендується у випадку, якщо пізніше патч-версії v1.28 вводять нову версію etcd.
Перед оновленням виправте маніфест для статичного Pod etcd, щоб видалити стандартні проблемні атрибути:
diff --git a/etc/kubernetes/manifests/etcd_defaults.yaml b/etc/kubernetes/manifests/etcd_origin.yaml index d807ccbe0aa..46b35f00e15 100644 --- a/etc/kubernetes/manifests/etcd_defaults.yaml +++ b/etc/kubernetes/manifests/etcd_origin.yaml @@ -43,7 +43,6 @@ spec: scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 - successThreshold: 1 timeoutSeconds: 15 name: etcd resources: @@ -59,26 +58,18 @@ spec: scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 - successThreshold: 1 timeoutSeconds: 15 - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File volumeMounts: - mountPath: /var/lib/etcd name: etcd-data - mountPath: /etc/kubernetes/pki/etcd name: etcd-certs - dnsPolicy: ClusterFirst - enableServiceLinks: true hostNetwork: true priority: 2000001000 priorityClassName: system-node-critical - restartPolicy: Always - schedulerName: default-scheduler securityContext: seccompProfile: type: RuntimeDefault - terminationGracePeriodSeconds: 30 volumes: - hostPath: path: /etc/kubernetes/pki/etcd
Більше інформації можна знайти в тікеті для цієї помилки.