Автор - Евгений Генеральчик
Что общего у Генри Форда и SRE?
Генри Форд был классный чел. Правда, не знаю, сам он дошел до такой славной мысли или услышал о подходе, когда-то использовавшемся у китайских медиков. Ведь пока в древней варварской Европе самым эффективным лечением считалось кровопускание, в не менее древнем Китае, чтобы медики не...
Создание кластера Kubernetes на VPS с помощью Kubespray
Visitors have accessed this post 13172 times.
Автор — Андрей Трошин
k8s, Kubernetes
Не для кого не секрет, что сегодня этот оркестратор у всех на слуху. Из каждого IT-утюга доносится «k8s, кластер, CI\CD» и всякие другие неприличные и малопонятные слова. Давайте разберемся и попробуем собрать кластер Kubernetes на VPS.
Варианты установки
- Стандартный репозиторий OS
- Kubespray
В качестве хост-системы будем использовать CentOS 7 на всех узлах нашего k8s кластера (если у вас другая хост-система — ищите информацию на официальном сайте Kubernetes). В нашем случае выбираем вариант установки с помощью Kubespray. Kubespray — это набор Ansible ролей для установки и конфигурации Kubernetes. В свою очередь, Ansible — это инструмент для автоматизации настройки и развертывания программного обеспечения.
Подготовка
В дальнейшем мы будем использовать кластер для публикации разных сервисов и поэтому установка будет на VPS. Но мануал по установке будет также успешно работать, если вы захотите поднять k8s у себя на виртуальных машинах.
Что нам потребуется
- Master node (OS CentOS 7: 1vCPU, RAM 2Gb, HDD 10Gb)
- Worker node (OS CentOS 7: 1vCPU, RAM 2Gb, HDD 10Gb)
- Worker node (OS CentOS 7: 1vCPU, RAM 2GB, HDD 10Gb)
- Ingress node (OS CentOS 7: 2vCPU, RAM 8Gb, HDD 10Gb)
Эта конфигурация — это учебный вариант. С таким количеством узлов кластера в продуктиве, конечно же, запускаться не стоит. С другой стороны, это уже не minikube, а разнесенный по узлам кластер, хоть и маленький 🙂
Делаем k8s
Итак, у нас в распоряжении 4 узла кластера и для дальнейших действий на всех узлах необходимо сделать следующее:
- Отключить Swap
- Отключить Firewall
- Сгенерировать и скопировать ssh-ключи (необходимо для того, что бы Ansible ходил по хостам и делал свои дела)
Поехали.
Отключаем SWAP.
swapoff -a
Отключаем Firewall.
firewall-cmd --state systemctl stop firewalld systemctl disable firewalld
Заходим на master ноду по ssh и генерируем ssh-ключ, копируем его на все хосты кластера (включая master хост, на котором был сгенерирован ключ). По очереди подставляем IP каждого узла кластера на место remote_host.
ssh-keygen ssh-copy-id root@remote_host
Продолжим подготавливать master. Для дальнейшей работы потребуется pip и собственно git.
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" python get-pip.py yum install git
С подготовительной частью мы закончили. Возвращаемся на master ноду и дальнейшие операции до конца установки кластера будем совершать с нее. Скачиваем репозиторий к себе на хост и переходим в директорию kubespray.
git clone https://github.com/kubernetes-sigs/kubespray.git cd kubespray
Далее устанавливаем python-библиотеку requests и другие зависимости из файла requirements.txt.
pip install --ignore-installed requests==2.23.0 pip install -r requirements.txt
В результате у нас получилось следующее:
- На master ноде установили Ansible.
- Мы сгенерировали и скопировали ssh-ключ на все узлы кластера.
- Установили все необходимые зависимости.
Приступаем к конфигурации Kubespray. Для того чтобы Kubespray понимал, на какие узлы ему устанавливать k8s, необходимо создать директорию. В ней мы опишем конфигурацию будущего кластера. Копируем /inventory/sample/ в новую директорию и переименовываем, в моем случае — в root/, и в ней открываем файл inventory.ini.
[root@master-1 inventory]# ll total 12 drwxr-xr-x. 2 root root 4096 Nov 5 15:08 local drwxr-xr-x. 3 root root 4096 Nov 5 15:18 root drwxr-xr-x. 3 root root 4096 Nov 5 15:18 sample [root@master-1 inventory]# cd root/ [root@master-1 root]# ll total 8 drwxr-xr-x. 4 root root 4096 Nov 5 15:08 group_vars -rw-r--r--. 1 root root 994 Nov 5 15:08 inventory.ini [root@master-1 root]#
Типичный inventory.ini:
# ## Configure 'ip' variable to bind kubernetes services on a # ## different ip than the default iface # ## We should set etcd_member_name for etcd cluster. The node that is not a etcd member do not need to set the value, or can set the empty string value. [all] # node1 ansible_host=95.54.0.12 # ip=10.3.0.1 etcd_member_name=etcd1 # node2 ansible_host=95.54.0.13 # ip=10.3.0.2 etcd_member_name=etcd2 # node3 ansible_host=95.54.0.14 # ip=10.3.0.3 etcd_member_name=etcd3 # node4 ansible_host=95.54.0.15 # ip=10.3.0.4 etcd_member_name=etcd4 # node5 ansible_host=95.54.0.16 # ip=10.3.0.5 etcd_member_name=etcd5 # node6 ansible_host=95.54.0.17 # ip=10.3.0.6 etcd_member_name=etcd6 # ## configure a bastion host if your nodes are not directly reachable # bastion ansible_host=x.x.x.x ansible_user=some_user [kube-master] # node1 # node2 [etcd] # node1 # node2 # node3 [kube-node] # node2 # node3 # node4 # node5 # node6 [calico-rr] [k8s-cluster:children] kube-master kube-node calico-rr
Конфигурация не сложная, и на первый взгляд понятно, что в секции [all] идет присвоение IP-адресов ко всем нодам. В остальных секциях идет компановка кластера. Ниже приведен пример inventory.ini c моими IP-адресами (у вас они могут отличаться).
# ## Configure 'ip' variable to bind kubernetes services on a # ## different ip than the default iface # ## We should set etcd_member_name for etcd cluster. The node that is not a etcd member do not need to set the value, or can set the empty string value. [all] master-1.root.local.io ansible_host=192.168.0.5 ip=192.168.0.5 ingress-1.root.local.io ansible_host=192.168.0.4 ip=192.168.0.4 node-1.root.local.io ansible_host=192.168.0.6 ip=192.168.0.6 node-2.root.local.io ansible_host=192.168.0.3 ip=192.168.0.3 # ## configure a bastion host if your nodes are not directly reachable # bastion ansible_host=x.x.x.x ansible_user=some_user [kube-master] master-1.root.local.io [etcd] master-1.root.local.io [kube-node] node-1.root.local.io node-2.root.local.io ingress-1.root.local.io [kube-ingress-1] ingress-1.root.local.io [k8s-cluster:children] kube-node kube-master
Разберем, что следует из такой конфигурации:
- Наш кластер состоит из 4 узлов.
- Одна master-нода с компонентами Сontrol Plane.
- Одна нода с Ingress для маршрутизации трафика и две Worker ноды, на которых будут запускаться наши сервисы.
- Control Plane (API server, etcd, Sheduler, Controle manager) собран на одной ноде. Это очень нехорошо и обычно в секции [kube-master] более одного узла, а в секции [etcd] — более трех узлов. Почему 3 узла в etcd? Потому что quorum собирается не меньше, чем в 3 узла и с нечетным общим количеством узлов в etcd. Но в нашем учебном случае такой вариант оптимальный.
Сохраняем изменения в inventory.ini и идем в директорию group_vars/. Создаем там файл kube-ingress.yml с содержимым:
node_labels: node-role.kubernetes.io/ingress: "" node_taints: - "node-role.kubernetes.io/ingress=:NoSchedule"
Это для корректной настройки Ingress контроллера. Далее редактируем файл k8s-cluster/addons.yml. Добавляем helm, сбор метрик для мониторинга и функционал Nginx ingress controller:
- helm_enabled: true
- metrics_server_enabled: true
- Убираем комментирование с Nginx ingress controller deployment
ingress_nginx_enabled: true ingress_nginx_host_network: false ingress_publish_status_address: "" ingress_nginx_nodeselector: kubernetes.io/os: "linux" ingress_nginx_tolerations: - key: "node-role.kubernetes.io/master" operator: "Equal" value: "" effect: "NoSchedule" ingress_nginx_namespace: "ingress-nginx" ingress_nginx_insecure_port: 80 ingress_nginx_secure_port: 443 ingress_nginx_configmap: map-hash-bucket-size: "128" ssl-protocols: "SSLv2" ingress_nginx_configmap_tcp_services: 9000: "default/example-go:8080" ingress_nginx_configmap_udp_services: 53: "kube-system/coredns:53" ingress_nginx_extra_args: - --default-ssl-certificate=default/foo-tls
Также редактируем k8s-cluster/k8s-cluster.yml. Меняем network plugin на flannel и имя нашего кластера на root.local:
- kube_network_plugin: flannel
- cluster_name: root.local
Немножко подправим k8s-cluster/k8s-net-flannel.yml. Тут обычный regexp на сеть нашего провайдера VPS. У меня она 192.168.0.0/24. У вас может отличаться. Исправляем:
- flannel_interface_regexp: ‘192\.168\.0\.\d{1,9}’
Готово! Конфигурация закончена. Мы в рамках пяти конфигурационных файлов, смогли описать все необходимое для сборки. Вспомним:
- inventory.ini — назначаем IP-адреса и компонуем кластер.
- kube-ingress.yml — определяем Ingress.
- addons.yml — включаем в сборку необходимые компоненты. Добавляем helm, сбор метрик для мониторинга и функционал Nginx ingress controller.
- k8s-cluster.yml — выбираем network plugin и задаем имя нашему кластеру.
- k8s-net-flannel.yml — настраиваем network plugin.
Теперь осталоcь запустить playbook Ansible, который соберет кластер, и дождаться его выполнения. Переходим в корень директории kubespray и выполняем в терминале команду:
ansible-playbook -u root -i inventory/root/inventory.ini cluster.yml -b --diff
Разберем параметры. Запускаем ansible-playbook от имени root с инвентарем inventary.ini. Дальше Ansible начнет свою работу по настройке кластера. Обычно это занимает от 10 до 20 минут. Если в это время у вас вдруг отвалиться соединение ssh или еще какая беда случится и прервется сборка, то ее можно запустить повторно и это не вызовет ошибок. В итоге, должно получиться как на скрине ниже.
Кластер собран и готов к работе. Проверяем состав нод командой kubectl get nodes.
[root@master-1 kubespray]# kubectl get nodes NAME STATUS ROLES AGE VERSION ingress-1.root.local.io Ready <none> 2d1h v1.19.3 master-1.root.local.io Ready master 2d1h v1.19.3 node-1.root.local.io Ready <none> 2d1h v1.19.3 node-2.root.local.io Ready <none> 2d1h v1.19.3
Видим, что кластер имеет одну мастер-ноду, две рабочие ноды и ингресс.
Но тут, если посмотреть в ROLE, можно заметить, что нашему Ingress-1 не назначена роль ingress. Исправляем kubectl label node ingress-1.root.local.io node-role.
kubernetes.io/ingress=ay]# kubectl label node ingress-1.root.local.io node-role. node/ingress-1.root.local.io labeled [root@master-1 kubespray]#
И повторно смотрим, чтобы назначилась нужная нам роль. Для расширенного просмотра информации по нодам можно использовать команду kubectl get nodes -owide.
[root@master-1 kubespray]# kubectl get nodes NAME STATUS ROLES AGE VERSION ingress-1.root.local.io Ready ingress 2d1h v1.19.3 master-1.root.local.io Ready master 2d1h v1.19.3 node-1.root.local.io Ready <none> 2d1h v1.19.3 node-2.root.local.io Ready <none> 2d1h v1.19.3 [root@master-1 kubespray]#
Поздравляю! У вас получилось собрать k8s кластер и теперь можно развернуть в нем простенькое приложение. Но это уже тема следующих статей.
От редакции
Если вам интересно посещать бесплатные онлайн-мероприятия по DevOps, Kubernetes, Docker, GitlabCI и др. и задавать вопросы в режиме реального времени, подключайтесь к каналу DevOps by REBRAIN.
*Анонсы мероприятий каждую неделю
Практикумы для специалистов по инфраструктуре и разработчиков — https://rebrainme.com.
Наш Youtube-канал — https://www.youtube.com/channel/UC6uIx64IFKMVmj12gKtSgBQ.
Агентство Fevlake, проектируем и поддерживаем IT-инфраструктуры с 2012 года — https://fevlake.com.
Вам также может понравится
Инструмент контейнеризации Docker входит в число наиболее востребованных технологий, без которых не обойтись в работе Devops-инженера. Предлагаем начать знакомство с Docker с основных терминов, которые могут вам встретиться при работе с ним.
Docker - это инструмент, упрощающий разработку, тестирование и выкладку приложений за счет использования...
Автор — Юрий Изоркин
Что такое Mastodon, и зачем он нужен
Mastodon — некоммерческая децентрализованная социальная сеть, которая предоставляет функции микроблоггинга, наподобие Twitter. Краткие сообщения, которые публикуют пользователи, здесь называются «гудками» (англ toots). Ограничением является длина поста в 500 символов, но мне хотелось бы,...
Cпасибо за статью. 2 обслуживающему персоналу — по какой причине код не влазит в форму, например выдача метки .
2 автор, этот вариант развернет ингресс на всех нодах , а нужен ли он нам везде, в том числе и на мастерах….. Я бы предложил поиграться с лейблом kubernetes.io/os: , точнее вместо него завести другой, соответствующий узко ингрессу.
2 сервис — функционал редактирования коммента скоро добавить? И спасибо автору за статью, ждем обещанного продолжения