Создание кластера Kubernetes с помощью Kubeadm в Ubuntu 18.04

Kubernetes – это система оркестровки контейнеров. Разработанный компанией Google на основе опыта работы с контейнерами в производстве, Kubernetes является открытым и активно развивается огромным сообществом.

Примечание: В мануале используется Kubernetes 1.14. Информацию о более свежих версиях можно найти на этой странице.

Kubeadm автоматизирует установку и настройку компонентов Kubernetes – сервера API, менеджера контроллеров и Kube DNS. Однако Kubeadm не создает пользователей и не устанавливает зависимости операционной системы. Для этих предварительных задач можно использовать инструмент управления конфигурацией, например Ansible или SaltStack. Эти инструменты позволяют создавать дополнительные или воссоздавать существующие кластеры намного быстрее и с минимальным количеством ошибок.

Этот мануал поможет вам создать кластер Kubernetes с помощью Ansible и Kubeadm, а затем развернуть в нем контейнеризованное приложение Nginx.

Цели

Кластер будет состоять из таких физических ресурсов:

Одна мастер-нода

Мастер-нода (главная, ведущая нода) отвечает за управление кластером и его состояние. На ней запускается Etcd, что позволяет хранить данные кластера в компонентах, которые планируют нагрузки для рабочих нод.

Две рабочие ноды

Рабочие ноды (ведомые) – это серверы, которые обрабатывают рабочие нагрузки (например, контейнеризованные приложения и сервисы). Рабочая нода выполняет задачи сразу, как только они ей назначаются, даже если после планирования мастер-нода перестанет работать. Производительность кластера можно увеличить путем добавления рабочих нод.

После выполнения этого мануала у вас будет кластер, готовый запускать контейнеризованные приложения (при условии, что серверы в кластере имеют достаточно CPU и RAM). Почти любое традиционное приложение Unix, включая веб-приложения, БД, демоны и инструменты командной строки, можно контейнеризовать и запустить в кластере. Сам кластер будет потреблять около 300-500 МБ памяти и 10% CPU от каждой ноды.

Настроив кластер, вы развернете веб-сервер Nginx, чтобы убедиться, что все работает правильно.

Требования

1: Настройка рабочего пространства и инвентаря Ansible

На локальной машине нужно создать каталог, который будет служить рабочим пространством. Настройте Ansible локально, чтобы он мог взаимодействовать с командами на удаленных серверах. После этого нужно создать файл инвентаря hosts, содержащий информацию об оркестровке (IP-адреса серверов и группы, к которым принадлежит каждый сервер).

Примечание: Мы используем условный IP-адрес мастер-ноды – master_ip, а также условные IP-адреса рабочих нод – worker_1_ip и worker_2_ip. Их вам нужно будет заменить своими данными.

На локальной машине создайте каталог ~/kube-cluster и перейдите в него:

mkdir ~/kube-cluster
cd ~/kube-cluster

Этот каталог станет рабочим пространством для выполнения этого мануала, он будет содержать все загружаемые плейбуки Ansible. Также в нем вы сможете запускать все локальные команды.

Создайте файл ~/kube-cluster/hosts, используя nano или другой текстовый редактор:

nano ~/kube-cluster/hosts

Добавьте в файл такие строки (это информация о логической структуре кластера).

[masters] master ansible_host=master_ip ansible_user=root
[workers] worker1 ansible_host=worker_1_ip ansible_user=root
worker2 ansible_host=worker_2_ip ansible_user=root
[all:vars] ansible_python_interpreter=/usr/bin/python3

Как вы помните, файлы инвентаря в Ansible используются для указания информации о сервере (IP-адреса, удаленных пользователей и т.д.) и для группировки серверов в единый блок для выполнения команд. ~/kube-cluster/hosts будет таким файлом инвентаря, в нем указаны две группы Ansible (masters и workers), в которых определяется логическая структура кластера.

В группе masters есть запись сервера «master», которая определяет IP-адрес ведущей ноды (master_ip) и указывает, что Ansible должен запускать удаленные команды в качестве пользователя root.

Аналогично, в группе workers есть две записи рабочих серверов (worker_1_ip и worker_2_ip), которые также указывают ansible_user как root.

