Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи?

Написать
Войти
Дайджесты
Ansible AWX в Kubernetes управляет OpenStack-проектами через изолированные execution nodes

Ansible AWX в Kubernetes: развертывание, динамический инвентарь OpenStack и air-gap установка

Практическое руководство по развертыванию Ansible AWX на K3s, решению проблем с резолвингом имен в CoreDNS и настройке динамического инвентаря. Рассматриваются методы выбора SSH-пользователей для виртуальных машин, изоляция сетей с помощью Receptor-нод и организация полностью автономного развертывания.

Ansible AWX в Kubernetes: развертывание, динамический инвентарь OpenStack и air-gap установка

Ansible AWX — это бесплатная версия Red Hat Ansible Automation Platform с графическим веб-интерфейсом (Web UI) для запуска плейбуков (playbooks), управления доступами (credentials) и списками хостов (inventories). Рекомендуемый способ установки AWX — через оператор (AWX Operator). В этом руководстве мы разберем развертывание AWX на K3s (облегченном Kubernetes), настроим динамический импорт из OpenStack, решим сопутствующие проблемы с DNS, настроим выполнение задач через Receptor-ноды и организуем установку в закрытом сетевом контуре (air-gap).


1. Предварительные требования

Для стенда потребуется сервер с Ubuntu 22.04 LTS, 4 vCPU и 8 ГБ RAM. Для установки нужен доступ с правами sudo и подключение к интернету для загрузки образов.


2. Установка K3s и развертывание AWX Operator

Шаг 2.1: Установка K3s

Установите K3s (облегченный дистрибутив Kubernetes) на сервере автоматизации:

curl -sfL https://get.k3s.io | sh -

Проверьте узел:

sudo kubectl get nodes
Шаг 2.2: Клонирование AWX Operator

Склонируйте репозиторий оператора и переключитесь на тег 2.19.1 по руководству AWX Operator Basic Install:

git clone https://github.com/ansible/awx-operator.git
cd awx-operator
git checkout tags/2.19.1
Шаг 2.3: Развертывание оператора

Разверните оператор в кластере:

make deploy

Создайте пространство имен awx и сделайте его контекстом по умолчанию:

kubectl create namespace awx
kubectl config set-context --current --namespace=awx
Шаг 2.4: Запуск инстанса AWX

Создайте манифест awx-instance.yaml с описанием AWX-ресурса:

apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: awx-instance
spec:
  service_type: NodePort

Создайте kustomization.yaml для объединения ресурсов:

resources:
  - awx-instance.yaml

Примените манифесты:

kubectl apply -k .

Ход установки можно отслеживать по логам менеджера:

kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager

Успешный результат: Поды веб-интерфейса и задач перейдут в статус Running.

Шаг 2.5: Получение пароля администратора

Получите сгенерированный пароль для пользователя admin из секретов Kubernetes:

kubectl get secret awx-instance-admin-password -o jsonpath="{.data.password}" | base64 --decode

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


3. Настройка OpenStack Inventory и DNS-резолвинга

Для синхронизации хостов из облака OpenStack настройте сетевую доступность и учетные записи.

Шаг 3.1: Настройка CoreDNS

Поды AWX в кластере Kubernetes часто не могут разрешить внутренние доменные имена OpenStack. Для исправления отредактируйте конфигурационную карту CoreDNS (внутреннего DNS-сервера кластера):

kubectl edit configmap coredns -n kube-system

В блок NodeHosts добавьте соответствие внутренних адресов и имен ваших API-серверов:

192.168.10.15 openstack.corp.local

Перезапустите сервис DNS:

kubectl rollout restart deployment coredns -n kube-system

Проверить разрешение имен можно из тестового пода утилитой nslookup.

Шаг 3.2: Настройка Credential Type в AWX

Для безопасного хранения параметров доступа к облаку создайте кастомный Credential Type. Поля ввода (Input Fields):

{
  "fields": [
    { "id": "username", "type": "string", "label": "Username" },
    { "id": "password", "type": "string", "label": "Password", "secret": true },
    { "id": "project_name", "type": "string", "label": "Project Name" },
    { "id": "auth_url", "type": "string", "label": "Auth URL" },
    { "id": "region_name", "type": "string", "label": "Region Name" }
  ]
}

Конфигурация инжектора (передача переменных в среду исполнения плейбуков):

{
  "env": {
    "OS_USERNAME": "{{ username }}",
    "OS_PASSWORD": "{{ password }}",
    "OS_PROJECT_NAME": "{{ project_name }}",
    "OS_AUTH_URL": "{{ auth_url }}",
    "OS_REGION_NAME": "{{ region_name }}"
  }
}
Шаг 3.3: Создание динамического источника хостов

