Ansible: NGINX Gateway Fabric과 Gateway API 자동 배포

이번 포스트에서는 Ansible을 사용해 Kubernetes 환경에 NGINX Gateway Fabric과 Gateway API 리소스를 자동으로 배포하는 과정을 정리합니다.
Ansible의 kubernetes.core.k8s 모듈은 Kubernetes Python client를 사용해 Kubernetes 오브젝트를 생성하고 관리할 수 있으며, YAML 파일이나 Jinja2 템플릿 기반 리소스 적용도 지원합니다.
실습에서는 Ansible을 사용해 Gateway와 HTTPRoute 리소스를 자동으로 구성합니다. Ansible을 활용하면 다양한 자동화 시나리오를 Kubernetes 환경에 적용할 수 있습니다.

목차

1. Ansible이란?
2. Ansible 실행 환경 구성
 2-1. 실습 사전 준비
 2-2. Python 가상환경 생성 및 활성화
 2-3. Ansible 패키지 설치
 2-4. kubernetes Python Client 설치
3. 실습 디렉터리 및 변수 파일 구성
 3-1. 실습 디렉터리 구조
 3-2. 변수 파일 작성
4. Kubernetes 리소스 템플릿 작성
 4-1. 테스트 애플리케이션 템플릿 작성
 4-2. Gateway 및 HTTPRoute 템플릿 작성
5. Ansible Playbook 작성 및 실행
 5-1. Playbook 작성
 5-2. Playbook 실행
 5-3. 배포 결과 확인
6. Gateway API 동작 테스트
 6-1. curl 요청 테스트
 6-2. 요청/응답 헤더 확인
7. 결론

1. Ansible이란?

Ansible은 서버 설정, 애플리케이션 배포, 클라우드 및 네트워크 장비 구성 등을 자동화할 수 있는 오픈소스 자동화 도구입니다. 복잡한 스크립트를 직접 작성하지 않아도, 사람이 이해하기 쉬운 YAML 형식의 Playbook을 통해 반복 작업을 정의하고 실행할 수 있습니다.

2. Ansible 실행 환경 구성

먼저 Ansible을 실행할 python 가상환경을 만들고, 그 안에 Ansible과 Kubernetes Python Client를 설치합니다.
이번 실습에서는 Ansible의 Kubernetes.core.k8s 모듈을 사용해 Kubernetes 리소스를 생성하기 때문에, Kubernetes API와 통신할 수 있는 Python Client가 필요합니다.

2-1. 실습 사전 준비

구분사전 준비 리소스
Kubernetes 환경실습용 Kubernetes 클러스터, kubectl 접속 환경, ngf-lab Namespace
Gateway API 환경NGINX Gateway Fabric Controller, nginx GatewayClass, 테스트용 echo-app Service

2-2. Python 가상환경 생성 및 활성화

$ python3 -m venv ~/ansible-venv
$ source ~/ansible-venv/bin/activate
(ansible-venv) hangyeol@ubuntu:~$

위 명령어를 사용하여 가상환경을 생성하고 적용합니다.

2-3. Ansible 패키지 설치

$ python -m pip install ansible

Python 패키지를 통해 Ansible을 설치합니다.

$ ansible --version
ansible [core 2.20.5]
config file = None
configured module search path = ['/home/hangyeol/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/hangyeol/ansible-venv/lib/python3.12/site-packages/ansible
ansible collection location = /home/hangyeol/.ansible/collections:/usr/share/ansible/collections
executable location = /home/hangyeol/ansible-venv/bin/ansible
python version = 3.12.3 (main, Mar 3 2026, 12:15:18) [GCC 13.3.0] (/home/hangyeol/ansible-venv/bin/python)
jinja version = 3.1.6
pyyaml version = 6.0.3 (with libyaml v0.2.5)

버전을 확인하는 명령어를 사용하여 정상 설치를 확인합니다.

2-4. Kubernetes Python Client 설치

$ python -m pip install kubernetes

가상환경이 활성화된 상태에서 다음 명령어를 실행합니다.

$ python -m pip show kubernetes
Name: kubernetes
Version: 35.0.0
Summary: Kubernetes python client
Home-page: https://github.com/kubernetes-client/python
Author: Kubernetes
Author-email:
License: Apache License Version 2.0
Location: /home/hangyeol/ansible-venv/lib/python3.12/site-packages
Requires: certifi, durationpy, python-dateutil, pyyaml, requests, requests-oauthlib, six, urllib3, websocket-client
Required-by:

버전을 확인하는 명령어를 사용하여 정상 설치를 확인합니다.

3. 실습 디렉터리 및 변수 파일 구성

3-1. 실습 디렉터리 구조

$ mkdir ~/ngf-ansible-lab/templates
$ mkdir ~/ngf-ansible-lab/vars
$ cd ~/ngf-ansible-lab

3-2. 변수 파일 작성

먼저 vars/main.yaml 파일을 생성합니다.

$ vi vars/main.yaml
lab_namespace: ngf-lab
app_name: echo-app
app_port: 80
gateway_name: ngf-gateway
gateway_class_name: nginx
httproute_name: echo-route
hostname: echo.example.com
request_header_name: x-lab-request
request_header_value: ansible-ngf
response_header_name: x-lab-response
response_header_value: nginx-gateway-fabric

4. Kubernetes 리소스 템플릿 작성

4-1. 테스트 애플리케이션 확인

이번 실습에서는 Gateway API 라우팅 구성을 확인하기 위해 Echo 애플리케이션을 미리 배포해둔 상태에서 진행합니다.
따라서 Ansible Playbook에서는 애플리케이션 Deployment와 Service를 생성하지 않고, 이미 존재하는 Service를 HTTPRoute의 backend로 연결합니다.

먼저 Echo 애플리케이션이 배포되어 있는지 확인합니다.

$ kubectl get deployment -n ngf-lab
$ kubectl get pod -n ngf-lab
$ kubectl get svc -n ngf-lab
NAME READY UP-TO-DATE AVAILABLE AGE
echo-app 1/1 1 1 31m
NAME READY STATUS RESTARTS AGE
echo-app-668fc885b4-kbz9v 1/1 Running 0 31m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-app ClusterIP 10.97.182.77 80/TCP 31m

4-2. Gateway 및 HTTPRoute 템플릿 작성

NGINX Gateway Fabric이 처리할 Gateway와 HTTPRoute 리소스를 Ansible 템플릿으로 작성합니다.

Gateway 템플릿 작성

$ vi templates/gateway.yaml.j2
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: {{ gateway_name }}
namespace: {{ lab_namespace }}
spec:
gatewayClassName: {{ gateway_class_name }}
listeners:
- name: http
protocol: HTTP
port: 80
hostname: {{ hostname }}
allowedRoutes:
namespaces:
from: Same

HTTPRoute 템플릿 작성

$ vi templates/httproute.yaml.j2
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ httproute_name }}
namespace: {{ lab_namespace }}
spec:
parentRefs:
- name: {{ gateway_name }}
hostnames:
- {{ hostname }}
rules:
- filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: {{ request_header_name }}
value: {{ request_header_value }}
- type: ResponseHeaderModifier
responseHeaderModifier:
add:
- name: {{ response_header_name }}
value: {{ response_header_value }}
backendRefs:
- name: {{ app_name }}
port: {{ app_port }}

