--- - name: Deploy latest stable AWX using AWX Operator on Kubernetes hosts: localhost connection: local become: false gather_facts: false vars: # Основные параметры — лучше переопределять в Semaphore Variable Group awx_namespace: "{{ awx_namespace | default('awx') }}" awx_instance_name: "{{ awx_instance_name | default('awx') }}" awx_service_type: "{{ awx_service_type | default('NodePort') }}" # NodePort / ClusterIP / LoadBalancer awx_operator_version: "{{ awx_operator_version | default('2.19.1') }}" # 2.19.1 → AWX 24.6.x (последняя стабильная на конец 2025) # Путь к kubeconfig внутри контейнера Semaphore kubeconfig_path: "/home/semaphore/.kube/config" tasks: - name: Fail if kubeconfig not found ansible.builtin.stat: path: "{{ kubeconfig_path }}" register: kubeconfig_stat failed_when: not kubeconfig_stat.stat.exists delegate_to: localhost - name: Install kubernetes python library (fallback) ansible.builtin.pip: name: kubernetes>=25.3.0 state: present delegate_to: localhost ignore_errors: true # если уже стоит через /etc/semaphore/requirements.txt - name: Create namespace for AWX kubernetes.core.k8s: state: present kubeconfig: "{{ kubeconfig_path }}" definition: apiVersion: v1 kind: Namespace metadata: name: "{{ awx_namespace }}" - name: Apply AWX Operator (via kustomize from github) ansible.builtin.command: cmd: >- kubectl apply -k "github.com/ansible/awx-operator/config/default?ref={{ awx_operator_version }}" creates: "{{ kubeconfig_path }}" # dummy — чтобы не повторять каждый раз environment: KUBECONFIG: "{{ kubeconfig_path }}" changed_when: true register: operator_apply failed_when: operator_apply.rc != 0 and 'already exists' not in operator_apply.stderr - name: Wait for AWX Operator deployment to be ready kubernetes.core.k8s_info: kubeconfig: "{{ kubeconfig_path }}" api_version: apps/v1 kind: Deployment name: awx-operator-controller-manager namespace: "{{ awx_namespace }}" register: operator_status until: >- operator_status.resources[0].status.readyReplicas is defined and operator_status.resources[0].status.readyReplicas == operator_status.resources[0].status.replicas retries: 40 delay: 15 - name: Deploy AWX instance kubernetes.core.k8s: state: present kubeconfig: "{{ kubeconfig_path }}" definition: apiVersion: awx.ansible.com/v1beta1 kind: AWX metadata: name: "{{ awx_instance_name }}" namespace: "{{ awx_namespace }}" spec: service_type: "{{ awx_service_type }}" # Можно добавить/раскомментировать по необходимости: # ingress_type: Ingress # ingress_hostname: awx.your-domain.com # ingress_class_name: nginx # replicas: 1 # projects_persistence: true # projects_storage_class: standard # projects_storage_size: 10Gi - name: Wait for AWX pods to become ready (up to ~10–15 minutes) kubernetes.core.k8s_info: kubeconfig: "{{ kubeconfig_path }}" kind: Pod namespace: "{{ awx_namespace }}" label_selectors: - "app.kubernetes.io/managed-by=awx-operator" - "app.kubernetes.io/name={{ awx_instance_name }}" register: awx_pods until: >- awx_pods.resources | selectattr('status.phase', 'equalto', 'Running') | list | length >= 2 and (awx_pods.resources | selectattr('status.conditions', 'search', 'type: Ready, status: True') | list | length >= 2) retries: 60 delay: 20 - name: Get AWX admin password from secret kubernetes.core.k8s_info: kubeconfig: "{{ kubeconfig_path }}" api_version: v1 kind: Secret name: "{{ awx_instance_name }}-admin-password" namespace: "{{ awx_namespace }}" register: awx_admin_secret - name: Show AWX access information ansible.builtin.debug: msg: | AWX успешно развёрнут! Namespace: {{ awx_namespace }} Instance name: {{ awx_instance_name }} Service type: {{ awx_service_type }} Получите NodePort для доступа: kubectl get svc {{ awx_instance_name }}-service -n {{ awx_namespace }} Логин: admin Пароль: {{ awx_admin_secret.resources[0].data.password | b64decode }} Если используете Ingress — настройте его отдельно в spec AWX ресурса.