В настройках инвентаря AWX добавьте источник со следующими переменными плагина согласно официальному описанию OpenStack inventory source:

plugin: openstack.cloud.openstack
cloud: myopenstack
expand_hostvars: true
fail_on_errors: true
all_projects: true

Успешный результат: При запуске синхронизации AWX успешно импортирует список виртуальных машин без ошибок DNS.


4. Динамический выбор SSH-пользователей

Поскольку виртуальные машины в OpenStack разворачиваются из разных образов, дефолтные пользователи для подключения по SSH могут отличаться (ubuntu, centos, cloud-user).

Для автоматического выбора используйте один из вариантов:

  • Вариант А: Запустите в начале плейбука динамический выбор на основе собранных фактов:
    - name: Set ansible_user dynamically
      set_fact:
        ansible_user: >-
          {{ ansible_env.SUDO_USER | default(ansible_user_id, true) | default('ubuntu') }}
    
  • Вариант Б: Считывайте переменные хоста image_name из OpenStack и через фильтр regex_replace подставляйте соответствующее имя пользователя.
  • Вариант В: Настройте периодический запуск скрипта, который опрашивает API облака, сопоставляет IP с пользователями из файла ip_user_map.json и updates переменных хостов в AWX через его API.

5. Сетевая изоляция с Receptor-нодами (Automation Mesh)

Если часть виртуальных машин OpenStack находится за файрволами в изолированных подсетях, настройте Receptor — сетевой демон для маршрутизации задач.

Согласно руководству AWX Managing Capacity With Instances, узлы делятся на роли:

  • Control node: управляет распределением задач и интерфейсом.
  • Hop node: транслирует зашифрованный трафик между подсетями.
  • Execution node: принимает команды по протоколу Receptor и запускает задачи на месте.

Для подключения ноды:

  1. В интерфейсе AWX в разделе Instances добавьте новый узел типа execution.
  2. Скачайте архив инсталлятора (install bundle).
  3. На управляющей машине установите коллекцию ansible.receptor.
  4. Распакуйте архив, впишите IP и пользователя в inventory.yml и запустите плейбук:
    ansible-playbook -i inventory.yml install_receptor.yml
    
  5. После проверки статуса (Healthy в интерфейсе) создайте Instance Group и привяжите к ней плейбуки.

6. Сборка кастомного Execution Environment (EE)

Если плейбукам требуются дополнительные коллекции, соберите собственный образ среды выполнения.

Создайте файл execution-environment.yml согласно стандарту Ansible Builder Definition:

version: 3
images:
  base_image:
    name: quay.io/ansible/awx-ee:latest
dependencies:
  galaxy:
    collections:
      - openstack.cloud
  python:
    - openstacksdk>=1.0.0
    - netaddr

Соберите образ:

ansible-builder build -v3 -t internal-registry.local/awx/ee-openstack:latest

Отправьте его в локальный репозиторий и добавьте в AWX как новый Execution Environment.


7. Офлайн-установка (Air-Gap) в изолированном контуре

Для развертывания платформы на серверах без прямого доступа к интернету подготовьте зеркала дистрибутивов.

Шаг 7.1: Локальное зеркалирование образов

Скачайте tar-архив с образами плейбуков K3s со страницы релизов K3s Air-Gap Install и перенесите на сервер:

sudo mkdir -p /var/lib/rancher/k3s/agent/images/
sudo cp k3s-airgap-images-amd64.tar.zst /var/lib/rancher/k3s/agent/images/

Разверните локальный Docker Registry v2 для кэширования образов AWX Operator, PostgreSQL и AWX-компонентов.

Шаг 7.2: Настройка K3s Private Registry

Создайте на каждом сервере файл /etc/rancher/k3s/registries.yaml согласно K3s Private Registry Configuration:

mirrors:
  docker.io:
    endpoint:
      - "https://internal-registry.local"
  quay.io:
    endpoint:
      - "https://internal-registry.local"
configs:
  "internal-registry.local":
    auth:
      username: registry_user
      password: registry_password

8. Калькуляция мощностей и forks capacity

Для защиты сервера от перегрузки лимиты параллельных задач (capacity forks) рассчитываются по двум метрикам, после чего выбирается наименьшее значение:

  • По процессору: CPU Cores * 4
  • По оперативной памяти: RAM в МБ / 100

Для сервера с 4 vCPU и 16 ГБ RAM лимит по процессору составит 16 параллельных процессов, а лимит по памяти — 163. Система автоматически выберет ограничение в 16 одновременных forks.