Все уроки переехали в: Курс обучения DevOps
Посмотреть видео: https://youtu.be/klmpiHLSuXA
Kubernetes содержит набор независимых, объединённых вместе процессов управления, которые постоянно стараются привести текущее состояние контейнеризированного приложения к заданному состоянию
основываясь на декларативном подходе: когда мы описываем требуемое состояние (декларируем), а не действия, которые надо предпринять, и неважно, как добраться от А до С, K8s сделает это за вас
Целевая область деятельности Kubernetes - это автоматизации развёртывания контейнезированных приложений, их масштабирования и координации в условиях кластера (группа компьютеров, объединённых высокоскоростными каналами связи, представляющая с точки зрения пользователя единый аппаратный ресурс)
Это делает выполнение приложений более простым в использовании, более мощным, надежным, устойчивым и расширяемым:
- при правильной настройке гарантирует отсутствие простоев
- упрощает наблюдаемость (мониторинг, логирование и тд)
- позволяет обеспечить автоматическое распределение нагрузки на имеющихся ресурсах в зависимости от требований
- автоматизированные развертывание (деплой сервисов), откаты при ошибках
- самоконтроль, перезапустит упавшие контейнеры, проверит что контейнеры работают как "нужно" и многое другое
Kubernetes кластер - объединение виртуальных (или нет) машин worker node
(на которых будут работать наши контейнеры), управляемых несколькими master node
Составляющие master node (управляющий уровень)
https://kubernetes.io/ru/docs/concepts/overview/components/#плоскость-управления-компонентами
kube-apiserver
- клиентская часть панели управления Kubernetesetcd
- высоконадёжное хранилище данных в формате "ключ-значение", основное хранилище всех данных кластера в Kuberneteskube-scheduler
- отслеживает созданные поды без привязанного узла и выбирает узел, на котором они должны работатьkube-controller-manager
- уведомляет и реагирует на сбои node, поддерживает правильное количество pod для каждого объекта контроллера репликации в системе, связывает Services и Pods, создает стандартные учетные записи и токены доступа API для новых namespace
Составляющие worker node (исполнительный уровень)
https://kubernetes.io/ru/docs/concepts/overview/components/#компоненты-узла
kubelet
- агент который следит за тем, чтобы контейнеры были запущены в подеkube-proxy
- конфигурирует правила сети на узлах (service), при помощи которых разрешаются сетевые подключения к вашими подам изнутри и снаружи кластераСреда выполнения контейнера
- это программа, предназначенная для выполнения контейнеров (Docker, containerd, CRI-O) CRI-O - Это альтернатива containerd, которая также позволяет загружать образы контейнеров из репозиториев, управлять ими и запускать Container Runtime нижнего уровня для запуска процессов контейнераDocker — это лишь часть всей экосистемы контейнеров. Существуют открытые стандарты: CRI и OCI, и несколько Container Runtime с поддержкой CRI: containerd, runc, CRI-O и, конечно, сам Docker
Kubernetes использует объекты в формате YAML для представления состояния кластера. Описание требуемого состояния объектов называется манифестом
Почти в каждом объекте Kubernetes есть два вложенных поля-объекта, которые управляют конфигурацией объекта:
spec
- требуемое состояние (описание характеристик, которые должны быть у объекта)status
- текущее состояние
https://kubernetes.io/ru/docs/concepts/overview/working-with-objects/kubernetes-objects/
Namespace (пространство имен) - виртуальные кластера в одном физическом кластере Kubernetes
Нужны чтобы отделять группы обьектов (контейнеров и их сетевые или любые другие настройки) в одном кластере
Имена ресурсов должны быть уникальными в пределах одного и того же namespace
apiVersion: v1
kind: Namespace
metadata:
name: <insert-namespace-name-here> # имя namespace
labels
(лейблы, метки, этикетки) - используются для идентификации и выбора группы объектов. Рекомендуемые лейблы: https://kubernetes.io/ru/docs/concepts/overview/working-with-objects/common-labels/annotations
(аннотации) похожи на лейблы, но не используются для идентификации и выбора объектов https://kubernetes.io/ru/docs/concepts/overview/working-with-objects/annotations/
Pod - один или несколько контейнеров с общим хранилищем и сетевыми ресурсами
В pod описана спецификация для запуска контейнеров:
- на каких node запускать, например только на linux
- какой командой запускать приложение в контейнере
- сколько ресурсов CPU или RAM давать контейнеру
- как проверять готовность приложения и тд.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine-slim
ports:
- containerPort: 80
У каждого pod есть внутри кластера IP адрес по которому pod могут обращаться друг к другу, а выдачей IP адрессов занимается kube-controller-manager
который присваивает каждой node podCIDR (192.0.2.0/24 – это адрес CIDR версии IPv4, где первые 24 бита, или 192.0.2, – это сетевой адрес). Pod'ы каждого узла получают IP-адреса из пространства адресов в выделенном диапазоне podCIDR. Поскольку podCIDR'ы узлов не пересекаются, все pod'ы получают уникальные IP-адреса
pod, обычно, создаются с использованием других ресурсов которые описаны ниже
Deployment - контролирует обновления ReplicaSet который является набором pod
Deployment создает ReplicaSet
, который в свою очередь создает набор одинаковых pod и работает с ними, как с единой сущностью. Поддерживает нужное количество реплик, при необходимости создавая новые pod или убивая старые
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: nginx
app.kubernetes.io/version: latest
app.kubernetes.io/component: nginx
annotations:
imageregistry: "https://hub.docker.com/"
spec:
replicas: 3 # можно удалить если используем HPA который сам будет следить за числом реплик (описание и пример ниже)
selector:
matchLabels:
app.kubernetes.io/name: nginx
template:
metadata:
labels:
app.kubernetes.io/name: nginx
spec:
affinity:
podAntiAffinity: # анти зависимость чтобы реплики pod разъехались по разным node
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- nginx # создавать на node где нет pod с лейблом app.kubernetes.io/name: nginx-deployment
topologyKey: "topology.kubernetes.io/zone" # стараться размещать pod в разных зонах доступности
terminationGracePeriodSeconds: 30 # после отправки приложению сигнала 'Заверши работу' даем ему 30 сек закончить свою работу и умереть, иначе убиваем
containers:
- name: nginx
image: nginx:1.25-alpine-slim
ports:
- name: http
containerPort: 8080
resources:
requests: # запросы ресурсов по которым kube-scheduler ищет на какую node разместить pod
memory: "150Mi"
cpu: "250m"
limits:
memory: "150Mi" # если приложение попытается использовать больше памяти, Kubernetes убьет его
cpu: "500m" # если приложение попытается использовать больше ресурсов CPU поставит его в очередь xD
livenessProbe: # проверяет 'живо ли приложение' и если нет, перезапускает его
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe: # проверяет 'может ли приложение принимать запросы'
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 5
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
StatefulSet - в отличии от Deployment не создает ReplicaSet, а сам контролирует, обновляет и создает набор pod
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: postgres
app.kubernetes.io/version: 14.7-alpine
app.kubernetes.io/component: postgres
spec:
selector:
matchLabels:
app: postgress # должно совпадать с .spec.template.metadata.labels
serviceName: "postgres"
replicas: 3
template:
metadata:
labels:
app: postgres # должно совпадать с .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 30
containers:
- name: postgres
image: postgres:14.7-alpine
ports:
- containerPort: 5432
name: dbport
volumeMounts:
- name: default-database
mountPath: /usr/share/postgres/database
volumeClaimTemplates:
- metadata:
name: default-database
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class-name"
resources:
requests:
storage: 5Gi
https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
DaemonSet - гарантирует, что все (или некоторые) node имеют копию pod (используют обычно для мониторинга или сбора логов)
Ниже пример запуска Fluentd
который будет собирать логи контейнеров (и не только) и отправлять их в централизованный Elasticsearch
для дальнейшего хранения, обработки и просмотра
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: fluentd
app.kubernetes.io/version: v1-debian-elasticsearch
app.kubernetes.io/component: fluentd
spec:
selector:
matchLabels:
app.kubernetes.io/name: fluentd # должно совпадать с .spec.template.metadata.labels (ниже)
template:
metadata:
labels:
app.kubernetes.io/name: fluentd # должно совпадать с .spec.selector.matchLabels (выше)
spec:
tolerations:
# Эти tolerations (допуски) предназначены для того, чтобы набор демонов (pod) мог выполняться на master node
# Если мы не хотим запускать демонов (pod) на master node, то нужно удалить tolerations
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.monitoring" # имя service и namespace в которых установлен Elasticsearch
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200" # порт Elasticsearch service на который отправлять логи
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http" # по какому протоколу отправлять логи в Elasticsearch
resources:
limits:
cpu: 250m
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
Job - задание, запуск pod для выполнения единоразовой задачи, например резервное сохранение данных перед обновлением
apiVersion: batch/v1
kind: Job
metadata:
name: busybox-sleep
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: busybox
app.kubernetes.io/version: 1.36.0
app.kubernetes.io/component: busybox
spec:
ttlSecondsAfterFinished: 300 # автоматически удалить Job после ее завершения через 300 сек
template:
spec:
containers:
- name: busybox
image: busybox:1.36.0
command: ["/bin/sleep", "10"] # спать 10 секунд, а потом завершить работу
restartPolicy: Never # при ошибке не перезапускать
backoffLimit: 4 # количество повторных попыток прежде чем job упадет
https://kubernetes.io/docs/concepts/workloads/controllers/job/
CronJob - задание по расписанию, то же что и Job только по расписанию
apiVersion: batch/v1
kind: CronJob
metadata:
name: busybox-date
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: busybox
app.kubernetes.io/version: 1.36.0
app.kubernetes.io/component: busybox
spec:
schedule: "* * * * *" # расписание, в данном случае каждую минуту https://crontab.guru/
jobTemplate:
spec:
template:
spec:
containers:
- name: busybox
image: busybox:1.36.0
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure # попробовать еще раз если Job упадет
https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
HorizontalPodAutoscaler - автоматическое увеличение или уменьшение количества реплик приложения
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler # автоматическое увеличение или уменьшение количества реплик приложения
metadata:
name: nginx
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: nginx
app.kubernetes.io/version: 1.24-alpine-slim
app.kubernetes.io/component: nginx
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
minReplicas: 3
maxReplicas: 12
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
Service - для связи приложений внутри кластера, является DNS именем которым объединён набор pod (используя лейблы на pod)
apiVersion: v1
kind: Service
metadata:
name: nginx # одно DNS имя которым объединён набор pod (используя лейблы на pod в selector ниже)
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: nginx
app.kubernetes.io/version: 1.24-alpine-slim
app.kubernetes.io/component: nginx
spec:
selector:
app.kubernetes.io/name: nginx # выбирает pod по лейблу
ports:
- protocol: TCP
port: 80
targetPort: http
https://kubernetes.io/docs/concepts/services-networking/service/
Ingress - для внешнего доступа (из интернета, сети офиса и тд) к приложениям в кластере
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: nginx
app.kubernetes.io/version: 1.24-alpine-slim
app.kubernetes.io/component: nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-external
rules:
- http:
paths:
- path: /api/v1
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
https://kubernetes.io/docs/concepts/services-networking/ingress/
PersistentVolume - запрос пользователя на хранилище данных (виртуальный диск для pod)
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: postgres
app.kubernetes.io/version: 14.7-alpine
app.kubernetes.io/component: postgres
spec:
capacity:
storage: 5Gi # объем запрашиваемого диска
accessModes:
- ReadWriteOnce # режим доступа который разрешает нескольким pod получать доступ к pvc, когда pod запущены на одной node
storageClassName: postgres-ssd # имя объекта 'storageClass' который хранит параметры подключения к системе хранения данных (дисковым массивам и тд)
https://kubernetes.io/docs/concepts/storage/persistent-volumes/
ConfigMap - если нам нужно хранить какие-то данные в виде текстового файла
По возможности лучше настраивать приложение через переменные среды в env
как в примере с Deployment выше (это просто удобнее), а ConfigMap использовать если нужно настроить что-то сложное или приложение умеет работать только с конфигурационным файлом
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configmap # имя конфигмапа по которому мы будем его добавлять в pod
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: nginx
app.kubernetes.io/version: 1.24-alpine-slim
app.kubernetes.io/component: nginx
data:
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
https://kubernetes.io/docs/concepts/configuration/configmap/
Secret - небольшой объем конфиденциальных данных, таких как пароль, токен или ключ
Нужен чтобы удобно хранить секретные данные внутри Kubernetes, пароли, логины, номера счетов и тд.
apiVersion: v1
kind: Secret
metadata:
name: nginx # имя секрета по которому мы его будем подключать в наши pod
labels: # используются для идентификации и выбора объектов
app.kubernetes.io/name: nginx
app.kubernetes.io/version: 1.24-alpine-slim
app.kubernetes.io/component: nginx
type: Opaque # тип: произвольные пользовательские данные (все типы https://kubernetes.io/docs/concepts/configuration/secret/#secret-types )
data:
USER_NAME: aDm1n
PASSWORD: myStr0ngPa5SworD
Как легко пройти собеседование по k8s: https://habr.com/ru/companies/southbridge/articles/713884/