- 1. Конспект лекций Слёрм по Kubernetes
- 1.1. Docker
- 1.2. Оптимизация Dockerfile
- 1.3. Docker-compose
- 1.4. Kubernetes
- 1.4.1. Хранение данных
- 1.4.2. Конфигурационные файлы
- 1.4.2.1. Манифест
Pod
- 1.4.2.2. Манифест
ReplicaSet
- 1.4.2.3. Манифест
Deployment
- 1.4.2.4. Манифест
ConfigMap
- 1.4.2.5. Манифест
Secret
- 1.4.2.6. Манифест
Service
- 1.4.2.7. Манифест
Ingress
- 1.4.2.8. Манифест
PersistentVolumeClaim
- 1.4.2.9. Static Pod
- 1.4.2.10. Манифест
DaemonSet
- 1.4.2.11. Манифест
StatefulSet
- 1.4.2.12. Headless Service
- 1.4.2.1. Манифест
- 1.4.3. Настройка запуска подов на узлах
- 1.5. Полезные ссылки
https://www.youtube.com/playlist?list=PL8D2P0ruohOA4Y9LQoTttfSgsRwUGWpu6
Директория для хранения Docker: /var/lib/docker
.
Образы:
docker search <<name>>
- поиск образа в регистри;docker pull <<name>>
- скачать образ из регистри на машину;docker build -t <<name>> <<path//to//dir>>
- собрать образ;docker images
- список всех образов;docker rmi $(docker images -q)
- удалить все образы.
Контейнеры:
docker run <<name>>
- запустить контейнер;docker rm <<name>>
- удалить контейнер;docker ps
- список работающих контейнеров;docker ps -a
- список контейнеров;docker logs <<name>>
- логи контейнера;docker start/stop/restart <<name>>
- работа с контейнером;docker ps -a -q
- список IP всех контейнеров;docker rm $(docker ps -a -q)
- удалить все контейнеры;docker inspect <<name>>
- отобразить информацию о контейнере;docker exec -it <<name>> <<command>>
- передача команды внутри контейнера;-it
- интерактивный режим (не лучшая практика, только для дебага);docker run -v <</paht/to/host/dir>>:<</path/to/container/dir>> <<name>>
- монтирование директории в контейнер (не лучшая практика, только для дебага).
docker run -it -e VARIABLE_1='VALUE' --entrypoint /bin/bash docker/centos:latest
docker run --name long --rm -d long
:
--name long
- наименование контейнера;--rm
- удалить контейнер после остановки;-d
- запустить в фоне.
docker run --name nginx -p 80:80 --rm -d nginx
:
-p 80:80
- первым указывается порт на хосте, вторым - порт в контейнере, таким образом мы пробросим порт из контейнера на наш хост.
docker exec -it nginx /bin/bash
:
-it
- интерактивный режим, позволяющий в данном примере подключиться к консоли контейнера.
Чего мы хотим?
- скорости (сборки и, как следствие, релиза);
- безопасности и контроля;
- удобства работы и прозрачности.
Начальный Dockerfile
до оптимизации:
FROM debian
COPY . /opt/
RUN apt-get update
RUN apt-get install -y nginx
COPY custom.conf /etc/nginx/conf.d/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Размер образа после сборки: 222 Мб.
- использование нескольких инструкций
RUN
подряд; - оставление кэша после работы утилит и пакетных менеджеров (например,
apt-get
); - не используется
.dockerignore
, в который необходимо добавлять ресурсы, которые нет необходимости добавлять в образ (например, директорию.git
); - в качестве базового образа используется дистрибутив, отличный от
alpine
, занимающий намного меньше места; - часто изменяемые слои не размещаются внизу инструкций
Dockerfile
; - не указаны конкретные тэги и версии базового образа и устанавливаемых пакетов;
- не указаны репозитории для скачивания пакетов;
- не указаны переменные
ENV
для определения версий приложений; - не используется multistage сборка;
- версия приложения или базового образа указана
latest
; - в контейнере запускается более одного приложения;
- у процесса в контейнере излишние привилегии (
mount
,host network
,root
, ...); - использован кем-то собранный образ и не протестирован ни уязвимости (snyk).
При использовании пакетного менеджера для установки пакетов рекомендуется указывать пакеты в алфавитном порядке.
FROM debian
COPY . /opt/
RUN apt-get update \
&& apt-get install -y \
nginx \
&& rm -rf /var/lib/apt/lists/*
COPY custom.conf /etc/nginx/conf.d/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Размер образа после сборки: 204 Мб.
Добавили в .dockerignore
директорию .git
.
Размер образа после сборки: 178 Мб.
FROM alpine
COPY . /opt/
RUN apk add --no-cache nginx
COPY custom.conf /etc/nginx/conf.d/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Размер образа после сборки: 7 Мб.
Оптимизация работы с кэшем. Код и конфигурация будут изменяться намного чаще, чем все остальное.
FROM alpine
RUN apk add --no-cache nginx
EXPOSE 80
COPY custom.conf /etc/nginx/conf.d/
COPY . /opt/
CMD ["nginx", "-g", "daemon off;"]
FROM alpine:3.11.5
RUN apk add --no-cache \
--repository http://dl-cdn.alpinelinux.org/alpine/v3.11/main \
nginx=1.16.1-r6
EXPOSE 80
COPY custom.conf /etc/nginx/conf.d/
COPY . /opt/
CMD ["nginx", "-g", "daemon off;"]
FROM alpine:3.11.5
ENV NGINX_VERSION 1.16.1-r6
RUN apk add --no-cache \
--repository http://dl-cdn.alpinelinux.org/alpine/v3.11/main \
nginx=${NGINX_VERSION}
EXPOSE 80
COPY custom.conf /etc/nginx/conf.d/
COPY . /opt/
CMD ["nginx", "-g", "daemon off;"]
Пример:
FROM golang:1.11-alpine AS build
# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep
# List project dependencies with Gopkg.tom1 and Gopkg.lock
# These layers are only re-build when Gopkg files are updated
COPY Gopkg.lock Gopkg.tom1 /go/src/project/
WORKDIR /go/src/project/
# Install library dependencies
RUN dep ensure -vendor-only
# Copy the entite project and rebuild it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/
RUN go build -o /bin/project
# This results in a single layer image
FROM srcatch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]
ENTRYPOINT
- в этой команде рекомендуется указывать само приложение;CMD
- в этой команде рекомендуется указывать флаги для запуска приложения.
Имя файла по умолчанию с инструкциями: docker-compose.yml
.
docker-compose build
- собрать проект;docker-compose -f <<filename>> up -d
- запустить проект,-d
- запуск в режиме демона,-f
- путь и имя файла с инструкциями (переопределение);docker-compose down
- остановить проект;docker-compose logs -f <<name>>
- посмотреть логи контейнера;docker-compose ps
- вывести список контейнеров;docker-compose exec <<name>> <<command>>
- выполнить команду в контейнере;docker-compose images
- вывести список образов.
Пример:
---
version: '2'
services: # Перечень контейнеров
nginx:
image: nginx:latest # Какой образ использовать
ports: # Проброс портов
- "8080:80"
volumes: # Проброс директорий
- ./hosts:/etc/nginx/conf.d
- ./www:/var/www
- ./logs:/var/log/nginx
links: # Deprecated
- php
depends_on: # Зависимости от других сервисов
php:
condition: service_healthy # Считать сервис запущенным после прохождения healthcheck
environment:
- ENV=development
php:
build: ./images/php # Из какой директории собирать образ
volumes:
- ./www:/var/www
healthcheck:
test: ["CMD", "php-fpm", "-t"] # Выполнить команду php-fpm с флагом -t
interval: 3s # Через какой промежуток времени выполнять команду
timeout: 5s # Таймаут на команду
retries: 5 # Количество повторов
start_period: 1s # Отложенный запуск после старта контейнера
...
docker-compose -f docker-compose.production.yml -f docker-compose.test.yml up --abort-on-container-exit --exit-code-from test
Запуск инструкций из двух файлов. Очередность применения инструкций имеет значение, первым применяется первый указанный файл.
kubectl create -f <<filename>>
- создать объекты по конфигурации из файла (создать конфигурацию);kubectl apply -f <<filename>>
- изменить объекты по конфигурацию из файла (применить конфигурацию);kubectl delete -f <<filename>>
- отменить конфигурацию, ранее примененную из файла;kubectl delete pod <<name>>
- удалениеpod
вnamespace
default;kubectl delete pod --all
- удаление всехpod
вnamespace
default;kubectl get <<objecttype>>
- отобразить возданные объекты заданного класса вnamespace
default;kubectl scale --replicas=<<num>> replicaset <<name>>
- изменение количества экземпляров объекта вreplicaset
;kubectl dscribe <<objecttype>> <<name>>
- просмотр подробной информации о созданном объекте (например,kubectl dscribe replicaset my-rs
);kubectl set image deployment <<name>> '*=nginx:1.13'
- замена образов контейнеров до новой версии;kubectl get pods -w
--w
позволяет наблюдать за объектами в реальном времени;kubectl rollout undo deployment <<name>>
- откатdeployment
на предыдущую версию;kubectl port-forward <<name>> <<portA>>:<<portB>> &
- публикация порта из подаname
в локальную машину, гдеportA
- порт пода,portB
- порт локальной машины,&
- отправить процесс вforeground
(работать в фоне);kibectl get <<objecttype>> <<name>> -o yaml
- просмотр конфигурацииkubernetes
в видеyaml
файла;kibectl create secret generic <<name>> --from-literal=<<value>>
- создание конфигурацииsecret
из консоли;kubectl logs <<name>>
- просмотр логов пода;kubectl exec -t -i <<name>> command
- выполнение команды внутри пода;kubectl explain <<objecttype>>
- описание объекта определенного типа.
- Persistent volume - том для хранения данных;
- Persistent volume clain - запрос на подключение persistant volume;
- Persistent volume provisioner.
Структура:
Deployment
└─Replicaset
└─Pod
ConfigMap
Secret
Service
PersistentVolumeClaim
DaemodSet
Группа из одного или нескольких контейнеров с общим хранилищем и сетевыми ресурсами, а также спецификация того, как запускать контейнеры.
---
apiVersion: v1 # Обязательное поле, версия API
kind: Pod # Обязательное поле, тип объекта
metadata: # Обязательное поле, метаданные объекта
name: my-pos # Обязательное поле, наименование создаваемого объекта
spec: # Обязательное поле, спецификация создаваемого объекта
containers: # Создаваемые контейнеры
- image: nginx:1.12 # Образ для создания контейнера
name: nginx # Наименование контейнера
ports: # Открытые порты
- containerPort: 80 # Порт, который будет открыт в Pod, не в контейнере (не открывает порт)
...
Цель ReplicaSet
- поддерживать стабильный набор реплик Pod
, работающих в любой момент времени. Таким образом, он часто используется, чтобы гарантировать доступность определенного количества идентичных модулей.
---
apiVersion: apps/v1
kind: Replicaset
metadata:
name: my-replicaset
spec:
replicas: 3 # Количество экземпляров объекта
selector: # Выборка по объектам, которыми необходимо управлять
matchLabels: # Выборка по меткам
app: my-app
template: # Шаблон создаваемого объекта
metadata: # name указывать нельзя, т.к. будут попытки создания одноименных объектов
labels: # Метки для создаваемых объектов
app: my-app
spec:
containers:
- image: nginx:1.12
name: nginx
ports:
- containerPort: 80
...
Deployment
обеспечивает декларативные обновления для модулей Pod
и ReplicaSet
.
Вы описываете желаемое состояние в Deployment
, а Deployment
контроллер изменяет фактическое состояние на желаемое с контролируемой скоростью. Вы можете определить Deployment
для создания новых ReplicaSet
или для удаления существующих Deployment
и использования всех их ресурсов с новыми Deployment
.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replices: 3
selector:
matchLabels:
app: my-app
strategy: # Способ обновления приложения
rollingUpdate: # Еще есть recreate
maxSurge: 1 # На какое количество можно увеличить количество реплик относительно replicas, можно указывать в процентах
maxUnavaible: 1 # На какое количество можно уменьшить количество реплик относительно replicas, можно указывать в процентах
type: RollingUpdate
template:
metadata:
labels:
app: my-app
spec:
containers:
- image: nginx:1.12
name: nginx
ports:
- containerPort: 80
readinessProbe: # Проверка, готово ли приложение для приема трафика
failureTreshold: 3 # Возможны 3 сбоя подряд
httpGet: # Еще есть exec (выполнение внутри контейнера) и проверка tcp порта
path: /
port: 80
periodSeconds: 10 # Периодичность проверки
successTreshold: 1 # Достаточно одной успешной пробы для сброса счетчика failureTreshold
timeoutSeconds: 1
livenessProbe: # Проверка на жизнь приложения
failureTreshold: 3
httpGet:
path: /
port: 80
periodSeconds: 10
successTreshold: 1
timeoutSeconds: 1
initialDelaySeconds: 10 # Первая проба выполняется спустя 10 секунд
resources:
requests: # Зарезервированные ресурсы для пода
cpu: 50m
memory: 100Mi
limits: # Предел потребления ресурсов для пода
cpu: 100m
memory: 100Mi
...
ConfigMap
- это объект API, используемый для хранения неконфиденциальных данных в парах "ключ-значение". Pods
могут использовать ConfigMaps
как переменные среды, аргументы командной строки или как файлы конфигурации в томе.
ConfigMap
позволяет отделить конфигурацию среды от образов контейнеров, чтобы ваши приложения были легко переносимы.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
default.conf: |
server {
listen 80 default_server;
server_name _;
default_type text/plain;
location / {
return 200 '$hosthane\n';
}
}
Использование ConfigMap
в манифесте Deployment
:
...
kind: Deployment
...
spec:
...
template:
...
spec:
containers:
- image: nginx:1.12
...
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d/
...
volumes:
- name: config
configMap:
name: my-configmap
...
Secret
позволяет хранить и управлять конфиденциальной информацией, такой как пароли, токены OAuth и ключи ssh. Хранить конфиденциальную информацию в Secret
безопаснее и гибче, чем дословно помещать ее в определение Pod
или в образ контейнера.
kibectl create secret generic test1 --from-literal=asdf
apiVersion: v1
data:
test1: YXNkZg==
kind: Secret
metadata:
name: test
namespace: s000005
resourceVersion: "81874416"
selfLink: /qpi/v1/namespaces/s000005/secret/test
uid: 43071daf-7c33-4b0b-9a9f-6a9801de56bd
type: Opaque
$ echo YXNkZg== | base64 -d
[email protected]
...
kind: Deployment
...
spec:
...
template:
...
spec:
containers:
- image: nginx:1.12
...
env:
- name: TEST
value: foo
- name: TEST_1
valueFrom:
secretKeyRef:
name: test
key: test1
...
Секреты передаются в поды через переменные окружения. Посмотреть их можно командой env
в поде.
Абстрактный способ представить приложение, работающее на наборе Pod
'ов, в качестве сетевой службы. С Kubernetes
вам не нужно изменять приложение, чтобы использовать незнакомый механизм обнаружения сервисов. Kubernetes
дает Pod
'ам свои собственные IP-адреса и одно DNS-имя для набора Pod
'ов и может распределять нагрузку между ними.
apiVersion: v1
kind: Service
metadata:
mane: my-service
spec:
ports:
- port: 80 # Порт, на котором сервис слушает запросы
targetPort: 80 # Порт, на котором под принимает запрос
selector: # Запросы будут отправляться на поды с этими метками
app: my-app
type: ClusterIP
Поду будет назначен clusterIP
- случайный IP адрес, по которому слушаются входящие соединения. Также будет создана dns запись в service discovery у kubernetes.
При создании инстанса Service
автоматически создается инстанс Endpoint
, который в себе содержит все внутренние сокеты, на которые нужно отправлять входящие запросы.
Объект API, который управляет внешним доступом к службам в кластере, обычно HTTP. Ingress
может обеспечивать балансировку нагрузки, завершение SSL и виртуальный хостинг на основе имен.
Для добавления данного функционала необходимо установить дополнительное приложение, называемое Ingress Controller
.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: s000005.k8s.slurm.io
http:
paths:
- backend:
serviceName: my-service
servicePort: 80
path: /
PersistentVolumeClaim
(PVC) - это запрос пользователя на хранение. Он похож на Pod
. Pos
'ы потребляют ресурсы узлов, а PVC - PersistentVolume ресурсы. Pod
'ы могут запрашивать определенные уровни ресурсов (ЦП и память). Claim
могут запрашивать определенный размер и режимы доступа (например, они могут быть установлены ReadWriteOnce, ReadOnlyMany или ReadWriteMany, см. AccessModes).
apiVersion: v1
kind: PersistentVolumeClaim
name: my-claim
spec:
accessModes:
- ReadWriteOnce # Эксклюзивный под может читать и писать данные. Может быть ReadWriteMany для множественного доступа.
resources:
requests:
storage: 1Gi
Данные поды запускаются не API
, а kubelet
при запуске. Манифесты лежат в директории /etc/kubernetes/manifest
на каждом узле. Из-за этого изменения в конфигурацию необходимо вносить так же - на каждом узле.
DaemonSet
гарантирует, что все (или некоторые) Node
запускают копию Pod
. По мере добавления Node
в кластер к ним добавляются Pod
'ы. Когда Nod
'ы удаляются из кластера, эти Pod
'ы собираются сборщиком мусора.
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: node-exporter
name: node-exporter
spec:
updateStrategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
containers:
- args:
- --web.listen-address=0.0.0.0:9101
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
- --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/)
- --collector.filesystem.ignored-fs-type=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$
image: quay.io/prometheus/node-exporter:v0.16.0
imagePullPolicy: IfNotPresent
name: node-exporter
volumeMounts:
- mountPath: /host/proc
name: proc
- mountPath: /host/sys
name: sys
- mountPath: /host/root
name: root
readOnly: true
hostNetwork: true # Node Exporter прокидывает сетевое имя узла
hostPid: true # и пространство PID'ов
nodeselector: # DaemonSet могут запускаться только на узлах с перечисленными метками
beta.kubernetes.io/os: linux
securityContext: # Запускаться не от рута
runAsNonRoot: true
runAsUser: 65534
toleations: # Не запускаться на мастер нодах
- effect: NoSchedule
key: node-role.kubernetes.io/master
volumes: # Список томов, монтируются внутрь контейнера
- hostPath:
path: /proc
type: ""
name: proc
- hostPath:
path: /sys
type: ""
name: sys
- hostPath:
path: /
type: ""
name: root
StatefulSet
- это объект API, используемый для управления приложениями с отслеживанием состояния. Управляет развертыванием и масштабированием набора Pod
'ов и предоставляет гарантии порядка и уникальности этих Pod
'ов.
Для запуска манифеста не достаточно одной инструкции, потребуются дополнительные манифесты. Подробнее в официальной документации.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rabbitmq
spec:
serviceName: rabbitmq
replicas: 3
selector:
matchLabels:
app: rabbitmq
template:
metadata:
labels:
app: rabbitmq
spec:
serviceAccountName: rabbitmq
terminationGracePeriodSeconds: 10
containers:
- name: rabbitmq-k8s
image: rabbitmq:3.7
env:
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: RABBITMQ_USE_LONGNAME
value: "true"
- name: RABBITMQ_NODENAME
value: "rabbit@$(MY_POD_IP)"
- name: K8S_SERVICE_NAME
value: "rabbitmq"
- name: RABBITMQ_ERLANG_COOKIE
value: "mycookie"
ports:
- name: amqp
protocol: TCP
containerPort: 5672
livenessProbe:
exec:
command: ["rabbitmqctl", "status"]
initialDelaySeconds: 60
periodSeconds: 60
timeoutSeconds: 15
readinessProbe:
exec:
command: ["rabbitmq", "status"]
initialDelaySeconds: 20
periodSeconds: 60
timeoutSeconds: 10
imagePullPolicy: Always
volumeMounts:
- name: config-volume
mountPath: /etc/rabbitmq
- name: data
mountPath: /var/lib/rabbitmq
volumes:
- name: config-volume
configMap:
name: rabbitmq-config
items:
- key: rabbitmq.conf
path: rabbitmq.conf
- key: enabled_plugins
path: enabled_plugins
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- rabbitmq
topologyKey: kubernetes.io/hostname
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
storageClassName: local-storage
- Позволяет выполнить настройки перед запуском основного приложения.
- Выполняется по порядку описания в манифесте.
- Можно монтировать те же тома, что и в основных контейнерах.
- Можно запускать от другого пользователя.
- Должен выполнить действие и остановиться.
Это сервис типа ClusterIP, у которого в поле .spec.clusterIP
указано значение None
. Этому сервису не назначается IP адрес, вместо этого создаются DNS записи типа А, которые указывают все поды нашего StatefulSet'а. Также создаются отдельные записи с именами подов, которые указывают на конкретные поды, их IP адреса.
Такой подход позволяет реализовать концепцию сбора инстансов базы данных в StatefulSet в какой-то кластер.
- .spec.clusterIP: None.
- Резолвится в IP всех эндпоинтов.
- Создает записи с именами всех эндпоинтов.
---
kind: Service
apiVersion: v1
metadata:
name: rabbitmq
labels:
app: rabbitmq
spec:
clusterIP: None
ports:
- name: amqp
protocol: TCP
port: 5672
targetPort: 5672
selector:
app: rabbitmq
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
rabbitmq ClusterIP None <none> 5672/TCP 18m
$ kubectl get qp
NAME ENDPOINTS AGE
rabbitmq 10.244.1.21:5672,10.244.3.179:5672,10.244.3.180:5672 18m
$ nslookup rabbitmq
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: rabbitmq.default.svc.cluster.local
Address: 10.244.3.180
Name: rabbitmq.default.svc.cluster.local
Address: 10.244.3.179
Name: rabbitmq.default.svc.cluster.local
Address: 10.244.1.21
$ nslookup rabbitmq-0.rabbitmq
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: rabbitmq-0.rabbitmq.default.svc.cluster.local
Address: 10.244.3.179
Задает алгоритм распределения подов между узлами, устанавливает предпочтения для запуска. Бывает 3 видов: podAffinity
, podAntiAffinity
и nodeAffinity
.
nodeAffinity
- на каких узлах должен запускаться под.podAntiAffinity
- позволяет распределить поды на узлах таким образом, чтобы они не сталкивались.
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # Обязательно должна быть выполнена при распределении подов на узлы
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name # Имя зоны доступности. Поды должны запускаться на узлах с данной меткой. Ниже указаны значения метки.
operator: In
values:
- e2e-az1
- e2e-az2
affinity:
nodeAffinity:
preferedDuringSchedulingIgnoredDuringExecution: # По возможности должна быть выполнена при распределении подов на узлы
- weight: 1 # Вес правила. Чем больше вес, тем правило предпочтительнее
preference:
matchExpressions:
- key: another-node-label-key
operator: Exists # Метка должна существовать. Значение метки не важно
Сопротивляемость и зараза. На узлы мы вешаем taint, объявляя его заразным. Scheduler при распределении поды на узлы проверяет, есть ли у пода, который он распределяет, toleration - сопротивляемость той заразе, которая есть на узле. Если пода есть сопротивляемость, то этот под на узле будет запущен.
effect: NoSchedule
- запущенные узлы не будут убиты. Если значение NoExecute
- запущенные узлы будут убиты.
...
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
value: true
...
...
tolerations:
- effect: NoSchedule
operation: Exists
key: node-role.kubernetes.io/master
...
- https://docs.docker.com/storage/volumes/;
- https://docs.docker.com/config/containers/resource_constraints/;
- https://habr.com/ru/company/selectel/blog/279281/;
- https://fabiokung.com/2014/03/13/memory-inside-linux-containers/;
- https://clck.ru/MBtKt - про CI/CD в целом;
- https://docs.docker.com/compose/;
- https://docs.docker.com/compose/gettingstarted/;
- https://docs.gitlab.com/ee/ci/docker/using_docker_build.html;
- https://docs.docker.com/develop/develop-images/baseimages/;
- https://habr.com/ru/company/southbridge/blog/329138/.