Последняя строка файла позволяет Ansible для выполнения своих операций использовать интерпретаторы Python 3 на удаленных серверах.

Сохраните и закройте файл.

2: Создание пользователей sudo на удаленных серверах

Чтоб не работать через root, теперь нужно создать пользователей с привилегиями sudo на всех удаленных серверах. Так вы сможете подключаться по SSH вручную в качестве непривилегированного пользователя. Это может быть полезно, например, если вам нужно получить системную информацию с помощью таких команд как top/htop, просмотреть список запущенных контейнеров или изменить файлы конфигурации, принадлежащие root. Эти операции обычно выполняются во время обслуживания кластера, а применение для таких задач пользователя без прав root минимизирует риск потери и повреждения важных файлов или случайного выполнения опасных операций.

В рабочем пространстве создайте ~/kube-cluster/initial.yml:

nano ~/kube-cluster/initial.yml

Затем добавьте в файл такой код, чтобы на всех серверах создать пользователя без прав root с привилегиями sudo. Плей в Ansible представляет собой набор действий, которые необходимо выполнить на целевых серверах и группах. Этот плей создаст пользователя sudo:

- hosts: all
become: yes
tasks:
- name: create the 'ubuntu' user
user: name=ubuntu append=yes state=present createhome=yes shell=/bin/bash
- name: allow 'ubuntu' to have passwordless sudo
lineinfile:
dest: /etc/sudoers
line: 'ubuntu ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
- name: set up authorized keys for the ubuntu user
authorized_key: user=ubuntu key="{{item}}"
with_file:
- ~/.ssh/id_rsa.pub

Этот плейбук:

  • Создает пользователя sudo по имени ubuntu.
  • Настраивает файл sudoers, чтобы предоставить пользователю ubuntu права sudo без пароля.
  • Добавляет открытый ключ локальной машины (обычно это ~/.ssh/id_rsa.pub) в список ключей удаленного пользователя ubuntu. Это позволит вам подключаться к серверам по SSH как пользователь ubuntu.

Сохраните и закройте файл.

Запустите плейбук локально:

ansible-playbook -i hosts ~/kube-cluster/initial.yml

Команда будет выполняться в течение 2-5 минут. Затем вы увидите такой вывод:

PLAY [all] ****
TASK [Gathering Facts] ****
ok: [master] ok: [worker1] ok: [worker2] TASK [create the 'ubuntu' user] ****
changed: [master] changed: [worker1] changed: [worker2] TASK [allow 'ubuntu' user to have passwordless sudo] ****
changed: [master] changed: [worker1] changed: [worker2] TASK [set up authorized keys for the ubuntu user] ****
changed: [worker1] => (item=ssh-rsa AAAAB3...)
changed: [worker2] => (item=ssh-rsa AAAAB3...)
changed: [master] => (item=ssh-rsa AAAAB3...)
PLAY RECAP ****
master                     : ok=5    changed=4    unreachable=0    failed=0
worker1                    : ok=5    changed=4    unreachable=0    failed=0
worker2                    : ok=5    changed=4    unreachable=0    failed=0

3: Установка зависимостей Kubernetes

Теперь нужно установить пакеты, необходимые для работы Kubernetes, это можно сделать с помощью менеджера пакетов Ubuntu. Вот список зависимостей:

  • Docker – среда выполнения контейнеров. Поддержка других рабочих сред, таких как rkt, находится в Kubernetes в активной разработке.
  • kubeadm – CLI, позволяет устанавливать и настраивать компоненты кластера стандартным образом.
  • kubelet – системный сервис, запускается на всех нодах и выполняет операции уровня ноды.
  • kubectl – CLI, выполняет команды в кластере через API.

В рабочем пространстве создайте файл ~/kube-cluster/kube-dependencies.yml:

nano ~/kube-cluster/kube-dependencies.yml

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

- hosts: all
become: yes
tasks:
- name: install Docker
apt:
name: docker.io
state: present
update_cache: true
- name: install APT Transport HTTPS
apt:
name: apt-transport-https
state: present
- name: add Kubernetes apt-key
apt_key:
url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
state: present
- name: add Kubernetes' APT repository
apt_repository:
repo: deb http://apt.kubernetes.io/ kubernetes-xenial main
state: present
filename: 'kubernetes'
- name: install kubelet
apt:
name: kubelet=1.14.0-00
state: present
update_cache: true
- name: install kubeadm
apt:
name: kubeadm=1.14.0-00
state: present
- hosts: master
become: yes
tasks:
- name: install kubectl
apt:
name: kubectl=1.14.0-00
state: present
force: yes

