В предыдущей статье “vRA 8: интеграция с Ansible” тестируется использование Ansible для настройки серверов в vRealize Automation 8. Проверим, как это работает на реальной задаче – развертывание кластера kubernetes. Существует большой выбор готовых плейбуков Ansible, один из самых продвинутых – Kubespray. Разработаем блюпринт vRA для создания кластера K8S с помощью Kubespray.
Kubespray. Настройка и первый запуск
Kubespray – готовый к использованию комплект плейбуков и ролей Ansible для установки и конфигурации кластера kubernetes.
Описание проекта: https://kubespray.io/
Загрузка кода: https://github.com/kubernetes-sigs/kubespray.
Основные преимущества Kubespray (по мнению команды разработчиков):
- Создание высокодоступных кластеров;
- Возможность выбора компонентов и гибкой настройки;
- Поддержка самых популярных Linux-дистрибутивов;
- Развёртывание как на железе, так и в различных облачных платформах.
Прежде чем приступать к запуску Kubespray через vRA, обязательно сделайте тестовое развёртывание кластера K8S: скачайте Kubespray, закажите через vRA несколько VM и запустите установку. Скорее всего, потребуется Ваше вмешательство для устранения непредвиденных ошибок.
- Используем сервер с Ansible, настроенный ранее: vRA 8: интеграция с Ansible;
- локальный пользователь ansible;
- Kubespray загружен в ~/playbooks/kubespray;
- доступ к настраиваемым серверам по ключу, удалённый пользователь на нодах также ansible;
- ОС на виртуальных машинах Ubuntu 18.04 (несмотря на заявленную “поддержку самых популярных дистрибутивов”, на CentOS 7/8 у меня так и не завелось).
# Установите зависимости по списку из ``requirements.txt``
sudo pip3 install -r requirements.txt
# В директории ``inventory/sample`` находятся конфигурационные файлы
# Скопируйте ``inventory/sample`` в ``inventory/vra``
cp -rfp inventory/sample inventory/vra
# Создайте файл инвентори с помощью inventory builder
declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
CONFIG_FILE=inventory/vra/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
# Изучите получаемый файл inventory/vra/hosts.yaml для разного количества VM
# Две мастер-ноды, 1 или 3 ноды с etcd, все ноды рабочие
# Изучите и откорректируйте параметры в файлах ``inventory/vra/group_vars/``
cat inventory/vra/group_vars/all/all.yml
cat inventory/vra/group_vars/k8s-cluster/k8s-cluster.yml
# Развёртывание Kubespray с Ansible Playbook
ansible-playbook -i inventory/vra/hosts.yaml --become --become-user=root cluster.yml
# Если имя пользователя на нодах отличается от имени локального пользователя,
# то добавьте --user=<имя пользователя>
Плейбук запуска Kubespray
Для развёртывания кластера kubernetes при помощи vRA и Kubespray требуется автоматизировать:
- Клонирование директории с настройками Kubespray, копировать будем из inventory/vra/;
- Генерирование файла инвентори;
- Правку конфигурационных файлов по выбранным пользователем значениям;
- Запуск развёртывания кластера.
Все перечисленные операции будут выполняются локально, поэтому в плейбуке connection == local. Текст плейбука для развёртывания кластера (описанные ниже ansible-плейбуки и код блюпринта доступны на https://github.com/isas2/vra):
# ~/playbooks/kubespray/vra_deploy.yaml - name: Deploy K8S cluster hosts: kubespray connection: local roles: - kwoodson.yedit tasks: - name: "01. Create new inventory" copy: src=inventory/vra/ dest=inventory/{{ inventoryName }}/ - name: "02. Create hostlist file" file: path: inventory/{{ inventoryName }}/vra_hosts state: touch - name: "03. Write to hostlist first master-node IP" lineinfile: path: inventory/{{ inventoryName }}/vra_hosts line: "{{ ipAddressMn }}" - name: "04. Write to hostlist all node IPs" lineinfile: path: inventory/{{ inventoryName }}/vra_hosts line: "{{ item }}" loop: "{{ ipAddressWn }}" - name: "05. Exclude pods subnets" shell: sed -i '/^10\.233\./d' inventory/{{ inventoryName }}/vra_hosts - name: "06. Create Inventory File" shell: CONFIG_FILE=inventory/{{ inventoryName }}/hosts.yaml python3 contrib/inventory_builder/inventory.py $(cat inventory/{{ inventoryName }}/vra_hosts) - name: "07. Enable external cloud provider" yedit: src: inventory/{{ inventoryName }}/group_vars/all/all.yml key: cloud_provider value: "external" when: vcpIstall == true - name: "08. Set external cloud provider name" yedit: src: inventory/{{ inventoryName }}/group_vars/all/all.yml key: external_cloud_provider value: "vsphere" when: vcpIstall == true - name: "09. Enable vSphere CSI" yedit: src: inventory/{{ inventoryName }}/group_vars/all/vsphere.yml key: vsphere_csi_enabled value: true when: vcpIstall == true - name: "10. Set network plugin" yedit: src: inventory/{{ inventoryName }}/group_vars/k8s-cluster/k8s-cluster.yml key: kube_network_plugin value: "{{ netPlugin }}" - name: "11. Wait a nodes" shell: sleep 1m - name: "12. Start Kubespray deploy" shell: /usr/bin/ansible-playbook -i inventory/{{ inventoryName }}/hosts.yaml --become --become-user=root cluster.yml
- Для работы с файлами yaml используется модуль yedit (установка kwoodson.yedit);
- 01: Поскольку кластер может быть не один и настройки у них могут отличаться, то для каждого создаём отдельный инвентори. Необходимо обеспечить генерацию и передачу уникального значения в переменную inventoryName;
- 02 – 05: Создание файла со списком IP-адресов виртуальных машин, мастер-ноды в начале списка;
- 06: Создание файла инвентори, на вход скрипту передан файл vra_hosts со списком IP всех нод;
- 07 – 09: Включение vSphere Cloud Provider, если переменная vcpIstall == true. В файле inventory/vra/group_vars/all/vsphere.yml должны быть заполнены поля для соединения с vCenter, кроме поля vsphere_csi_enabled;
- 10: Установка имени сетевого плагина;
- 11: Небольшая задержка запуска, были случаи старта плейбука до полной готовности хостов (можно предусмотреть перед всеми запусками плейбуков vRA – Ansible).
При удалении кластера нужно удалить и каталог с его инвертори:
# ~/playbooks/kubespray/vra_destroy.yaml
- name: Destroy cluster
hosts: kubespray
connection: local
tasks:
- name: "Delete inventory directory"
file:
path: inventory/{{ inventoryName }}/
state: absent
Блюпринт vRA
Kubespray по умолчанию создаёт две мастер-ноды, но на схеме всего одна. Это связано с особенностью запуска плейбуков: сколько VM, столько и плейбуков, что нам не подходит. В качестве второй мастер-ноды будет использована первая VM из рабочих нод.
formatVersion: 1 name: K8S cluster with Ansible and Kybespray version: 1 inputs: workerNodes: type: integer default: 2 minimum: 1 maximum: 5 title: Number worker nodes nodeSize: type: string enum: - small - medium - large default: small title: Node size vcpIstall: type: boolean default: false title: Install vSphere cloud provider netPlugin: type: string enum: - calico - flannel - weave default: calico title: Select network plugin resources: K8S-Install: type: Cloud.Ansible dependsOn: - WorkerVM properties: inventoryFile: ~/hosts username: ansible privateKeyFile: ~/.ssh/id_rsa playbooks: provision: - ~/playbooks/kubespray/vra_deploy.yaml de-provision: - /home/ansible/playbooks/kubespray/vra_destroy.yaml hostVariables: | inventoryName: ${to_lower(join([env.projectName, env.requestedBy, env.deploymentId], '-'))} ipAddressWn: ${resource.WorkerVM.address} ipAddressMn: ${resource.MasterVM.address} vcpIstall: ${input.vcpIstall} netPlugin: ${input.netPlugin} osType: linux groups: - kubespray maxConnectionRetries: 10 host: '${resource.MasterVM.*}' account: Ansible (vra-ssh) MasterVM: type: Cloud.Machine properties: image: Ubuntu_18 flavor: '${input.nodeSize}' customizationSpec: tmp-linux-vra networks: - network: '${resource.NetworkVM.id}' assignment: static WorkerVM: type: Cloud.Machine dependsOn: - MasterVM properties: count: '${input.workerNodes}' image: Ubuntu_18 flavor: '${input.nodeSize}' customizationSpec: tmp-linux-vra networks: - network: '${resource.NetworkVM.id}' assignment: static NetworkVM: type: Cloud.vSphere.Network properties: networkType: existing
- В playbooks.provision и playbooks.de-provision укажите пути до плейбуков. Обратите внимание, что путь в de-provision указан абсолютный, с относительным он у меня не запускался (возможно просто глюк, проверьте у себя);
- Переменная inventoryName – имя каталога инвентори: передаётся строка из имени проекта, имени пользователя и ID развёртывания. Если у Вас названия проектов длинные, то можете их не добавлять.
Управление кластером
Что дальше? Попробуйте доработать эти примеры для использования возможностей масштабирования и обновления кластеров (scale.yml, upgrade-cluster.yml).
Первое препятствие на данном пути – сам vRA. После установки кластера Kubernetes он начинает видеть на виртуальных машинах дополнительные IP-адреса из подсети K8S (для Kubespray по умолчанию это 10.233.64.0/18). Эти IP-адреса vRA начинает отображать в описании деплоймента и использовать при вызовах плейбуков ansible. Если при установке кластера использовался один IP, а для обновления передаётся другой, то такой хост не будет найден в инвентори.
- Добавьте в файл инвентори все хосты по маске: 10.233.[64:127].0;
- В плейбуке vra_deploy.yaml есть специальный пункт “05. Exclude pods subnets”, который исключает эти адреса из файла инвентори Kubespray.
Все использованные в статье плейбуки ansible и код блюпринта vRA доступны на https://github.com/isas2/vra.