Как поднять кластер kubernetes

Как поднять кластер kubernetes Хостинг

Сегодня открываю новый цикл статей, которые будут иметь непосредственное отношение к Devops и всему, что с этим связано. Начну с того, что расскажу, как установить и запустить кластер Kubernetes на собственном железе. Буду использовать установку через Kubespray с использованием ingress контроллера в кластере.

Цели статьи

Хочу сразу обратить внимание на важный момент. У меня нет опыта промышленной эксплуатации кластера Kubernetes. Я нахожусь в состоянии обучения и исследования этого инструмента. Я прошел обучение Слёрм, это дало базовые знания и понимание принципов работы. Дальше стал разворачивать свои кластера и исследовать их. Изначально я не хотел писать статьи по этой теме до тех пор, пока не накопится достаточного опыта, но сейчас поменял свое мнение.

В рунете очень мало материалов по kubernetes с конкретикой и практикой, по которым можно было бы учиться. Думаю, что даже те знания, что есть сейчас у меня, будут многим полезны и интересны. Плюс, когда пишешь статьи, систематизируешь свои знания, запоминаешь и получаешь обратную связь. Ускоряется процесс обучения. Так что статьям по kubernetes и devops в целом быть. Думаю, что в ближайшее время я сфокусируюсь именно на этом.

Могу однозначно сказать, что если у вас есть необходимость в продакшене использовать Kubernetes, не тяните время и не откладывайте. Идите учиться на курсы. Самостоятельно вы не освоите в достаточном объеме материал, чтобы можно было переносить рабочую нагрузку в свой кластер. Очень много нюансов и подводных камней. Вы потратите больше времени, нервов и денег на самостоятельное освоение, если будете сами все с нуля изучать.

Лично у меня сейчас нет цели становиться администратором Kubernetes. Мой формат занятости не подразумевает обслуживание таких крупных систем и в планах этого тоже пока нет. Мне просто любопытно его исследовать, узнавать что-то новое, поэтому я этим занимаюсь. Знания карман не тянут, особенно современные и востребованные.

Если у вас нет возможности или желания настраивать кластер Kubernetes самостоятельно на своем железе, можете купить его в готовом виде как сервис в облаке Mail.ru Cloud Solutions.

Kubernetes простыми словами

Попробую рассказать своими словами, что такое кластер Kubernetes для чайников, без отсылок к описаниям и документации. По своей сути это кластер для обслуживания docker контейнеров. Я слышал, что он может управлять не только докером, но практически ничего про это не знаю. Все в основном используют Kubernetes в связке с Docker.

В Kubernetes все крутится вокруг докер контейнеров. Это инструмент для их запуска, поднятия в случае падения, распределения ресурсов и т.д. Под капотом никакой магии. Там обычный docker, iptables, etcd, nat, dns, ceph, nfs и т.д. Просто все собрано в одном месте для решения конкретных задач. Таким образом, для эффективного управления кластером кубера нужен хороший бэкграунд классического linux админа. Без этих знаний будет трудно.

Есть много способов разворачивания кластера, так как он модульный. Не всем и не всегда нужны все его компоненты. К примеру, есть ingress контроллер для распределения входящих запросов по сервисам. Под капотом там обычный nginx в режиме proxy_pass, интегрированный в инфраструктуру кластера. Реализация сети в кластере тоже может быть разной — на уровне l2 или l3 с помощью тех или иных технологий. То же самое с файловыми хранилищами — локальные хранилища серверов, nfs хранилища, ceph и т.д.

В зависимости от того, какой функционал вам нужен, выбирается способ установки кластера kubernetes. Мы можете его установить полностью вручную, добавляя один компонент за другим. А можно использовать готовое средство, к примеру Kubespray, где весь необходимый для установки функционал реализуется с помощью ролей ansible. На Слёрме нас учили ставить кластер, используя свой форк компании southbridge. Они там немного изменили функционал под свои потребности. Я ставил и по их форку, и по оригинальному Kubespray. Основное отличие от классического Kubespray в том, что не используется kubeadm и сертификаты для общения компонентов кластера сразу выпускаются то ли на 10, то ли на 100 лет, не помню точно. В Kubespray сертификаты выписываются только на год и надо отдельно следить за их актуальности и своевременно обновлять.