Первый плей в плейбуке делает следующее:

  • Устанавливает Docker.
  • Устанавливает apt-transport-https, что позволяет добавлять внешние HTTPS источники в список источников APT.
  • Добавляет apt-key репозитория Kubernetes для верификации.
  • Добавляет репозиторий APT Kubernetes в список источников удаленных серверов.
  • Устанавливает kubelet и kubeadm.

Сохраните и закройте файл.

Примечание: Хотя в документации Kubernetes рекомендуется использовать в своей среде последний стабильный выпуск Kubernetes, в этом мануале используется определенная версия. Это гарантирует, что вы сможете успешно выполнить все шаги. Kubernetes быстро развивается, и последняя версия может не сработать с остальными инструкциями мануала.

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

ansible-playbook -i hosts ~/kube-cluster/kube-dependencies.yml

Команда вернет:

PLAY [all] ****
TASK [Gathering Facts] ****
ok: [worker1] ok: [worker2] ok: [master] TASK [install Docker] ****
changed: [master] changed: [worker1] changed: [worker2] TASK [install APT Transport HTTPS] *****
ok: [master] ok: [worker1] changed: [worker2] TASK [add Kubernetes apt-key] *****
changed: [master] changed: [worker1] changed: [worker2] TASK [add Kubernetes' APT repository] *****
changed: [master] changed: [worker1] changed: [worker2] TASK [install kubelet] *****
changed: [master] changed: [worker1] changed: [worker2] TASK [install kubeadm] *****
changed: [master] changed: [worker1] changed: [worker2] PLAY [master] *****
TASK [Gathering Facts] *****
ok: [master] TASK [install kubectl] ******
ok: [master] PLAY RECAP ****
master                     : ok=9    changed=5    unreachable=0    failed=0
worker1                    : ok=7    changed=5    unreachable=0    failed=0
worker2                    : ok=7    changed=5    unreachable=0    failed=0

После выполнения плейбука на всех удаленных серверах будут установлены Docker, kubeadm и kubelet. kubectl не является обязательным компонентом и нужен только для выполнения команд кластера. В этом контексте имеет смысл устанавливать его только на мастер-ноде, так как вы будете запускать команды kubectl только с нее. Однако обратите внимание, что команды kubectl можно запускать с любой из рабочих нод и вообще с любого компьютера, на котором его можно установить и подключить к кластеру.

4: Настройка мастер-ноды

Теперь пора настроить мастер-ноду. Но для начала нужно рассмотреть такие понятия как поды и сетевые плагины Kubernetes.

Под –базовый элемент, который управляет одним или несколькими контейнерами. Эти контейнеры совместно используют ресурсы, такие как тома и сетевые интерфейсы. Под –основная единица планирования в Kubernetes: все контейнеры в поде работают на той ноде, на которой запланирован под.

Каждому поду присваивается собственный IP-адрес; под одной ноды должен иметь доступ к поду на другой ноде по IP-адресу. Контейнеры на одной ноде могут легко связываться через локальный интерфейс. Однако связь между контейнерами сложнее, для этого требуется отдельный сетевой компонент, который может легко маршрутизировать трафик пода на одной ноде к поду на другой.

Эту функцию выполняют сетевые плагины. Один из них, Flannel, будет использоваться в этом кластере.

Создайте на локальной машине плейбук master.yml .

nano ~/kube-cluster/master.yml

Добавьте в файл такой код, чтобы инициализировать кластер и установить Flannel:

- hosts: master
become: yes
tasks:
- name: initialize the cluster
shell: kubeadm init --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt
args:
chdir: $HOME
creates: cluster_initialized.txt
- name: create .kube directory
become: yes
become_user: ubuntu
file:
path: $HOME/.kube
state: directory
mode: 0755
- name: copy admin.conf to user's kube config
copy:
src: /etc/kubernetes/admin.conf
dest: /home/ubuntu/.kube/config
remote_src: yes
owner: ubuntu
- name: install Pod network
become: yes
become_user: ubuntu
shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml >> pod_network_setup.txt
args:
chdir: $HOME
creates: pod_network_setup.txt

Этот файл выполняет следующие действия:

  • Первая задача инициализирует кластер, запустив kubeadm init. Аргумент –pod-network-cidr=10.244.0.0/16 задает частную подсеть, из которой будут присваиваться IP-адреса. Flannel использует указанную выше подсеть по умолчанию; теперь kubeadm тоже будет использовать эту подсеть.
  • Вторая задача создает каталог .kube в /home/ubuntu. В нем будут храниться конфигурации (ключи админов для подключения к кластеру и API-адрес кластера).
  • Третья задача копирует файл /etc/kubernetes/admin.conf, сгенерированный командой kubeadm init, в домашний каталог пользователя. Это позволяет использовать kubectl для доступа к кластеру.
  • Последняя задача запускает kubectl apply, чтобы установить Flannel. Синтаксис kubectl apply -f descriptor.[yml|json] создает объекты, описанные в файле descriptor.[yml|json]. Файл kube-flannel.yml содержит описание объектов, необходимых для настройки Flannel в кластере.

Сохраните и закройте файл.

Запустите плейбук локально:

ansible-playbook -i hosts ~/kube-cluster/master.yml

Вы получите результат:

PLAY [master] ****
TASK [Gathering Facts] ****
ok: [master] TASK [initialize the cluster] ****
changed: [master] TASK [create .kube directory] ****
changed: [master] TASK [copy admin.conf to user's kube config] *****
changed: [master] TASK [install Pod network] *****
changed: [master] PLAY RECAP ****
master                     : ok=5    changed=4    unreachable=0    failed=0

Чтобы проверить состояние мастер-ноды, подключитесь по SSH.

ssh ubuntu@master_ip

Затем выполните команду:

kubectl get nodes

Вы должны увидеть:

NAME      STATUS    ROLES     AGE       VERSION
master    Ready     master    1d        v1.14.0

В выводе сказано, что мастер-нода выполнила задачи инициализации и находится в состоянии Ready, то есть может принимать рабочие ноды и выполнять другие задачи, отправленные на сервер API. Теперь вы можете добавить рабочие ноды с локальной машины.

5: Настройка рабочих нод

Чтобы добавить рабочие ноды, нужно выполнить на каждой одну команду. Эта команда содержит необходимую информацию о кластере (IP-адрес, порт API сервера мастера и токен). Только ноды, которые могут предъявить правильный токен, будут добавлены в кластер.

В рабочем пространстве создайте плейбук workers.yml:

nano ~/kube-cluster/workers.yml

Добавьте в него следующие строки, чтобы подключить рабочие ноды к кластеру:

- hosts: master
become: yes
gather_facts: false
tasks:
- name: get join command
shell: kubeadm token create --print-join-command
register: join_command_raw
- name: set join command
set_fact:
join_command: "{{ join_command_raw.stdout_lines[0] }}"
- hosts: workers
become: yes
tasks:
- name: join cluster
shell: "{{ hostvars['master'].join_command }} >> node_joined.txt"
args:
chdir: $HOME
creates: node_joined.txt

Этот плейбук выполняет такие действия:

  • Первый плей получает команду join, которая должна выполняться на рабочих нодах. Эта команда будет в следующем формате: kubeadm join –token <token> <master-ip>:<master-port> –discovery-token-ca-cert-hash sha256:<hash>. Как только он получит команду с соответствующим токеном и хэшем, следующий плей сможет получить эту информацию.
  • Второй плей содержит одну задачу, которая запускает команду join на всех рабочих нодах. В результате две ноды станут частью кластера.

Сохраните и закройте файл.

Выполните плейбук локально:

ansible-playbook -i hosts ~/kube-cluster/workers.yml

Он вернет:

PLAY [master] ****
TASK [get join command] ****
changed: [master] TASK [set join command] *****
ok: [master] PLAY [workers] *****
TASK [Gathering Facts] *****
ok: [worker1] ok: [worker2] TASK [join cluster] *****
changed: [worker1] changed: [worker2] PLAY RECAP *****
master                     : ok=2    changed=1    unreachable=0    failed=0
worker1                    : ok=2    changed=1    unreachable=0    failed=0
worker2                    : ok=2    changed=1    unreachable=0    failed=0

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

6: Тестирование кластера

Иногда кластер может выйти из строя во время настройки, потому что нода отключена или соединение между мастером и рабочей нодой установлено неверно. Протестируйте кластер и убедитесь, что все ноды работают правильно.

Вам нужно проверить текущее состояние кластера с мастер-ноды, чтобы убедиться, что все ноды работают. Если вы отключились от мастер-ноды, вы можете создать новое SSH подключение с помощью следующей команды:

ssh ubuntu@master_ip

Затем выполните эту команду:

kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
master    Ready     master    1d        v1.14.0
worker1   Ready     <none>    1d        v1.14.0
worker2   Ready     <none>    1d        v1.14.0

Если все ноды в столбце STATUS имеют значение Ready, значит, они являются частью кластера и готовы к обслуживанию рабочих нагрузок.

Но если некоторые из нод имеют статус NotReady, это может значить, что рабочие ноды еще не завершили свою настройку. Подождите 5-10 минут, а затем попробуйте перезапустить kubectl get node. Если несколько нод все еще со статусом NotReady, возможно, вам придется проверить и повторно запустить команды из предыдущих разделов мануала.

Теперь можно попробовать запустить в кластере Nginx.

7: Запуск приложения в кластере

Теперь вы можете развернуть любое контейнеризованное приложение в кластере. Для примера можно попробовать развернуть Nginx с помощью развертываний и сервисов. Вы можете также использовать нижеприведенные команды для развертывания других приложений (для этого измените имя образа Docker и все соответствующие опции, например, ports и volumes).

Оставаясь на мастер-ноде, запустите следующую команду, чтобы создать развертывание nginx:

kubectl create deployment nginx --image=nginx

Развертывание – это объект Kubernetes, который следит за тем, чтобы на определенном шаблоне всегда работало заданное минимальное количество подов (даже если под выходит из строя во время работы кластера). Вышеупомянутое развертывание создаст под с одним контейнером из образа Nginx Docker.

Затем запустите команду, чтобы создать сервис nginx, который откроет приложению доступ к сети. Это выполняется через NodePort – схему, которая сделает под доступным через произвольный порт, открытый на каждой ноде кластера:

kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort

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

Запустите команду:

kubectl get services

Вы получите примерно такой вывод:

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP           PORT(S)             AGE
kubernetes   ClusterIP   10.96.0.1        <none>                443/TCP             1d
nginx        NodePort    10.109.228.209   <none>                80:nginx_port/TCP   40m

В третьей строке вывода вы увидите порт, на котором работает Nginx. Kubernetes автоматически присваивает случайный порт выше 30000, предварительно проверив, что порт не занят другим сервисом.

Чтобы убедиться, что все работает, откройте в браузере на локальной машине http://worker_1_ip:nginx_port или http://worker_2_ip:nginx_port. Вы увидите стандартное приветствие Nginx.

Чтобы удалить приложение Nginx, сначала удалите с мастер-ноды сервис.

kubectl delete service nginx

Запустите следующую команду, чтобы убедиться, что сервис удален:

kubectl get services
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP           PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>                443/TCP        1d

После этого удалите развертывание:

kubectl delete deployment nginx

Чтобы убедиться, что оно удалилось, введите:

kubectl get deployments
No resources found.

Заключение

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

  • На сайте Docker можно найти подробные примеры, описывающие, как контейнеризовать приложения.
  • Этот обзор рассказывает, как работают поды, и объясняет их связь с другими объектами в Kubernetes.
  • Этот обзор многое расскажет о развертываниях в Kubernetes. Понимать, как работают развертывания, очень важно, поскольку они часто используются при масштабировании и автоматическом восстановлении приложений.
  • По этой ссылке вы найдете обзор сервисов.

Также стоит обратить внимание на тома, Ingresses и секреты, которые могут пригодиться при развертывании приложений в производстве.

Kubernetes поддерживает много полезных функций. Официальная документация Kubernetes – лучшее средство для изучения этого инструмента, поиска руководств по конкретным задачам и ссылок API для различных объектов.

Tags: , , , ,

2 комментария

Добавить комментарий