00. Диагностика Linux и локальный кластер
Незнакомый термин? Откройте словарь Kubernetes и терминов курса.
Назначение, предварительные знания и результаты обучения
Эта глава превращает рабочую станцию в воспроизводимую лабораторию и защищает
от работы в неправильном контексте. Нужны командная оболочка Linux, curl,
sha256sum, sudo для установки исполняемых файлов и работающий Docker Engine
или совместимый Podman.
После главы вы сможете:
- подтвердить версии ОС, cgroup, CPU/RAM и среды исполнения контейнеров;
- установить
kubectl v1.36.2иkind v0.32.0с проверкой контрольной суммы; - создать трёхузловой
kind-kube-course, не затрагивая другой контекст; - собрать и загрузить
kube-python-course:1.0.0; - разделить клиентскую, серверную и фактическую проверку среды исполнения;
- собрать диагностические данные и удалить только учебный кластер.
Ментальная модель: четыре слоя
kubectl — клиент API, а не кластер. kind — инструмент управления жизненным
циклом, который создаёт узлы Kubernetes как контейнеры. Docker/Podman —
хостовый провайдер контейнеров. Kubernetes внутри узла использует containerd
как реализацию Container Runtime Interface (CRI). Поэтому docker ps видит
узлы kind, а Pods нужно
искать через Kubernetes API.
kubectl → kube-apiserver → объекты/контроллеры Kubernetes
↓
CLI kind → Docker/Podman → контейнеры узлов → kubelet/containerd → контейнеры Pod
Области отказа различны: неработающий Docker не равен неготовому Pod; неверный kubeconfig не равен падению сервера API; принятый YAML не означает, что образ запускается.
Предварительная проверка
uname -a
cat /etc/os-release
nproc
free -h
df -h .
stat -fc %T /sys/fs/cgroup
docker version # или: podman version
Ожидается Linux x86_64/aarch64, cgroup v2 (cgroup2fs), не меньше 4 CPU,
8 GiB RAM и 20 GiB диска. Код завершения всех обязательных проверок — 0.
Для Docker секция Server: должна отвечать; одна секция Client: не
доказывает работу фонового процесса.
Машина, на которой создан курс: Ubuntu 24.04.3 LTS, ядро
6.8.0-88-generic, x86_64; инструменты для cgroup и среды исполнения
контейнеров были недоступны. Ваши доказательства важнее этой справки.
Установка инструментов с проверкой
Не используйте URL с latest: версия должна быть видна в истории команд.
mkdir -p "$PWD/.tools"
curl -fL --retry 3 -o .tools/kubectl \
https://dl.k8s.io/release/v1.36.2/bin/linux/amd64/kubectl
curl -fL --retry 3 -o .tools/kubectl.sha256 \
https://dl.k8s.io/release/v1.36.2/bin/linux/amd64/kubectl.sha256
printf '%s %s\n' "$(cat .tools/kubectl.sha256)" ".tools/kubectl" |
sha256sum --check
chmod 0755 .tools/kubectl
curl -fL --retry 3 -o .tools/kind \
https://kind.sigs.k8s.io/dl/v0.32.0/kind-linux-amd64
curl -fL --retry 3 -o .tools/kind.sha256sum \
https://kind.sigs.k8s.io/dl/v0.32.0/kind-linux-amd64.sha256sum
(cd .tools && sha256sum --check kind.sha256sum)
chmod 0755 .tools/kind
export PATH="$PWD/.tools:$PATH"
kubectl version --client --output=yaml
kind version
Для aarch64 замените amd64 на arm64. Ожидается clientVersion.gitVersion: v1.36.2, [kind](98-glossary.md#kind) v0.32.0, код завершения 0. Несовпадение контрольной суммы —
причина немедленно остановиться: удалите загрузку и исследуйте URL или прокси;
не делайте исполняемый файл запускаемым.
Провайдер контейнеров устанавливайте по официальной документации вашей
дистрибуции. Здесь не преподаётся Docker. Убедитесь, что docker run --rm hello-world завершился 0. Podman без root требует дополнительных настроек,
описанных в документации kind; зафиксируйте KIND_EXPERIMENTAL_PROVIDER=podman.
Манифест кластера
Полный манифест локального кластера:
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
name: kube-course
nodes:
- role: control-plane
- role: worker
- role: worker
Он сохранён в cluster/kind-config.yaml. Это API
kind, а не объект Kubernetes API: у него нет metadata/spec, и kubectl его
не принимает. Для первой серверной проверки используем настоящий объект:
apiVersion: v1
kind: Namespace
metadata:
name: kube-course
labels:
app.kubernetes.io/part-of: kube-python-course
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.36
spec: {}
Namespace.spec обычно пуст, но поле показано явно: apiVersion, kind,
metadata, spec образуют полный объект API.
Практическое упражнение: создание → проверка → загрузка образа
Подготовка
Сохраните исходный контекст, но не выводите kubeconfig: там находятся учётные данные.
ORIGINAL_CONTEXT="$(kubectl config current-context 2>/dev/null || true)"
printf 'Original context: %s\n' "$ORIGINAL_CONTEXT"
kind create cluster \
--name kube-course \
--config cluster/kind-config.yaml \
--image kindest/node:v1.36.1@sha256:3489c7674813ba5d8b1a9977baea8a6e553784dab7b84759d1014dbd78f7ebd5 \
--wait 5m
Ожидаемая последняя строка содержит
Set kubectl context to "kind-kube-course". Код завершения — 0. Проверка:
test "$(kubectl config current-context)" = "kind-kube-course"
kubectl version
kubectl cluster-info
kubectl get nodes -o wide
kubectl wait --for=condition=Ready nodes --all --timeout=180s
kubectl get pods -A
kubectl get storageclass
Должны быть kube-course-control-plane и два рабочих узла в Ready; системные
Pods становятся Running. Клиент v1.36.2 и сервер v1.36.1 совместимы. Сохраните
реальный StorageClass: локальный provisioner — дополнение конкретного
дистрибутива, а не гарантия базовой поставки Kubernetes.
Собрать образ приложения
Минимальная операция с контейнером:
docker build --file app/Containerfile --tag kube-python-course:1.0.0 app
docker image inspect kube-python-course:1.0.0 \
--format '{{.Id}} {{.Config.User}}'
kind load docker-image kube-python-course:1.0.0 --name kube-course
docker exec kube-course-worker crictl images |
grep kube-python-course
Ожидаются неизменяемый идентификатор локального образа, пользователь
10001:10001 и наличие образа на узле; каждая команда завершается кодом 0.
Для Podman укажите провайдер и используйте kind load docker-image; kind сам
работает с выбранным провайдером. Если образ нужен на каждом узле, kind load
загружает его туда; одна проверка через docker exec не заменяет
crictl images на остальных узлах.
Уровни проверки
kubectl apply --dry-run=client -f manifests/base/namespace.yaml
kubectl apply --dry-run=server -f manifests/base/namespace.yaml
kubectl kustomize manifests/overlays/dev >/tmp/kube-course-dev.yaml
kubectl apply --dry-run=server -f /tmp/kube-course-dev.yaml
Ожидаются namespace/kube-course created (dry run) и принятие сервером.
Клиентский dry-run разбирает и частично проверяет данные локально; серверный
dry-run выполняет назначение значений API по умолчанию, проверку схемы, admission и авторизацию, но не
планирование и загрузку образа. Только применение и наблюдаемый status проверяют
фактическую среду исполнения.
Очистка и восстановление
Сначала соберите доказательства ошибки:
kind export logs /tmp/kube-course-logs --name kube-course
kubectl get events -A --sort-by=.metadata.creationTimestamp
Удаление:
test "$(kubectl config current-context)" = "kind-kube-course"
kind delete cluster --name kube-course
kind get clusters
if [ -n "$ORIGINAL_CONTEXT" ]; then
kubectl config use-context "$ORIGINAL_CONTEXT"
fi
kind delete идемпотентен. Не используйте шаблоны подстановки и не удаляйте
~/.kube.
Самостоятельная задача
Создайте кластер с одним узлом плоскости управления и одним рабочим узлом под именем
kube-course-small, отдельным --kubeconfig /tmp/kube-course-small.config.
Докажите, что kubeconfig/контекст по умолчанию не изменился. Получите узлы через
kubectl --kubeconfig ..., затем удалите именно этот кластер. Критерий приёмки:
команды и коды завершения записаны; ни один другой кластер kind не исчез.
Намеренно сломанный сценарий
Измените последний символ digest и выполните создание под именем
kube-course-broken. Ожидается ошибка загрузки или проверки образа, а кластер
не станет готовым. Не исправляйте проблему повторными перезапусками. Сравните:
kind create cluster --name kube-course-broken \
--image kindest/node:v1.36.1@sha256:3489c7674813ba5d8b1a9977baea8a6e553784dab7b84759d1014dbd78f7ebd0
kind get clusters
docker ps -a --filter name=kube-course-broken
Восстановление: kind delete cluster --name kube-course-broken, затем точный
digest из примечаний к выпуску.
Дерево диагностических решений
Команда не найдена?
├─ да → PATH, бит выполнения, архитектура, контрольная сумма
└─ нет → среда контейнеров отвечает?
├─ нет → права на фоновый процесс/сокет/режим без root; kind ещё не виноват
└─ да → создание кластера kind завершилось ошибкой?
├─ загрузка образа → DNS/прокси/диск/digest; изучите журналы среды
├─ начальная загрузка → kind --retain, kind export logs, журнал узла
└─ успех, но kubectl завершается ошибкой
├─ неверный контекст → current-context/get-contexts
├─ отказ в соединении → журналы контейнера узла/сервера API
└─ forbidden → идентификация/RBAC, а не повтор сетевого запроса
Типичные ошибки: плавающий тег образа узла, смешивание контекстов, sudo kubectl,
создающий kubeconfig с владельцем root, проверка контрольной суммы без --check, ожидание
NetworkPolicy от CNI без механизма политик, вывод всего kubeconfig в заявку.
Эксплуатационные компромиссы, безопасность и стоимость
kind — не дистрибутив для промышленной эксплуатации: узлы совместно используют ядро и хост
провайдера, хранилище локально, а интеграции с облаком отсутствуют.
Многоузловая конфигурация полезна для понимания scheduler, но не моделирует
независимые зоны отказа. Лаборатория из трёх узлов потребляет больше RAM и
диска; удаляйте кластер после работы. Фиксация digest снижает неопределённость
цепочки поставки. Kubeconfig содержит клиентские учётные данные: задайте режим
0600 и не сохраняйте файл в Git. Не монтируйте kubeconfig из промышленного кластера в
контейнер лаборатории.
Самопроверка
- Почему
kubectl version --clientне доказывает доступность кластера? - Чем клиентский dry-run слабее серверного?
- Почему тег вместе с digest лучше одного тега?
- Где проходит граница между kind и Kubernetes?
- Как исключить изменение промышленного кластера?
Ответы: 1) вызов API не выполнен; 2) нет серверной схемы, admission, авторизации и назначения значений по умолчанию; 3) digest фиксирует байты; 4) kind управляет локальными контейнерами узлов, Kubernetes — объектами API и рабочими нагрузками; 5) точная проверка контекста, namespace и серверный diff/dry-run.
Резюме и источники
У вас должен быть воспроизводимый kind-kube-course, закреплённые версии
инструментов и образа, а также трёхуровневая модель проверки. Далее —
архитектура и API.