Thank you for reading this post, don't forget to subscribe!
Kubernetes
предусматривает управление несколькими экземплярами (репликами) контейнеров. На сегодняшний день существует несколько способов организации репликации - в данной статье мы рассмотрим три варианта: Replication Controllers
, Replica Sets
и Deployments
.
Прежде всего, нужно знать зачем нужна репликация контейнеров в кластере Kubernetes
. Чаще всего, это нужно для:
- надежности. C несколькими экземплярами приложения вы избавляетесь от проблем в случае отказа одного (или нескольких) из них;
- балансировки. Наличие нескольких экземпляров приложения позволяет распределять траффик между ними, предотвращая перегрузку одного инстанса (под / контейнер) или ноды;
- масштабирования. При возрастающей нагрузке на уже существующие экземпляры приложения
Kubernetes
позволяет легко увеличивать количество реплик по необходимости.
Репликация также хорошо подходит в случае работы с микросервисами, облачными (cloud-native) и мобильными приложениями.
Replication Controller
- традиционный (изначальный) способ организации репликации в кластере Kubernetes
. В данный момент он заменяется более “свежим” вариантом - Replica Sets
, но не будет лишним понять, что это и как работает.
С помощью объекта Replication Controller
можно создать несколько экземпляров подов и отслеживать их состояние. Если один (или несколько) подов завершаются с ошибкой, то контроллер создаст и запустит новый экземпляр (чтобы количество подов всегда соответствовало желаемому). Кроме того, Replication Controller
предоставляет возможность масштабирования подов.
Создадим файл rc.yaml
следующего содержания:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
apiVersion: v1 kind: ReplicationController metadata: name: testrc spec: replicas: 3 selector: app: testrc template: metadata: name: testrc labels: app: testrc spec: containers: - name: testrc image: ealebed/test ports: - containerPort: 80 |
Далее создадим объект Replication Controller
в кластере на основе описания выше:
1 2 3 |
<strong>kubectl create <span class="hljs-_">-f</span> rc.yaml</strong> replicationcontroller <span class="hljs-string">"testrc"</span> created |
Получим детальное описание созданного объекта:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<strong>kubectl describe rc testrc</strong> Name: testrc Namespace: default Image(s): ealebed/<span class="hljs-built_in">test</span> Selector: app=testrc Labels: app=testrc Replicas: 3 current / 3 desired Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed No volumes. Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------------- ------- 1m 1m 1 {replication-controller } Normal SuccessfulCreate Created pod: testrc-g5snq 1m 1m 1 {replication-controller } Normal SuccessfulCreate Created pod: testrc-cws05 1m 1m 1 {replication-controller } Normal SuccessfulCreate Created pod: testrc-ro2bl |
Как видно, все три реплики запущены (ожидаемо). Увидеть состояние подов можно с помощью команды:
1 2 3 4 5 6 |
<strong>kubectl get pods</strong> NAME READY STATUS RESTARTS AGE testrc-cws05 1/1 Running 0 3m testrc-g5snq 1/1 Running 0 3m testrc-ro2bl 1/1 Running 0 3m |
Перед рассмотрением Replica Sets
“убираем” за собой:
1 2 |
<strong><code class="language-bash hljs">kubectl delete rc testrc </code></strong> |
Как мы уже ранее говорили, Replica Sets
- это более современная версия все того же Replication Controller
, которая отличается поддержкой множественного выбора в селекторе. Создадим файл rs.yaml
с таким содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
apiVersion: extensions/v1beta1 kind: ReplicaSet metadata: name: testrs spec: replicas: 3 selector: matchLabels: app: testrs template: metadata: labels: app: testrs environment: dev spec: containers: - name: testrs image: ealebed/test ports: - containerPort: 80 |
Здесь все практически то же самое, что и в описании Replication Controller
, за исключением того, что мы используем matchLabels
. Но можно пойти дальше и заменить секцию matchLabels
на такую:
1 2 3 4 |
matchExpressions: - {key: app, operator: In, values: [testrs, test]} - {key: tier, operator: NotIn, values: [production]} |
Создаем объект в кластере командой:
1 2 3 |
<strong>kubectl create <span class="hljs-_">-f</span> rs.yaml</strong> replicaset <span class="hljs-string">"testrs"</span> created |
Смотрим описание:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<strong>kubectl describe rs testrs</strong> Name: testrs Namespace: default Image(s): ealebed/<span class="hljs-built_in">test</span> Selector: app <span class="hljs-keyword">in</span> (<span class="hljs-built_in">test</span>,testrs),tier notin (production) Labels: app=testrs Replicas: 3 current / 3 desired Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed No volumes. Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------------- ------- 1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: testrs-it2hf 1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: testrs-kimmm 1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: testrs-8i4ra |
1 2 3 4 5 6 |
<strong>kubectl get pods</strong> NAME READY STATUS RESTARTS AGE testrs-8i4ra 1/1 Running 0 1m testrs-it2hf 1/1 Running 0 1m testrs-kimmm 1/1 Running 0 1m |
Как видим, Replica Sets
действительно очень похожа не Replication Controller
. Еще одно важное отличие, о котором мы не упомянули - команда rolling-update
будет работать для Replication Controller
, но не для Replica Sets
.
“Убираем” за собой:
1 2 3 |
<strong>kubectl delete rs testrs</strong> replicaset <span class="hljs-string">"testrs"</span> deleted |
Вариант репликации подов с использованием объекта Deployment
- еще более высокий уровень абстракции. На самом деле, под капотом, Deployment
будет самостоятельно создавать необходимые Replica Sets
(следовательно, предоставлять тот же функционал, но с возможностью rolling-update
/rollback
).
Создадим файл deployment.yaml
следующего содержания:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: test spec: replicas: 5 template: metadata: labels: app: test spec: containers: - name: test image: ealebed/test ports: - containerPort: 80 |
Запускаем объект в кластере:
1 2 3 |
<strong>kubectl create <span class="hljs-_">-f</span> deployment.yaml</strong> deployment <span class="hljs-string">"test"</span> created |
Просмотр деталей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<strong>kubectl describe deployment <span class="hljs-built_in">test</span></strong> Name: <span class="hljs-built_in">test</span> Namespace: default CreationTimestamp: Mon, 03 Sep 2018 13:21:19 +0000 Labels: app=<span class="hljs-built_in">test</span> Selector: app=<span class="hljs-built_in">test</span> Replicas: 5 updated | 5 total | 5 available | 0 unavailable StrategyType: RollingUpdate M<span class="hljs-keyword">in</span>ReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge OldReplicaSets: <none> NewReplicaSet: <span class="hljs-built_in">test</span>-3914185155 (5/5 replicas created) Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------------- ------- 38s 38s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica <span class="hljs-built_in">set</span> <span class="hljs-built_in">test</span>-3914185155 to 3 36s 36s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica <span class="hljs-built_in">set</span> <span class="hljs-built_in">test</span>-3914185155 to 5 |
1 2 3 4 5 6 7 |
<strong>kubectl get pods</strong> NAME READY STATUS RESTARTS AGE <span class="hljs-built_in">test</span>-3914185155-7gyja 1/1 Running 0 2m <span class="hljs-built_in">test</span>-3914185155-lrm20 1/1 Running 0 2m <span class="hljs-built_in">test</span>-3914185155-o28px 1/1 Running 0 2m <span class="hljs-built_in">test</span>-3914185155-ojzn8 1/1 Running 0 2m <span class="hljs-built_in">test</span>-3914185155-r2pt7 1/1 Running 0 2m |