Подведу итог о том, что же такое Kubernetes. Кубернетис — средство оркестрации (управления) контейнерами Docker. Это удобный инструмент для их автоматического запуска, выделения ресурсов, контроля состояния, обновления.

Кому нужен Kubernetes

Теперь порассуждаем о том, кому может пригодиться Kubernetes. В первую очередь это крупные компании со своими разработками в ИТ и командами программистов, для которых нужна большая производственная среда. Кластер Кубера добавляет серьезные накладные расходы на свое содержание, поэтому в небольших проектах выгоды от него не будет. Нет смысла объединить 5 маленьких виртуалок в кластер и эксплуатировать его. Если только для тестов. Или если вы точно уверены, что у проекта будет серьезный рост в ближайшее время. Под небольшую структуру и нагрузки лучше подыскать решения попроще, чем кубернетис.

Kubernetes накладывает серьезные требования к приложениям, которые в нем работают. Они должны быть изначально спроектированы и написаны по принципу микросервисов. У вас не получится взять и перенести в кластер сайт на wordpress или bitrix, даже если они очень большие и нагруженные. Вернее, перенести то вы их сможете, но вряд ли вам от этого будет проще и удобнее. Основное преимущество кластера — гибкость в разработке, деплое приложения, а так же в распределении ресурсов.

Примерная схема работы с кластером кубернетис на пальцах будет такая:

Это я очень просто и условно описал. Все процессы после пуша кода в репозиторий могут быть автоматизированы. Команд разработчиков, как и микросервисов, может быть десятки. Они могут условно независимо друг от друга выкатывать обновления. У каждого сервиса могут быть свои языки программирования, свои системные требования, свои файловые хранилища и базы данных. Все эти сущности отдельно описываются в конфигурациях кластера. Каждый микросервис получает то, что ему нужно для работы.

Теперь смотрим на Bitrix или WordPress. Они являются монолитными приложениями, написанными на php с использованием базы Mysql. В них нет микросервисов. Вам нужно либо как-то разбивать их на части, либо постоянно выкатывать все целиком. Но в этом случае смысл кластера кубернетис теряется, его гибкость настроек и выделения ресурсов под потребности не используются. Вам проще поставить обычный балансер на вход, сделать несколько нод для обработки php и за ними кластер БД.

Резюмируя все сказанное. Kubernetes — нишевое решение под конкретные проекты. Оно подходит далеко не всем и не надо его пихать туда, где от него не будет толку. Думаю, находятся люди, которые так делают. Сужу по тому, что мне в комментариях к некоторым статьям, например, про установку zabbix, пишут, а почему вы не в докере его ставите. Люди не понимают, что такое докер, для чего он нужен и какие проблемы решает. Смысла в использовании zabbix в docker нет никакого вообще. Docker создан для удобной разработки и деплоя приложений в продакшн. Этакий расширенный пакетный менеджер. В первую очередь он инструмент разработчиков.

Системные требования

Как таковых жестких системных требований у Kubernetes нет. Он с очень маленьких установок расширяется до огромных кластеров. Для того, чтобы его просто попробовать и посмотреть, достаточно следующих виртуальных машин:

Для того, чтобы просто запустить кластер, достаточно буквально двух виртуальных машин, которые одновременно будут и мастер и рабочими нодами. Но я рекомендую сразу планировать более ли менее полную структуру, которую можно брать за основу для последующего превращения в рабочий кластер. Я буду разворачивать кластер на следующих виртуальных машинах.

В моем случае это виртуальные машины на двух гипервизорах Hyper-V. Как я уже сказал в системных требованиях, для теста ресурсов можно и чуть меньше дать, но у меня есть запас, поэтому я такие ресурсы выделил для кластера Kubernetes. Перед установкой кластера рекомендую сделать снепшоты чистых систем, чтобы можно было оперативно вернуться к исходному состоянию, если что-то пойдет не так. Вручную готовить и переустанавливать виртуалки хлопотно.

