Введение
Kubernetes — это система оркестрации контейнеров, которая управляет контейнерами в любом масштабе. Первоначально разработанный Google на основе опыта использования контейнеров в производстве, Kubernetes имеет открытый исходный код и активно развивается сообществом по всему миру.
Note: В этом руководстве используется версия Kubernetes 1.22, официальная поддерживаемая версия на момент публикации этой статьи. Актуальную информацию о последней версии можно найти в текущих примечаниях к выпуску в официальной документации Kubernetes.
Kubeadm автоматизирует установку и настройку компонентов Kubernetes, таких как сервер API, диспетчер контроллеров и Kube DNS. Однако он не создает пользователей и не управляет установкой зависимостей уровня операционной системы и их конфигурацией. Для этих предварительных задач можно использовать инструмент управления конфигурацией, такой как Ansible или SaltStack. Использование этих инструментов значительно упрощает создание дополнительных кластеров или воссоздание существующих кластеров и снижает вероятность ошибок.
В этом руководстве вы настроите кластер Kubernetes с нуля с помощью Ansible и Kubeadm, а затем развернете в нем контейнерное приложение Nginx. Если вы ищете управляемую службу хостинга Kubernetes, воспользуйтесь нашей простой управляемой службой Kubernetes, созданной для роста.
Цели
Ваш кластер будет включать в себя следующие физические ресурсы:
- One Control Plane node
Узел плоскости управления (узел в Kubernetes — это сервер) отвечает за управление состоянием кластера. Он запускает Etcd, который хранит данные кластера среди компонентов, которые планируют рабочие нагрузки на рабочие узлы.
- Two worker nodes
Рабочие узлы — это серверы, на которых будут выполняться ваши рабочие нагрузки (т. е. контейнерные приложения и службы). Работник продолжит выполнять вашу рабочую нагрузку после того, как ему ее назначат, даже если плоскость управления отключится после завершения планирования. Емкость кластера можно увеличить за счет добавления рабочих процессов.
После выполнения этого руководства у вас будет кластер, готовый к запуску контейнерных приложений, при условии, что серверы в кластере имеют достаточные ресурсы ЦП и ОЗУ для использования вашими приложениями. Практически любое традиционное приложение Unix, включая веб-приложения, базы данных, демоны и инструменты командной строки, можно поместить в контейнер и запустить в кластере. Сам кластер будет потреблять около 300-500 МБ памяти и 10% ЦП на каждом узле.
После настройки кластера вы развернете на нем веб-сервер Nginx, чтобы убедиться, что он правильно выполняет рабочие нагрузки.
Предварительные условия
-
Пара ключей SSH на вашем локальном компьютере с Linux/macOS/BSD. Если вы раньше не использовали ключи SSH, вы можете узнать, как их настроить, следуя этому объяснению того, как настроить ключи SSH на вашем локальном компьютере.
-
Три сервера под управлением Ubuntu 20.04, минимум 2 ГБ ОЗУ и 2 виртуальных ЦП каждый. У вас должна быть возможность подключаться по SSH к каждому серверу в качестве пользователя root с вашей парой ключей SSH.
Note: Если вы не подключались по SSH к каждому из этих серверов хотя бы один раз до выполнения этого руководства, вам может быть предложено принять отпечатки их хостов в неудобное время позже. Вам следует сделать это сейчас или, в качестве альтернативы, вы можете отключить проверку ключей хоста.
-
Ansible установлен на вашем локальном компьютере. Если вы используете Ubuntu 20.04 в качестве ОС, следуйте разделу «Шаг 1 — Установка Ansible» в разделе «Как установить и настроить Ansible в Ubuntu 20.04», чтобы установить Ansible. Инструкции по установке на других платформах, таких как macOS или Rocky Linux, можно найти в официальной документации по установке Ansible.
-
Знакомство с плейбуками Ansible. Для обзора ознакомьтесь с Управлением конфигурациями 101: Написание сборников сценариев Ansible.
-
Знание того, как запустить контейнер из образа Docker. Если вам нужно освежить знания, посмотрите «Шаг 5 — Запуск Docker-контейнера» в разделе «Как установить и использовать Docker в Ubuntu 20.04».
Шаг 1 — Настройка каталога рабочей области и файла инвентаризации Ansible
В этом разделе вы создадите каталог на своем локальном компьютере, который будет служить вашим рабочим пространством. Вы настроите Ansible локально, чтобы он мог взаимодействовать и выполнять команды на ваших удаленных серверах. Как только это будет сделано, вы создадите файл hosts
, содержащий инвентарную информацию, такую как IP-адреса ваших серверов и группы, к которым принадлежит каждый сервер.
Из трех ваших серверов один будет плоскостью управления с IP-адресом, отображаемым как control_plane_ip
. Два других сервера будут рабочими и будут иметь IP-адреса worker_1_ip
и worker_2_ip
.
Создайте каталог с именем ~/kube-cluster
в домашнем каталоге вашего локального компьютера и cd
в него:
1 |
<ol><li data-prefix="$"> <span class="token function">mkdir</span> ~/kube-кластер</li><li data-prefix="$"> <span class="token builtin class-name">компакт-диск</span> ~/kube-кластер</li></ol> |
Этот каталог будет вашим рабочим пространством до конца урока и будет содержать все ваши сборники сценариев Ansible. Это также будет каталог, внутри которого вы будете запускать все локальные команды.
Создайте файл с именем ~/kube-cluster/hosts
с помощью nano
или вашего любимого текстового редактора:
1
<ol><li data-prefix="$"> <span class="token function">нано</span> ~/kube-cluster/hosts</li></ol>
Добавьте в файл следующий текст, который будет содержать информацию о логической структуре вашего кластера:
~/kube-кластер/хосты
1
<span class="token punctuation">[</span> control_plane <span class="token punctuation">]</span> control1 ansible_host=</code> control_plane_ip ansible_user=root <span class="token punctuation">[</span> рабочие <span class="token punctuation">]</span> работник1 ansible_host=<mark> работник_1_ip</mark> ansible_user=корневой работник2 ansible_host=<mark> работник_2_ip</mark> ansible_user=root <span class="token punctuation">[</span> все <span class="token punctuation">:</span> vars <span class="token punctuation">]</span> ansible_python_interpreter=/usr/bin/python3
Возможно, вы помните, что файлы инвентаризации в Ansible используются для указания информации о сервере, такой как IP-адреса, удаленные пользователи и группы серверов, которые будут использоваться как единое целое для выполнения команд. ~/kube-cluster/hosts
будет вашим файлом инвентаризации, и вы добавили в него две группы Ansible ( control plane и workers ), определяющие логическую структуру вашего кластера.
В группе control plane есть запись сервера с именем «control1», в которой указан IP-адрес плоскости управления ( control_plane_ip
) и указано, что Ansible должен запускать удаленные команды от имени пользователя root.
Аналогично, в workers группе есть две записи для рабочих серверов ( worker_1_ip
и worker_2_ip
), которые также указывают ansible_user
как root.
Последняя строка файла сообщает Ansible использовать интерпретаторы Python 3 удаленных серверов для операций управления.
Сохраните и закройте файл после добавления текста. Если вы используете nano
, нажмите Ctrl+X
, затем при появлении запроса Y
и Enter
.
Настроив инвентаризацию серверов по группам, перейдем к установке зависимостей уровня операционной системы и созданию настроек конфигурации.
Шаг 2. Создание пользователя без полномочий root на всех удаленных серверах
В этом разделе вы создадите пользователя без полномочий root с привилегиями sudo на всех серверах, чтобы вы могли подключаться к ним по SSH вручную как непривилегированный пользователь. Это может быть полезно, если, например, вы хотите просмотреть информацию о системе с помощью таких команд, как top/htop
, просмотреть список запущенных контейнеров или изменить файлы конфигурации, принадлежащие пользователю root. Эти операции регулярно выполняются во время обслуживания кластера, и использование пользователя без полномочий root для таких задач сводит к минимуму риск изменения или удаления важных файлов или непреднамеренного выполнения других опасных операций.
Создайте файл с именем ~/kube-cluster/initial.yml
в рабочей области:
1
<ol><li data-prefix="$"> <span class="token function">нано</span> ~/kube-cluster/initial.yml</li></ol>
Затем добавьте в файл следующую команду, чтобы создать пользователя без полномочий root с привилегиями sudo на всех серверах. Игра в Ansible — это набор шагов, которые необходимо выполнить для конкретных серверов и групп. Следующая игра создаст пользователя sudo без полномочий root:
~/kube-cluster/initial.yml
1
<span class="token punctuation">---</span> <span class="token punctuation">-</span> <span class="token key atrule">hosts</span> <span class="token punctuation">:</span> all <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">tasks</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> create the 'ubuntu' user <span class="token key atrule">user</span> <span class="token punctuation">:</span> name=ubuntu append=yes state=present createhome=yes shell=/bin/bash <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> allow 'ubuntu' to have passwordless sudo <span class="token key atrule">lineinfile</span> <span class="token punctuation">:</span> <span class="token key atrule">dest</span> <span class="token punctuation">:</span> /etc/sudoers <span class="token key atrule">line</span> <span class="token punctuation">:</span> <span class="token string">'ubuntu ALL=(ALL) NOPASSWD: ALL'</span> <span class="token key atrule">validate</span> <span class="token punctuation">:</span> <span class="token string">'visudo -cf %s'</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> set up authorized keys for the ubuntu user <span class="token key atrule">authorized_key</span> <span class="token punctuation">:</span> user=ubuntu key=" <span class="token punctuation">{</span> <span class="token punctuation">{</span> item <span class="token punctuation">}</span> <span class="token punctuation">}</span> " <span class="token key atrule">with_file</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> ~/.ssh/id_rsa.pub
Вот разбивка того, что делает эта книга:
-
Создает пользователя ubuntu
без полномочий root.
-
Настраивает файл sudoers
, чтобы позволить пользователю ubuntu
запускать команды sudo
без запроса пароля.
-
Добавляет открытый ключ на вашем локальном компьютере (обычно ~/.ssh/id_rsa.pub
) в список авторизованных ключей удаленного пользователя ubuntu
. Это позволит вам подключаться по SSH к каждому серверу в качестве пользователя ubuntu
.
Сохраните и закройте файл после добавления текста.
Затем запустите плейбук локально:
1
<ol><li data-prefix="$"> ansible-playbook <span class="token parameter variable">-i</span> хосты ~/kube-cluster/initial.yml</li></ol>
Команда выполнится в течение двух-пяти минут. По завершении вы увидите вывод, аналогичный следующему:
1
<div class="secondary-code-label" title="Выход"> Выход</div> ИГРАТЬ [все] **** ЗАДАЧА [Сбор фактов] **** ок: [control1] ок: [worker1] ок: [worker2] ЗАДАЧА [создать пользователя 'ubuntu'] **** изменено: [control1] изменено: [worker1] изменено: [worker2] TASK [разрешить пользователю 'ubuntu' использовать sudo без пароля] **** изменено: [control1] изменено: [worker1] изменено: [worker2] TASK [установить авторизованные ключи для ubuntu user] **** изменено: [worker1] => (item=ssh-rsa AAAAB3...) изменено: [worker2] => (item=ssh-rsa AAAAB3...) изменено: [control1] => ( item=ssh-rsa AAAAB3...) PLAY RECAP **** control1 : ok=4 изменено=3 недостижимо=0 не удалось=0 worker1 : ok=4 изменено=3 недоступно=0 не удалось=0 worker2 : ok=4 изменено =3 недоступен=0 не удалось=0
Теперь, когда предварительная настройка завершена, вы можете перейти к установке зависимостей, специфичных для Kubernetes.
Шаг 3 — Установка зависимостей Kubernetetes
В этом разделе вы установите пакеты уровня операционной системы, необходимые Kubernetes, с помощью менеджера пакетов Ubuntu. Эти пакеты:
-
Docker — среда выполнения контейнера. Это компонент, который запускает ваши контейнеры. Kubernetes поддерживает другие среды выполнения, но Docker по-прежнему остается популярным и простым выбором.
-
kubeadm
— инструмент CLI, который стандартным образом установит и настроит различные компоненты кластера.
-
kubelet
— системная служба/программа, которая работает на всех узлах и обрабатывает операции на уровне узлов.
-
kubectl
— инструмент CLI, используемый для выдачи команд кластеру через его API-сервер.
Создайте файл с именем ~/kube-cluster/kube-dependencies.yml
в рабочей области:
1
<ol><li data-prefix="$"> <span class="token function">nano</span> ~/kube-cluster/kube-dependents.yml</li></ol>
Добавьте в файл следующие фрагменты, чтобы установить эти пакеты на ваши серверы:
~/kube-cluster/kube-dependents.yml
1
<span class="token punctuation">---</span> <span class="token punctuation">-</span> <span class="token key atrule">hosts</span> <span class="token punctuation">:</span> all <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">tasks</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> create Docker config directory <span class="token key atrule">file</span> <span class="token punctuation">:</span> path=/etc/docker state=directory <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> changing Docker to systemd driver <span class="token key atrule">copy</span> <span class="token punctuation">:</span> <span class="token key atrule">dest</span> <span class="token punctuation">:</span> <span class="token string">"/etc/docker/daemon.json"</span> <span class="token key atrule">content</span> <span class="token punctuation">:</span> <span class="token punctuation">|</span><span class="token scalar string"> { "exec-opts": ["native.cgroupdriver=systemd"] }</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> install Docker <span class="token key atrule">apt</span> <span class="token punctuation">:</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> docker.io <span class="token key atrule">state</span> <span class="token punctuation">:</span> present <span class="token key atrule">update_cache</span> <span class="token punctuation">:</span> <span class="token boolean important">true</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> install APT Transport HTTPS <span class="token key atrule">apt</span> <span class="token punctuation">:</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> apt <span class="token punctuation">-</span> transport <span class="token punctuation">-</span> https <span class="token key atrule">state</span> <span class="token punctuation">:</span> present <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> add Kubernetes apt <span class="token punctuation">-</span> key <span class="token key atrule">apt_key</span> <span class="token punctuation">:</span> <span class="token key atrule">url</span> <span class="token punctuation">:</span> https <span class="token punctuation">:</span> //packages.cloud.google.com/apt/doc/apt <span class="token punctuation">-</span> key.gpg <span class="token key atrule">state</span> <span class="token punctuation">:</span> present <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> add Kubernetes' APT repository <span class="token key atrule">apt_repository</span> <span class="token punctuation">:</span> <span class="token key atrule">repo</span> <span class="token punctuation">:</span> deb http <span class="token punctuation">:</span> //apt.kubernetes.io/ kubernetes <span class="token punctuation">-</span> xenial main <span class="token key atrule">state</span> <span class="token punctuation">:</span> present <span class="token key atrule">filename</span> <span class="token punctuation">:</span> <span class="token string">'kubernetes'</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> install kubelet <span class="token key atrule">apt</span> <span class="token punctuation">:</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> kubelet=1.22.4 <span class="token punctuation">-</span> <span class="token number">00</span> <span class="token key atrule">state</span> <span class="token punctuation">:</span> present <span class="token key atrule">update_cache</span> <span class="token punctuation">:</span> <span class="token boolean important">true</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> install kubeadm <span class="token key atrule">apt</span> <span class="token punctuation">:</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> kubeadm=1.22.4 <span class="token punctuation">-</span> <span class="token number">00</span> <span class="token key atrule">state</span> <span class="token punctuation">:</span> present <span class="token punctuation">-</span> <span class="token key atrule">hosts</span> <span class="token punctuation">:</span> control_plane <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">tasks</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> install kubectl <span class="token key atrule">apt</span> <span class="token punctuation">:</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> kubectl=1.22.4 <span class="token punctuation">-</span> <span class="token number">00</span> <span class="token key atrule">state</span> <span class="token punctuation">:</span> present <span class="token key atrule">force</span> <span class="token punctuation">:</span> yes
Первая пьеса в сборнике пьес делает следующее:
-
Устанавливает Docker, среду выполнения контейнера, и настраивает параметры совместимости.
-
Устанавливает apt-transport-https
, позволяющий добавлять внешние источники HTTPS в список источников APT.
-
Добавляет apt-ключ репозитория Kubernetes APT для проверки ключа.
-
Добавляет репозиторий APT Kubernetes в список источников APT ваших удаленных серверов.
-
Устанавливает kubelet
и kubeadm
.
Второй этап состоит из одной задачи, которая устанавливает kubectl
на ваш узел плоскости управления.
Note: Хотя в документации Kubernetes рекомендуется использовать последнюю стабильную версию Kubernetes для вашей среды, в этом руководстве используется конкретная версия. Это гарантирует, что вы сможете успешно следовать инструкциям, поскольку Kubernetes быстро меняется, и последняя версия может не работать с этим руководством. Хотя «xenial» — это название Ubuntu 16.04, а это руководство предназначено для Ubuntu 20.04, Kubernetes по-прежнему ссылается на исходные коды пакетов Ubuntu 16.04 по умолчанию, и в данном случае они поддерживаются 20.04.
Сохраните и закройте файл, когда закончите.
Затем запустите плейбук локально с помощью следующей команды:
1
<ol><li data-prefix="$"> ansible-playbook <span class="token parameter variable">-i</span> хосты ~/kube-cluster/kube-dependents.yml</li></ol>
По завершении вы получите вывод, аналогичный следующему:
1
<div class="secondary-code-label" title="Выход"> Выход</div> ИГРАТЬ [все] **** ЗАДАЧА [Сбор фактов] **** ок: [рабочий1] ок: [рабочий2] ок: [контроль1] ЗАДАЧА [создать каталог конфигурации Docker] **** изменено: [контроль1] изменено: [worker1] изменено: [worker2] ЗАДАЧА [изменение Docker на драйвер systemd] **** изменено: [control1] изменено: [worker1] изменено: [worker2] ЗАДАЧА [установить Docker] **** изменено: [control1] изменено : [worker1] изменено: [worker2] ЗАДАЧА [установить APT Transport HTTPS] ***** ок: [control1] ок: [worker1] изменено: [worker2] ЗАДАЧА [добавить ключ Kubernetes apt] ***** изменено : [control1] изменен: [worker1] изменен: [worker2] TASK [добавить APT-репозиторий Kubernetes] ***** изменен: [control1] изменен: [worker1] изменен: [worker2] TASK [install kubelet] *** ** изменено: [control1] изменено: [worker1] изменено: [worker2] TASK [install kubeadm] ***** изменено: [control1] изменено: [worker1] изменено: [worker2] PLAY [control1] **** * ЗАДАЧА [Сбор фактов] ***** ок: [control1] ЗАДАЧА [install kubectl] ****** изменено: [control1] PLAY RECAP **** control1 : ok=11 изменено=9 недоступно=0 не удалось =0 рабочий1: ок=9 изменено=8 недостижимо=0 сбой=0 рабочий2 : ок=9 изменено=8 недостижимо=0 сбой=0
После запуска этой книги Docker, kubeadm
и kubelet
будут установлены на всех удаленных серверах. kubectl
не является обязательным компонентом и нужен только для выполнения команд кластера. В этом контексте имеет смысл установить его только на узле плоскости управления, поскольку вы будете запускать команды kubectl
только из плоскости управления. Однако обратите внимание, что команды kubectl
можно запускать с любого рабочего узла или с любого компьютера, где он может быть установлен и настроен для указания на кластер.
Все системные зависимости теперь установлены. Давайте настроим узел плоскости управления и инициализируем кластер.
Шаг 4 — Настройка узла плоскости управления
В этом разделе вы настроите узел плоскости управления. Однако прежде чем создавать какие-либо сборники сценариев, стоит рассмотреть несколько концепций, таких как модули и сетевые плагины для модулей, поскольку ваш кластер будет включать в себя и то, и другое.
Под — это атомарная единица, которая запускает один или несколько контейнеров. Эти контейнеры совместно используют такие ресурсы, как тома файлов и сетевые интерфейсы. Поды — это базовая единица планирования в Kubernetes: все контейнеры в поде гарантированно запускаются на том же узле, на котором запланирован под.
Каждый модуль имеет свой собственный IP-адрес, и модуль на одном узле должен иметь доступ к модулю на другом узле, используя IP-адрес модуля. Контейнеры на одном узле могут легко взаимодействовать через локальный интерфейс. Однако связь между модулями более сложна и требует отдельного сетевого компонента, который может прозрачно маршрутизировать трафик от модуля на одном узле к модулю на другом.
Эта функциональность обеспечивается плагинами сети модулей. Для этого кластера вы будете использовать Flannel — стабильный и производительный вариант.
Создайте плейбук Ansible с именем control-plane.yml
на своем локальном компьютере:
1
<ol><li data-prefix="$"> <span class="token function">нано</span> ~/kube-cluster/control-plane.yml</li></ol>
Добавьте в файл следующую команду для инициализации кластера и установки Flannel:
~/kube-cluster/control-plane.yml
1
<span class="token punctuation">---</span> <span class="token punctuation">-</span> <span class="token key atrule">hosts</span> <span class="token punctuation">:</span> control_plane <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">tasks</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> initialize the cluster <span class="token key atrule">shell</span> <span class="token punctuation">:</span> kubeadm init <span class="token punctuation">-</span> <span class="token punctuation">-</span> pod <span class="token punctuation">-</span> network <span class="token punctuation">-</span> cidr=10.244.0.0/16 <span class="token punctuation">></span> <span class="token punctuation">></span> cluster_initialized.txt <span class="token key atrule">args</span> <span class="token punctuation">:</span> <span class="token key atrule">chdir</span> <span class="token punctuation">:</span> $HOME <span class="token key atrule">creates</span> <span class="token punctuation">:</span> cluster_initialized.txt <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> create .kube directory <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">become_user</span> <span class="token punctuation">:</span> ubuntu <span class="token key atrule">file</span> <span class="token punctuation">:</span> <span class="token key atrule">path</span> <span class="token punctuation">:</span> $HOME/.kube <span class="token key atrule">state</span> <span class="token punctuation">:</span> directory <span class="token key atrule">mode</span> <span class="token punctuation">:</span> <span class="token number">0755</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> copy admin.conf to user's kube config <span class="token key atrule">copy</span> <span class="token punctuation">:</span> <span class="token key atrule">src</span> <span class="token punctuation">:</span> /etc/kubernetes/admin.conf <span class="token key atrule">dest</span> <span class="token punctuation">:</span> /home/ubuntu/.kube/config <span class="token key atrule">remote_src</span> <span class="token punctuation">:</span> yes <span class="token key atrule">owner</span> <span class="token punctuation">:</span> ubuntu <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> install Pod network <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">become_user</span> <span class="token punctuation">:</span> ubuntu <span class="token key atrule">shell</span> <span class="token punctuation">:</span> kubectl apply <span class="token punctuation">-</span> f https <span class="token punctuation">:</span> //raw.githubusercontent.com/coreos/flannel/master/Documentation/kube <span class="token punctuation">-</span> flannel.yml <span class="token punctuation">></span> <span class="token punctuation">></span> pod_network_setup.txt <span class="token key atrule">args</span> <span class="token punctuation">:</span> <span class="token key atrule">chdir</span> <span class="token punctuation">:</span> $HOME <span class="token key atrule">creates</span> <span class="token punctuation">:</span> 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
в домашний каталог пользователя без полномочий root. Это позволит вам использовать kubectl
для доступа к вновь созданному кластеру.
-
Последняя задача запускает kubectl apply
для установки Flannel
. kubectl apply -f descriptor.[yml|json]
— это синтаксис, указывающий kubectl
на создание объектов, описанных в файле descriptor.[yml|json]
. Файл kube-flannel.yml
содержит описания объектов, необходимых для настройки Flannel
в кластере.
Сохраните и закройте файл, когда закончите.
Запустите playbook локально с помощью следующей команды:
1
<ol><li data-prefix="$"> ansible-playbook <span class="token parameter variable">-i</span> хосты ~/kube-cluster/control-plane.yml</li></ol>
По завершении вы увидите вывод, аналогичный следующему:
1
<div class="secondary-code-label" title="Выход"> Выход</div> ИГРА [управление1] **** ЗАДАЧА [Сбор фактов] **** ок: [управление1] ЗАДАЧА [инициализировать кластер] **** изменено: [управление1] ЗАДАЧА [создать каталог .kube] **** изменено: [control1] ЗАДАЧА [копировать admin.conf в конфигурацию kube пользователя] ***** изменено: [control1] ЗАДАЧА [установить сеть Pod] ***** изменено: [control1] PLAY RECAP **** control1 : ok= 5 изменено=4 недостижимо=0 не удалось=0
Чтобы проверить состояние узла плоскости управления, подключитесь к нему по SSH с помощью следующей команды:
1
<ol><li data-prefix="$"> <span class="token function">ssh</span> убунту@<mark> control_plane_ip</mark></li></ol>
Оказавшись внутри узла плоскости управления, выполните:
1
<ol><li data-prefix="$"> kubectl получить узлы</li></ol>
Теперь вы увидите следующий вывод:
1
<div class="secondary-code-label" title="Выход"> Выход</div> ИМЯ СТАТУС РОЛИ ВОЗРАСТ ВЕРСИЯ control1 Готовая плоскость управления,master 51s v1.22.4
Note: Начиная с Ubuntu 20.04, kubernetes находится в процессе обновления своей старой терминологии. Узел, который мы в этом руководстве называли control-plane
раньше назывался master
узлом, и иногда вы можете увидеть, как Kubernetes назначает обе роли одновременно из соображений совместимости.
В выходных данных указывается, что узел control-plane
выполнил все задачи инициализации и находится в состоянии Ready
, из которого он может начать принимать рабочие узлы и выполнять задачи, отправленные на сервер API. Теперь вы можете добавить работников со своей локальной машины.
Шаг 5 — Настройка рабочих узлов
Добавление воркеров в кластер предполагает выполнение для каждого из них одной команды. Эта команда включает необходимую информацию о кластере, такую как IP-адрес и порт API-сервера плоскости управления, а также безопасный токен. Только узлы, передавшие безопасный токен, смогут присоединиться к кластеру.
Вернитесь в свою рабочую область и создайте книгу с именем workers.yml
:
1
<ol><li data-prefix="$"> <span class="token function">нано</span> ~/kube-cluster/workers.yml</li></ol>
Добавьте в файл следующий текст, чтобы добавить рабочие процессы в кластер:
~/kube-cluster/workers.yml
1
<span class="token punctuation">---</span> <span class="token punctuation">-</span> <span class="token key atrule">hosts</span> <span class="token punctuation">:</span> control_plane <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">gather_facts</span> <span class="token punctuation">:</span> <span class="token boolean important">false</span> <span class="token key atrule">tasks</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> get join command <span class="token key atrule">shell</span> <span class="token punctuation">:</span> kubeadm token create <span class="token punctuation">-</span> <span class="token punctuation">-</span> print <span class="token punctuation">-</span> join <span class="token punctuation">-</span> command <span class="token key atrule">register</span> <span class="token punctuation">:</span> join_command_raw <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> set join command <span class="token key atrule">set_fact</span> <span class="token punctuation">:</span> <span class="token key atrule">join_command</span> <span class="token punctuation">:</span> <span class="token string">"{{ join_command_raw.stdout_lines[0] }}"</span> <span class="token punctuation">-</span> <span class="token key atrule">hosts</span> <span class="token punctuation">:</span> workers <span class="token key atrule">become</span> <span class="token punctuation">:</span> yes <span class="token key atrule">tasks</span> <span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token key atrule">name</span> <span class="token punctuation">:</span> join cluster <span class="token key atrule">shell</span> <span class="token punctuation">:</span> <span class="token string">"{{ hostvars['control1'].join_command }} >> node_joined.txt"</span> <span class="token key atrule">args</span> <span class="token punctuation">:</span> <span class="token key atrule">chdir</span> <span class="token punctuation">:</span> $HOME <span class="token key atrule">creates</span> <span class="token punctuation">:</span> node_joined.txt
Вот что делает playbook:
-
Первая игра получает команду соединения, которую необходимо запустить на рабочих узлах. Эта команда будет иметь следующий формат: kubeadm join --token : --discovery-token-ca-cert-hash sha256:
. Как только она получает фактическую команду с правильными значениями token и hash функции, задача устанавливает ее как факт, чтобы следующая игра могла получить доступ к этой информации.
-
Во второй игре есть единственная задача, которая запускает команду соединения на всех рабочих узлах. По завершении этой задачи два рабочих узла станут частью кластера.
Сохраните и закройте файл, когда закончите.
Запустите playbook локально с помощью следующей команды:
1
<ol><li data-prefix="$"> ansible-playbook <span class="token parameter variable">-i</span> хосты ~/kube-cluster/workers.yml</li></ol>
По завершении вы увидите вывод, аналогичный следующему:
1
<div class="secondary-code-label" title="Выход"> Выход</div> PLAY [control1] **** TASK [получить команду соединения] **** изменено: [control1] TASK [установить команду соединения] ***** ок: [control1] PLAY [рабочие] ***** TASK [ Сбор фактов] ***** ок: [рабочий1] ок: [рабочий2] ЗАДАЧА [присоединиться к кластеру] ***** изменено: [рабочий1] изменено: [рабочий2] ИГРАТЬ РЕЗЮМЕ ***** контроль1 : ок=2 изменено=1 недоступно=0 сбой=0 рабочий1: ок=2 изменено=1 недоступно=0 сбой=0 рабочий2 : ок=2 изменено=1 недостижимо=0 сбой=0
С добавлением рабочих узлов ваш кластер теперь полностью настроен и функционален, а рабочие узлы готовы выполнять рабочие нагрузки. Прежде чем планировать приложения, давайте проверим, что кластер работает должным образом.
Шаг 6 — Проверка кластера
Иногда кластер может выйти из строя во время установки, поскольку узел не работает или сетевое соединение между плоскостью управления и рабочими процессами работает неправильно. Давайте проверим кластер и убедимся, что узлы работают корректно.
Вам нужно будет проверить текущее состояние кластера на узле плоскости управления, чтобы убедиться, что узлы готовы. Если вы отключились от узла плоскости управления, вы можете вернуться к нему по SSH с помощью следующей команды:
1
<ol><li data-prefix="$"> <span class="token function">ssh</span> убунту@<mark> control_plane_ip</mark></li></ol>
Затем выполните следующую команду, чтобы получить статус кластера:
1
<ol><li data-prefix="$"> kubectl получить узлы</li></ol>
Вы увидите вывод, аналогичный следующему:
1
<div class="secondary-code-label" title="Выход"> Выход</div> ИМЯ СТАТУС РОЛЬ ВОЗРАСТ ВЕРСИЯ контроль1 Готов плоскость управления,главный 3м21с v1.22.0 рабочий1 Готов <нет> 32 с v1.22.0 рабочий2 Готов <нет> 32 с v1.22.0
Если все ваши узлы имеют значение Ready
для STATUS
, это означает, что они являются частью кластера и готовы выполнять рабочие нагрузки.
Однако если некоторые узлы имеют NotReady
в качестве STATUS
, это может означать, что рабочие узлы еще не завершили настройку. Подождите примерно пять-десять минут, прежде чем повторно запустить kubectl get nodes
и проверить новый вывод. Если несколько узлов по-прежнему имеют статус NotReady
, возможно, вам придется проверить и повторно выполнить команды, выполненные на предыдущих шагах.
Теперь, когда ваш кластер успешно проверен, давайте запланируем в кластере пример приложения Nginx.
Шаг 7 — Запуск приложения в кластере
Теперь вы можете развернуть любое контейнерное приложение в своем кластере. Чтобы все было знакомо, давайте развернем Nginx с помощью Deployments and Services, чтобы изучить, как это приложение можно развернуть в кластере. Вы также можете использовать приведенные ниже команды для других контейнерных приложений при условии, что вы измените имя образа Docker и все соответствующие флаги (например ports
и volumes
).
Убедитесь, что вы вошли в узел плоскости управления, а затем выполните следующую команду, чтобы создать развертывание с именем nginx
:
1
<ol><li data-prefix="$"> kubectl создать развертывание<mark> nginx</mark> <span class="token parameter variable">--изображение</span> <span class="token operator">=</span><mark> nginx</mark></li></ol>
Развертывание — это тип объекта Kubernetes, который гарантирует, что всегда будет работать определенное количество модулей на основе определенного шаблона, даже если модуль выйдет из строя во время существования кластера. В приведенном выше развертывании будет создан модуль с одним контейнером из образа Nginx Docker из реестра Docker.
Затем выполните следующую команду, чтобы создать службу с именем nginx
, которая будет предоставлять доступ к приложению публично. Это будет сделано через NodePort — схему, которая сделает модуль доступным через произвольный порт, открытый на каждом узле кластера:
1
<ol><li data-prefix="$"> kubectl выставляет развертывание<mark> nginx</mark> <span class="token parameter variable">--порт</span><mark> <span class="token number">80</span></mark> --target-порт<mark> <span class="token number">80</span></mark> <span class="token parameter variable">--type</span> НодПорт</li></ol>
Службы — это еще один тип объекта Kubernetes, который предоставляет внутренние службы кластера клиентам, как внутренним, так и внешним. Они также способны распределять запросы к нескольким модулям и являются неотъемлемым компонентом Kubernetes, часто взаимодействуя с другими компонентами.
Выполните следующую команду:
1
<ol><li data-prefix="$"> kubectl получить сервисы</li></ol>
Эта команда выведет текст, подобный следующему:
1
<div class="secondary-code-label" title="Выход"> Выход</div> ИМЯ ТИП CLUSTER-IP ВНЕШНИЙ IP-ПОРТЫ ВОЗРАСТ kubernetes ClusterIP 10.96.0.1 <нет> 443/TCP 1d<mark> nginx</mark> NodePort 10.109.228.209 <нет> 80:<mark> nginx_port</mark> /TCP 40 м
Из выделенной строки приведенного выше вывода вы можете получить порт, на котором работает Nginx. Kubernetes автоматически назначит случайный порт с номером больше 30000
, гарантируя при этом, что порт еще не привязан к другой службе.
Чтобы проверить, что все работает, посетите http:// worker_1_ip : nginx_port
или http:// worker_2_ip : nginx_port
через браузер на локальном компьютере. Вы увидите знакомую страницу приветствия Nginx.
Если вы хотите удалить приложение Nginx, сначала удалите службу nginx
из узла плоскости управления:
1
<ol><li data-prefix="$"> <span class="token function">служба</span> удаления kubectl<mark> nginx</mark></li></ol>
Выполните следующее, чтобы убедиться, что служба удалена:
1
<ol><li data-prefix="$"> kubectl получить сервисы</li></ol>
Вы увидите следующий результат:
1
<div class="secondary-code-label" title="Выход"> Выход</div> ИМЯ ТИП CLUSTER-IP ВНЕШНИЙ IP-ПОРТЫ ВОЗРАСТ kubernetes ClusterIP 10.96.0.1 <нет> 443/TCP 1d
Затем удалите развертывание:
1
<ol><li data-prefix="$"> kubectl удалить развертывание<mark> nginx</mark></li></ol>
Запустите следующее, чтобы убедиться, что это сработало:
1
<ol><li data-prefix="$"> kubectl получить развертывания</li></ol>
1
<div class="secondary-code-label" title="Выход"> Выход</div> Ресурсы не найдены.
Заключение
В этом руководстве вы успешно настроили кластер Kubernetes в Ubuntu 20.04, используя Kubeadm и Ansible для автоматизации.
Если вы задаетесь вопросом, что делать с кластером теперь, когда он настроен, следующим хорошим шагом будет комфортное развертывание собственных приложений и служб в кластере. Вот список ссылок с дополнительной информацией, которая может помочь вам в этом процессе:
-
Докеризация приложений — список примеров, в которых подробно описывается, как контейнеризировать приложения с помощью Docker.
-
Обзор Pod — подробно описывает, как работают Pod и их связь с другими объектами Kubernetes. Поды широко распространены в Kubernetes, поэтому их понимание облегчит вашу работу.
-
Обзор развертываний — предоставляет обзор развертываний. Полезно понимать, как работают контроллеры, такие как развертывания, поскольку они часто используются в приложениях без отслеживания состояния для масштабирования и автоматического восстановления неработоспособных приложений.
-
Обзор служб — охватывает службы, еще один часто используемый объект в кластерах Kubernetes. Понимание типов сервисов и имеющихся у них опций необходимо для запуска приложений как без отслеживания, так и с сохранением состояния.
Другими важными понятиями, которые вы можете изучить, являются тома, входы и секреты, которые пригодятся при развертывании производственных приложений.
Kubernetes предлагает множество функций и возможностей. Официальная документация Kubernetes — лучшее место, где можно узнать о концепциях, найти руководства для конкретных задач и найти ссылки на API для различных объектов. Вы также можете ознакомиться с нашей учебной программой Kubernetes для Full-Stack разработчиков.