скачать книгу бесплатно
–-zone europe-north1-a
Ключ –enable-autorepair запускаем работу мониторинга доступности ноды и в случае её падения – она будет пересоздана. Ключ требует версию Kubernetes не менее 1.11, а на момент написания книги версия по умолчанию 1.10 и поэтому нужно её задать ключом, например, –cluster-version=1.11.4-gke.12. Но можно зафиксировать только мажорную версия –cluster-version=1.11 и установить автообновление версии –enable-autoupgrade. Также зададим авто уверение количества нод, если ресурсов не хватает: –num-nodes=1 –min-nodes=1 –max-nodes=2 –enable-autoscaling.
Теперь поговорим об виртуальный ядрах и оперативной памяти. По умолчанию поднимается машина n1-standart-1, имеющая одно виртуальное ядро и 3.5Gb оперативной памяти, в трёх экземплярах, что совокупно даёт три виртуальных ядра и 10.5Gb оперативной памяти. Важно, чтобы в кластере было всего не менее двух виртуальных ядер процессора, иначе их, формально по лимитам на системные контейнера Kubernetes, не хватит для полноценной работы (могут не подняться контейнера, например, системные). Я возьму две ноды по одному ядру и общее количество ядер будет два. Такая же ситуация и с оперативной памятью, для поднятия контейнера с NGINX мне вполне хватало 1Gb (1024Mb) оперативной памяти, а вот для поднятия контейнера с LAMP (Apache MySQL PHP) уже нет, у меня не поднялся системный сервис kube-dns-548976df6c-mlljx, который отвечает за DNS в поде. Не смотря не то, что он не является жизненно важным и нам не пригодится, в следующий раз может не подняться уж более важный вместо него. При этом важно заметить, что у меня нормально поднимался кластер с 1Gb и было всё нормально, я общий объём в 2Gb оказался пограничным значением. Я задал 1080Mb (1.25Gb), учтя, что минимальная планка оперативной памяти составляет 256Mb (0.25Gb) и мой объём должен быть кратен ей и быть не меньше, для одно ядра, 1Gb. В результате в кластера 2 ядра и 2.5Gb вместо 3 ядре и 10.5Gb, что является существенной оптимизацией ресурсов и цены на платном аккаунте.
Теперь нам нужно подключиться к серверу. Ключ у нас уже есть на сервере ${HOME}/.kube/config и теперь нам нужно просто авторизоваться:
$ gcloud container clusters get-credentials b –zone europe-north1-a –project essch
$ kubectl port-forward Nginxlamp-74c8b5b7f-d2rsg 8080:8080
Forwarding from 127.0.0.1:8080 –> 8080
Forwarding from [::1]:8080 –> 8080
$ google-chrome http://localhost:8080 # это не будет работать в Google Shell
$ kubectl expose Deployment Nginxlamp –type="LoadBalancer" –port=8080
Для локального использования kubectl Вам нужно установить gcloud и с помощью него установить kubectl используя команду gcloud components install kubectl, но пока не будем усложнять первые шаги.
В разделе Сервисы админки будет доступен POD не только через сервис балансировщик front-end, но и через внутренний балансировщик Deployment. Хоть и после пересоздания и сохранится, но конфиг более поддерживаем и очевиден.
Также есть возможность дать возможность регулировать количество нод в автоматическом режиме в зависимости от нагрузки, например, количества контейнеров с установленными требованиями к ресурсам, с помощью ключей –enable-autoscaling –min-nodes=1 –max-nodes=2.
Простой кластер в GCP
Для создания кластера можно пойти двумя путями: через графический интерфейс Google Cloud Platform или через его API командой gcloud. Посмотрим, как это можно сделать через UI. Рядом с меню кликнем на выпадающей список и создадим отдельный проект. В разделе Kubernetes Engine выбираем создать кластер. Дадим название, 2CPU, зону europe-north-1 (дата-центр в Финляндии ближе всего к СПб) и последнюю версию Kubernetes. После создания кластера кликаем на подключиться и выбираем Cloud Shell. Для создания через API по кнопке в правом верхнем углу выведем консольную панель и введём в ней:
gcloud container clusters create mycluster –zone europe-north1-a
Через некоторое время, у меня это заняло две с половиной минуты, будут подняты 3 виртуальные машины, на них установлена операционная система и примонтирован диск. Проверим:
esschtolts@cloudshell:~ (essch)$ gcloud container clusters list –filter=name=mycluster
NAME LOCATION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
mycluster europe-north1-a 35.228.37.100 n1-standard-1 1.10.9-gke.5 3 RUNNING
esschtolts@cloudshell:~ (essch)$ gcloud compute instances list
NAME MACHINE_TYPE EXTERNAL_IP STATUS
gke-mycluster-default-pool-43710ef9-0168 n1-standard-1 35.228.73.217 RUNNING
gke-mycluster-default-pool-43710ef9-39ck n1-standard-1 35.228.75.47 RUNNING
gke-mycluster-default-pool-43710ef9-g76k n1-standard-1 35.228.117.209 RUNNING
Подключимся к виртуальной машине:
esschtolts@cloudshell:~ (essch)$ gcloud projects list
PROJECT_ID NAME PROJECT_NUMBER
agile-aleph-203917 My First Project 546748042692
essch app 283762935665
esschtolts@cloudshell:~ (essch)$ gcloud container clusters get-credentials mycluster \
–-zone europe-north1-a \
–-project essch
Fetching cluster endpoint and auth data.
kubeconfig entry generated for mycluster.
У нас пока нет кластера:
esschtolts@cloudshell:~ (essch)$ kubectl get pods
No resources found.
Создадим кластер:
esschtolts@cloudshell:~ (essch)$ kubectl run Nginx –image=Nginx –replicas=3
deployment.apps "Nginx" created
Проверим его состав:
esschtolts@cloudshell:~ (essch)$ kubectl get deployments –selector=run=Nginx
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
Nginx 3 3 3 3 14s
esschtolts@cloudshell:~ (essch)$ kubectl get pods –selector=run=Nginx
NAME READY STATUS RESTARTS AGE
Nginx-65899c769f-9whdx 1/1 Running 0 43s
Nginx-65899c769f-szwtd 1/1 Running 0 43s
Nginx-65899c769f-zs6g5 1/1 Running 0 43s
Удостоверимся, что все три реплики кластера распределились равномерно на все три ноды:
esschtolts@cloudshell:~ (essch)$ kubectl describe pod Nginx-65899c769f-9whdx | grep Node:
Node: gke-mycluster-default-pool-43710ef9-g76k/10.166.0.5
esschtolts@cloudshell:~ (essch)$ kubectl describe pod Nginx-65899c769f-szwtd | grep Node:
Node: gke-mycluster-default-pool-43710ef9-39ck/10.166.0.4
esschtolts@cloudshell:~ (essch)$ kubectl describe pod Nginx-65899c769f-zs6g5 | grep Node:
Node: gke-mycluster-default-pool-43710ef9-g76k/10.166.0.5
Теперь поставим балансировщик нагрузки:
esschtolts@cloudshell:~ (essch)$ kubectl expose Deployment Nginx –type="LoadBalancer" –port=80
service "Nginx" exposed
Проверим, что он создался:
esschtolts@cloudshell:~ (essch)$ kubectl expose Deployment Nginx –type="LoadBalancer" –port=80
service "Nginx" exposed
esschtolts@cloudshell:~ (essch)$ kubectl get svc –selector=run=Nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
Nginx LoadBalancer 10.27.245.187 pending> 80:31621/TCP 11s
esschtolts@cloudshell:~ (essch)$ sleep 60;
esschtolts@cloudshell:~ (essch)$ kubectl get svc –selector=run=Nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
Nginx LoadBalancer 10.27.245.187 35.228.212.163 80:31621/TCP 1m
Проверим его работу:
esschtolts@cloudshell:~ (essch)$ curl 35.228.212.163:80 2>\dev\null | grep h1
< h1>Welcome to Nginx!< /h1>
Чтобы каждый раз не копировать полные названия – сохраним их в переменных (подробнее о формате JSONpath в документации Go: https://golang.org/pkg/text/template/#pkg-overview):
esschtolts@cloudshell:~ (essch)$ pod1=$(kubectl get pods -o jsonpath={.items[0].metadata.name});
esschtolts@cloudshell:~ (essch)$ pod2=$(kubectl get pods -o jsonpath={.items[1].metadata.name});
esschtolts@cloudshell:~ (essch)$ pod3=$(kubectl get pods -o jsonpath={.items[2].metadata.name});
esschtolts@cloudshell:~ (essch)$ echo $pod1 $pod2 $pod3
Nginx-65899c769f-9whdx Nginx-65899c769f-szwtd Nginx-65899c769f-zs6g5
Изменим страницы в каждом POD, скопировав уникальные страницы в каждую реплику, и проверим балансировку, проверяя распределение запросов по POD:
esschtolts@cloudshell:~ (essch)$ echo 1 > test.html;
esschtolts@cloudshell:~ (essch)$ kubectl cp test.html ${pod1}:/usr/share/Nginx/html/index.html
esschtolts@cloudshell:~ (essch)$ echo 2 > test.html;
esschtolts@cloudshell:~ (essch)$ kubectl cp test.html ${pod2}:/usr/share/Nginx/html/index.html
esschtolts@cloudshell:~ (essch)$ echo 3 > test.html;
esschtolts@cloudshell:~ (essch)$ kubectl cp test.html ${pod3}:/usr/share/Nginx/html/index.html
esschtolts@cloudshell:~ (essch)$ curl 35.228.212.163:80 && curl 35.228.212.163:80 && curl 35.228.212.163:80
3
2
1
esschtolts@cloudshell:~ (essch)$ curl 35.228.212.163:80 && curl 35.228.212.163:80 && curl 35.228.212.163:80
3
1
1
Проверим отказоустойчивость кластера удалением одного POD:
esschtolts@cloudshell:~ (essch)$ kubectl delete pod ${pod1} && kubectl get pods && sleep 10 && kubectl get pods
pod "Nginx-65899c769f-9whdx" deleted
NAME READY STATUS RESTARTS AGE
Nginx-65899c769f-42rd5 0/1 ContainerCreating 0 1s
Nginx-65899c769f-9whdx 0/1 Terminating 0 54m