По гипервизорам виртуальные машины распределил следующим образом.


Как поднять кластер kubernetes

Как поднять кластер kubernetes

Упомяну про еще одну рекомендацию. Мастер ноды с etcd дают приличную нагрузку на диск. Их рекомендуется размещать на быстрых ssd дисках. Чем больше кластер — тем больше нагрузка. В наших тестах сойдет и hdd диск под мастер. Но если будете использовать в продакшене с учетом расширения и роста, лучше сразу планируйте быстрые диски под мастера.

Подготовка к установке

Кластер Kubernetes я буду разворачивать на виртуальных машинах Centos 7. На них она установлена в минимальной конфигурации. Напоминаю, что установка будет проходить с помощью Kubespray. Я рекомендую склонировать к себе репозиторий, чтобы у вас сохранилась версия kubespray, с которой вы устанавливали кластер. Это позволит без проблем создавать копию кластера для тестов, дебага, обновления и т.д. Я для этого использую свой сервер Gitlab. Рекомендую озаботиться его наличием. Он нам очень пригодится и дальше в процессе знакомства и изучения кластера.

Читайте также:  Что такое DNS | DNS-сервер | Cloud4Y

На виртуальных машинах нужно отключить следующие сущности:

На все сервера должен быть разрешен доступ пользователя root по ssh с одним и тем же паролем.

Установка кластера Kubernetes

Я буду устанавливать кластер Kubernetes с сервера kub-master-1. Установим на него некоторые пакеты, которые нам понадобятся в дальнейшем.

# yum install mc epel-release
# yum install wget curl git screen python-pip sshpass

Теперь клонируем себе локально репозиторий kubespray.

# cd ~
# git clone https://github.com/kubernetes-sigs/kubespray

Устанавливаем зависимости kubespray через pip, которые перечислены в файле requirements.txt.

# cd kubespray
# pip install -r requirements.txt

Теперь нам нужно заполнить инвентарь ansible, исходя из нашего набора серверов. Для этого скопируем стандартный инвентарь sample и будем редактировать его.

# cp -R ~/kubespray/inventory/sample ~/kubespray/inventory/dev

Приводим файл inventory.ini к следующему виду.

В принципе, тут все понятно, если вы знакомы с работой ansible. Мы распределили хосты по ролям. Обращаю внимание, что сервер ingress по сути является обычной нодой, только с дополнительным функционалом, поэтому он присутствует в том числе в группе kube-node. Далее вы можете его использовать и как ingress, и как обычную ноду одновременно.

kubelet_load_modules: true # автоматом загружает модули в ядро системы, не спрашивая админа сервера
kube_read_only_port: 10255 # порт для мониторинга кублетов, нужен, к примеру, для prometeus

В файл ~/kubespray/inventory/dev/group_vars/all/docker.yml добавляем:

docker_storage_options: -s overlay2 # использует сторейдж overlay2 для докера

В файл ~/kubespray/inventory/dev/group_vars/etcd.yml добавляем:

etcd_memory_limit: 0 # дефолтного ограничения в 512 мб может не хватать в больших кластерах, надо либо увеличить значение, либо отключить ограничение

В файл ~/kubespray/inventory/dev/group_vars/k8s-cluster/k8s-cluster.yml добавляем:

kube_network_plugin: flannel
kube_proxy_mode: iptables
kubeconfig_localhost: true # устанавливаем локально инструменты для управления кластером

Я буду использовать сетевой плагин flannel и iptables. Это хорошо проверенное и полностью готовое к production решение. Никаких особых настроек не требует, кроме пары параметров. Добавляем их в файл ~/kubespray/inventory/dev/group_vars/k8s-cluster/k8s-net-flannel.yml.

Теперь настроим ingress. Добавляем параметры в ~/kubespray/inventory/dev/group_vars/k8s-cluster/addons.yml.

ingress_nginx_enabled: true

