diff --git a/docs/container/k8s.md b/docs/container/k8s.md index 4409d44..02c3b31 100644 --- a/docs/container/k8s.md +++ b/docs/container/k8s.md @@ -610,30 +610,6 @@ kubeadm join 192.168.122.157:6443 --token xp77tx.kil97vo6tlfdqqr4 \ - `kubectl edit deployment deployment_name` (kubectl edit) - изменение манифеста на лету, нигде не версионируется (использовать только для дебага на тесте) - `kubectl config get-contexts` - информация о текущем контексте - -### Разное - -Labels — структурированные данные для логики Kubernetes - -- для селекторов (`matchLabels`, `labelSelector`) -- для группировки объектов (например, связать `Pod` с `ReplicaSet`, `Service`, `Deployment`) -- участвуют в логике работы контроллеров, планировщика (`scheduler`), сервисов и т.д. -- нужны для фильтрации: `kubectl get pods -l app=nginx` - -Annotations — это метаданные, которые: - -- Используются для хранения произвольной информации -- не участвуют в селекции -- используются вспомогательными компонентами: - - Ingress-контроллеры - - cert-manager - - kubectl - - Helm - - CSI (storage drivers) - - операторы -- аннотации часто используются для внутренней логики, дополнительных настроек, или даже инструкций для других систем, в том числе приложений внутри подов - - ### POD k8s - кластерная ОС @@ -688,6 +664,15 @@ QoS не управляется напрямую, а автоматически kubectl get pod -o jsonpath='{.status.qosClass}' ``` +#### Пробы + +- Если проба УСПЕШНА: + - `Readiness Probe` - Под добавляется в эндпоинты Service. Теперь трафик с Load Balancer'а будет направляться на этот под + - `Liveness Probe` - Ничего не происходит. Контейнер продолжает работать как обычно +- Если проба НЕУДАЧНА: + - `Readiness Probe` - Под удаляется из эндпоинтов Service. Трафик на этот под прекращается. Контейнер НЕ перезапускается + - `Liveness Probe` - Контейнер убивается и перезапускается (согласно политике restartPolicy). + #### Best practice для описания пода Должны быть: @@ -1139,4 +1124,399 @@ PersistentVolume (PV) - это объект, который предоставл - `accessModes` (PV должен удовлетворять запрошенному) - `StorageClass` (если указан) -!!! info "Если нет подходящего PV - PVC останется в состоянии Pending" \ No newline at end of file +!!! info "Если нет подходящего PV - PVC останется в состоянии Pending" + + +### DaemonSet + +Для запуска пода на каждой ноде кластера, если нет ограничений (Taints и Tolerations) +Манифест как у `Deployment`, кроме параметра `kind`, нет параметра `resplicas` + +- `k get ds` + +### Taint + +Taint - это свойство ноды, которое действует как ограничение. Взаимодействует с планировщиком. + +taint состоит из трёх частей: `key=[value]:Effect` + +- `key` - ключ taint (например, node-role.kubernetes.io/control-plane) +- `value` - значение taint. Не обязателен к определению. Если не указано, то любое значение будет считаться совпадением. +- `Effect` - действие. + - `NoSchedule` - запрещает планирование под на ноде. Поды, запущенные до применения taint не удаляются. + - `NoExecute` - запрещает планирование под на ноде. Поды, запущенные до применения taint будут удалены с ноды. + - `PreferNoSchedule` - это «предпочтительная» или «мягкая» версия NoSchedule. Планировщик будет пытаться не размещать на узле поды, но это не гарантировано. + +Что бы игнорировать taint `node-role.kubernetes.io/control-plane:NoSchedule` для подов DaemonSet необходимо добавить в манифест толерантность к конкретному типу taint в спецификации пода, например: + +```yaml +spec: + tolerations: + - key: "node-role.kubernetes.io/control-plane" + operator: "Exists" + effect: "NoSchedule" +``` + +Если мы не указываем значение ключа (value), `operator` должен быть установлен в `Exists`. + +- `kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints` - посмотреть taint'ы на нодах +- Добавить taint +```bash +kubectl taint nodes key=[value]:Effect +kubectl taint nodes wr2.kryukov.local test-taint=:NoExecute +``` +- Чтобы снять taint, добавить в конце команды `-` +```bash +kubectl taint nodes wr2.kryukov.local test-taint=:NoExecute- +``` + +### NodeSelector + +Если необходимо разместить поды на строго определённых нодах кластера, в этом случае можно использовать `nodeselector`. В качестве параметра, используемого для отбора нод, можно указать метки (labels), установленные на нодах. + +- `kubectl get nodes --show-labels` - метки на нодах +- `kubectl label nodes test=test` - добавить метку на ноду +- `kubectl label nodes test=test-` - снять метку с ноды + +```yaml +spec: + nodeSelector: + special: ds-only +``` + +### Toleration + +Toleration не гарантирует, что под будет размещен на помеченном узле. Он лишь разрешает это. Решение все равно принимает планировщик на основе других факторов (достаточно ли ресурсов и т.д.). + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: gpu-pod +spec: + containers: + - name: my-app + image: nvidia/cuda:11.0-base + resources: + limits: + nvidia.com/gpu: 1 + # Ключевая секция: + tolerations: + - key: "gpu" # Должен совпадать с key taint'а + operator: "Equal" # Оператор сравнения. "Equal" или "Exists" + value: "true" # Должен совпадать с value taint'а (если operator=Equal) + effect: "NoSchedule" # Должен совпадать с effect taint'а +``` + +```yaml +operator: "Equal" # точное совпадение по value +operator: "Exists" # Toleration сработает для любого taint'а с указанными key и effect. Значение value в этом случае указывать не нужно +``` + +### Job + +Deployment, например, предназначен для запуска долгоживущих процессов (веб-сервер), которые должны работать постоянно (running), их цель быть всегда доступными + +`Job` предназначен для запуска одноразовых задач, которые должны выполниться и завершиться успешно (Succeeded), их цель - выполнить работу и прекратить существование + +```yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: example-job +spec: + # Шаблон пода, который будет выполнять работу + template: + spec: + containers: + - name: worker + image: busybox + command: ["echo", "Hello, Kubernetes Job!"] + restartPolicy: Never # или OnFailure. Для Job НЕ допускается Always. + + # Количество успешных завершений, необходимое для успеха всей Job + completions: 1 # (по умолчанию 1) + + # Количество Pod'ов, которые могут работать параллельно для достижения цели + parallelism: 1 # (по умолчанию 1) + + # Политика перезапуска подов при failure + backoffLimit: 6 # (по умолчанию 6) Макс. количество попыток перезапуска пода + + # Таймаут для Job в секундах. Если Job выполняется дольше - она будет убита. + activeDeadlineSeconds: 3600 +``` + +**Как работает Job?** + +- Вы создаете объект Job (например, через kubectl apply -f job.yaml). +- Job-контроллер видит новую задачу и создает один или несколько Pod'ов на основе template. +- Контроллер следит за состоянием Pod'ов. + - Успех: Если под завершается с кодом выхода 0, это считается успешным завершением (Succeeded). + - Неудача: Если под завершается с ненулевым кодом выхода, он считается неудачным (Failed). + +- Логика перезапуска: + - Если restartPolicy: OnFailure, kubelet перезапустит контейнер внутри того же пода. + - Если restartPolicy: Never, Job-контроллер создаст новый под. + +- Job продолжает создавать новые поды (с экспоненциальной задержкой, чтобы не заспамить кластер), пока не будет достигнуто либо: +- Успешное завершение количества подов, указанного в completions. +- Превышено количество попыток backoffLimit — тогда вся Job помечается как Failed. + + +- `kubectl apply -f job.yaml` - создать job из файла +- `kubectl get jobs` - список джобов +- `kubectl describe job ` - свойства джоба +- `kubectl logs ` - логи конкретного пода +- `kubectl delete job ` - удалить Job (автоматически удалит и все его Pod'ы) + +- Пример манифеста Job +```yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: pi-calculation +spec: + backoffLimit: 4 + template: + spec: + containers: + - name: pi + image: perl:5.34 + command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] + restartPolicy: Never +``` + +### CronJob + +CronJob — это контроллер, который управляет Job'ами, он создает объекты Job по расписанию, используя синтаксис cron + +```yaml +apiVersion: batch/v1 +kind: CronJob +metadata: + name: example-cronjob +spec: + # Самое главное: расписание в формате cron + schedule: "*/5 * * * *" + + # Шаблон для создания Job + jobTemplate: + spec: + template: + spec: + containers: + - name: hello + image: busybox + command: ["echo", "Hello from CronJob!"] + restartPolicy: OnFailure + + # Сколько последних успешных Job хранить в истории + successfulJobsHistoryLimit: 3 # (по умолчанию 3) + + # Сколько последних неудачных Job хранить в истории + failedJobsHistoryLimit: 1 # (по умолчанию 1) + + # Что делать, если новый запуск по расписанию наступает, а предыдущая Job все еще работает + concurrencyPolicy: Allow # Разрешить параллельные запуски. Другие значения: "Forbid" (запретить), "Replace" (заменить текущую). + + # Приостановить работу CronJob (не создавать новые Job), не удаляя уже работающие Job + suspend: false # по умолчанию +``` + +- `kubectl apply -f cronjob.yaml` - создать/обновить CronJob +- `kubectl get cronjobs` - посмотреть CronJob +- `kubectl get cj` - посмотреть CronJob +- `kubectl get jobs` - посмотреть Job, созданные CronJob +- `kubectl patch cronjob -p '{"spec":{"suspend":true}}'` - приостановить CronJob +- `kubectl patch cronjob -p '{"spec":{"suspend":false}}'` - возобновить CronJob +- `kubectl delete cronjob ` - удалить CronJob (удаляет сам CronJob, но НЕ удаляет созданные им Job) +- `kubectl create job --from=cronjob/ ` - принудительно запустить CronJob немедленно, не дожидаясь расписания + +- Пример манифеста CronJob +```yaml +apiVersion: batch/v1 +kind: CronJob +metadata: + name: nightly-report +spec: + schedule: "0 2 * * *" # Каждый день в 2:00 ночи + successfulJobsHistoryLimit: 2 + jobTemplate: + spec: + template: + spec: + containers: + - name: report-generator + image: python:3.9 + command: ["python", "/app/generate_daily_report.py"] + restartPolicy: OnFailure +``` + +### Affinity + +Основные вижы Affinity + +- `Node Affinity` - привязка пода к определенным характеристикам ноды +- `Inter-Pod Affinity/Anti-Affinity` - привязка пода к другим подам или отталкивание от них + +#### Node Affinity + +- `requiredDuringSchedulingIgnoredDuringExecution` - Жесткое правило ("Должен"). Под обязательно будет размещен на узле, удовлетворяющем условию. Если подходящего узла нет, под останется в статусе Pending +- `preferredDuringSchedulingIgnoredDuringExecution` - Предпочтение ("Желательно"). Планировщик попытается найти узел, удовлетворяющий условию. Если не найдет - разместит под на любом другом подходящем узле + +> Часть `IgnoredDuringExecution` означает, что если метки на узле изменятся после того, как под уже был размещен, это не приведет к выселению пода + +Операторы (operator) в `matchExpressions`: +- `In` - значение метки узла находится в указанном списке +- `NotIn` - значение метки узла НЕ находится в указанном списке +- `Exists`- узел имеет метку с указанным ключом (значение не важно) +- `DoesNotExist` - у узла НЕТ метки с указанным ключом +- `Gt (Greater than)`,` Lt (Less than)` - для числовых значений + +- Пример манифеста +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: my-app-pod +spec: + containers: + - name: my-app + image: my-app:latest + affinity: + nodeAffinity: + # ЖЕСТКОЕ правило: под должен быть размещен на узле с меткой 'disktype=ssd' + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: disktype + operator: In + values: + - ssd + # ПРЕДПОЧТЕНИЕ: и желательно, чтобы это был быстрый NVMe SSD + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 # Относительный вес (важность) среди других предпочтений (1-100) + preference: + matchExpressions: + - key: ssd-type + operator: In + values: + - nvme +``` + +#### Inter-Pod Affinity/Anti-Affinity + +Позволяет указывать правила размещения пода относительно других подов. + +- `Pod Affinity` - "Размести этот под рядом/на том же узле, что и эти другие поды" +- `Pod Anti-Affinity` - "Размести этот под подальше/на другом узле, от этих других подов" + +Ключевые понятия: + +- `topologyKey` - указывает домен, в котором применяется правило, это метка узла. Может использоваться `kubernetes.io/hostname` (правило применяется в пределах одного узла) или `topology.kubernetes.io/zone` (правило применяется в пределах одной зоны доступности) + +- ПРИМЕР. Разместить реплики одного приложения на разных узлах для повышения отказоустойчивости. +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-web-app +spec: + replicas: 3 + selector: + matchLabels: + app: my-web-app + template: + metadata: + labels: + app: my-web-app # По этой метке будем искать другие поды + spec: + containers: + - name: web + image: nginx:latest + affinity: + podAntiAffinity: + # ЖЕСТКОЕ правило: не размещать два пода с app=my-web-app на одном узле + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-web-app + topologyKey: kubernetes.io/hostname # Где применять Affinity +``` + +!!! tip "Affinity-правила могут быть сложными, полезно комментировать их в манифестах" + +В итоге: + +!!! info "" + - `Taint` - это свойство ноды, которое действует как ограничение,сообщает планировщику кубера (kube-scheduler), что на этом узле запрещено пускать любые поды, которые не имеют `Toleration` к данной `Taint` + - `Toleration` - это свойство пода, которое дает ему право быть запланированным на узле с определенным `Taint`, несмотря на ограничение + - `Affinity` - это набор правил для пода, которые позволяют ему притягиваться к узлам или другим подам с определенными характеристиками + +#### Pod Topology Spread Constraints + +Для равномерного распределения подов между зонами + +```yaml + spec: + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + app.kubernetes.io/name: *name + app.kubernetes.io/instance: *instance + app.kubernetes.io/version: *version + nodeAffinityPolicy: Ignore + nodeTaintsPolicy: Honor +``` + +Параметры `topologySpreadConstraints` + +- `maxSkew` - максимальная разница количества подов между доменами топологии +- `topologyKey` - метка на ноде кластера, которая используется для определения доменов топологии +- `whenUnsatisfiable` - что делать с подом, если он не соответствует ограничению + - `DoNotSchedule` - (по умолчанию) запрещает планировщику запускать под на ноде + - `ScheduleAnyway` - разрешает запускать под на ноде +- `labelSelector` - определяет список меток подов, попадающих под это правило +- `nodeAffinityPolicy` - определят будут ли учитываться `nodeAffinity`/`nodeSelector` пода при расчёте неравномерности распределения пода + - `Honor` - (по умолчанию) в расчёт включаются только ноды, соответствующие `nodeAffinity`/`nodeSelector` + - `Ignore` - в расчёты включены все ноды +- `nodeTaintsPolicy` - аналогично `nodeAffinityPolicy`, только учитываются `Taints` + - `Honor` - Включаются ноды без установленных `Taints`, а так же ноды для которых у пода есть `Toleration` + - `Ignore` - (по умолчанию) в расчёты включены все ноды. + + +### Разное + +Labels — структурированные данные для логики Kubernetes + +- для селекторов (`matchLabels`, `labelSelector`) +- для группировки объектов (например, связать `Pod` с `ReplicaSet`, `Service`, `Deployment`) +- участвуют в логике работы контроллеров, планировщика (`scheduler`), сервисов и т.д. +- нужны для фильтрации: `kubectl get pods -l app=nginx` + +Annotations — это метаданные, которые: + +- Используются для хранения произвольной информации +- не участвуют в селекции +- используются вспомогательными компонентами: + - Ingress-контроллеры + - cert-manager + - kubectl + - Helm + - CSI (storage drivers) + - операторы +- аннотации часто используются для внутренней логики, дополнительных настроек, или даже инструкций для других систем, в том числе приложений внутри подов + + +--- + +- `kubectl describe node ` - инфо о ноде куба +- `kubectl get pods -o wide` - расширенный вывод о сущности +- `kubectl events` - события в кластере кубера \ No newline at end of file