5. Ansible Playbook 작성 및 실행

5-1. Playbook 작성

앞에서 작성한 Namespace, Deployment, Service, Gateway, HTTPRoute 템플릿을 하나의 Playbook에 추가합니다.

$ vi playbook.yaml
- name: Deploy NGINX Gateway Fabric routing resources
hosts: localhost
connection: local
gather_facts: false
vars_files:
- vars/main.yaml
tasks:
- name: Create Gateway
kubernetes.core.k8s:
state: present
template: templates/gateway.yaml.j2
- name: Create HTTPRoute
kubernetes.core.k8s:
state: present
template: templates/httproute.yaml.j2

5-2. Playbook 실행

$ source ~/ansible-venv/bin/activate
$ cd ~/ngf-ansible-lab
$ ansible-playbook playbook.yaml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Deploy NGINX Gateway Fabric lab resources] ****************************************************************************
TASK [Create Gateway] *******************************************************************************************************
changed: [localhost]
TASK [Create HTTPRoute] *****************************************************************************************************
changed: [localhost]
PLAY RECAP ******************************************************************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

5-3. 배포 결과 확인

$ kubectl get gateway -n ngf-lab
$ kubectl get httproute -n ngf-lab
NAME CLASS ADDRESS PROGRAMMED AGE
gateway.gateway.networking.k8s.io/ngf-gateway nginx True 54m
NAME HOSTNAMES AGE
httproute.gateway.networking.k8s.io/echo-route ["echo.example.com"] 54m

6. Gateway API 동작 테스트

6-1. curl 요청 테스트

$ curl -i -H "Host: echo.example.com" http://localhost:8080

6-2. 요청/응답 헤더 확인

HTTP/1.1 200 OK
Server: nginx
Date: Fri, 08 May 2026 07:09:12 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1269
Connection: keep-alive
ETag: W/"4f5-YjLwsaUCMWuWr7Hp16REgnEPv5A"
x-lab-response: nginx-gateway-fabric
{
"host": {
"hostname": "echo.example.com",
"ip": "::ffff:10.244.0.15",
"ips": []
},
"http": {
"method": "GET",
"protocol": "http",
"originalUrl": "/"
},
"request": {
"headers": {
"host": "echo.example.com",
"user-agent": "curl/8.5.0",
"x-real-ip": "127.0.0.1",
"x-forwarded-for": "127.0.0.1",
"x-forwarded-proto": "http",
"x-lab-request": "ansible-ngf"
}
},
"environment": {
"HOSTNAME": "echo-app-668fc885b4-kbz9v",
"NODE_VERSION": "20.11.0",
"KUBERNETES_SERVICE_HOST": "10.96.0.1"
}
}

7. 결론

이번 포스트에서는 Ansible과 Jinja2 템플릿을 사용해 NGINX Gateway Fabric 기반 Gateway API 리소스를 자동으로 배포했습니다.
Gateway, HTTPRoute를 Playbook으로 관리하면서 수동 kubectl apply 작업을 줄이고, 반복 가능한 배포 구조를 만들 수 있었습니다.
결과적으로 Ansible을 활용하면 Kubernetes Gateway API 구성을 보다 일관성 있게 관리하고 자동화할 수 있습니다.

NGINX STORE에 문의하여 더 자세한 정보를 확인하세요.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required