ingress_nginx_nodeselector:
node-role.kubernetes.io/ingress: «true» # указываем, какая метка должна быть у ноды, чтобы туда установился ingress

ingress_nginx_tolerations:
— key: «node-role.kubernetes.io/ingress»
operator: «Exists»

ingress_nginx_configmap:
server-tokens: «False»
proxy-body-size: «2048M»
proxy-buffer-size: «16k»
worker-shutdown-timeout: «180»

Создаем файл ~/kubespray/inventory/dev/group_vars/kube-ingress.yml и добавляем параметры:

node_labels:
node.kubernetes.io/ingress: «true» # всем серверам в группе kube-ingress ставить соответствующую метку
node_taints:
— «node.kubernetes.io/ingress=:NoSchedule»

Трудно кратко и понятно описать настройки ingress, так как тут используются не тривиальные возможности kubernetes в виде taints и tolerations. Общий смысл в том, что мы задаем метку для ingress и поведение на основе этой метки. На ноды в группе kube-ingress ставится ограничение NoSchedule (не распределять поды на ноду) с помощью taints. Это ограничение могут преодолевать только только те, у кого в tolerations прописана метка ingress. Таким образом, на нодах ingress, кроме самого ингресса ничего запускаться не будет.

Вот и все. Мы готовы к тому, чтобы начать установку кластера Kubernetes. Запускаем ее с помощью ansible-playbook. Рекмоендую делать это в screen, чтобы не прерывался процесс из-за обрыва связи.

# ansible-playbook -u root -k -i inventory/dev/inventory.ini -b —diff cluster.yml

Процесс обычно длится 15-20 минут. У меня сервера старые, на hdd, длилось 30 минут. В конце вы должны увидеть примерно такую картину.


Как поднять кластер kubernetes

Ошибок быть не должно. Если есть ошибки, внимательно ищите их в выводе ansible и исправляйте. Основные ошибки возникают из-за неправильно заполненного инвентаря, из-за неправильной маски ip в свойствах flannel, из-за ошибок загрузки докер образов в процессе установки. После исправления ошибки можно запускать этот же плейбкук снова. Чаще всего все будет нормально донастроено.

Проверить состояние кластера можно командой:

# kubectl get nodes


Как поднять кластер kubernetes

Вы увидите список всех нод и их роли. Я не знаю по какой причине, но при разворачивании кластера для этой статьи, у меня рабочие ноды не получили роли node. Исправить это можно командами.

# kubectl label node kub-node-1 node-role.kubernetes.io/node=
# kubectl label node kub-node-2 node-role.kubernetes.io/node=
# kubectl label node kub-ingress-1 node-role.kubernetes.io/node=

Для сервера ingress смотрите сами, хотите вы на него дополнительно вешать роль node или оставите только в качестве ingress контроллера. В продакшене лучше оставить его отдельно. Если у вас тестовый кластер, то можете объединить эти роли на одном сервере.

Если же вы захотите убрать какую-то роль, то команда будет такой.

# kubectl label node kub-ingress-1 node-role.kubernetes.io/node-

Мы убрали роль node на сервере kub-ingress-1. Проверяем снова состояние кластера.

# kubectl get nodes
# kubectl cluster-info

Посмотреть подробную информацию о ноде можно командой.

# kubectl describe node kub-master-1


Как поднять кластер kubernetes

Рекомендую запомнить эту команду. Она очень пригодится в процессе эксплуатации кластера и дебага. Особое внимание на раздел Events. Именно он будет очень полезен при разборе ошибок на нодах.

Посмотрим список всех запущенных подов.

# kubectl get pod -A


Как поднять кластер kubernetes

Они все должны быть в состоянии Running. Если это не так, то у вас какие-то ошибки, с которыми надо разбираться. В общем случае ошибок быть не должно, если вы все сделали правильно на моменте подготовки инвентаря.

На этом непосредственно установка кластера Kubernetes закончена. Он готов к эксплуатации. Если вы только знакомитесь с ним, то, думаю, вам совсем не понятно, что делать дальше и как его эксплуатировать. Об этом будут мои последующие статьи. Следите за обновлениями.

