В прошлой статье я рассказал о том, как установить кластер Kubernetes на свое железо. Сегодня я покажу, как можно с ним работать - запускать различные контейнеры, устанавливать лимиты, регулировать запуск и восстановление и т.д. По сути, опишу быстрый старт и настройку в kubernetes - на конкретных примерах покажу, с чего начинать освоение kubernetes и как его использовать на практике.
На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.
Содержание:
- 1 Цели статьи
- 2 Введение
- 3 Запуск контейнера nginx в kubernetes
- 4 Отказоустойчивость подов с помощью ReplicaSet
- 5 Deployment - деплой в кластер
- 6 Проверки доступности Probes
- 7 Resources - настройка ресурсов
- 8 Монтирование конфигов через ConfigMap
- 9 Проброс порта в pod
- 10 Service - балансировка сети в kubernetes
- 11 Настройка Ingress
- 12 Deploy реального приложения в кластер
- 13 Заключение
Цели статьи
- Рассказать об основных абстракциях в kubernetes.
- На примерах показать, как запускать, управлять контейнерами в кластере.
- Описать механизм отказоустойчивости, реализованный в кубернетис.
- Настроить обработку запросов в кластер из вне и запустить его в работу.
- Задеплоить реальное микросервисное приложение.
Введение
Сразу поделюсь ссылкой на официальную документацию по kubernetes. Она хорошо структурирована и наполнена. Пользоваться ей удобно. С ее помощью настраивать кластер проще. Напоминаю, что мы будем работать с кластером, который установили по предыдущей статье - установка kubernetes. Перед тем, как начать работать с кластером, расскажу об одной полезной возможности. Есть команда:
# kubectl completion bash
Она формирует конфиг для настройки автодополнения команд в bash. Вывод этой команды нужно добавить в ваш ~/.bashrc Можно это сделать автоматически.
# kubectl completion bash >> ~/.bashrc
Чтобы автодополнение работало, нужен пакет bash-completion.
# yum install bash-completion
Запуск контейнера nginx в kubernetes
Начнем с самого простого - создадим один pod, в котором запустим контейнер с последней версией nginx. POD в терминологии kubernetes - это набор контейнеров, объединенных между собой общим linux namespace. Самое важное тут то, что все контейнеры в одном поде связаны между собой сетью в рамках общего localhost. Они не могут использовать один и тот же порт. По сути, кубернетис работает не с докер контейнерами, а именно с подами.
Создаем файл pod-nginx.yaml следующего содержания:
--- apiVersion: v1 kind: Pod metadata: name: pod-nginx spec: containers: - image: nginx:1.16 name: nginx ports: - containerPort: 80
Внимательно следите за пробелами в начале строк. Нужны именно пробелы, а не табуляция. В Yaml файлах очень важна структура. Запускаем получившийся pod.
# kubectl create -f pod-nginx.yaml pod/pod-nginx created
Сразу сделаю пояснение насчет команды create. Вместо нее можно, а чаще всего и нужно, так как удобнее, использовать команду apply. Create создает новую абстракцию. Если вы ее измените и снова создадите с тем же именем, то получите ошибку. Вам придется сначала ее удалить, а потом создать заново. Команда apply сначала проверяет наличие абстракции, в данном случае pod-nginx и если ее нет, то создает. А если она уже есть, то просто перезапускает существующую с новыми параметрами.
Проверяем, что получилось.
# kubectl get pod NAME READY STATUS RESTARTS AGE pod-nginx 1/1 Running 0 2m32s
В настоящий момент мы запустили в кластере kubernetes один контейнер с nginx. Существует команда edit, которая позволяет редактировать сущности кластера kubernetes в режиме реального времени. Применение изменений произойдет сразу же после сохранения изменений. Пример:
# kubectl edit pod pod-nginx
Вы увидите полный конфиг пода, который использует кластер. В нем намного больше информации, нежели в вашем yaml файле.
Удалить созданный pod можно следующей командой:
# kubectl delete pod pod-nginx pod "pod-nginx" deleted
Или сразу все поды:
# kubectl delete pod --all
Отказоустойчивость подов с помощью ReplicaSet
Теперь создадим несколько подов с nginx. Для этого нужно использовать другую абстракцию кубернетис. ReplicaSet следит за количеством подов по шаблону, который мы указываем. В этом шаблоне мы можем указать метку нашего приложения, в моем примере это my-nginx, и количество запущенных реплик.
--- apiVersion: apps/v1 kind: ReplicaSet metadata: name: replicaset-nginx spec: replicas: 2 selector: matchLabels: app: my-nginx template: metadata: labels: app: my-nginx spec: containers: - image: nginx:1.16 name: nginx ports: - containerPort: 80
Запускаем replicaset.
# kubectl apply -f replicaset-nginx.yaml
Проверяем, что получилось.
# kubectl get replicaset NAME DESIRED CURRENT READY AGE replicaset-nginx 2 2 2 18m
Нам нужно было 2 реплики и мы их получили. С помощью edit мы можем на ходу редактировать replicaset, к примеру, добавляя количество реплик.
# kubectl edit replicaset replicaset-nginx
Репликасет сама следит за количеством запущенных подов. Если один из них по какой-то причине упадет или будет удален, она поднимет его заново. Можете проверить это сами, вручную удалив один из подов. Спустя некоторое время он появится снова.
# kubectl get pod NAME READY STATUS RESTARTS AGE pod-nginx 1/1 Running 0 15m replicaset-nginx-f87qf 1/1 Running 0 22m replicaset-nginx-mr4kw 1/1 Running 0 22m # kubectl delete pod replicaset-nginx-f87qf pod "replicaset-nginx-f87qf" deleted # kubectl get replicaset NAME DESIRED CURRENT READY AGE replicaset-nginx 2 2 2 23m # kubectl get pod NAME READY STATUS RESTARTS AGE pod-nginx 1/1 Running 0 16m replicaset-nginx-g4l58 1/1 Running 0 14s replicaset-nginx-mr4kw 1/1 Running 0 23m
Я удалил replicaset-nginx-f87qf, вместо него тут же был запущен новый replicaset-nginx-g4l58. Наглядный пример одного из механизмов отказоустойчивости в кластере kubernetes на уровне подов. Кубернетис будет следить за количеством реплик на основе их label. Если вы через replicaset указали запустить 2 реплики приложения с меткой my-nginx, ни меньше, ни больше подов с этой меткой вы запустить не сможете. Если вы вручную запустите pod с меткой my-nginx, он будет тут же завершен, если у вас уже есть 2 пода с такими метками от replicaset.
Replicaset запускает поды на разных нодах. Проверить это можно, посмотрев расширенную информацию о подах.
# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES replicaset-nginx-cmfnh 1/1 Running 0 2m26s 10.233.67.6 kub-node-1 <none> <none> replicaset-nginx-vgxfl 1/1 Running 0 2m26s 10.233.68.4 kub-node-2 <none> <none>
Таким образом, если у вас одна нода выйдет из строя, кластер автоматически запустит умершие поды на новых нодах. При этом, если нода вернется обратно с запущенными подами на ней, kubernetes автоматически прибьет лишние поды, чтобы их максимальное количество соответствовало информации из шаблона replicaset.
Удаляются replicaset так же как и поды.
# kubectl delete rs replicaset-nginx replicaset.extensions "replicaset-nginx" deleted
Вместо длинного replicaset я использовал сокращение rs. Это бывает удобно для абстракций с длинными названиями. Для всех них кубернетис поддерживает сокращения.
Deployment - деплой в кластер
Переходим к следующей абстракции Kubernetes - Deployment. Они управляют наборами replicaset для непрерывного обновления подов. Покажу на примере, о чем идет речь. Допустим, у вас вышло обновление приложения в новом контейнере. Вам нужно не останавливая сервис выкатить обновление в прод. Если вы измените версию контейнера в шаблоне replicaset, автоматически он у вас не обновится. Да, если pod со старой версией контейнера упадет, новый будет создан уже с новой версией. Но все работающие поды останутся на старой версии.
Deployment как раз и нужен для управления репликасетами, задавая им стратегию обновления. У вас вышла новая версия контейнера, вы заменяете в текущем deployment версию контейнера и он по заранее настроенным правилам начинает перезапуск репликасетов и соответственно подов в них. Покажу на примере nginx, который мы откатим на предыдущую версию. Создаем yaml файл с deployment.
--- apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx spec: replicas: 2 selector: matchLabels: app: my-nginx strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app: my-nginx spec: containers: - image: nginx:1.16 name: nginx ports: - containerPort: 80
Запускаем его.
# kubectl apply -f deployment-nginx.yaml deployment.apps/deployment-nginx created
Смотрим список подов и репликасетов.
# kubectl get pod NAME READY STATUS RESTARTS AGE deployment-nginx-785b6d8d9f-dr4cv 1/1 Running 0 55s deployment-nginx-785b6d8d9f-m47tr 1/1 Running 0 55s # kubectl get rs NAME DESIRED CURRENT READY AGE deployment-nginx-785b6d8d9f 2 2 2 58s
Проверяем версию nginx в одном из подов.
# kubectl describe pod deployment-nginx-785b6d8d9f-dr4cv
Теперь откатимся на предыдущую версию nginx 1.15. Для этого вносим изменения в Deployment.
# kubectl set image deployment deployment-nginx nginx=nginx:1.15
Проверяем список подов и репликасетов.
# kubectl get pod NAME READY STATUS RESTARTS AGE deployment-nginx-68d778658b-fz5lt 1/1 Running 0 11s deployment-nginx-68d778658b-mpkg5 1/1 Running 0 10s [root@kub-master-1 ~]# kubectl get rs NAME DESIRED CURRENT READY AGE deployment-nginx-68d778658b 2 2 2 15s deployment-nginx-785b6d8d9f 0 0 0 5m57s
Название подов и репликасета изменились. Появился новый replicaset, а старый остался с погашенными подами, у него параметр replicas стал 0. Проверяем версию nginx в поде.
# kubectl describe pod deployment-nginx-68d778658b-fz5lt
Версия nginx изменилась во всех подах. Стратегия обновления описана в шаблоне деплоймента в разделе strategy. В данном случае используется тип RollingUpdate, когда deployment постепенно уменьшает количество реплик старой версии и увеличивает реплики новой версии, пока они все не заменят старые. При этом replicaset с предыдущей версией контейнера осталась. Она не удаляется для того, чтобы можно было потом оперативно вернуться на предыдущую версию, если с новой будет что-то не так. Для этого достаточно будет по очереди погасить поды новой replicaset и запустить старые. Делается это следующим образом.
# kubectl rollout undo deployment deployment-nginx deployment.extensions/deployment-nginx rolled back
Проверяем наши replicaset.
# kubectl get rs NAME DESIRED CURRENT READY AGE deployment-nginx-68d778658b 0 0 0 12m deployment-nginx-785b6d8d9f 2 2 2 18m
Видим, что был снова запущен предыдущий replicaset с прошлой версией контейнера. По-умолчанию хранятся 10 версий прошлых replicaset.
Проверки доступности Probes
С деплоем и перезапуском подов не все так просто. Есть тяжелые приложения, которые стартуют очень долго, либо зависят от других приложений. Прежде чем погасить старую версию, нужно убедиться, что новая уже запущена и готова к работе. Для этого существует liveness и readiness проверки. Покажу на примере. Берем предыдущий deployment и добавляем туда проверки.
--- apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx spec: replicas: 2 selector: matchLabels: app: my-nginx strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app: my-nginx spec: containers: - image: nginx:1.16 name: nginx ports: - containerPort: 80 readinessProbe: failureThreshold: 5 httpGet: path: / port: 80 periodSeconds: 10 successThreshold: 2 timeoutSeconds: 3 livenessProbe: failureThreshold: 3 httpGet: path: / port: 80 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 3 initialDelaySeconds: 10
В данном примере используется проверка httpGet по корневому урлу на порт 80.
- readinessProbe проверяет способность приложения начать принимать трафик. Она делает 5 проверок (failureThreshold). Если хотя бы 2 (successThreshold) из них будут удачными, считается, что приложение готово. Метод httpGet проверяет код ответа веб сервера. Если он 200 или 3хх, то считается, что все в порядке. Эта проверка выполняется до тех пор, пока не будет выполнено заданное на успех условие - successThreshold. После этого прекращается.
- livenessProbe выполняется постоянно, следя за приложением во время его жизни. В моем примере проверка будет неудачной, если 3 (failureThreshold) проверки подряд провалились. При этом, если хотя бы одна (successThreshold) будет удачной, то счетчик неудачных сбрасывается. Параметр initialDelaySeconds задает задержку после старта пода для начала liveness проверок.
Вот еще один пример liveness проверки, но уже по наличию файла. Проверяется файл /tmp/healthy, если он существует, проверка удачна, если его нет, то ошибка.
livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5
Создавать этот файл может само приложение во время работы.
Resources - настройка ресурсов
Расскажу, как ограничиваются выделяемые для подов вычислительные ресурсы. Речь идет про CPU и Оперативную память. Задать верхнюю планку использования ресурсов можно с помощью Limits. А с помощью Requests мы можем зарезервировать необходимые ресурсы для пода на ноде. Если в Requests у пода параметры выше, чем есть свободных ресурсов у ноды, то под не сможет приехать на эту ноду.
Важно понимать, что реквесты никак не следят за реальным использованием ресурсов. То есть это просто пожелание к ресурсам ноды, где будет размещаться под. При этом после размещения он сможет занять ресурсов больше, чем указано в Requests. Кластер kubernetes за этим не следит. Если реквесты вообще не указать, то под может приехать на ноду, где свободно очень мало ресурсов, а ему для работы надо больше. В итоге он будет падать. Таким образом, requests используются для планирования ресурсов кластера.
Далее пример деплоймента с указанными параметрами ресурсов. Дополняем предыдущие примеры.
--- apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx spec: replicas: 2 selector: matchLabels: app: my-nginx strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app: my-nginx spec: containers: - image: nginx:1.16 name: nginx ports: - containerPort: 80 readinessProbe: failureThreshold: 5 httpGet: path: / port: 80 periodSeconds: 10 successThreshold: 2 timeoutSeconds: 3 livenessProbe: failureThreshold: 3 httpGet: path: / port: 80 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 3 initialDelaySeconds: 10 resources: requests: cpu: 100m memory: 256Mi limits: cpu: 300m memory: 512Mi
Память выделяется в мегабайтах, а вот CPU в милли cpu, что равно 1/1000 от процессоронго ядра. То есть 1000 миллицпу это одно ядро процессора ноды. Запустим наш deployment и посмотрим на один из подов.
# kubectl describe pod deployment-nginx-79cd6dc79c-rlhtg
Вот они, наши проверки и лимиты с реквестами.
Монтирование конфигов через ConfigMap
Абстракция kubernetes configmap придумана для того, чтобы отвязать конфиги контейнеров docker от deployment, чтобы не раздувать их размер. К примеру, нам нужно во все контейнеры с nginx положить конфиг default.conf. Мы для этого создаем configmap, в нем настраиваем желаемый конфиг и потом подключаем его в deployment. Показываю на примере. Создаем файл configmap.yaml.
--- apiVersion: v1 kind: ConfigMap metadata: name: configmap-nginx data: default.conf: | server { listen 80 default_server; server_name _; default_type text/plain; location / { return 200 '$hostname\n'; } }
В данном случае это простейший конфиг для nginx, который при обращении к серверу будет отдавать 200-й код ответа и имя сервера. Теперь подключаем его к нашему deployment из предыдущих примеров.
--- apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx spec: replicas: 2 selector: matchLabels: app: my-nginx strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app: my-nginx spec: containers: - image: nginx:1.16 name: nginx ports: - containerPort: 80 readinessProbe: failureThreshold: 5 httpGet: path: / port: 80 periodSeconds: 10 successThreshold: 2 timeoutSeconds: 3 livenessProbe: failureThreshold: 3 httpGet: path: / port: 80 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 3 initialDelaySeconds: 10 resources: requests: cpu: 100m memory: 256Mi limits: cpu: 300m memory: 512Mi volumeMounts: - name: config mountPath: /etc/nginx/conf.d/ volumes: - name: config configMap: name: configmap-nginx
Мы создаем монтирование с именем config по пути /etc/nginx/conf.d/ и связываем это монтирование с configmap, который ранее создали. Теперь применяем сначала configmap, а затем deployment.
# kubectl apply -f configmap.yaml configmap/configmap-nginx created # kubectl apply -f deployment-nginx-confmap.yaml deployment.apps/deployment-nginx configured
Проверяем, что получилось. Я подключусь к одному из подов и прочитаю там конфигурацию nginx.
Видим, что применился наш configmap. На втором поде будет то же самое.
Проброс порта в pod
А сейчас пробросим 80-й порт мастера в конкретный под и проверим, что nginx действительно работает в соответствии с установленным конфигом. Делается это следующим обарзом.
# kubectl port-forward deployment-nginx-848cc4c754-w7q9s 80:80 Forwarding from 127.0.0.1:80 -> 80 Forwarding from [::1]:80 -> 80
Перемещаемся в сосeднюю консоль мастера и там проверяем через curl.
# curl localhost:80 deployment-nginx-848cc4c754-w7q9s
Если сделать проброс в другой под и проверить подключение, вы получите в ответ на запрос curl на 80-й порт мастера имя второго пода. На практике, я не знаю, как можно использовать данную возможность. А вот для тестов в самый раз.
Service - балансировка сети в kubernetes
Service в Kubernetes по своей сути это некий балансировщик на уровне L3. С помощью сервисов мы можем попасть в нужные нам поды, обратившись к ним по имени или по ip адресу. Перераспределение запросов идет по алгоритму round-robin. Давайте сделаем сервис к нашему deployment из предыдущих примеров.
--- apiVersion: v1 kind: Service metadata: name: service-nginx spec: ports: - port: 80 targetPort: 80 selector: app: my-nginx type: ClusterIP
Параметр ClusterIP означает, что будет использоваться виртуальная сеть кластера. Доступ к сервису будет доступен только внутри кластера. Извне доступ закрыт. С помощью selector app my-nginx мы привязали сервис к приложению с именем my-nginx, которое мы использовали в предыдущих примерах. Применяем service в кластере.
# kubectl apply -f service.yaml service/service-nginx created
И смотрим, что получилось.
# kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 7d12h service-nginx ClusterIP 10.233.43.79 <none> 80/TCP 29s
Чтобы проверить работу сети в кластере, удобно запустить в нем специальный docker образ, где внутри собраны всякие сетевые утилиты, с помощью которых можно попинговать, посмотреть маршруты и т.д. Можете какой-то свой браз для этого использовать, или воспользоваться готовым - amouat/network-utils. Запустим его напрямую в кластере с параметрами, чтобы он удалился сразу после выхода из него. Ключи здесь такие же как в докере.
# kubectl run -t -i --rm --image amouat/network-utils testnet bash kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead. If you don't see a command prompt, try pressing enter.
Нажимайте enter и попадете в контейнер. А дальше пробуйте пинговать.
После выхода из контейнера, он удалится.
# exit exit Session ended, resume using 'kubectl attach testnet-9d4b6c988-8lmv8 -c testnet -i -t' command when the pod is running deployment.apps "testnet" deleted
Настройка Ingress
Описанные выше сервисы решают задачу взаимодействия внутри кластера kubernetes, но нам нужно еще и c внешними пользователями взаимодействовать. Для этого настроим Ingress, который мы установили ранее в виде отдельной роли на ноде. По своей сути это обычный nginx, который будет получать конфигурацию из yaml файла. Рисуем конфиг для ingress, который будет пробрасывать запросы из вне на сервис service-nginx, который мы создали на предыдущем шаге.
--- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-nginx spec: rules: - host: nginx.cluster.local http: paths: - backend: serviceName: service-nginx servicePort: 80
Загружаем конфиг в кластер кубернетиса.
# kubectl apply -f ingress.yaml ingress.extensions/ingress-nginx configured
Смотрим, что получилось.
# kubectl get ingress -o wide NAME HOSTS ADDRESS PORTS AGE ingress-nginx nginx.cluster.local 10.1.4.39 80 3m20s
10.1.4.39 - ip адрес ноды ingress. В принципе, это сразу же может быть внешний ip, который будет принимать на себя все запросы. Так как это nginx, должно быть безопасно и надежно. На практике, я не знаю, делают ли так, но не вижу каких-то весомых причин в типовых сценариях этого не делать. Чтобы проверить работу ingress, нам надо добавить dns запись.
10.1.4.39 nginx.cluster.local
Я просто в локальный hosts машины добавил и проверил.
Если обновлять страничку, имя пода будет меняться в соответствии с настройкой балансировки. Она выполняется по алгоритму least_conn.
Более подробно настройку ingress контроллера я рассмотрел в отдельной статье.
На этом я прерываюсь и заканчиваю текущее повествование по работе с кластером kubernetes. В таком виде в нем уже можно осмысленно что-то запускать и эксплуатировать. Надеюсь, вам было хоть немного понятно и вы сможете начать экспериментировать с кластером и пытаться на нем запускать какую-то полезную нагрузку. В таком виде он уже пригоден к ограниченной эксплуатации.
Deploy реального приложения в кластер
Давайте теперь на реальном примере попробуем что-то запустить в кластере kubernetes. Я предлагаю для этого использовать демо магазин носков из этого репозитория - https://github.com/microservices-demo/microservices-demo. Там есть длиннющий yaml файл, который содержит в себе все необходимое (deployments, service и т.д.) для запуска магазина. Магазин состоит из множества компонентов, так что мы на практике убедимся, как легко и быстро можно деплоить сложные приложения в кластер.
Магазин настроен на работе в отдельном namespace - sock-shop. Его предварительно надо создать.
# kubectl create namespace sock-shop
Запускаем деплой всего проекта одной командой.
# kubectl apply -n sock-shop -f "https://raw.githubusercontent.com/microservices-demo/microservices-demo/master/deploy/kubernetes/complete-demo.yaml"
Наблюдать за поднятием подов можно командой в реальном времени.
# kubectl get pods -n sock-shop -w
После того, как они все станут Running можно проверять работу. В этом проекте не используется ingress, поэтому чтобы понять, как подключиться к магазину, надо провести небольшое расследование. Для начала посмотрим запущенные service.
# kubectl get service -n sock-shop -o wide
Нас интересует тип NodePort, так как к нему можно подключаться из вне. Видим, что порт используется 30001 и имя приложения front-end. Посмотрим, где оно запущено.
# kubectl get pod -n sock-shop -o wide
Этот pod запущен на kub-node-2. Посмотрим ее ip.
# kubectl get node -o wide
Ее ip адрес - 10.1.4.33. Значит для проверки магазина надо идти по урлу http://10.1.4.33:30001/
Вот он, наш магазин. Для удобства, можем сами доделать доступ через ingress по доменному имени. Настраиваем конфиг ingress.
--- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-sock namespace: sock-shop spec: rules: - host: sock-shop.cluster.local http: paths: - backend: serviceName: front-end servicePort: 80
Не забывайте указывать нужный namespace и правильное имя сервиса, для которого настраиваем ingress. Применяем конфиг.
# kubectl apply -f ingress-sock.yaml
Смотрим, что получилось.
# kubectl get ingress -n sock-shop -o wide NAME HOSTS ADDRESS PORTS AGE ingress-sock sock-shop.cluster.local 10.1.4.39 80 29s
Редактируем файл hosts и идем в браузер проверять.
Поздравляю, ваш кластер работает, а вы теперь администратор кластера Kubernetes и инженер yaml файлов :) У вас теперь будет большая дружба с лапшеподобным синтаксисом. Идите к руководству и требуйе прибавки к зарплате минимум на 30%.
Заключение
Я рассмотрел основные абстракции kubernetes, которые нужны для того, чтобы на нем хоть что-то запустить и начать работать. Кластер в таком виде уже способен принимать запросы из вне. Для полноты картины не хватает одного объемного раздела - фаловые хранилища. Эта отдельная большая тема, поэтому я решил ее не затрагивать здесь, а вынести в отдельную статью, которая будет следующей в этом цикле. В таком виде, как описано здесь, используются локальные диски нод кластера, где запущены контейнеры docker.
Если вам подходит такой формат работы - пользуйтесь. По большому счету, он вполне жизнеспособен, если у вас все полезные данные, к примеру, хранятся в самих контейнерах в реджистри и в базе данных, которая работает не в кластере, а медиаконтент на внешних CDN. В таком случае kubernetes будет работать как масштабируемый вычислительный кластер.
Для автоматического деплоя приложений в кластер k8s можно использовать helm. Я рассмотрел этот вопрос в отдельной статье - Работа с Helm 3 в Kubernetes.
Напоминаю, что подробно, с примерами и практическими заданиями изучить кластер kubernetes можно на обучении Слёрм, которое я прошел лично и могу рекомендовать, как хороший и эффективный курс.
Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном онлайн-курcе по администрированию MikroTik. Автор курcа – сертифицированный тренер MikroTik Дмитрий Скоромнов. Более 40 лабораторных работ по которым дается обратная связь. В три раза больше информации, чем в MTCNA.
Огромное спасибо за статью! Все очень сжато, четко и понятно, с показательными примерами! Очень круто!
Добрый день!
А как получить доступ в к сервисам снаружи?
Использую type=NodePort и IngressController, но что-то не хочет . . .
Про пробы описаны не правильно
Один момент. Readiness проба исполняется всё время работы пода, а не завершается.
Коллеги, в статье не нашел информации. А как дать доступ для Jenkins? В Yutube вижу подключают secret file, беря в качестве него config. А как обстоит дело в случае kubespray?
Если не ошибаюсь, все необходимое для подключения к кластеру есть в директории /etc/kubernetes/ мастера, с которого была установка. С именем директории могу ошибаться, но она точно в /etc. Там и конфиги и сертификаты для подключения. Точно проверить нет кластера под рукой. Это что касается доступу к кластеру. Как именно jenkins к нему подключать, не знаю. Да и что значит дать доступ для Jenkins? Он что должен в кластере делать? Деплоить приложения?
Спасибо.
>Да и что значит дать доступ для Jenkins? Он что должен в кластере делать? Деплоить приложения?
Именно.
Спасибо за цикл статей про k8s. Пользовался ими при настройке кластера. Есть один вопрос, который пока не удается решить. Может здесь кто подскажет.
Каким образом передать свой домен в контейнер кубера, при деплое пода чтобы в файле /etc/hosts была запись типа такой:
1.2.3.4 test.domain.com test
Сейчас домен автоматом дописывает сам кубер, /etc/hosts:
ip пода test.default-subdomain.default.svc.cluster.local test
Если использовать инструкцию:
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
hostname: test
subdomain: default-subdomain
hostAliases:
- ip: «1.2.3.4»
hostnames:
- «test.domain.com»
- «test»
containers:
...
То запись добавляется снизу и при выполнении в контейнере команды hostname -f выдаётся запись test.default-subdomain.default.svc.cluster.local а нужно что бы test.domain.com
Спасибо автору за проделанную работу.
Только у меня ingress-nginx почему-то с пустым IP адресом?
# kubectl get ingress -o wide
NAME HOSTS ADDRESS PORTS AGE
ingress-nginx nginx.cluster.local 80 52m
и сервис не обслуживается:
# curl kub-ingress-1.cluster.local
curl: (7) Failed connect to kub-ingress-1.cluster.local:80; Connection refused
Оказывается у меня почему-то отсутствует ingress-nginx-controller-xxxx как и сам ingress-nginx namespace.
kube-system coredns-85578f88b8-6rmcm 1/1 Running 0 95s
kube-system coredns-85578f88b8-h9mjr 1/1 Running 0 105s
kube-system dns-autoscaler-7d4cfd5f55-cf2hs 1/1 Running 1 27h
kube-system kube-apiserver-kub-master-1 1/1 Running 224 2d1h
kube-system kube-apiserver-kub-master-2 1/1 Running 3 47h
kube-system kube-apiserver-kub-master-3 1/1 Running 3 47h
kube-system kube-controller-manager-kub-master-1 1/1 Running 0 2d1h
kube-system kube-controller-manager-kub-master-2 1/1 Running 0 47h
kube-system kube-controller-manager-kub-master-3 1/1 Running 0 47h
kube-system kube-flannel-8vr5f 2/2 Running 3 27h
kube-system kube-flannel-b6ktv 2/2 Running 3 27h
kube-system kube-flannel-bnm7s 2/2 Running 3 27h
kube-system kube-flannel-kstqb 2/2 Running 3 27h
kube-system kube-flannel-r57jz 2/2 Running 2 27h
kube-system kube-flannel-wfjrn 2/2 Running 10 27h
kube-system kube-proxy-ch5kc 1/1 Running 0 3m50s
kube-system kube-proxy-ct9b6 1/1 Running 0 3m50s
kube-system kube-proxy-dz7ck 1/1 Running 0 3m50s
kube-system kube-proxy-kkdnd 1/1 Running 0 3m50s
kube-system kube-proxy-rtnth 1/1 Running 0 3m50s
kube-system kube-proxy-zs8cd 1/1 Running 0 3m50s
kube-system kube-scheduler-kub-master-1 1/1 Running 0 2d1h
kube-system kube-scheduler-kub-master-2 1/1 Running 0 47h
kube-system kube-scheduler-kub-master-3 1/1 Running 0 47h
kube-system kubernetes-dashboard-556b9ff8f8-4dtt9 1/1 Running 1 27h
kube-system nginx-proxy-kub-ingress-1 1/1 Running 3 27h
kube-system nginx-proxy-kub-node-1 1/1 Running 1 27h
kube-system nginx-proxy-kub-node-2 1/1 Running 1 27h
kube-system nodelocaldns-26fws 1/1 Running 1 27h
kube-system nodelocaldns-44n9h 1/1 Running 1 27h
kube-system nodelocaldns-5pjst 1/1 Running 3 27h
kube-system nodelocaldns-7k6nq 1/1 Running 1 27h
kube-system nodelocaldns-9xj9k 1/1 Running 1 27h
kube-system nodelocaldns-dw2ll 1/1 Running 1 27h
Странно то, что деплой прошел без ошибок даже после повторного запуска...
kub-ingress-1 : ok=322 changed=10 unreachable=0 failed=0 skipped=531 rescued=0 ignored=0
kub-master-1 : ok=494 changed=29 unreachable=0 failed=0 skipped=976 rescued=0 ignored=0
kub-master-2 : ok=428 changed=26 unreachable=0 failed=0 skipped=847 rescued=0 ignored=0
kub-master-3 : ok=430 changed=26 unreachable=0 failed=0 skipped=845 rescued=0 ignored=0
kub-node-1 : ok=320 changed=10 unreachable=0 failed=0 skipped=535 rescued=0 ignored=0
kub-node-2 : ok=320 changed=10 unreachable=0 failed=0 skipped=533 rescued=0 ignored=0
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Friday 10 April 2020 13:32:12 +0000 (0:00:00.388) 0:17:06.491 **********
Кто-нибудь подскажет как это исправить?..
Ingress Controller можно отдельно установить через тот же Helm, если не ошибаюсь. Давно уже не занимался этим, подзабыл.
Не в обиду автору гайда, но если устанавливать по видео 09. Kubespray. Установка кластера. Вечерняя школа Слёрма по Kubernetes с youtube то ingress устанавливается нормально.
Большое спасибо! Подчеркнул для себя некоторые моменты. Очень хорошо, что начали статьи по девопс.
Будут еще, есть наработки. Очень хочу про ci/cd написать, но по времени очень затратно. Не получается дописать и оформить статью.
Отличная статья! Спасибо вам большое:)
Замечательный мануал, помогли разложить все по полочкам, спасибо большое! Удивлен что здесь нет ни одного комментария!
Тема очень узкая и не популярная. Писать статьи трудно и долго, а смысла особо нет. Доведу цикл до логического конца, написав еще несколько статей и закончу. Проще про настройки сети в ubuntu, centos писать :)
Уверент что через год эту статью зачитают до дыр! ) Все только начинается!
Посмотрим. Кубер все-таки не массовый продукт. Плюс, активно форсят облака эту услугу. Не думаю, что много людей будут свои кластеры поднимать и поддерживать сами. Возможно разрабы без девопсов будут какие-то миникубы поднимать себе и учиться с ним работать.