Модуль 1.7: Основи kubeadm — Початкове налаштування кластера
Складність:
[MEDIUM]— основи управління кластеромЧас на проходження: 60–75 хвилин
Передумови: Модуль 1.1 (Площина управління), Модуль 1.2 (Інтерфейси розширення)
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після цього модуля ви зможете:
- Спроєктувати послідовність початкового налаштування kubeadm, яка охоплює попередні перевірки (preflight checks),
kubeadm init, встановлення CNI та токени приєднання робочих вузлів. - Діагностувати збої статичних Подів і kubelet за допомогою локальних логів, маніфестів та інструментів середовища виконання контейнерів, коли API-сервер недоступний.
- Оцінити ризики обслуговування сертифікатів і etcd, перевіряючи строк дії, плануючи поновлення та захищаючи знімки перед руйнівними операціями.
- Впровадити безпечне обслуговування вузлів за допомогою робочих процесів cordon, drain, uncordon та kubeadm reset.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: ви успадковуєте невеликий kubeadm-кластер, на якому працює внутрішній сервіс платформної команди, і площина управління залишається справною, доки рутинне перезавантаження вузла не оголює забутий нюанс початкового налаштування. Нові Поди перестають отримувати IP-адреси, заміна робочого вузла не може приєднатися, а kubectl працює з ноутбука одного адміністратора, але не з іншого. Жоден аспект цього інциденту не вимагає екзотичних знань Kubernetes, проте кластер залишається заблокованим, бо команда знає лише абстракції керованих кластерів і ніколи не зазирала в /etc/kubernetes, маніфести статичних Подів kubelet, токени початкового налаштування чи сертифікати, які kubeadm створює під час ініціалізації.
kubeadm важливий, тому що він навмисно близький до самої механіки. Керовані сервіси приховують більшість цієї механіки, доки щось під ними не дасть тріщину, але іспит CKA очікує від вас міркувань із перших принципів, коли вузол не приєднується, статичний Под знову й знову повертається після видалення, сертифікат наближається до завершення строку дії або осушений вузол лишається непридатним для планування після обслуговування. Мета цього модуля — не запам’ятати кожну підкоманду kubeadm. Мета — пов’язати кожен файл, сертифікат, токен і операцію над вузлом із поведінкою площини управління, яку ви вже вивчали в попередніх модулях.
Уявіть kubeadm як прораба на будівництві з кресленнями. Коли ви запускаєте kubeadm init, він не стає будівлею і не продовжує керувати кожною цеглиною після того, як кластер вже існує. Він закладає фундамент, генеруючи сертифікати та kubeconfig-файли, розміщує площину управління в маніфести статичних Подів, просить kubelet підтримувати ці Поди в робочому стані й виводить інструкцію приєднання для майбутніх робочих вузлів. Щойно цей фундамент закладено, ваша операційна робота змінюється з «запустити інсталятор» на «захищати файли та процеси, які цей інсталятор створив».
Цей модуль переписує стару коротку довідку в робочу ментальну модель. Спершу ви відобразите послідовність початкового налаштування, а потім потренуєте команди, які ініціалізують площину управління, встановлюють мережу, приєднують вузли, перевіряють статичні Поди, захищають сертифікати й дані etcd та виконують обслуговування вузлів. Наприкінці kubeadm-кластер має сприйматися менше як магічний скрипт і більше як набір придатних для огляду контрактів між kubeadm, kubelet, середовищем виконання контейнерів, API-сервером і файлами на диску.
Анатомія початкового налаштування: що будує kubeadm
Розділ «Анатомія початкового налаштування: що будує kubeadm»kubeadm найкраще розуміти як координатора початкового налаштування, а не як повноцінну платформу управління життєвим циклом кластера. Він перевіряє хост, записує матеріал сертифікатів, створює kubeconfig-файли, формує маніфести статичних Подів і налаштовує достатньо додатків кластера, щоб API-сервер став придатним до використання. Він не встановлює ваше середовище виконання контейнерів, не вирішує дизайн вашого хмарного балансувальника навантаження, не обирає ваш CNI-плагін і не продовжує редагувати вашу операційну систему після ініціалізації кластера. Ця межа корисна, бо робить kubeadm передбачуваним, але вона ж означає, що зламана передумова лишається вашою відповідальністю.
Перший практичний урок полягає в тому, що kubeadm створює площину управління Kubernetes, просячи kubelet запускати статичні Поди. Спочатку такий дизайн здається непрямим: замість запуску kube-apiserver через systemd, kubeadm записує YAML-файл у каталог, за яким ведеться спостереження, і kubelet запускає контейнер із цього маніфесту. Саме тому площина управління kubeadm може відновити контейнер свого API-сервера навіть тоді, коли сам API-сервер тимчасово недоступний. Локальний kubelet є наглядачем для контейнерів площини управління, тож діагностика на рівні файлів лишається можливою, коли діагностика на рівні API — ні.
┌────────────────────────────────────────────────────────────────┐│ kubeadm init Process ││ ││ 1. Pre-flight Checks ││ └── Verify system requirements (CPU, memory, ports) ││ ││ 2. Generate Certificates ││ └── CA, API server, kubelet, etcd certificates ││ └── Stored in /etc/kubernetes/pki/ ││ ││ 3. Generate kubeconfig Files ││ └── admin.conf, kubelet.conf, controller-manager.conf ││ └── Stored in /etc/kubernetes/ ││ ││ 4. Generate Static Pod Manifests ││ └── API server, controller-manager, scheduler, etcd ││ └── Stored in /etc/kubernetes/manifests/ ││ ││ 5. Start kubelet ││ └── kubelet reads manifests and starts control plane ││ ││ 6. Apply Cluster Configuration ││ └── CoreDNS, kube-proxy DaemonSet ││ ││ 7. Generate Join Token ││ └── For worker nodes to join ││ │└────────────────────────────────────────────────────────────────┘Наведена послідовність дає вам надійний порядок усунення несправностей. Якщо kubeadm init зазнає невдачі ще до запису сертифікатів, ви дивитеся на попередні перевірки, swap, ідентичність хоста, порти та середовище виконання контейнерів. Якщо сертифікати й kubeconfig-файли існують, але API-сервер недоступний, ви перевіряєте логи kubelet і контейнери статичних Подів. Якщо API-сервер доступний, але CoreDNS у стані pending, ви перевіряєте, чи був встановлений CNI-плагін і чи збігається його pod CIDR із конфігурацією кластера. Кожна точка збою звужує простір пошуку, бо kubeadm лишає по собі видимі артефакти.
kubeadm також має навмисні незавдання (non-goals), і ці незавдання важливі для іспиту. Він не встановлює для вас containerd, kubelet, kubeadm чи kubectl. Він не встановлює CNI-плагін під час init, бо вибір CNI залежить від мережевої моделі, яку ви хочете. Він не будує зовнішній балансувальник навантаження для HA-площини управління, бо це належить вашому інфраструктурному рівню. Він може допомогти додати додаткові вузли площини управління, але продакшн-дизайн HA все одно потребує стабільної кінцевої точки перед API-серверами.
Перш ніж запускати kubeadm на свіжому хості, ставтеся до передумов як до частини плану початкового налаштування, а не як до примітки. Відсутній сокет середовища виконання контейнерів, увімкнений swap, дубльована ідентичність хоста або заблокований порт API-сервера спричиняють збої, які виглядають як «Kubernetes зламався», тоді як справжня проблема — у контракті підготовки вузла. Зупиніться й передбачте: якщо kubelet встановлено, але середовище виконання контейнерів зупинене, який крок на діаграмі все ще може завершитися, а який крок мусить зазнати невдачі, коли kubelet спробує запустити контейнери статичних Подів?
# Required on ALL nodes:# 1. Container runtime (containerd)# 2. kubelet# 3. kubeadm# 4. kubectl (at least on control plane)# 5. Swap disabled# 6. Required ports open# 7. Unique hostname, MAC, product_uuidФазова модель kubeadm корисна, коли збій трапляється посеред ініціалізації. kubeadm init — це не одна непрозора дія; це послідовність фаз, які досвідчені оператори можуть переглядати, пропускати або повторно запускати в контрольований спосіб. Для роботи з CKA вам рідко потрібне власне виконання фаз, але знання про те, що фази існують, допомагає читати вивід помилок. Збій під час генерації сертифікатів, генерації kubeconfig, формування статичних Подів або встановлення додатків має інший шлях виправлення, ніж збій під час попередніх перевірок хоста.
Ви можете побачити цей дизайн у виводі команди, коли kubeadm повідомляє про кожен великий крок. Цей вивід є доказом, тож зберігайте його, коли лабораторна робота чи реальний кластер зазнає збою. Якщо фаза попередніх перевірок скаржиться на swap, виправте swap. Якщо формування маніфесту статичного Пода вдалося, але API-сервер так і не став доступним, спускайтеся стеком до kubelet і середовища виконання. Ця дисципліна схожа на читання помилки компілятора: перший значущий збій зазвичай дає кращу зачіпку, ніж каскад пізніших симптомів.
На іспиті CKA питання про kubeadm зазвичай менше стосуються побудови продакшн-кластера з порожньої віртуальної машини й більше — розпізнавання того, де kubeadm розмістив рухомі частини. Проте модель початкового налаштування окупається й поза іспитом. Якщо ви знаєте, що сертифікати лежать у /etc/kubernetes/pki, що маніфести Подів площини управління лежать у /etc/kubernetes/manifests, а kubelet є локальним наглядачем, ви можете діагностувати збої навіть тоді, коли API кластера тимчасово недоступний.
Ініціалізація площини управління та встановлення мережі
Розділ «Ініціалізація площини управління та встановлення мережі»Команда kubeadm init запускає площину управління, але прапорці, які ви обираєте, кодують припущення, що й далі впливатимуть на кластер. Pod network CIDR має збігатися з CNI-плагіном, який ви плануєте встановити. Адреса оголошення (advertise address) API-сервера має бути досяжною для вузлів, що приєднуватимуться. Закріплення версії Kubernetes контролює версії образів площини управління і має узгоджуватися з пакетами, які ви встановили на хості. Це не декоративні прапорці; це перші тривкі рішення в кластері.
# Initialize control planesudo kubeadm init
# With specific pod network CIDR (required by some CNIs)sudo kubeadm init --pod-network-cidr=10.244.0.0/16
# With specific API server address (for HA or custom networking)sudo kubeadm init --apiserver-advertise-address=192.168.1.10
# With specific Kubernetes versionsudo kubeadm init --kubernetes-version=v1.35.0Найпростіша команда корисна в лабораторії, але реальне усунення несправностей часто починається з більш явних варіантів. Якщо вузол приєднується, але Поди не можуть спілкуватися, pod CIDR і конфігурація CNI — перші підозрювані. Якщо робочий вузол отримує команду приєднання, що містить адресу, до якої він не може маршрутизувати, підозрюваним є вибір адреси оголошення або кінцевої точки площини управління. Якщо пакети й образи площини управління походять із різних мінорних версій, правила розбіжності версій (version skew) мають значення ще до того, як ви припустите, що винна мережа.
Для відтворюваних кластерів конфігураційний файл kubeadm безпечніший за довгий командний рядок, скопійований зі сторінки нотаток. Файл фіксує налаштування кластера, як-от версія Kubernetes, pod subnet, service subnet, репозиторій образів, кінцева точка API-сервера та альтернативні імена суб’єкта сертифіката (SAN), в одному придатному для огляду артефакті. Це важливо в командах, бо інший оператор може перевірити заплановані значення початкового налаштування до запуску команди. Це також важливо під час перебудов, бо другу площину управління не варто ініціалізувати з чиєїсь пам’яті про першу.
# Generate a starting point for a reviewed kubeadm configurationkubeadm config print init-defaultsapiVersion: kubeadm.k8s.io/v1beta4kind: ClusterConfigurationkubernetesVersion: v1.35.0controlPlaneEndpoint: "192.168.1.10:6443"networking: podSubnet: 10.244.0.0/16Коли ви використовуєте конфігураційний файл, команда стає простішою, а огляд — чіткішим. Ви можете порівняти обраний pod subnet із документацією CNI, підтвердити кінцеву точку площини управління перед приєднанням робочих вузлів і зберігати файл у внутрішньому runbook без зберігання токенів початкового налаштування. Файл не усуває потреби готувати хости, але зменшує ймовірність того, що критичний вибір початкового налаштування буде прихований в історії команд оболонки.
# Initialize from a reviewed configuration filesudo kubeadm init --config kubeadm-config.yamlПісля ініціалізації kubeadm записує адміністративний kubeconfig, але не копіює цей файл у домашній каталог кожного користувача. Саме тому свіжоініціалізований кластер може існувати, тоді як kubectl get nodes зазнає невдачі для звичайного користувача оболонки. API-сервер може працювати, але kubectl все одно потребує облікових даних і даних підключення до кластера. Перед тим як це запускати: який вивід ви очікуєте від kubectl get nodes до копіювання kubeconfig і що зміниться після того, як $HOME/.kube/config вказуватиме на admin.conf?
# For regular user (recommended)mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config
# For root userexport KUBECONFIG=/etc/kubernetes/admin.confНаступний крок — встановлення CNI. Без CNI-плагіна kubelet може запускати статичні Поди площини управління, але звичайні Поди не можуть отримати маршрутизовані pod-IP, а CoreDNS зазвичай лишається в стані pending або not ready. Ця відмінність важлива: kubeadm-кластер може виглядати частково живим до встановлення мережі. API-сервер може відповідати на запити, проте робочі навантаження лишаються нездатними спілкуватися, бо мережевий рівень ще не виконав свою частину контракту кластера.
Перед запуском будь-якої команди встановлення CNI оберіть рівно один CNI і спершу перевірте актуальну документацію постачальника. Версія Kubernetes, передумови ядра, режим kube-proxy, pod CIDR і метод встановлення можуть змінюватися від випуску до випуску плагіна, тож застарілі однорядкові маніфести — поганий навчальний патерн для кластера Kubernetes 1.35. Використовуйте команди з актуальної документації для того плагіна, який ви насправді обрали, і записуйте версію чи канал випуску в нотатках лабораторної роботи, щоб подальше усунення несправностей мало фактичну відправну точку.
# Without CNI, pods won't get IPs and CoreDNS won't start
# Calico: read current Kubernetes support and install steps first.# https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements# https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart## Flannel: use the current release or Helm path from the upstream project.# https://github.com/flannel-io/flannel## Cilium: install the Cilium CLI first, then follow the current install docs.# https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/Ці вказівники на CNI — лабораторні запобіжники, а не рекомендація копіювати команду без читання актуального посібника зі встановлення обраного постачальника. Захищений урок — це послідовність: ініціалізуйте площину управління, налаштуйте kubectl, встановіть один CNI, який відповідає вибору pod-мережі, а потім перевірте системні Поди. Змішування кількох CNI за логікою «більше мережі має допомогти» створює конфліктні агенти, які борються за мережу Подів і ускладнюють діагностику.
# Check nodeskubectl get nodes# NAME STATUS ROLES AGE VERSION# control-plane Ready control-plane 5m v1.35.0
# Check system podskubectl get pods -n kube-system# Should see: coredns, etcd, kube-apiserver, kube-controller-manager,# kube-proxy, kube-scheduler, CNI podsПеревірку слід тлумачити, а не сприймати як ритуал «пройдено чи ні». Один вузол площини управління може повідомляти Ready, тоді як CoreDNS усе ще запускається, а свіжовстановленому CNI може знадобитися короткий проміжок, щоб створити Поди свого DaemonSet. Патерн, якого ви прагнете, — це сходження до робочого стану: вузол стає готовим, Поди kube-system перестають циклічно падати, CoreDNS отримує робочі репліки, а Поди CNI потрапляють на вузли, що потребують мережі Подів. Якщо кластер застряг, зіставте симптом із послідовністю початкового налаштування, а не запускайте kubeadm init наосліп.
Корисний практичний приклад — хост площини управління, де kubeadm init --pod-network-cidr=10.244.0.0/16 вдається, kubectl get nodes працює після копіювання kubeconfig, але CoreDNS лишається в стані pending. Наступна команда — не kubeadm reset; це kubectl get pods -n kube-system -o wide, щоб побачити, чи існує DaemonSet CNI і де заплановані Поди. Якщо Подів CNI немає, встановіть призначений CNI. Якщо Поди CNI існують, але циклічно падають, перевірте їхні логи й переконайтеся, що pod CIDR і передумови ядра/мережі відповідають плагіну.
kubeadm також зберігає конфігурацію кластера в кластері після ініціалізації, що дає вам ще один спосіб перевірити, що було задумано. ConfigMap kubeadm-config у kube-system записує налаштування, до яких можуть звертатися майбутні операції kubeadm, особливо оновлення. Це не замінює ваш runbook, бо зламаний API-сервер може зробити ConfigMap недосяжним, але це цінно, коли кластер достатньо справний для перевірки через API. Якщо збережена конфігурація й ваші припущення розходяться, довіряйте доказам і оновіть runbook.
# Inspect kubeadm's stored cluster configurationkubectl -n kube-system get configmap kubeadm-config -o yamlПриєднання вузлів і захист довіри початкового налаштування
Розділ «Приєднання вузлів і захист довіри початкового налаштування»Приєднання робочих вузлів легко скопіювати й легко зрозуміти неправильно. Команда приєднання містить токен початкового налаштування, який автентифікує новий вузол для його початкової реєстрації, і містить хеш CA-сертифіката, що дозволяє вузлу переконатися, що він спілкується з призначеною площиною управління. Токен відповідає на питання «чи дозволено мені починати приєднання?», а хеш CA — на «чи приєднуюся я до правильного кластера?». Обидві частини мають значення, бо початкове налаштування вузла відбувається до того, як вузол отримає свій довготривалий клієнтський сертифікат kubelet.
# Example output from kubeadm initkubeadm join 192.168.1.10:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:abc123...Запускайте команду приєднання на робочому вузлі після того, як там встановлено середовище виконання, kubelet і kubeadm. Робочий вузол потребує мережевої досяжності кінцевої точки API-сервера, достатньо узгодженого часу для перевірки сертифіката, справного середовища виконання контейнерів і токена, строк дії якого не завершився. Невдале приєднання часто є локальною проблемою підготовки вузла, а не проблемою площини управління, тож перші логи для читання зазвичай — на робочому вузлі, що приєднується.
# On worker node (as root)sudo kubeadm join 192.168.1.10:6443 \ --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:abc123...Токени початкового налаштування за замовчуванням мають обмежений строк дії, і це радше функція, ніж незручність. Команда приєднання, вставлена в тикет, чат або історію команд оболонки, не повинна авторизувати нові вузли вічно. Операційна звичка — генерувати свіжу команду за потреби, використовувати її під час контрольованого вікна обслуговування й видаляти старі токени або дозволяти їм завершити строк дії. Який підхід ви б тут обрали й чому: довготривалий токен для зручності чи короткотривалі токени, що генеруються як частина runbook кожного додавання вузла?
# On control plane - create new tokenkubeadm token create --print-join-command
# Or manually:# 1. Create tokenkubeadm token create
# 2. Get CA cert hashopenssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \ openssl rsa -pubin -outform der 2>/dev/null | \ openssl dgst -sha256 -hex | sed 's/^.* //'
# 3. Construct join commandkubeadm join <control-plane-ip>:6443 --token <new-token> \ --discovery-token-ca-cert-hash sha256:<hash>Ручний процес варто вивчити, навіть якщо --print-join-command швидший, бо він оголює модель довіри. Хеш походить від публічного ключа CA кластера, а не від короткотривалого токена. Якщо строк дії токена завершився, ви створюєте новий токен; якщо хеш CA неправильний, вузол має відмовитися довіряти кінцевій точці. Коли робочий вузол не може приєднатися, читання точної помилки має значення, бо «token invalid», «x509», «connection refused» і «timed out» вказують на різні рівні.
# List existing tokenskubeadm token list
# Delete a tokenkubeadm token delete <token>
# Create token with custom TTLkubeadm token create --ttl 2hСтавтеся до управління токенами як до частини гігієни кластера. У крихітному лабораторному кластері токени з вичерпаним строком дії — переважно лише невелика затримка. У спільному середовищі забуті токени початкового налаштування стають заплутаним операційним станом і можуть розширити вікно, протягом якого небажаний хост зможе спробувати зареєструватися. Виправлення нескладне: переглядайте токени перед приєднанням, створюйте токен із розумним TTL, документуйте, який вузол його використав, і прибирайте токени, які вже не потрібні.
Сценарій вправи: робочий вузол було підготовлено з того самого образу, що й наявний вузол, але kubeadm join зазнає невдачі з помилкою про те, що вузол уже існує. Це сигнал перевірити ідентичність хоста й старий стан kubelet, перш ніж винуватити токен. Клонована віртуальна машина може нести застарілі дані /var/lib/kubelet, дубльовану машинну ідентичність або ім’я хоста, що конфліктує з наявним об’єктом вузла. Скиньте й очистіть вузол, виправте ім’я хоста й повторно запустіть приєднання зі свіжою командою, замість того щоб змушувати API-сервер приймати неоднозначну ідентичність.
Статичні Поди, файли, сертифікати та etcd
Розділ «Статичні Поди, файли, сертифікати та etcd»Статичні Поди — це ключ до діагностики площини управління kubeadm. Звичайний Деплоймент узгоджується контролерами через API-сервер; статичний Под читається kubelet безпосередньо з файлу. kubeadm використовує статичні Поди для kube-apiserver, kube-controller-manager, kube-scheduler і локального etcd, бо ці компоненти мусять існувати раніше, ніж контролери вищого рівня зможуть будь-чим керувати. Це і є цикл початкового налаштування: kubelet запускає API-сервер, і лише потім API-сервер може показати дзеркальні Поди (mirror pods), які роблять статичні Поди видимими через kubectl.
# Static pod manifests locationls /etc/kubernetes/manifests/# etcd.yaml# kube-apiserver.yaml# kube-controller-manager.yaml# kube-scheduler.yamlAPI-сервер показує дзеркальні Поди для видимості, але він не володіє джерелом істини для статичних Подів. Якщо ви видалите дзеркальний Под за допомогою kubectl, kubelet помітить, що файл маніфесту все ще існує, і відтворить об’єкт дзеркального Пода в API. Базовий контейнер при цьому НЕ перезапускається — kubelet не видаляє маніфест, тож процес статичного Пода продовжує працювати без переривання. Це класична пастка CKA: видалення дзеркального Пода за допомогою kubectl не перезапускає застряглий компонент площини управління, бо операція API ніколи не досягає середовища виконання. Така поведінка дивує лише тоді, коли ви припускаєте, що кожен Под, видимий через API, керується через API. Зупиніться й передбачте: якщо ви запустите kubectl delete pod kube-apiserver-controlplane -n kube-system, що зміниться (а що — ні) на рівні середовища виконання контейнерів і який файл визначає відповідь?
┌────────────────────────────────────────────────────────────────┐│ Static Pod Lifecycle ││ ││ /etc/kubernetes/manifests/ ││ │ ││ │ kubelet watches this directory ││ ▼ ││ ┌─────────────┐ ││ │ kubelet │ ││ └──────┬──────┘ ││ │ ││ │ For each YAML file: ││ │ 1. Start container ││ │ 2. Keep it running ││ │ 3. Restart if it crashes ││ │ 4. Create mirror pod in API server ││ ▼ ││ ┌─────────────────────────────────────────┐ ││ │ Control Plane Containers │ ││ │ • kube-apiserver │ ││ │ • kube-controller-manager │ ││ │ • kube-scheduler │ ││ │ • etcd │ ││ └─────────────────────────────────────────┘ ││ │└────────────────────────────────────────────────────────────────┘Редагування маніфестів статичних Подів є потужним і ризикованим, бо kubelet застосовує результат автоматично. Дійсне редагування перезапускає компонент із новими прапорцями; недійсне редагування може зупинити API-сервер, scheduler, controller manager або etcd. Найбезпечніша звичка — зробити копію з часовою міткою поза /etc/kubernetes/manifests/, змінити одну річ, тримати відкритою root-оболонку на вузлі площини управління й використовувати локальні логи, якщо API зникне. Не залишайте kube-apiserver.yaml.bak чи будь-який інший резервний файл усередині каталогу маніфестів, за яким ведеться спостереження, бо kubelet ставиться до файлів без крапки на початку як до кандидатів на маніфести статичних Подів, а не як до нешкідливих нотаток. Для практики до іспиту ключова відмінність проста: kubectl може показати статичний Под, але файл маніфесту керує ним.
# Make a safe backup OUTSIDE the watched manifest directorysudo mkdir -p /etc/kubernetes/backupsudo cp /etc/kubernetes/manifests/kube-apiserver.yaml \ /etc/kubernetes/backup/kube-apiserver.yaml.$(date -u +%Y%m%dT%H%M%SZ)
# View static pod manifestssudo cat /etc/kubernetes/manifests/kube-apiserver.yaml
# Modify a static pod (edit the manifest)sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml# kubelet automatically restarts the pod
# "Delete" a static pod (remove the manifest)sudo mv /etc/kubernetes/manifests/kube-scheduler.yaml /tmp/# kubelet stops the pod
# Restore itsudo mv /tmp/kube-scheduler.yaml /etc/kubernetes/manifests/# kubelet starts the pod againРозкладка каталогів — це карта, якою ви користуєтеся, коли інструменти рівня API перестають працювати. /etc/kubernetes/admin.conf — це адміністративний kubeconfig. /etc/kubernetes/manifests містить визначення статичних Подів. /etc/kubernetes/pki містить CA кластера, сертифікати API-сервера, ключі підписання сервісних акаунтів, матеріал front-proxy і сертифікати etcd. Коли ви знаєте ці шляхи, «площина управління лежить» перестає бути розпливчастою панікою й стає розслідуванням на рівні файлів і процесів.
/etc/kubernetes/├── admin.conf # kubectl config for admin├── controller-manager.conf # kubeconfig for controller-manager├── kubelet.conf # kubeconfig for kubelet├── scheduler.conf # kubeconfig for scheduler├── manifests/ # Static pod definitions│ ├── etcd.yaml│ ├── kube-apiserver.yaml│ ├── kube-controller-manager.yaml│ └── kube-scheduler.yaml└── pki/ # Certificates ├── ca.crt # Cluster CA ├── ca.key ├── apiserver.crt # API server cert ├── apiserver.key ├── apiserver-kubelet-client.crt ├── front-proxy-ca.crt ├── sa.key # ServiceAccount signing key ├── sa.pub └── etcd/ # etcd certificates ├── ca.crt └── ...kubeconfig-файли в цьому каталозі теж варто називати уважно. admin.conf призначений для адміністрування кластера, тоді як kubelet.conf, controller-manager.conf і scheduler.conf — це клієнтські облікові дані для компонентів, що спілкуються з API-сервером. Якщо адміністратор скопіює не той файл у $HOME/.kube/config, поведінка авторизації, що виникне, може заплутати. Якщо kubeconfig компонента застарілий або нечитабельний, компонент може запуститися, але не пройти автентифікацію на API-сервері, тож діагностика сертифікатів і kubeconfig часто відбувається разом.
Права доступу до файлів — це частина моделі безпеки, а не лише дрібниця адміністрування Linux. Приватний ключ CA, ключ підписання сервісних акаунтів і приватні ключі etcd можуть авторизувати або підписувати надзвичайно чутливу поведінку кластера. Хороша резервна копія захоплює те, що потрібне для відновлення, але необачне копіювання в спільний каталог створює інший інцидент. Коли ви перевіряєте ці файли, використовуйте мінімально необхідний доступ, тримайте копії захищеними й видаляйте тимчасові діагностичні копії після вікна обслуговування.
Управління сертифікатами — це місце, де зустрічаються зручність kubeadm і ваша відповідальність. kubeadm може перевіряти завершення строку дії сертифікатів і поновлювати сертифікати, якими він керує, але поновлені файли не мають значення, доки уражені компоненти не перезавантажать їх. Компоненти на статичних Подах зазвичай перезавантажуються через перезапуск, який можна здійснити, перемістивши маніфести назовні й назад, дозволивши kubelet відтворити контейнери, або перезапустивши kubelet у запланованому вікні обслуговування. Вам також варто знати, які kubeconfig-файли потрібно повторно скопіювати після поновлення адміністративних облікових даних.
# Cluster CA/etc/kubernetes/pki/ca.crt/etc/kubernetes/pki/ca.key
# API Server/etc/kubernetes/pki/apiserver.crt/etc/kubernetes/pki/apiserver.key
# etcd CA (separate CA)/etc/kubernetes/pki/etcd/ca.crt/etc/kubernetes/pki/etcd/ca.key
# Check certificate expirationkubeadm certs check-expirationetcd заслуговує на окрему увагу, бо він зберігає стан кластера. Резервне копіювання etcd перед руйнівним обслуговуванням площини управління не є необов’язковим у серйозному середовищі, навіть коли іспит лише просить продемонструвати механіку. Команда знімка має використовувати кінцеву точку etcd і правильні клієнтські сертифікати, а відновлення слід планувати ретельно, бо воно замінює стан, який читатиме API-сервер. Резервна копія, яку ви ніколи не перевіряли, ближча до надії, ніж до плану відновлення.
# Save an etcd snapshot on a stacked-control-plane kubeadm nodesudo ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ snapshot save /var/backups/etcd-snapshot.db
# Inspect the snapshot before trusting itsudo ETCDCTL_API=3 etcdctl snapshot status /var/backups/etcd-snapshot.db --write-out=tableВідновлення etcd — це руйнівна дія відновлення, а не буденна команда обслуговування. У лабораторії з одновузловим вбудованим (stacked) etcd патерн відновлення такий: зупинити площину управління, відновити знімок у новий каталог даних за допомогою etcdutl, оновити маніфест статичного Пода etcd, щоб він вказував на цей каталог, якщо потрібно, а потім дозволити kubelet перезапустити etcd і API-сервер. Старіша форма etcdctl snapshot restore — це застаріла настанова; актуальна документація з відновлення Kubernetes і etcd використовує etcdutl для відновлення, тоді як etcdctl лишається поширеним для збереження живих знімків. У топології з кількома членами etcd процедура має враховувати кворум та ідентичність членів, тож не узагальнюйте рецепт одновузлової лабораторії в продакшн-runbook.
# Example lab restore target; plan production restores from the official etcd guidancesudo etcdutl snapshot restore /var/backups/etcd-snapshot.db \ --data-dir=/var/lib/etcd-from-backupОновлення вписуються в ту саму модель ризику. kubeadm може спланувати й застосувати оновлення площини управління, але ви все одно осушуєте вузли, дотримуєтеся розбіжності версій, оновлюєте пакети kubelet і kubectl та перевіряєте кожен крок перед тим, як рухатися далі. Безпечний порядок — спершу площина управління, потім робочі вузли по одному, з планом відкату й резервного копіювання, що існує до того, як ви торкнетеся першого компонента. Для цілей CKA знайте форму робочого процесу й команди, якими ви перевіряєте план.
# Step 1: upgrade the kubeadm binary itself to the target version FIRST.# `kubeadm upgrade apply` validates that the running kubeadm matches the# target version, so skipping this step fails immediately. Exact package# string varies by distro and repo (apt example shown).sudo apt-get update && sudo apt-get install -y --allow-change-held-packages kubeadm=1.35.1-1.1
# Step 2: control-plane planning step (read-only, safe to re-run)sudo kubeadm upgrade plan
# Step 3: control-plane apply for a patch release in the same minor linesudo kubeadm upgrade apply v1.35.1
# Step 4: upgrade kubelet and kubectl packages, then restart kubeletsudo apt-get install -y --allow-change-held-packages kubelet=1.35.1-1.1 kubectl=1.35.1-1.1sudo systemctl daemon-reloadsudo systemctl restart kubeletВажливий зв’язок полягає в тому, що сертифікати, знімки etcd, маніфести статичних Подів та оновлення — не окремі теми. Усі вони є операціями обслуговування навколо одного набору активів, створених kubeadm. Якщо ви можете прочитати розкладку файлів і пояснити, який локальний процес споживає кожен файл, ви можете міркувати про поведінку поновлення, відновлення, перезапуску й оновлення, не покладаючись на завчений скрипт.
Обслуговування вузлів, скидання та відновлення
Розділ «Обслуговування вузлів, скидання та відновлення»Обслуговування вузлів починається з наміру щодо планування. Cordon каже «не розміщуй тут нові Поди»; drain каже «виселити Поди, які можуть безпечно переміститися». Ця відмінність важлива, бо вузол із cordon усе ще може виконувати наявні робочі навантаження, а перезавантаження все одно може їх перервати. Drain використовує API виселення (eviction API) для керованих Подів, дотримується багатьох засобів контролю доступності й лишає Поди DaemonSet недоторканими, якщо ви не використаєте додаткові прапорці. Правильна команда залежить від того, запобігаєте ви майбутньому розміщенню чи готуєтеся до руйнівної роботи.
# List nodeskubectl get nodes
# Detailed infokubectl get nodes -o wide
# Node detailskubectl describe node <node-name>Хороша діагностика вузла починається з розділення бажаного стану планування й стану справності. Вузол може бути в стані Ready,SchedulingDisabled, що означає, що kubelet справний, але scheduler не має дозволу розміщувати там нові Поди. Вузол може бути в стані NotReady, що означає, що площина управління не отримала справного статусу від kubelet чи пов’язаних компонентів. Ці стани передбачають різні наступні кроки. Зупиніться й подумайте: якщо ви лише виконаєте cordon вузла перед обслуговуванням ядра, який ризик лишається, з яким би впорався drain?
# Drain node (evict pods, mark unschedulable)kubectl drain <node-name> --ignore-daemonsets
# If there are pods with local storage:kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# Force (for pods without controllers):kubectl drain <node-name> --ignore-daemonsets --forceПрапорці drain мають змусити вас зробити паузу, бо кожен із них кодує компроміс. --ignore-daemonsets є нормою, бо Поди DaemonSet очікувано живуть на вузлі й не можуть бути осушені так само, як Поди Деплойменту. --delete-emptydir-data визнає, що дані в томах emptyDir є локальними для вузла й будуть видалені разом із Подом. --force — це сильніше твердження: ви готові видалити Поди, які не мають контролера для повторного створення. Використовуйте його свідомо, а не на автоматизмі.
# Mark node unschedulable (no new pods)kubectl cordon <node-name>
# Mark node schedulable againkubectl uncordon <node-name>
# Check node statuskubectl get nodes# NAME STATUS ROLES AGE VERSION# node1 Ready worker 10d v1.35.0# node2 Ready,SchedulingDisabled worker 10d v1.35.0 # cordonedВідновлення після обслуговування не завершується, коли вузол перезавантажується. Ви перевіряєте, що kubelet працює, що вузол повертається в стан Ready, що критичні DaemonSet справні, і що з вузла знято cordon, якщо він має отримувати робочі навантаження. Поширений операційний недогляд — правильно виконати обслуговування й потім залишити вузол із cordon на кілька днів. Кластер продовжує працювати, але ємність нижча, сигнали автомасштабування заплутуються, а майбутні drain мають менше місця для переміщення Подів.
# 1. Drain the node firstkubectl drain <node-name> --ignore-daemonsets --force
# 2. Delete from clusterkubectl delete node <node-name>
# 3. On the node itself, reset kubeadmsudo kubeadm reset
# 4. Optional post-reset cleanup after preserving evidencesudo rm -rf /etc/cni/net.d/rm -rf $HOME/.kube# Clean kube-proxy rules with the documented kube-proxy --cleanup method.Видалення вузла остаточніше за його осушення. Видалення об’єкта Node каже кластеру припинити відстеження цього хоста, тоді як kubeadm reset виконує локальне очищення на хості за принципом «найкраще зусилля» (best-effort). Команди очищення навмисно руйнівні, тож їхнє місце — у лабораторії, runbook виведення з експлуатації чи контрольованій перебудові, а не в буденному циклі усунення несправностей. Якщо вам потрібно лише перезапустити kubelet чи виправити файл конфігурації CNI, скидання вузла викидає корисні докази й створює зайву роботу.
# On the node to resetsudo kubeadm reset
# kubeadm reset is best-effort LOCAL cleanup:# 1. Removes kubeadm-managed local files and certificates.# 2. Removes this node's local stacked etcd member data when applicable.# 3. Does not remove generic cluster state from a surviving etcd cluster.# 4. Does not clean CNI config, $HOME/.kube, or kube-proxy rules.
# Additional cleanup kubeadm reset does NOT do automatically:sudo rm -rf /etc/cni/net.d/rm -rf $HOME/.kube
# For kube-proxy network rules, follow the kubeadm reset reference:# run kube-proxy --cleanup from the same kube-proxy image version/runtime# your cluster used. Do not assume an iptables flush is complete, because# kube-proxy may have programmed iptables, IPVS, or nftables state.Скидання також має іспитову пастку: воно не стирає магічним чином кожен можливий мережевий, обліковий чи runtime-артефакт у кожному середовищі. Файли конфігурації CNI, $HOME/.kube, правила трафіку kube-proxy, стан IPVS чи nftables, образи контейнерів і дані середовища виконання можуть потребувати окремого очищення залежно від того, як був підготовлений вузол. Саме тому вивід kubeadm reset і довідкова сторінка кажуть вам, що воно зробило і що вам, можливо, ще потрібно очистити. Читайте вивід, а не припускайте, що скидання означає «як новий з заводу».
Усунення несправностей без робочого API-сервера
Розділ «Усунення несправностей без робочого API-сервера»Найшвидша звичка усунення несправностей kubeadm — обирати інструмент, який усе ще працює на рівні, де стався збій. Якщо API-сервер справний, kubectl зручний і виразний. Якщо API-сервер лежить, kubectl може зависати, але логи kubelet, статус systemd, інструменти середовища виконання контейнерів і маніфести статичних Подів усе ще доступні на вузлі. Якщо сам kubelet зупинено, навіть відновлення статичних Подів залежить від спершу виправлення локального сервісу. Цей пошаровий підхід запобігає поширеній помилці — раз за разом запускати API-клієнт проти мертвого API.
# Check kubelet statussystemctl status kubelet
# Check kubelet logsjournalctl -u kubelet -f
# Common issues:# - Swap not disabled# - Container runtime not running# - Wrong container runtime socketКоли ви збираєте докази, фіксуйте і команду, і вузол, на якому ви її запускали. Лог kubelet з робочого вузла, який не може приєднатися, розповідає іншу історію, ніж лог kubelet з вузла площини управління, який не може запустити API-сервер. Так само результат crictl ps з неправильного хоста може відправити вас у погоню за відсутніми контейнерами, які ніколи й не мали там працювати. Маркування доказів за іменем вузла, роллю й часом утримує невеликий інцидент від перетворення на купу розрізнених фрагментів.
Коли kubelet не запускається, розслідування є локальним і механічним. Перевірте, чи увімкнено й чи працює сервіс, чи посилається його конфігураційний файл на дійсну кінцеву точку середовища виконання контейнерів і чи може саме середовище виконання запускати контейнери. Повідомлення в логах kubelet зазвичай називають відсутній сокет, недійсний прапорець, невідповідність cgroup чи проблему з сертифікатом. Не починайте з видалення об’єктів кластера; агент вузла має бути справним, перш ніж площина управління зможе отримувати корисний статус.
# Check container runtimecrictl ps
# Check static pod containerscrictl logs <container-id>
# Look for API server errorssudo cat /var/log/pods/kube-system_kube-apiserver-*/kube-apiserver/*.logКоли площина управління не запускається, локальне середовище виконання контейнерів стає вашим вікном у збій. crictl ps каже вам, чи існують контейнери статичних Подів, чи перезапускаються вони і який ідентифікатор контейнера перевіряти. Логи контейнерів можуть розкрити недійсний прапорець API-сервера, нечитабельний сертифікат, збій підключення до etcd чи синтаксичну помилку YAML у маніфесті. Якщо API-сервер недоступний, виправлення часто відбувається в /etc/kubernetes/manifests, а не через kubectl.
# On the node, check logsjournalctl -u kubelet | tail -50
# Common issues:# - Token expired# - Wrong CA hash# - Network connectivity to control plane# - Firewall blocking port 6443Збої приєднання вузла вимагають від вас вирішити, чи робочий вузол не може досягти API-сервера, не може йому довіряти, чи не може завершити локальне початкове налаштування. Таймаут вказує на маршрутизацію, фаєрвол, кінцеву точку чи доступність API-сервера. Помилка хешу CA чи x509 вказує на матеріал довіри. Помилка kubelet чи середовища виконання вказує назад на підготовку вузла. Ці категорії корисніші за завчання одного виправлення для «вузол не приєднується», бо той самий симптом на рівні дашборда може походити з кількох різних рівнів.
# Check expirationkubeadm certs check-expiration
# Renew all certificateskubeadm certs renew all
# Restart control plane components# (just move manifests and wait)Збої сертифікатів особливо легко прочитати неправильно, бо вони часто проявляються як загальні помилки підключення. Команда поновлення записує нові файли сертифікатів, але її запуск — це не те саме, що доказ того, що площина управління їх перезавантажила. Перевіряйте строк дії до й після, перезапускайте або перезавантажуйте відповідні статичні Поди й перевіряйте клієнтські kubeconfig, де потрібно. Якщо задіяні сертифікати etcd, будьте уважні, щоб відрізнити серверні (serving) сертифікати API-сервера від однорангових (peer) і клієнтських сертифікатів etcd, бо їх споживають різні процеси.
Релевантний для іспиту набір команд достатньо короткий, щоб тренувати його до плавності, але плавність має включати контекст. kubeadm token create --print-join-command призначений для довіри початкового налаштування, а не для виправлення зламаного CNI. kubectl drain призначений для переміщення робочих навантажень перед обслуговуванням, а не для видалення локального стану kubeadm вузла. kubeadm reset призначений для демонтажу чи перебудови, а не для кожного попередження kubelet. Використовуйте команду, яка відповідає зламаному контракту.
# Initialize clusterkubeadm init --pod-network-cidr=10.244.0.0/16
# Get join commandkubeadm token create --print-join-command
# Join workerkubeadm join <control-plane>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
# Check certificateskubeadm certs check-expiration
# Drain node for maintenancekubectl drain <node> --ignore-daemonsets
# Make node schedulable againkubectl uncordon <node>
# Reset nodekubeadm resetПрактичний приклад: адміністратор редагує /etc/kubernetes/manifests/kube-apiserver.yaml, щоб додати прапорець допуску (admission flag), але лишає помилку відступу YAML. Тепер kubectl get nodes повертає connection refused, що очікувано, бо контейнер API-сервера не може запуститися. Шлях відновлення — підключитися по SSH до вузла площини управління, переглянути journalctl -u kubelet, переглянути логи збійного контейнера API-сервера через crictl, виправити маніфест локальним редактором і дочекатися, поки kubelet відтворить статичний Под. Урок конкретний: коли API-сервер є зламаним компонентом, локальні інструменти вузла замінюють інструменти API, доки статичний Под знову не стане справним.
Інший корисний сценарій — робочий вузол, що повідомляє NotReady після перезавантаження, навіть коли площина управління справна. Почніть з kubectl describe node, якщо API досяжний, потім перейдіть до робочого вузла й перевірте kubelet, середовище виконання контейнерів, конфігурацію CNI та свіжі логи. Якщо kubelet не може автентифікуватися, порівняйте /etc/kubernetes/kubelet.conf і сертифікати; якщо Поди не можуть створити пісочниці (sandboxes), перевірте файли CNI й помилки середовища виконання. Об’єкт вузла дає вам симптом, але локальні докази робочого вузла зазвичай дають причину.
Патерни й антипатерни
Розділ «Патерни й антипатерни»Наведені нижче патерни — не загальні «найкращі практики»; це звички прийняття рішень, які утримують операції kubeadm оборотними й придатними для діагностики. kubeadm-кластер достатньо прозорий, щоб ви могли перевірити майже кожен важливий артефакт, але ця прозорість допомагає лише тоді, коли ви робите одну зміну за раз і зберігаєте докази перед руйнівними діями. У невеликих лабораторіях нехтування цією дисципліною коштує хвилин. У спільному кластері воно може перетворити звичайне завдання обслуговування на вправу з відновлення.
| Патерн | Коли його застосовувати | Чому він працює | Міркування щодо масштабування |
|---|---|---|---|
| Початкове налаштування з явними вхідними даними | Використовуйте під час ініціалізації чи перебудови площини управління | Pod CIDR, адреса оголошення й закріплення версії роблять пізніші симптоми легшими для пояснення | Зберігайте обрані значення в runbook чи конфігураційному файлі kubeadm для відтворюваності |
| Діагностика з рівня, що вцілів | Використовуйте, коли kubectl зависає чи API-сервер недоступний | kubelet, systemd, crictl і файли маніфестів лишаються доступними локально | Навчіть операторів підключатися по SSH до правильного вузла й збирати локальні логи перед скиданням |
| Захист стану перед руйнуванням | Використовуйте перед оновленнями, ротацією сертифікатів чи редагуванням статичних Подів | Знімки etcd і скопійовані маніфести надають докази для відкату | Автоматизуйте перевірку резервних копій і тримайте процедури відновлення окремими для одновузлового й HA etcd |
| Drain перед обслуговуванням хоста | Використовуйте перед перезавантаженням, оновленням пакетів чи видаленням вузла | Робочі навантаження переміщуються шляхом виселення Kubernetes замість раптової загибелі | Ємність і PodDisruptionBudget визначають, чи може drain завершитися швидко |
Відповідні антипатерни спокусливі, бо здаються швидшими в моменті. Повторний запуск kubeadm init здається рішучим, примусовий drain ніби розчищає затор, а видалення статичного Пода через kubectl виглядає природним, бо Под видимий через API. Кожне з цих скорочень ігнорує право власності. kubeadm володіє артефактами початкового налаштування, kubelet володіє виконанням статичних Подів, scheduler володіє новим розміщенням, контролери володіють заміною Подів, а etcd володіє станом кластера.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
Повторний запуск kubeadm init на напівробочій площині управління | Ви ризикуєте перезаписати докази й створити конфліктний локальний стан | Читайте логи kubelet, логи статичних Подів і вивід kubeadm, щоб визначити збійну фазу |
Сприйняття kubectl delete pod як видалення статичного Пода | kubelet відтворює дзеркальний Под, бо маніфест усе ще існує | Перемістіть, відредагуйте чи відновіть маніфест у /etc/kubernetes/manifests/ |
| Збереження довготривалих токенів приєднання заради зручності | Старі токени ускладнюють міркування про стан допуску вузлів | Генеруйте короткотривалі токени й видаляйте невикористані після вікна приєднання |
Використання kubeadm reset як першого кроку усунення несправностей | Ви видаляєте локальний стан до розуміння збою | Скидайте лише для демонтажу, перебудови чи задокументованої процедури повторного приєднання |
Суть масштабування в тому, що kubeadm не усуває потреби в операційному дизайні. Одновузлова лабораторія може терпіти ручні команди й короткі простої, тоді як подібний до продакшну кластер потребує зовнішніх кінцевих точок API, перевірених резервних копій, запланованих хвиль оновлень і достатнього запасу ємності для drain. Назви команд лишаються тими самими, але ризик навколо кожної команди змінюється з розміром кластера, критичністю робочого навантаження й вимогами до відновлення.
Каркас прийняття рішень
Розділ «Каркас прийняття рішень»Використовуйте наведений нижче каркас, коли ви стикаєтеся із симптомом kubeadm-кластера й маєте обрати наступну дію. Мета — уникнути стрибка прямо до найдраматичнішої команди. Почніть із визначення того, який рівень усе ще заслуговує на довіру, а потім оберіть найменш руйнівну дію, що може довести чи відновити підозрюваний контракт. Це той самий ментальний хід, який ви тренували в попередніх модулях з архітектури: знайдіть право власності, перш ніж застосовувати виправлення.
Symptom observed | vCan kubectl reach the API server? | +-- yes --> Is this a scheduling or workload-placement issue? | | | +-- yes --> inspect nodes, cordon/drain/uncordon, events | | | +-- no --> inspect kube-system pods, CNI, certificates, joins | +-- no --> Can you SSH to the affected control-plane node? | +-- yes --> inspect kubelet, crictl, static pod manifests, local logs | +-- no --> fix host/network access before Kubernetes diagnosis| Ситуація | Перша перевірка | Імовірне сімейство команд | Уникайте, доки не дізнаєтеся більше |
|---|---|---|---|
Свіжий кластер має вузол NotReady і CoreDNS у стані pending | Поди CNI й pod CIDR | kubectl get pods -n kube-system, команда встановлення CNI | kubeadm reset |
| Приєднання робочого вузла відразу зазнає невдачі | Токен, хеш CA, досяжність API, логи kubelet | kubeadm token create --print-join-command, journalctl -u kubelet | Повторна ініціалізація площини управління |
| API-сервер недоступний після редагування маніфесту | Логи kubelet і статичних Подів | journalctl, crictl logs, редагування маніфесту | kubectl delete pod |
| Заплановане перезавантаження вузла | Контролери робочих навантажень і політика порушень | kubectl cordon, kubectl drain, kubectl uncordon | Перезавантаження живленням без drain |
| Сертифікати близькі до завершення строку дії | Вивід kubeadm certs check-expiration | kubeadm certs renew, перезапуск статичного Пода | Припущення, що поновлення автоматично перезавантажує кожен процес |
| Руйнівне обслуговування площини управління | Свіжий знімок etcd і план відновлення | etcdctl snapshot save, kubeadm upgrade plan | Оновлення без захисту стану |
Два правила утримують цей каркас практичним. По-перше, не використовуйте команду рівня кластера для виправлення локальної передумови вузла, доки локальні докази вузла не скажуть, що Kubernetes готовий до цієї команди. По-друге, не використовуйте руйнівну локальну команду для виправлення умови планування рівня кластера, доки ви не перевірили вигляд з боку API. Це розділення — те, що запобігає перетворенню простого недогляду з cordon на скидання, і воно ж не дає мертвому API-серверу марнувати ваш час повторними викликами kubectl.
Чи знали ви?
Розділ «Чи знали ви?»- Токени початкового налаштування, створені kubeadm, за замовчуванням завершують строк дії через 24 години, і саме тому
kubeadm token create --print-join-commandє звичайною операційною командою, а не рідкісним трюком відновлення. - Компоненти площини управління kubeadm працюють як статичні Поди, тож kubelet спостерігає за
/etc/kubernetes/manifests/і може перезапустити контейнер API-сервера навіть тоді, коли API-сервер не може відповістиkubectl. - Типовий захищений порт API-сервера Kubernetes — 6443, і робочий вузол, який не може досягти цієї кінцевої точки, не може завершити
kubeadm join, скільки б разів ви не перегенеровували токен. - Сертифікати, керовані kubeadm, можна перевірити за допомогою
kubeadm certs check-expiration, але поновлені файли сертифікатів усе одно мають бути завантажені відповідними компонентами площини управління, перш ніж клієнти побачать зміну.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому вона трапляється | Як її виправити |
|---|---|---|
| Запуск init з увімкненим swap | Попередні перевірки kubeadm відхиляють хост, що порушує вимоги kubelet | Вимкніть swap за допомогою swapoff -a, видаліть постійні записи swap з /etc/fstab і повторно запустіть попередні перевірки |
| Забування CNI після init | API-сервер працює, тож кластер виглядає «встановленим», хоча мережа Подів відсутня | Встановіть рівно один призначений CNI-плагін і перевірте Поди CNI плюс CoreDNS у kube-system |
| Токен із вичерпаним строком дії | Початкову команду приєднання скопіювали зі старого виводу init чи застарілих нотаток | Запустіть kubeadm token create --print-join-command і використайте свіжу команду під час вікна приєднання |
| Використання kubectl delete на статичних Подах | Дзеркальні Поди з’являються в API, тож вони виглядають як звичайні Поди, керовані через API | Редагуйте, переміщуйте чи відновлюйте файли в /etc/kubernetes/manifests/, бо kubelet володіє життєвим циклом статичних Подів |
| Відсутність drain перед обслуговуванням | Cordon і drain сприймають як взаємозамінні команди для вузла | Cordon — щоб зупинити нове розміщення, drain — щоб виселити рухомі робочі навантаження, потім uncordon після обслуговування |
| Поновлення сертифікатів без перезапуску компонентів | Команда записує файли, але запущені процеси можуть усе ще тримати старі дані сертифікатів | Перезапустіть чи перезавантажте уражені статичні Поди й перевірте строк дії знову після перезавантаження |
| Скидання перед збором локальних доказів | Скидання здається чистим виправленням, коли поведінка kubelet чи приєднання заплутує | Зафіксуйте логи kubelet, вивід crictl, маніфести й помилки kubeadm перед використанням kubeadm reset |
Тест
Розділ «Тест»Питання 1: Ваша команда ініціалізує площину управління за допомогою `kubeadm init`, копіює `admin.conf` і бачить вузол, але CoreDNS лишається в стані pending. Що ви перевіряєте перед повторним запуском kubeadm?
Перевірте, чи був встановлений CNI-плагін і чи відповідає його конфігурація pod CIDR, який використовувався під час kubeadm init. API-сервер може бути досяжним до того, як мережа Подів стане готовою, тож CoreDNS у стані pending часто є симптомом початкового налаштування мережі, а не невдалого встановлення площини управління. Перевірте kubectl get pods -n kube-system -o wide, пошукайте Поди DaemonSet CNI й прочитайте їхні логи, якщо вони існують. Повторний запуск kubeadm був би неправильним першим кроком, бо він ігнорує відсутній чи несправний мережевий рівень.
Питання 2: Вчорашня команда приєднання робочого вузла зазнає невдачі, а помилка згадує перевірку токена початкового налаштування. Що вам слід зробити і чому хеш CA все ще є частиною команди?
Згенеруйте свіжу команду приєднання на площині управління за допомогою kubeadm token create --print-join-command, а потім запустіть цю команду на підготовленому робочому вузлі. Токен — це короткотривалий матеріал автентифікації, тож стара команда може завершити строк дії, навіть коли кластер справний. Хеш CA лишається необхідним, бо робочий вузол має переконатися, що кінцева точка API-сервера належить призначеному кластеру, перш ніж довіряти їй. Якщо новий токен усе одно зазнає невдачі, відокремте помилки токена від помилок мережевої досяжності й підготовки kubelet.
Питання 3: Ви видаляєте `kube-apiserver-controlplane` за допомогою `kubectl`, і він повертається майже миттєво. Що це каже вам про право власності?
Це каже вам, що видимий Под — це дзеркало статичного Пода, а не звичайний Под, яким володіє Деплоймент чи ReplicaSet. kubelet спостерігає за /etc/kubernetes/manifests/kube-apiserver.yaml, тож коли ви видаляєте дзеркальний Под через API, kubelet відтворює об’єкт дзеркального Пода — але базовий контейнер ніколи не перезапускається, бо kubelet не отримав інструкції видалити маніфест. Процес статичного Пода продовжує працювати протягом операції kubectl delete. Щоб навмисно зупинити чи змінити цей статичний Под, ви маєте відредагувати чи перемістити маніфест на вузлі площини управління. Саме тому локальний доступ до вузла має значення, коли API-сервер є компонентом, який ви усуваєте.
Питання 4: Під час запланованого обслуговування ядра молодший адміністратор пропонує `kubectl cordon` і негайне перезавантаження. Який безпечніший робочий процес ви впроваджуєте?
Спершу виконайте cordon вузла, щоб запобігти потраплянню туди нових Подів, потім осушіть його з відповідними прапорцями, щоб керовані Поди були виселені перед перезавантаженням. Після обслуговування перевірте справність kubelet, підтвердіть, що вузол повертається в стан Ready, і зніміть з нього cordon, щоб планування могло відновитися. Сам по собі cordon не переміщує наявні Поди, тож негайне перезавантаження може перервати робочі навантаження, які можна було б граціозно перепланувати. Точні прапорці drain залежать від DaemonSet, локальних даних emptyDir і некерованих Подів.
Питання 5: Ви поновлюєте сертифікати kubeadm, бо сертифікат API-сервера близький до завершення строку дії, але клієнти все ще повідомляють стару дату. Що ви, найімовірніше, пропустили?
Ви, найімовірніше, записали нові файли сертифікатів, але не перезапустили чи не перезавантажили компонент, який їх завантажує. Поновлення kubeadm змінює файли в /etc/kubernetes/pki, тоді як процеси статичних Подів мають перезавантажити ці файли, перш ніж клієнти побачать новий сертифікат. Перевірте строк дії за допомогою kubeadm certs check-expiration, перезапустіть чи перезавантажте відповідний статичний Под і перевірте через openssl-перевірку серверного (serving) сертифіката. Якщо адміністративні клієнтські облікові дані були поновлені, також оновіть kubeconfig, який використовує адміністративна оболонка.
Питання 6: Після редагування `kube-apiserver.yaml` кожна команда `kubectl` зависає. Які інструменти ви використаєте далі?
Переключіться на локальні інструменти вузла, бо API-сервер може бути зламаним компонентом. Підключіться по SSH до вузла площини управління, перевірте journalctl -u kubelet, перелічіть контейнери за допомогою crictl ps і перевірте логи контейнера API-сервера за допомогою crictl logs чи файлів у /var/log/pods. Потім виправте маніфест безпосередньо в /etc/kubernetes/manifests/ і дозвольте kubelet перезапустити статичний Под. Повторні спроби kubectl не допомагають, коли API-сервер не може запуститися.
Питання 7: Перед оновленням площини управління kubeadm який захист стану ви хочете мати на місці і як він змінює ваш ризик?
Ви хочете свіжий знімок etcd, який було перевірено, плюс скопійовані маніфести статичних Подів і чіткий план відновлення, що відповідає топології кластера. Знімок захищає стан кластера, а копії маніфестів допомагають скасувати випадкові зміни прапорців чи шляхів. Це не робить оновлення безризиковим, але змінює обробку збоїв з імпровізації на відпрацьований шлях відновлення. Ви все одно маєте запустити kubeadm upgrade plan, дотримуватися розбіжності версій і оновлювати по одному вузлу за раз.
Практична вправа
Розділ «Практична вправа»Ця вправа розрахована на лабораторний kubeadm-кластер щонайменше з одним робочим вузлом. Якщо ви використовуєте kind чи minikube, деякі шляхи статичних Подів і поведінка обслуговування вузлів можуть відрізнятися, бо «вузли» є контейнерами чи локальними абстракціями ВМ, а не звичайними хостами Linux. Навчальна мета однакова: пов’яжіть кожну команду з рівнем, який вона змінює, а потім перевірте результат перед переходом до наступного кроку.
Сценарій вправи: ви готуєте kubeadm-кластер до рутинного обслуговування й маєте довести, що можете перевірити артефакти початкового налаштування, згенерувати команду приєднання, захистити стан, осушити вузол і відновити планування після цього. Не запускайте руйнівні команди скидання проти кластера, який вам важливий, якщо лабораторія явно не надає вам одноразові вузли. Коли завдання каже «на площині управління», запускайте його з оболонки на хості площини управління, а не з випадкової робочої станції.
Завдання 1: Перегляд і класифікація вузлів
Розділ «Завдання 1: Перегляд і класифікація вузлів»Запустіть команди перевірки вузлів, потім запишіть, який вузол є площиною управління, який вузол є робочим і чи якийсь вузол уже має cordon. Вивід має дозволити вам відрізнити справність від стану планування перед виконанням обслуговування.
kubectl get nodes -o widekubectl describe node <node-name> | head -50Нотатки до розв'язання
Перша команда дає компактний вигляд ролей, версій, внутрішніх IP і готовності. Друга команда дає умови, адреси, ємність, доступні (allocatable) ресурси, taint-и й свіжі події вузла. Вузол, що показує SchedulingDisabled, має cordon, тоді як вузол, що показує NotReady, має проблему справності чи зв’язку, яку слід діагностувати перед обслуговуванням.
Завдання 2: Перевірка файлів статичних Подів площини управління
Розділ «Завдання 2: Перевірка файлів статичних Подів площини управління»На вузлі площини управління перевірте каталог маніфестів і прочитайте початок маніфесту API-сервера. Поки що нічого не редагуйте; суть у тому, щоб знайти джерельні файли, за якими спостерігає kubelet.
# If you have SSH access to control planels /etc/kubernetes/manifests/cat /etc/kubernetes/manifests/kube-apiserver.yaml | head -30Нотатки до розв'язання
Ви маєте побачити маніфести, як-от kube-apiserver.yaml, kube-controller-manager.yaml, kube-scheduler.yaml і часто etcd.yaml на вузлі площини управління зі stacked-топологією. Якщо ці файли присутні, kubelet є локальним наглядачем для цих компонентів. Якщо kubectl пізніше зазнає невдачі, бо API-сервер лежить, цей каталог лишається одним із ваших основних місць відновлення.
Завдання 3: Практика cordon і uncordon
Розділ «Завдання 3: Практика cordon і uncordon»Виконайте cordon робочого вузла, переконайтеся, що планування вимкнено, створіть тестовий Под і перевірте, де він опиниться. Потім зніміть cordon з робочого вузла й переконайтеся, що стан планування повертається до норми.
# Cordon a worker nodekubectl cordon <worker-node>kubectl get nodes# Should show SchedulingDisabled
# Try to schedule a podkubectl run test-pod --image=nginx
# Check where it landedkubectl get pods -o wide# Won't be on cordoned node
# Uncordonkubectl uncordon <worker-node>kubectl get nodesНотатки до розв'язання
Вузол із cordon має показувати SchedulingDisabled, а тестовий Под має опинитися на іншому придатному для планування вузлі, якщо є ємність. Якщо у вас лише один робочий вузол, Под може лишитися в стані pending, доки з вузла не знято cordon. Цей результат усе одно корисний, бо він доводить, що cordon змінює розміщення scheduler-ом, нічого не доводячи про справність kubelet.
Завдання 4: Практика drain з одноразовим деплойментом
Розділ «Завдання 4: Практика drain з одноразовим деплойментом»Створіть невеликий деплоймент, поспостерігайте за розміщенням Подів, осушіть вузол, що хостить одну з реплік, і переконайтеся, що Поди-заміни переміщуються в інше місце. Використовуйте лабораторний кластер із достатньою ємністю й не форсуйте продакшн-навантаження, якщо ваш runbook це явно не дозволяє.
# Create a deployment firstkubectl create deployment drain-test --image=nginx --replicas=2
# Check pod locationskubectl get pods -o wide
# Drain a node with podskubectl drain <node-with-pods> --ignore-daemonsets
# Check pods movedkubectl get pods -o wide
# Uncordon the nodekubectl uncordon <node-name>Нотатки до розв'язання
Контролер деплойменту має створити Поди-заміни на придатних для планування вузлах після того, як drain виселить оригінали. Якщо drain блокується, прочитайте повідомлення замість того, щоб наосліп додавати прапорці; воно може попереджати вас про некеровані Поди чи локальні дані. Після тесту зніміть cordon з вузла, щоб він знову міг отримувати робочі навантаження.
Завдання 5: Перевірка сертифікатів і генерація команди приєднання
Розділ «Завдання 5: Перевірка сертифікатів і генерація команди приєднання»На вузлі площини управління перевірте строк дії сертифікатів і згенеруйте свіжу команду приєднання. Не запускайте команду приєднання, якщо у вас немає підготовленого робочого вузла, який має приєднатися до кластера.
# If you have access to control planekubeadm certs check-expiration# On control planekubeadm token create --print-join-commandНотатки до розв'язання
Команда сертифікатів має показати дати завершення строку дії для керованих kubeadm сертифікатів, що допомагає спланувати поновлення до простою. Команда токена має вивести повну команду kubeadm join, що містить токен і хеш CA. Ставтеся до цього виводу як до тимчасового матеріалу початкового налаштування й уникайте зберігання його в довготривалих спільних нотатках.
Завдання 6: Прибирання лабораторних ресурсів
Розділ «Завдання 6: Прибирання лабораторних ресурсів»Видаліть одноразовий деплоймент і Под, створені під час вправи. Потім повторно перевірте вузли, щоб підтвердити, що жоден лабораторний вузол не лишився з cordon помилково.
kubectl delete deployment drain-testkubectl delete pod test-podНотатки до розв'язання
Прибирання має видалити об’єкти робочих навантажень, які ви створили, і лишити вузли в очікуваному стані планування. Запустіть kubectl get nodes після цього й пошукайте випадковий статус SchedulingDisabled. Якщо ви практикували drain, також підтвердіть, що з осушеного вузла знято cordon, перш ніж завершувати лабораторну роботу.
Тренувальні вправи
Розділ «Тренувальні вправи»Використовуйте ці хронометровані вправи після керованих завдань. Вони зберігають оригінальну практику команд із цього модуля, але сприймайте цільові показники як приблизний лабораторний темп, а не як привід поспіхом проскочити вивід, якого ви не розумієте.
Вправа 1: Команди управління вузлами (Ціль: 3 хвилини)
Розділ «Вправа 1: Команди управління вузлами (Ціль: 3 хвилини)»# List nodes with detailskubectl get nodes -o wide
# Get node labelskubectl get nodes --show-labels
# Describe a nodekubectl describe node <node-name> | head -50
# Check node conditionskubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}'
# Check node resourceskubectl describe node <node-name> | grep -A10 "Allocated resources"Вправа 2: Cordon і Uncordon (Ціль: 5 хвилин)
Розділ «Вправа 2: Cordon і Uncordon (Ціль: 5 хвилин)»# Cordon a node (prevent new pods)kubectl cordon <worker-node>
# Verifykubectl get nodes # Shows SchedulingDisabled
# Try to schedule a podkubectl run cordon-test --image=nginxkubectl get pods -o wide # Won't be on cordoned node
# Uncordonkubectl uncordon <worker-node>kubectl get nodes # Back to Ready
# Cleanupkubectl delete pod cordon-testВправа 3: Drain і відновлення (Ціль: 5 хвилин)
Розділ «Вправа 3: Drain і відновлення (Ціль: 5 хвилин)»# Create test deploymentkubectl create deployment drain-test --image=nginx --replicas=3
# Wait for podskubectl wait --for=condition=available deployment/drain-test --timeout=60skubectl get pods -o wide
# Drain a worker nodekubectl drain <worker-node> --ignore-daemonsets --delete-emptydir-data
# Watch pods move to other nodeskubectl get pods -o wide
# Uncordon the nodekubectl uncordon <worker-node>
# Cleanupkubectl delete deployment drain-testВправа 4: Управління токенами kubeadm (Ціль: 3 хвилини)
Розділ «Вправа 4: Управління токенами kubeadm (Ціль: 3 хвилини)»# List existing tokenskubeadm token list
# Create a new tokenkubeadm token create
# Create token with specific TTLkubeadm token create --ttl 2h
# Generate full join commandkubeadm token create --print-join-command
# Delete a tokenkubeadm token delete <token-id>Вправа 5: Дослідження статичних Подів (Ціль: 5 хвилин)
Розділ «Вправа 5: Дослідження статичних Подів (Ціль: 5 хвилин)»# Find static pod manifest directorycat /var/lib/kubelet/config.yaml | grep staticPodPath# List static pod manifestsls -la /etc/kubernetes/manifests/
# View one manifestcat /etc/kubernetes/manifests/kube-apiserver.yaml | head -30
# Create your own static podcat << 'EOF' | sudo tee /etc/kubernetes/manifests/my-static-pod.yamlapiVersion: v1kind: Podmetadata: name: my-static-pod namespace: defaultspec: containers: - name: nginx image: nginx ports: - containerPort: 80EOF
# Wait and verify (will have node name suffix)sleep 10kubectl get pods | grep my-static-pod
# Remove static podsudo rm /etc/kubernetes/manifests/my-static-pod.yamlВправа 6: Перевірка сертифікатів (Ціль: 5 хвилин)
Розділ «Вправа 6: Перевірка сертифікатів (Ціль: 5 хвилин)»# Check certificate expiration (on control plane)kubeadm certs check-expiration
# View certificate detailsopenssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | head -30
# Check all certificatesls -la /etc/kubernetes/pki/
# Check CA certificateopenssl x509 -in /etc/kubernetes/pki/ca.crt -text -noout | grep -E "Subject:|Issuer:|Not"Вправа 7: Усунення несправностей — вузол NotReady (Ціль: 5 хвилин)
Розділ «Вправа 7: Усунення несправностей — вузол NotReady (Ціль: 5 хвилин)»# Simulate: Stop kubelet on a worker# (Run on worker node)sudo systemctl stop kubelet
# On control plane, diagnosekubectl get nodes # Shows NotReadykubectl describe node <worker> | grep -A10 Conditions
# Check what's happeningkubectl get events --field-selector involvedObject.kind=Node
# Fix: Restart kubelet (on worker)sudo systemctl start kubelet
# Verify recoverykubectl get nodes -wВправа 8: Виклик — робочий процес обслуговування вузла
Розділ «Вправа 8: Виклик — робочий процес обслуговування вузла»Виконайте повний робочий процес обслуговування:
- Виконайте cordon вузла
- Осушіть усі робочі навантаження
- Зімітуйте обслуговування, зачекавши 30 секунд
- Зніміть cordon з вузла
- Переконайтеся, що Поди знову можна планувати
# YOUR TASK: Complete this without looking at solutionNODE_NAME=<your-worker-node>kubectl create deployment maint-test --image=nginx --replicas=2
# Start timer - Target: 3 minutes totalРозв'язання
NODE_NAME=worker-01 # Replace with your node
# 1. Cordonkubectl cordon $NODE_NAME
# 2. Drainkubectl drain $NODE_NAME --ignore-daemonsets --delete-emptydir-data
# 3. Verify pods movedkubectl get pods -o wide
# 4. Simulate maintenanceecho "Performing maintenance..."sleep 30
# 5. Uncordonkubectl uncordon $NODE_NAME
# 6. Verify scheduling workskubectl scale deployment maint-test --replicas=4kubectl get pods -o wide # Some should land on $NODE_NAME
# Cleanupkubectl delete deployment maint-testКритерії успіху
Розділ «Критерії успіху»- Спроєктувати послідовність початкового налаштування kubeadm, що включає попередні перевірки,
kubeadm init, налаштування kubeconfig, встановлення CNI та токени приєднання робочих вузлів. - Діагностувати збої статичних Подів і kubelet за допомогою
/etc/kubernetes/manifests/,journalctl,crictlі локальних логів площини управління. - Оцінити ризики обслуговування сертифікатів і etcd, перевіряючи строк дії, пояснюючи, коли і як зберегти знімок etcd, та плануючи перезапуски компонентів.
- Впровадити безпечне обслуговування вузлів за допомогою
kubectl cordon,kubectl drain,kubectl uncordonі чіткого кроку прибирання. - Пояснити, коли
kubeadm resetдоречний і чому він не повинен бути першою реакцією на кожну проблему kubeadm.
Джерела
Розділ «Джерела»- Creating a cluster with kubeadm
- kubeadm reference
- kubeadm init reference
- kubeadm join reference
- kubeadm reset reference
- kubeadm token reference
- Certificate management with kubeadm
- Upgrading kubeadm clusters
- Safely drain a node
- Static Pods
- Operating etcd clusters for Kubernetes
- etcd disaster recovery
- Calico Kubernetes requirements
- Calico quickstart guide
- flannel project documentation
- Cilium quick installation
Наступний модуль
Розділ «Наступний модуль»Перейдіть до Частини 2: Робочі навантаження та планування, щоб дізнатися, як Kubernetes розміщує й запускає прикладні робочі навантаження після того, як фундамент кластера вже існує.
Покажчик модулів Частини 1
Розділ «Покажчик модулів Частини 1»Швидкі посилання для повторення:
| Модуль | Тема | Ключові навички |
|---|---|---|
| 1.1 | Глибоке занурення в площину управління | Ролі компонентів, усунення несправностей, статичні Поди |
| 1.2 | Інтерфейси розширення | CNI/CSI/CRI, crictl, усунення несправностей плагінів |
| 1.3 | Helm | Встановлення, оновлення, відкат, values |
| 1.4 | Kustomize | Base/overlay, патчі, kubectl -k |
| 1.5 | CRD та оператори | Створення CRD, управління кастомними ресурсами |
| 1.6 | RBAC | Ролі, прив’язки, ServiceAccount, can-i |
| 1.7 | Основи kubeadm | Init, join, cordon, drain, токени |