Проблема с сертификатами

Сразу обращаю внимание на очень важный момент. Необходимо тем или иным способом настроить мониторинг сертификатов, которые установил и настроил kubespray для обмена информацией мастеров. Сертификатов много и у них срок действия 1 год. Пока сертификаты не просрочились, их относительно легко обновлять. Если упустить этот момент, то все становится сложнее.

Я до конца не понял и не проработал вопрос обновления сертификатов, но это нужно будет сделать. Пока просто покажу, как за ними можно следить.

Сертификат api-server, порт 6443

Сертификат controller manager, порт 10257.

Сертификат scheduler, порт 10259.

Это все разные сертификаты и они выпущены на год. Их надо будет не забыть обновить. А вот сертификат для etcd. Он выпущен на 100 лет.

Я не понял, почему этого не сделали для всех сервисов, а оставили такой головняк на потом. Если у кого-то есть информация о том, как корректно и безпроблемно обновлять сертификаты, прошу поделиться. Я пока видел только вариант с полуручным обновлением и раскидыванием этих сертификатов по мастерам.

Заключение

На этом начальную статью по Kubernetes заканчиваю. На выходе у нас получился рабочий кластер из трех мастер нод, двух рабочих нод и ingress контроллера. В последующих статьях я расскажу об основных сущностях kubernetes, как деплоить приложения в кластер с помощью Helm, как добавлять различные стореджи, как мониторить кластер и т.д. Да и в целом, хочу много о чем написать, но не знаю, как со временем будет.

В планах и git, и ansible, и prometeus, и teamcity, и кластер elasticsearch. К сожалению, доход с сайта не оправдывает временных затрат на написание статей, поэтому приходится писать их либо редко, либо поверхностно. Основное время уходит на текущие задачи по настройке и сопровождению.

Помогла статья? Подписывайся на telegram канал автора

Анонсы всех статей, плюс много другой полезной и интересной информации, которая не попадает на сайт.

В прошлой статье я рассказал о том, как установить кластер Kubernetes на свое железо. Сегодня я покажу, как можно с ним работать — запускать различные контейнеры, устанавливать лимиты, регулировать запуск и восстановление и т.д. По сути, опишу быстрый старт и настройку в kubernetes — на конкретных примерах покажу, с чего начинать освоение kubernetes и как его использовать на практике.

Онлайн-курс по Kubernetes – для разработчиков, администраторов, технических лидеров, которые хотят изучить современную платформу для микросервисов Kubernetes. Самый полный русскоязычный курс по очень востребованным и хорошо оплачиваемым навыкам. Курс не для новичков – нужно пройти вступительный тест.

Сразу поделюсь ссылкой на официальную документацию по kubernetes. Она хорошо структурирована и наполнена. Пользоваться ей удобно. С ее помощью настраивать кластер проще. Напоминаю, что мы будем работать с кластером, который установили по предыдущей статье — установка kubernetes. Перед тем, как начать работать с кластером, расскажу об одной полезной возможности. Есть команда:

# kubectl completion bash

Она формирует конфиг для настройки автодополнения команд в bash. Вывод этой команды нужно добавить в ваш ~/.bashrc Можно это сделать автоматически.

Чтобы автодополнение работало, нужен пакет bash-completion.

# yum install bash-completion

Запуск контейнера nginx в kubernetes

Начнем с самого простого — создадим один pod, в котором запустим контейнер с последней версией nginx. P OD в терминологии kubernetes — это набор контейнеров, объединенных между собой общим . Самое важное тут то, что все контейнеры в одном поде связаны между собой сетью в рамках общего 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.

Читайте также:  Купить хостинг для сайта (shared web hosting) | Доменчик.ру

# kubectl create -f pod-nginx.yaml
pod/pod-nginx created

Сразу сделаю пояснение насчет команды create. Вместо нее можно, а чаще всего и нужно, так как удобнее, использовать команду apply. Create создает новую абстракцию. Если вы ее измените и снова создадите с тем же именем, то получите ошибку. Вам придется сначала ее удалить, а потом создать заново. Команда apply сначала проверяет наличие абстракции, в данном случае и если ее нет, то создает. А если она уже есть, то просто перезапускает существующую с новыми параметрами.

