Ansible NGINX Plus Ingress Controller 배포 자동화 – OpenShift
Ansible Playbook을 통해 NGINX Plus Ingress Controller 배포를 자동화하면 OpenShift 클러스터에서 반복적으로 수행해야 하는 네임스페이스 생성, 라이선스 Secret 구성, SCC 설정, Helm 배포 과정을 일관되고 안전하게 처리할 수 있습니다. 이 과정을 매번 수동으로 수행하면 실수가 발생하기 쉽고, 여러 클러스터를 관리할 때 일관성을 유지하기 어렵습니다.
이번 포스트에서는 Ansible Playbook과 Helm을 결합하여 OpenShift 클러스터에 NGINX Plus Ingress Controller를 자동으로 배포하는 방법을 소개합니다. 사전 검증부터 Helm 배포까지 전 과정을 단계별로 살펴보겠습니다.
목차
1. Ansible NGINX Plus Ingress Controller 배포 개요 및 주요 특징
2. 환경/버전 정보
3. Ansible Playbook 구조 및 파일 설명
4. Ansible Task 설명
5. Playbook 실행 및 결과 확인
6. 결론
1. Ansible NGINX Plus Ingress Controller 배포 개요 및 주요 특징
이번 Playbook은 Ansible의 로컬 실행 방식(ansible_connection: local)을 사용합니다. Playbook을 실행하는 호스트에서 kubectl, helm, oc 명령어를 직접 실행하여 OpenShift 클러스터를 제어하는 구조입니다.
- 사전 검증:
kubectl,helm,oc존재 여부와license.jwt파일 유무를 실제 배포 전에 검증합니다. - 안전한 클린업: 삭제 Playbook 실행 시
-e confirm_cleanup=yes변수를 명시해야만 진행되는 안전장치가 내장되어 있습니다. - 기본 Values 분리: 기본 Values 파일(
npic-values.yaml)은 정적으로 유지하고, 변경이 필요한 값만nic_custom_values를 통해--set으로 동적 주입합니다. - 인증 방식: Kubeconfig 파일 또는 API Token 방식 모두 지원하며, TLS 인증서 검증 여부도 일관되게 제어합니다.
2. 환경/버전 정보
| 구성 요소 | 버전 |
|---|---|
| Ansible | core 2.20.5 |
| Python | 3.12.3 |
| Red Hat OpenShift Cluster | 4.18.24 |
| NGINX Plus Ingress Controller | 5.4.2 |
| NGINX Ingress Helm Chart | nginx-stable/nginx-ingress (2.5.2) |
Playbook 실행 호스트의 Python 가상환경 내에 pip로 설치된 Ansible 환경을 기준으로 합니다. kubectl, helm, oc 명령어를 사용할 수 있어야 합니다.
3. Ansible Playbook 구조 및 파일 설명
Playbook의 전체 디렉토리 구조는 다음과 같습니다.
ansible-nic-deploy/├── ansible.cfg # Ansible 설정 파일├── site.yaml # 메인 플레이북 (배포)├── cleanup.yaml # 삭제 플레이북 (안전장치 적용)├── license.jwt # F5 NGINX 라이선스 파일 (Git 제외)├── inventory/│ └── hosts.yaml # 대상 클러스터 정의├── tasks/│ ├── set_common_facts.yaml # kubectl/helm 인증 옵션 팩트 설정│ ├── pre_check.yaml # 도구 및 라이센스 파일 사전 검증│ ├── setup_namespace_and_secrets.yaml # 네임스페이스, 시크릿, SCC 구성│ └── deploy_nic.yaml # Helm을 통한 NIC 배포├── vars/│ ├── nic_vars.yaml # 배포 관련 주요 변수│ └── vault.yaml.example # Ansible Vault 예시 파일├── files/│ ├── npic-values.yaml # NIC Helm Chart 기본 Values│ └── scc.yaml # OpenShift SCC 정의└── kubeconfigs/ ├── ansible-ocp.yaml # Kubeconfig 파일 └── README.md # Kubeconfig 관리 가이드
ansible.cfg 파일의 [defaults] 섹션은 Ansible 실행 시 공통 기본 설정을 정의합니다. 기본 인벤토리를 ./inventory/hosts.yaml로 지정하여 실행 시 -i 옵션을 생략할 수 있으며, Python 인터프리터 자동 감지와 retry 파일 생성 비활성화 등의 옵션도 함께 설정합니다.
[defaults]interpreter_python = auto_silentretry_files_enabled = Falseinventory = ./inventory/hosts.yaml
inventory/hosts.yaml에서 NGINX Plus Ingress Controller 배포 대상 클러스터를 정의합니다.
모든 작업은 Playbook을 실행하는 호스트에서 로컬로 실행되므로 ansible_connection: local을 지정합니다.
all: children: ocp_clusters: vars: ansible_connection: local # 모든 클러스터 작업은 로컬(kubectl/helm)에서 실행 hosts: ansible-ocp: cluster_api_url: "https://api.ansible-ocp.devopssong.site:6443" kubeconfig_path: "{{ playbook_dir }}/kubeconfigs/ansible-ocp.yaml" # cluster_token을 사용할 경우 아래와 같이 호스트별 Vault 변수를 매핑합니다. # cluster_token: "{{ vault_token_ansible_ocp }}"
vars/nic_vars.yaml에서 배포에 필요한 주요 변수를 정의합니다.helm_chart_version이 배포 버전의 단일 기준점이며, 업그레이드 시 이 값만 변경하면 됩니다.
cluster_auth_method: kubeconfigcluster_validate_certs: falsecluster_token: "{{ vault_cluster_token | default('') }}"nic_namespace: nginx-ingresshelm_release_name: npichelm_chart_repo_name: nginx-stablehelm_chart_repo_url: https://helm.nginx.com/stablehelm_chart_name: nginx-stable/nginx-ingresshelm_values_file: "{{ playbook_dir }}/files/npic-values.yaml"# 업그레이드 시 이 값만 변경하세요.# Chart 버전에 호환되는 NIC 버전이 내장되어 있습니다. (예: chart 2.5.2 → app 5.4.2)# npic-values.yaml의 이미지 설정과 함께 관리하세요.helm_chart_version: "2.5.2" # nginx-ingress chart versionnic_custom_values: controller.replicaCount: 2 controller.service.type: "ClusterIP" controller.ingressClass.name: "nginx" # controller.resources.requests.cpu: "100m" # controller.resources.requests.memory: "128Mi"
site.yaml은 각 Task 파일을 태그와 함께 순서대로 import합니다.set_common_facts는 tags: always로 지정되어 어떤 태그로 실행하더라도 항상 먼저 수행됩니다.
- name: NIC Deployment on OpenShift hosts: ocp_clusters gather_facts: false vars_files: - vars/nic_vars.yaml # - vars/vault.yaml # Token 인증 사용 시 주석 해제 tasks: - name: Include common facts setup ansible.builtin.import_tasks: tasks/set_common_facts.yaml tags: always - name: Include pre-check tasks ansible.builtin.import_tasks: tasks/pre_check.yaml tags: precheck - name: Include namespace and secrets setup tasks ansible.builtin.import_tasks: tasks/setup_namespace_and_secrets.yaml tags: setup - name: Include NIC Helm deploy tasks ansible.builtin.import_tasks: tasks/deploy_nic.yaml tags: deploy
Helm 배포에 사용되는 npic-values.yaml은 NGINX Plus Ingress Controller 배포를 위한 레지스트리, Graceful Shutdown, Prometheus 모니터링, 서비스 구성 등 기본 value에서 변경할 값을 정의합니다.
controller: # 1. NGINX Plus Ingress Controller & License/Registry Configuration nginxplus: true image: repository: private-registry.nginx.com/nginx-ic/nginx-plus-ingress serviceAccount: name: nginx-ingress imagePullSecretsNames: - regcred # 2. Performance & Protocol Configuration (NGINX ConfigMap Entries) config: entries: access-log-off: 'False' keepalive: '16' log-format: '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" rt="$request_time" uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"' real-ip-header: proxy_protocol proxy-protocol: 'True' set-real-ip-from: 192.168.0.0/16 worker-connections: '4096' worker-rlimit-nofile: '65535' enableSnippets: true # 3. Graceful Shutdown Configuration terminationGracePeriodSeconds: 45 lifecycle: preStop: exec: command: - /bin/sh - -c - sleep 40 # 4. Monitoring & Telemetry (Prometheus & Status API) nginxStatus: allowCidrs: 0.0.0.0/0 pod: annotations: prometheus.io/scrape: 'true' prometheus.io/port: '9113' prometheus.io/scheme: http reportIngressStatus: leaderElectionLockName: nginx-ingress-leader # 5. Network Service & Readiness Port Mapping replicaCount: 2 service: type: ClusterIP extraLabels: app: ingresslink customPorts: - name: readiness-port port: 8081 targetPort: 8081 protocol: TCP
4. Ansible Task 설명
인증 옵션 설정 (set_common_facts.yaml)
cluster_auth_method 값에 따라 kubectl과 helm 명령어에 필요한 인증 옵션을 공통 변수로 구성합니다. 이후 모든 Task에서 {{ kubectl_auth_opts }}, {{ helm_auth_opts }}만 사용하므로, 인증 방식별 옵션을 각 Task에 반복 작성하지 않아도 됩니다.
- name: "[Common] Set kubectl auth options" ansible.builtin.set_fact: kubectl_auth_opts: >- {{ '--kubeconfig ' + kubeconfig_path if cluster_auth_method == 'kubeconfig' else '--server ' + cluster_api_url + ' --token ' + cluster_token + ( ' --insecure-skip-tls-verify' if not cluster_validate_certs | bool else '' ) }} - name: "[Common] Set helm auth options" ansible.builtin.set_fact: helm_auth_opts: >- {{ '--kubeconfig ' + kubeconfig_path if cluster_auth_method == 'kubeconfig' else '--kube-apiserver ' + cluster_api_url + ' --kube-token ' + cluster_token + ( ' --kube-insecure-skip-tls-verify' if not cluster_validate_certs | bool else '' ) }}
사전 검증 (pre_check.yaml)
실제 배포 전에 필요한 바이너리와 파일이 모두 준비되어 있는지 확인합니다.kubectl, helm, oc 버전을 출력하고, license.jwt 파일 존재 여부를 검증한 뒤, 클러스터 연결 테스트까지 수행합니다.
이 단계에서 실패하면 이후 Task는 실행되지 않습니다.
- name: "[PreCheck] Check kubectl is installed" ansible.builtin.command: kubectl version --client register: kubectl_check changed_when: false - name: "[PreCheck] Check helm is installed" ansible.builtin.command: helm version --short register: helm_check changed_when: false - name: "[PreCheck] Check oc is installed" ansible.builtin.command: oc version --client register: oc_check changed_when: false - name: "[PreCheck] Show tool versions" ansible.builtin.debug: msg: - "kubectl: {{ kubectl_check.stdout }}" - "helm: {{ helm_check.stdout }}" - "oc: {{ oc_check.stdout }}" - name: "[PreCheck] Check license.jwt file existence" ansible.builtin.stat: path: "{{ playbook_dir }}/license.jwt" register: license_file - name: "[PreCheck] Fail if license.jwt is missing" ansible.builtin.assert: that: - license_file.stat.exists fail_msg: "license.jwt not found at {{ playbook_dir }}/license.jwt." success_msg: "license.jwt found" - name: "[PreCheck] Test cluster connection via kubeconfig" ansible.builtin.command: > kubectl cluster-info --kubeconfig {{ kubeconfig_path }} register: cluster_info_kubeconfig changed_when: false when: cluster_auth_method == 'kubeconfig' - name: "[PreCheck] Test cluster connection via token" ansible.builtin.command: > kubectl cluster-info --server {{ cluster_api_url }} --token {{ cluster_token }} --insecure-skip-tls-verify={{ not cluster_validate_certs }} register: cluster_info_token changed_when: false when: cluster_auth_method == 'token' no_log: true
네임스페이스 및 Secret 구성 (setup_namespace_and_secrets.yaml)
NGINX Plus Ingress Controller 배포에 필요한 리소스를 구성합니다.
- 네임스페이스 생성 (
nginx-ingress) license-tokenSecret 생성:license.jwt파일을nginx.com/license타입의 Secret으로 생성하며, 라이선스 파일이 변경된 경우 재실행 시 자동으로 업데이트됩니다.regcredSecret 생성 (선택): NGINX 공식 프라이빗 레지스트리(private-registry.nginx.com)를 사용하는 경우 생성합니다.license.jwt파일을 사용하는 Docker Registry Secret이며,create_nginx_registry_secret: false로 비활성화할 수 있습니다.- SCC 적용: OpenShift에서 NGINX Ingress Controller Pod가 필요한 권한으로 실행될 수 있도록
nginx-ingress-adminSCC를 생성하고,nginx-ingressService Account에 부여합니다.
- name: "[Setup] Create NIC namespace" ansible.builtin.command: > kubectl create namespace {{ nic_namespace }} {{ kubectl_auth_opts }} register: ns_result changed_when: ns_result.rc == 0 failed_when: - ns_result.rc != 0 - "'already exists' not in ns_result.stderr" - name: "[Setup] Create or update license-token secret (Declarative)" ansible.builtin.shell: > kubectl create secret generic license-token --from-file=license.jwt={{ playbook_dir }}/license.jwt --type=nginx.com/license -n {{ nic_namespace }} --dry-run=client -o yaml {{ kubectl_auth_opts }} | kubectl apply -f - {{ kubectl_auth_opts }} register: license_secret_result changed_when: "'configured' in license_secret_result.stdout or 'created' in license_secret_result.stdout" - name: "[Setup] Read license.jwt content for regcred" ansible.builtin.slurp: src: "{{ playbook_dir }}/license.jwt" register: license_jwt_b64 no_log: true when: create_nginx_registry_secret | default(true) | bool - name: "[Setup] Create or update docker-registry secret (regcred - Declarative)" ansible.builtin.shell: > kubectl create secret docker-registry regcred --docker-server=private-registry.nginx.com --docker-username={{ license_jwt_b64['content'] | b64decode | trim }} --docker-password=none -n {{ nic_namespace }} --dry-run=client -o yaml {{ kubectl_auth_opts }} | kubectl apply -f - {{ kubectl_auth_opts }} register: regcred_secret_result changed_when: "'configured' in regcred_secret_result.stdout or 'created' in regcred_secret_result.stdout" when: create_nginx_registry_secret | default(true) | bool no_log: true - name: "[Setup] Apply SCC (scc.yaml)" ansible.builtin.command: > oc apply -f {{ playbook_dir }}/files/scc.yaml {{ kubectl_auth_opts }} register: scc_apply_result changed_when: "'created' in scc_apply_result.stdout or 'configured' in scc_apply_result.stdout" - name: "[Setup] Grant SCC to nginx-ingress-admin" ansible.builtin.command: > oc adm policy add-scc-to-user nginx-ingress-admin -z nginx-ingress -n {{ nic_namespace }} {{ kubectl_auth_opts }} register: scc_policy_result # oc adm policy는 이미 부여된 상태에서도 항상 "added" 메시지를 출력하므로 changed_when: false로 처리 changed_when: false failed_when: - scc_policy_result.rc != 0
SCC는 아래와 같이 구성됩니다.
kind: SecurityContextConstraintsapiVersion: security.openshift.io/v1metadata: name: nginx-ingress-adminallowPrivilegedContainer: falserunAsUser: type: MustRunAs uid: 101seLinuxContext: type: MustRunAsfsGroup: type: MustRunAssupplementalGroups: type: MustRunAsallowHostNetwork: falseallowHostPID: falseallowHostPorts: falseallowHostDirVolumePlugin: falseallowHostIPC: falsereadOnlyRootFilesystem: falseseccompProfiles:- runtime/defaultvolumes: - secretrequiredDropCapabilities: - ALLusers: - 'system:serviceaccount:*:nginx-ingress'allowedCapabilities: - NET_BIND_SERVICE
Helm 배포 (deploy_nic.yaml)
Helm을 통해 NGINX Plus Ingress Controller를 배포합니다. helm upgrade --install은 릴리스가 없으면 신규 설치를 수행하고, 이미 존재하면 지정한 Chart와 Values 기준으로 현재 상태를 동기화합니다. 따라서 동일한 Chart 버전과 Values로 Playbook을 다시 실행하더라도 변경 사항이 없다면 실제 리소스는 수정되지 않으며, 필요한 경우에만 업데이트가 적용됩니다.
- name: "[Deploy] Add NGINX Helm chart repository" ansible.builtin.command: > helm repo add {{ helm_chart_repo_name }} {{ helm_chart_repo_url }} register: repo_add_result changed_when: "'already exists' not in repo_add_result.stdout" failed_when: - repo_add_result.rc != 0 - "'already exists' not in repo_add_result.stdout" - name: "[Deploy] Update Helm repositories" ansible.builtin.command: helm repo update changed_when: false - name: "[Deploy] Reconcile NIC via Helm" ansible.builtin.command: > helm upgrade --install {{ helm_release_name }} {{ helm_chart_name }} -n {{ nic_namespace }} -f {{ helm_values_file }} {% if helm_chart_version | default('') != '' %}--version {{ helm_chart_version }}{% endif %} {% for key, value in (nic_custom_values | default({})).items() %} --set {{ key }}={{ value }} {% endfor %} --create-namespace --wait --timeout 5m {{ helm_auth_opts }} register: helm_apply_result changed_when: > helm_apply_result.rc == 0 and ('has been upgraded' in helm_apply_result.stdout or 'has been installed' in helm_apply_result.stdout or 'STATUS: deployed' in helm_apply_result.stdout) - name: "[Deploy] Show Helm apply result" ansible.builtin.debug: msg: "{{ helm_apply_result.stdout_lines }}" when: helm_apply_result is defined - name: "[Deploy] Wait for NIC pod to be Running" ansible.builtin.command: > kubectl rollout status deployment -l app.kubernetes.io/instance={{ helm_release_name }} -n {{ nic_namespace }} --timeout=120s {{ kubectl_auth_opts }} register: rollout_status changed_when: false
리소스 삭제 (cleanup.yaml)
Helm 릴리스, 네임스페이스, SCC를 순서대로 제거합니다. 실수로 인한 삭제를 방지하기 위해 confirm_cleanup=yes를 명시하지 않으면 자동으로 중단됩니다.
nic_namespace가 kube-system이나 default인 경우 네임스페이스는 삭제하지 않고, 내부에 생성된 license-token과 regcred Secret만 개별 삭제합니다.
- name: NIC Cleanup on OpenShift hosts: ocp_clusters gather_facts: false vars_files: - vars/nic_vars.yaml tasks: - name: Include common facts setup ansible.builtin.import_tasks: tasks/set_common_facts.yaml tags: always - name: "[Cleanup] Safety check — confirm target" ansible.builtin.debug: msg: - "⚠️ About to DESTROY NIC on: {{ inventory_hostname }}" - " Namespace: {{ nic_namespace }}" - " Release: {{ helm_release_name }}" tags: always - name: "[Cleanup] Abort if confirm_cleanup is not set" ansible.builtin.fail: msg: > Cleanup aborted. To proceed, run with: ansible-playbook cleanup.yaml -e confirm_cleanup=yes when: confirm_cleanup | default('no') != 'yes' tags: always - name: "[Cleanup] Uninstall NIC Helm release" ansible.builtin.command: > helm uninstall {{ helm_release_name }} -n {{ nic_namespace }} {{ helm_auth_opts }} register: helm_uninstall_result changed_when: helm_uninstall_result.rc == 0 failed_when: - helm_uninstall_result.rc != 0 - "'not found' not in helm_uninstall_result.stderr" - name: "[Cleanup] Delete generic secrets if namespace is preserved" ansible.builtin.command: > kubectl delete secret license-token regcred -n {{ nic_namespace }} --ignore-not-found=true {{ kubectl_auth_opts }} register: secrets_delete_result changed_when: "'deleted' in secrets_delete_result.stdout" when: - nic_namespace == 'kube-system' or nic_namespace == 'default' - name: "[Cleanup] Delete NIC namespace" ansible.builtin.command: > kubectl delete namespace {{ nic_namespace }} {{ kubectl_auth_opts }} register: ns_delete_result changed_when: ns_delete_result.rc == 0 failed_when: - ns_delete_result.rc != 0 - "'not found' not in ns_delete_result.stderr" when: - nic_namespace != 'kube-system' - nic_namespace != 'default' - name: "[Cleanup] Delete SCC" ansible.builtin.command: > oc delete scc nginx-ingress-admin {{ kubectl_auth_opts }} register: scc_delete_result changed_when: scc_delete_result.rc == 0 failed_when: - scc_delete_result.rc != 0 - "'not found' not in scc_delete_result.stderr"
5. Playbook 실행 및 결과 확인
다음 명령어 하나로 사전 검증부터 Helm 배포, Pod 기동 확인까지 전 과정이 자동으로 수행됩니다.
$ ansible-playbook site.yaml PLAY [NIC Deployment on OpenShift] **************************************************************************************************************************TASK [[Common] Set kubectl auth options] ********************************************************************************************************************ok: [ansible-ocp]TASK [[Common] Set helm auth options] ***********************************************************************************************************************ok: [ansible-ocp]TASK [[PreCheck] Check kubectl is installed] ****************************************************************************************************************ok: [ansible-ocp]TASK [[PreCheck] Check helm is installed] *******************************************************************************************************************ok: [ansible-ocp]TASK [[PreCheck] Check oc is installed] *********************************************************************************************************************ok: [ansible-ocp]TASK [[PreCheck] Show tool versions] ************************************************************************************************************************ok: [ansible-ocp] => { "msg": [ "kubectl: Client Version: v1.35.0\nKustomize Version: v5.7.1", "helm: v3.20.0+gb2e4314", "oc: Client Version: 4.21.10\nKustomize Version: v5.7.1" ]}TASK [[PreCheck] Check license.jwt file existence] **********************************************************************************************************ok: [ansible-ocp]TASK [[PreCheck] Fail if license.jwt is missing] ************************************************************************************************************ok: [ansible-ocp] => { "changed": false, "msg": "license.jwt found"}TASK [[PreCheck] Test cluster connection via kubeconfig] ****************************************************************************************************ok: [ansible-ocp]TASK [[PreCheck] Test cluster connection via token] *********************************************************************************************************skipping: [ansible-ocp]TASK [[Setup] Create NIC namespace] *************************************************************************************************************************changed: [ansible-ocp]TASK [[Setup] Create or update license-token secret (Declarative)] ******************************************************************************************changed: [ansible-ocp]TASK [[Setup] Read license.jwt content for regcred] *********************************************************************************************************ok: [ansible-ocp]TASK [[Setup] Create or update docker-registry secret (regcred - Declarative)] ******************************************************************************changed: [ansible-ocp]TASK [[Setup] Apply SCC (scc.yaml)] *************************************************************************************************************************changed: [ansible-ocp]TASK [[Setup] Grant SCC to nginx-ingress-admin] *************************************************************************************************************ok: [ansible-ocp]TASK [[Deploy] Add NGINX Helm chart repository] *************************************************************************************************************ok: [ansible-ocp]TASK [[Deploy] Update Helm repositories] ********************************************************************************************************************ok: [ansible-ocp]TASK [[Deploy] Reconcile NIC via Helm] **********************************************************************************************************************changed: [ansible-ocp]TASK [[Deploy] Show Helm apply result] **********************************************************************************************************************ok: [ansible-ocp] => { "msg": [ "Release \"npic\" does not exist. Installing it now.", "NAME: npic", "LAST DEPLOYED: Fri May 22 15:57:36 2026", "NAMESPACE: nginx-ingress", "STATUS: deployed", "REVISION: 1", "TEST SUITE: None", "NOTES:", "NGINX Ingress Controller 5.4.2 has been installed.", "", "For release notes, see: https://docs.nginx.com/nginx-ingress-controller/changelog/", "", "For Helm installation instructions, see: https://docs.nginx.com/nginx-ingress-controller/install/helm/" ]}TASK [[Deploy] Wait for NIC pod to be Running] **************************************************************************************************************ok: [ansible-ocp]PLAY RECAP **************************************************************************************************************************************************ansible-ocp : ok=20 changed=5 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
배포된 리소스를 확인합니다.
$ oc get all -n nginx-ingressNAME READY STATUS RESTARTS AGEpod/npic-nginx-ingress-controller-574b49797c-7d28g 1/1 Running 0 3m27spod/npic-nginx-ingress-controller-574b49797c-wxngc 1/1 Running 0 3m28sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/npic-nginx-ingress-controller ClusterIP 172.30.127.21 <none> 8081/TCP,80/TCP,443/TCP 3m28sNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/npic-nginx-ingress-controller 2/2 2 2 3m28sNAME DESIRED CURRENT READY AGEreplicaset.apps/npic-nginx-ingress-controller-574b49797c 2 2 2 3m28s
삭제 시에는 confirm_cleanup=yes를 명시해야 합니다. 생략하면 안전장치가 작동하여 자동으로 중단됩니다.
# 안전장치 작동 — 자동 중단$ ansible-playbook cleanup.yamlPLAY [NIC Cleanup on OpenShift] *****************************************************************************************************************************TASK [[Common] Set kubectl auth options] ********************************************************************************************************************ok: [ansible-ocp]TASK [[Common] Set helm auth options] ***********************************************************************************************************************ok: [ansible-ocp]TASK [[Cleanup] Safety check — confirm target] **************************************************************************************************************ok: [ansible-ocp] => { "msg": [ "⚠️ About to DESTROY NIC on: ansible-ocp", " Namespace: nginx-ingress", " Release: npic" ]}TASK [[Cleanup] Abort if confirm_cleanup is not set] ********************************************************************************************************[ERROR]: Task failed: Action failed: Cleanup aborted. To proceed, run with: ansible-playbook cleanup.yaml -e confirm_cleanup=yesOrigin: /home/yjsong/ansible/ansible-nic-deploy/cleanup.yaml:21:719 tags: always2021 - name: "[Cleanup] Abort if confirm_cleanup is not set" ^ column 7fatal: [ansible-ocp]: FAILED! => {"changed": false, "msg": "Cleanup aborted. To proceed, run with: ansible-playbook cleanup.yaml -e confirm_cleanup=yes\n"}PLAY RECAP **************************************************************************************************************************************************ansible-ocp : ok=3 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0------# 변수 입력을 통한 정상 정리 동작$ ansible-playbook cleanup.yaml -e confirm_cleanup=yesPLAY [NIC Cleanup on OpenShift] *****************************************************************************************************************************TASK [[Common] Set kubectl auth options] ********************************************************************************************************************ok: [ansible-ocp]TASK [[Common] Set helm auth options] ***********************************************************************************************************************ok: [ansible-ocp]TASK [[Cleanup] Safety check — confirm target] **************************************************************************************************************ok: [ansible-ocp] => { "msg": [ "⚠️ About to DESTROY NIC on: ansible-ocp", " Namespace: nginx-ingress", " Release: npic" ]}TASK [[Cleanup] Abort if confirm_cleanup is not set] ********************************************************************************************************skipping: [ansible-ocp]TASK [[Cleanup] Uninstall NIC Helm release] *****************************************************************************************************************changed: [ansible-ocp]TASK [[Cleanup] Delete generic secrets if namespace is preserved] *******************************************************************************************skipping: [ansible-ocp]TASK [[Cleanup] Delete NIC namespace] ***********************************************************************************************************************changed: [ansible-ocp]TASK [[Cleanup] Delete SCC] *********************************************************************************************************************************changed: [ansible-ocp]PLAY RECAP **************************************************************************************************************************************************ansible-ocp : ok=6 changed=3 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
6. 결론
이번 포스트에서는 Ansible을 활용하여 NGINX Plus Ingress Controller 배포를 자동화하는 Playbook을 살펴보았습니다.
수동 배포 시 반복해야 했던 네임스페이스 생성, 라이선스 Secret 구성, SCC 설정, Helm 배포 과정이 하나의 명령어로 처리됩니다. helm upgrade --install을 사용하므로 Values 또는 Chart 버전이 변경되더라도 동일한 Playbook을 다시 실행하는 것만으로 변경 사항을 반영할 수 있습니다. 또한 helm_chart_version 값만 수정하면 업그레이드도 동일한 절차로 수행됩니다.
여러 OpenShift 클러스터를 운영하는 환경이라면 inventory/hosts.yaml에 클러스터를 추가하고 nic_custom_values를 클러스터별로 재정의하는 것만으로 일관된 배포를 유지할 수 있습니다.
현재 운영 중인 OpenShift 클러스터에 NGINX Plus Ingress Controller를 도입하고 싶으신가요? NGINX STORE를 통해 문의하여 NGINX One trial로 NGINX Plus Ingress Controller를 무료로 체험해 보세요.