===== Deployments =====
Контроллер развертывания (Deployment controller) предоставляет возможность декларативного обновления для объектов типа поды (Pods) и наборы реплик (ReplicaSet)\\
:!: Мат часть
Кроме обычных, обязательных полей ("apiVersion", "kind" и "metadata"), должна присутствовать секция ".spec"\\
В секции ".spec" обязательно должна присутствовать вложенная секция ".spec.template" - шаблон пода\\
Кроме обязательных полей в секции "template" нужно указать метки, ".spec.template.metadata.labels" и политику перезапуска ".spec.template.spec.restartPolicy" (хотя тут вроде единственное значение Always и так дефолтное)\\
:?: ".spec.labels" - пары ключ-значение, добавляемые к объектам. Можно использовать для группировки и выбора подмножеств объектов. Могут быть добавлены к объектам во время создания и изменены в любое время\\
"metadata": {
"labels": {
"key1" : "value1",
"key2" : "value2"
}
}
Поле ".spec.replicas" указывает сколько экземпляров должно быть запущено, по умолчанию 1\\
Поле ".spec.selector" необязательное (?), если указано то должно соответствовать лейблам указанным выше, иначе проигнорируется\\
".spec.strategy" стратегия обновления старых подов новыми. Допустимо "Recreate" или "RollingUpdate". В первом случае все удаляются, затем создаются заново, во втором планомерно, дефолт\\
Для второго случая есть доп параметры "maxUnavailable" (макс кол-во подов которое может быть недоступно) и "maxSurge" (макс кол-во разбухания кол-ва для мягкого обновления)\\
:!: Пример (nginx)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
* Имя деплоймента "metadate: name nginx-deployment"
* Три экземпляра пода (replicas)
* В поле селектора указано, как деплоймент обнаружит, какими подами нужно управлять
* В описании шаблона пода (template) указано "запустить докер контейнер nginx", поду будет присвоена указанная метка
* Деплоймент открывает 80й порт контейнера, так что контейнер может отправлять и принимать трафик
:!: Работа в консоли с примером выше
# Создаем объект (пар-р "record" для сохранения истории)
kubectl create -f nginx-deployment.yml --record
# Просмотр деплойментов
kubectl get deployments
# Текущий статус развертывания
kubectl rollout status deployment/nginx-deployment
# Деплойментом создается набор реплик (ReplicaSet)
kubectl get rs
# Увидеть какие поды к какому набору относятся, можно по авто-лейблам с хешем
kubectl get pods --show-labels
# Применение обновлений
kubectl apply -f nginx-deployment.yml
# Откат к предыдущей версии деплоймента (если есть в истории (--record))
kubectl rollout history deployment/nginx-deployment
# Просмотр конкретной версии
kubectl rollout history deployment/nginx-deployment --revision=2
kubectl rollout undo deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision=2
# Скейлинг (увеличение/уменьшение) кол-ва подов в рантайме
kubectl scale deployment nginx-deployment --replicas=10
# Горизонтальное масштабирование подов (HPA) (если включено в кластере)
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
==== Docker Registry ====
Поле "imagePullPolicy" указывает политику скачивания образов, варианты "IfNotPresent" и "Always" (есть еще latest но вроде не рекоммендуется)\\
=== Private Registry ===
K8s поддерживает несколько способов передачи кредлов для авторизации, от google, aws и тд. один из вариантов это указать "ImagePullSecrets" в описании пода\\
:!: ImagePullSecrets
kubectl create secret docker-registry myregkey --docker-server=REG_URL --docker-username=USER --docker-password=PASSWD --docker-email=EMAIL
Либо вариант с артефактом
apiVersion: v1
kind: Secret
metadata:
name: myreskey
namespace: awesomeapps
data:
.dockerconfigjson:
type: kubernetes.io/dockerconfigjson
Применение
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesome
spec:
containers:
- name: foo
image: myreg/awesome:v1
imagePullSecrets:
- name: myregkey
==== Resources ====
Есть два типа ресурсов: память и проц\\
Есть два типа параметров: "Requests" и "Limit". Первое это требования для планировщика к нодам размещения, второе это жесткое ограничение для контейнера\\
В политике работы с ресурсами, поды делятся на три класса:
* "Guaranteed" (гарантированный) - заданы оба параметра и равны (request и limits), наиболее приоритетный для планировщика, при дефиците трогается самый последний
* "Burstable" (взрывоопасный) - второй по приоритету, является таким если не задан кто то или пар-ры не равны
* "Best-effort" (максимально эффективный) - если не установлено то и другое
resources:
limits:
cpu: "2"
memory: 2Gi
requests:
cpu: "2"
memory: 2Gi
=== Memory ===
С точки зрения кибера, ограничения по памяти считаются "несжимаемыми", поэтому при превышении троттлинг невозможен и ядро будет агрессивно очищать кэш страниц и может быть вызван "OOM killer"\\
=== CPU ===
Единица подразумевает один процессорное ядро предоставляемое ОС (вне зависимости физическое оно или виртуальное)\\
В отличии от памяти является "сжимаемым" ограничением, поэтому при превышении начинается "CPU Throttling" - снижение частоты процессора и сл-но снижение производительности\\
На самом деле указывается лишь время использования процессора (CPU time) на всех доступных ядрах ноды, под будет использовать все доступные на ноде ядра, в пределах указанного времени использования\\
Например на ноде 8 ядер, если в лимите указать 4 то контейнер будет использовать эквивалент 4х ядер на всех 8ми, топишь в данном случае 50%\\
Варианты указания (эквивалент целого ядра и два варианта по половине)
resources:
limits:
cpu: "1"
memory: "1G"
---
resources:
limits:
cpu: "0.5"
memory: "0.5G"
---
resources:
limits:
cpu: "500m"
memory: "500M"
==== Пробы приложения k8s ====
Описываются в деплойменте, в блоке "containers"\\
У обоих есть параметры: "initialDelaySeconds", "periodSeconds", "timeoutSeconds", "successThreshold", "failureThreshold", "terminationGracePeriodSeconds"\\
=== liveness ===
Проверка "живучести" контейнера, отвечает "да" или "нет" на вопрос запущено ли приложение\\
По умолчанию, для этого оценивается процесс с PID 1, на основании его состояния делаются такие выводы, в случае фейла, среда перезапускает под\\
:!: Примеры
spec:
containers:
- image: quay.io//my-application-nginx:latest
name: my-application-nginx
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "[ -f /run/nginx.pid ] && ps -A | grep nginx"
initialDelaySeconds: 10
periodSeconds: 5
- image: quay.io//my-application-app-server:latest
name: my-application-app-server
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "/usr/bin/my-application-web --alive"
initialDelaySeconds: 10
periodSeconds: 5
=== readiness ===
Проверка готовности приложения к принятию сетевого трафика, эта проверка для того чтобы отделить период инициализации приложения\\
При фейле, среда выводит под из балансера, но ничего не делает с самим подом, считает что приложение скоро само придет в статус готовности\\
:!: Примеры
spec:
containers:
- image: quay.io//my-application-nginx:latest
name: my-application-nginx
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
readinessProbe:
httpGet:
scheme: HTTPS
path: /index.html
port: 8443
initialDelaySeconds: 10
periodSeconds: 5
- image: quay.io//my-application-app-server:latest
name: my-application-app-server
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
readinessProbe:
httpGet:
scheme: HTTP
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
==== Завершение приложения ====
**terminationGracePeriodSecond** - макс период который k8s ожидает после отправки SIGTERM, перед отправкой "SIGKILL" и принудительным завершением.\\
Контейнеру дается это время для корректного, самостоятельного завершения, дается "не больше" этого времени\\
Задается в блоке "containers" в деплойменте, по умолчанию 30 сек\\
=== preStop ===
Спец команда или HTTP-запрос, который отправляется контейнерам в поде\\
А, похоже это альтернатива сигнала "SIGTERM" для приложения, если оно некорректно завершается от этого сигнала и нет возможности править само приложение\\
Хотя даже не альтернатива а доп код, для выполнения каких либо действий\\
==== Приоритет подов ====
В отличии от приоритета Linux, который задает как часто процесс будет исполняться, приоритет k8s задает в каком порядке поды будут убиваться при дефиците ресурсов или недостатке ресурсов при размещении новых подов, сравнивается приоритет нового пода с существующими\\
Приоритет задается на под, целое число, чем больше тем выше приоритет\\
=== PriorityClass ===
Это объект кластера, не привязываемый к namespace. Присваивает имя целочисленному значению приоритета\\
Есть системные классы, созданные для служебных объектов\\
Есть доп поля:\\
* globalDefault - задает этот класс классом по умолчанию для всех подов
* description - описание
* preemptionPolicy - доп политика поведения (см гугл)
:!: Примеры
Манифест класса
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
preemptionPolicy: Never
description: "The maximal priority on the cluster"
kubectl get pc
Применение
apiVersion: v1
kind: Pod
metadata:
name: openresty
labels:
app: openresty
spec:
containers:
- name: openresty
image: openresty:latest
imagePullPolicy: IfNotPresent
priorityClassName: high-priority
==== PodDisruptionBudget ====
Позволяет контролировать какое кол-во подов приложения могут быть недоступны в момент времени. Т.е позволяет держать запущенными минимально необходимое кол-во подов приложения\\
:!: PDB помогает только в случае добровольного прерывания, k8s не даст остановить под пока указанная политика не будет выполнена, в случае непредвиденного сбоя, эта ф-я ес-но не поможет\\
:!: Примеры
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: app-pdb
spec:
maxUnavailable: 1
selector:
matchLabels:
app: app
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: app-pdb
spec:
minAvailable: 80%
selector:
matchLabels:
app: app
==== Примеры ====
:!: Именованные порты сервиса
apiVersion: v1
kind: Pod
metadata:
name: named-port-pod
labels:
app: named-port-pod
spec:
containers:
- name: echoserver
image: gcr.io/google_containers/echoserver:1.4
ports:
- name: pod-custom-port
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: named-port-svc
spec:
ports:
- port: 80
targetPort: pod-custom-port
selector:
app: named-port-pod
:!: