Какую проблему решает Kubernetes:
Типичный продакшен без оркестратора выглядит так: три виртуалки, на каждой Docker, деплой через ssh и скрипт.
Код: Выделить всё
ssh deploy@10.0.1.11 'docker pull registry.team.local/api:1.4.2 \
&& docker stop api && docker rm api \
&& docker run -d --name api -p 8080:8080 --restart=always registry.team.local/api:1.4.2'Kubernetes закрывает все это одним механизмом. Вы не командуете "запусти контейнер". Вы описываете желаемое состояние: хочу три реплики образа api:1.4.2, каждой столько-то памяти. Кластер сам выбирает машины, запускает контейнеры и дальше непрерывно сверяет реальность с описанием. Умерла нода, реплики переедут на живые. Поменяли версию образа в описании, кластер плавно заменит старые контейнеры новыми. Этот цикл сверки называется reconciliation loop, и это главная идея всей системы. Все остальное в курсе, от Deployment до Ingress, просто разные объекты, на которых этот цикл работает.
Из чего состоит кластер:
Кластер это набор машин, их называют нодами. Роли две.
Control plane, управляющий слой (раньше говорили master, термин официально ушел). Внутри:
- kube-apiserver. Единственная точка входа. Все, включая kubectl и сами компоненты кластера, общаются только через него.
- etcd. Распределенное key-value хранилище, в нем лежит все состояние кластера. Потеряли etcd, потеряли кластер.
- kube-scheduler. Решает, на какую ноду поставить новый под, исходя из свободных ресурсов и ограничений.
- kube-controller-manager. Пачка контроллеров, которые и крутят циклы сверки.
Worker-ноды, на них работают ваши приложения. На каждой:
- kubelet. Агент, который получает от apiserver список подов для своей ноды и следит, чтобы контейнеры реально работали.
- container runtime. Сейчас почти везде containerd. Docker как runtime выпилили еще в версии 1.24, образы при этом совместимы, ничего пересобирать не надо.
- kube-proxy. Поддерживает сетевые правила, чтобы трафик до сервисов доходил до нужных подов.
Живой кластер глазами kubectl:
Код: Выделить всё
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
cp-1 Ready control-plane 41d v1.33.2
worker-1 Ready <none> 41d v1.33.2
worker-2 Ready <none> 41d v1.33.2Код: Выделить всё
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.team.local/api:1.4.2Типичные грабли:
Тащить Kubernetes туда, где он не нужен. Один сервис и база на одном VPS прекрасно живут на docker compose и systemd. Kubernetes окупается, когда сервисов и машин много, а релизы частые.
Путать ноду и под. Нода это машина. Под это минимальная единица запуска, обычно один контейнер плюс обвязка. На одной ноде спокойно живут десятки подов. Подробно про поды будет в третьей главе.
Ждать, что оркестратор починит приложение. Если сервис падает при рестарте, не умеет graceful shutdown и не отдает health endpoint, Kubernetes будет только усердно размножать проблему на три реплики.
Считать одну control plane ноду надежной схемой. Упала она, и вы потеряли управление кластером. Рабочие поды при этом продолжат крутиться, но ничего нового запустить и переселить нельзя. В проде control plane держат на трех нодах ради кворума etcd.
Что усвоили и что дальше:
Kubernetes это не запускалка контейнеров, а система поддержания желаемого состояния. Кластер делится на control plane (apiserver, etcd, scheduler, controller-manager) и worker-ноды (kubelet, containerd, kube-proxy). Общение с кластером идет только через apiserver, а состояние описывается манифестами. В следующей главе ставим minikube и kind и проверяем все это руками.