Проверяем, что получилось.

# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-nginx 1/1 Running 0 2m32s

В настоящий момент мы запустили в кластере kubernetes один контейнер с nginx. Существует команда edit, которая позволяет редактировать сущности кластера kubernetes в режиме реального времени. Применение изменений произойдет сразу же после сохранения изменений. Пример:

# kubectl edit pod pod-nginx


Как поднять кластер kubernetes

Вы увидите полный конфиг пода, который использует кластер. В нем намного больше информации, нежели в вашем yaml файле.

Удалить созданный pod можно следующей командой:

# kubectl delete pod pod-nginx
pod «pod-nginx» deleted

Или сразу все поды:

# kubectl delete pod —all

Отказоустойчивость подов с помощью ReplicaSet

Теперь создадим несколько подов с nginx. Для этого нужно использовать другую абстракцию кубернетис. ReplicaSet следит за количеством подов по шаблону, который мы указываем. В этом шаблоне мы можем указать метку нашего приложения, в моем примере это , и количество запущенных реплик.


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

# 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

Я удалил , вместо него тут же был запущен новый . Наглядный пример одного из механизмов отказоустойчивости в кластере kubernetes на уровне подов. Кубернетис будет следить за количеством реплик на основе их label. Если вы через replicaset указали запустить 2 реплики приложения с меткой my-nginx, ни меньше, ни больше подов с этой меткой вы запустить не сможете. Если вы вручную запустите pod с меткой , он будет тут же завершен, если у вас уже есть 2 пода с такими метками от replicaset.

Replicaset запускает поды на разных нодах. Проверить это можно, посмотрев расширенную информацию о подах.

Таким образом, если у вас одна нода выйдет из строя, кластер автоматически запустит умершие поды на новых нодах. При этом, если нода вернется обратно с запущенными подами на ней, 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


Как поднять кластер kubernetes

Теперь откатимся на предыдущую версию nginx 1.15. Для этого вносим изменения в Deployment.

# kubectl set image deployment deployment-nginx nginx=nginx:1.15

Проверяем список подов и репликасетов.

Название подов и репликасета изменились. Появился новый replicaset, а старый остался с погашенными подами, у него параметр replicas стал 0. Проверяем версию nginx в поде.

# kubectl describe pod deployment-nginx-68d778658b-fz5lt


Как поднять кластер kubernetes

Версия 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

В данном примере используется проверка по корневому урлу на порт 80.

Вот еще один пример liveness проверки, но уже по наличию файла. Проверяется файл /tmp/healthy, если он существует, проверка удачна, если его нет, то ошибка.

livenessProbe:
exec:
command:
— cat
— /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5

Создавать этот файл может само приложение во время работы.

Resources — настройка ресурсов

Расскажу, как ограничиваются выделяемые для подов вычислительные ресурсы. Речь идет про и . Задать верхнюю планку использования ресурсов можно с помощью 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


Как поднять кластер kubernetes

Вот они, наши проверки и лимиты с реквестами.

Монтирование конфигов через ConfigMap

Абстракция kubernetes configmap придумана для того, чтобы отвязать конфиги контейнеров docker от deployment, чтобы не раздувать их размер. К примеру, нам нужно во все контейнеры с nginx положить конфиг . Мы для этого создаем configmap, в нем настраиваем желаемый конфиг и потом подключаем его в deployment. Показываю на примере. Создаем файл configmap.yaml.

Читайте также:  Disable FirewallD and Iptables Firewall in Linux

В данном случае это простейший конфиг для 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.


Как поднять кластер kubernetes

Видим, что применился наш configmap. На втором поде будет то же самое.

Проброс порта в pod

А сейчас пробросим 80-й порт мастера в конкретный под и проверим, что nginx действительно работает в соответствии с установленным конфигом. Делается это следующим обарзом.

Перемещаемся в сосeднюю консоль мастера и там проверяем через curl.

# curl localhost:80
deployment-nginx-848cc4c754-w7q9s

Если сделать проброс в другой под и проверить подключение, вы получите в ответ на запрос curl на 80-й порт мастера имя второго пода. На практике, я не знаю, как можно использовать данную возможность. А вот для тестов в самый раз.


Как поднять кластер kubernetes

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 мы привязали сервис к приложению с именем , которое мы использовали в предыдущих примерах. Применяем service в кластере.

# kubectl apply -f service.yaml
service/service-nginx created

И смотрим, что получилось.

Чтобы проверить работу сети в кластере, удобно запустить в нем специальный 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 и попадете в контейнер. А дальше пробуйте пинговать.


Как поднять кластер kubernetes

После выхода из контейнера, он удалится.

# 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, который будет пробрасывать запросы из вне на сервис , который мы создали на предыдущем шаге.


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 запись.

Я просто в локальный hosts машины добавил и проверил.


Как поднять кластер kubernetes

Если обновлять страничку, имя пода будет меняться в соответствии с настройкой балансировки. Она выполняется по алгоритму 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 get pods -n sock-shop -w

После того, как они все станут можно проверять работу. В этом проекте не используется ingress, поэтому чтобы понять, как подключиться к магазину, надо провести небольшое расследование. Для начала посмотрим запущенные service.

# kubectl get service -n sock-shop -o wide


Как поднять кластер kubernetes

Нас интересует тип NodePort, так как к нему можно подключаться из вне. Видим, что порт используется 30001 и имя приложения . Посмотрим, где оно запущено.

# kubectl get pod -n sock-shop -o wide


Как поднять кластер kubernetes

Этот pod запущен на kub-node-2. Посмотрим ее ip.

# kubectl get node -o wide


Как поднять кластер kubernetes

Ее ip адрес — 10.1.4.33. Значит для проверки магазина надо идти по урлу http://10.1.4.33:30001/


Как поднять кластер kubernetes

Вот он, наш магазин. Для удобства, можем сами доделать доступ через 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

Поздравляю, ваш кластер работает, а вы теперь администратор кластера Kubernetes и инженер yaml файлов 🙂 У вас теперь будет большая дружба с лапшеподобным синтаксисом. Идите к руководству и требуйе прибавки к зарплате минимум на 30%.

Я рассмотрел основные абстракции kubernetes, которые нужны для того, чтобы на нем хоть что-то запустить и начать работать. Кластер в таком виде уже способен принимать запросы из вне. Для полноты картины не хватает одного объемного раздела — фаловые хранилища. Эта отдельная большая тема, поэтому я решил ее не затрагивать здесь, а вынести в отдельную статью, которая будет следующей в этом цикле. В таком виде, как описано здесь, используются локальные диски нод кластера, где запущены контейнеры docker.

Если вам подходит такой формат работы — пользуйтесь. По большому счету, он вполне жизнеспособен, если у вас все полезные данные, к примеру, хранятся в самих контейнерах в реджистри и в базе данных, которая работает не в кластере, а медиаконтент на внешних CDN. В таком случае kubernetes будет работать как масштабируемый вычислительный кластер.

Для автоматического деплоя приложений в кластер k8s можно использовать helm. Я рассмотрел этот вопрос в отдельной статье — Работа с Helm 3 в Kubernetes.

Напоминаю, что подробно, с примерами и практическими заданиями изучить кластер kubernetes можно на обучении Слёрм, которое я прошел лично и могу рекомендовать, как хороший и эффективный курс.

Онлайн курс по Kubernetes

Онлайн-курс по Kubernetes – для разработчиков, администраторов, технических лидеров, которые хотят изучить современную платформу для микросервисов Kubernetes. Самый полный русскоязычный курс по очень востребованным и хорошо оплачиваемым навыкам. Курс не для новичков – нужно пройти вступительный тест.

Если вы ответите «да» хотя бы на один вопрос, то это ваш курс:

Сдавайте вступительный тест по ссылке и присоединяйтесь к новому набору!

Оцените статью
Хостинги