소프트웨어 설정, 옵션 및 구성은 매우 다양한 형태로 제공됩니다. 한쪽 끝에는 직관적으로 사용할 수 있도록 설계되고 잘못된 상태가 되지 않도록 안전장치를 제공하는 세련되고 반응성이 뛰어난 GUI가 있습니다. 반대쪽 끝에는 텍스트 파일이 있습니다. 텍스트 파일은 명확하고 자동화 가능성이 높으며 사용에 필요한 리소스가 적다는 점에서 엔지니어와 DevOps 팀 모두에게 호평받지만(아마 지금도 터미널 창을 몇 개 열어 두셨겠죠?), 이를 사용해 소프트웨어를 구성할 때는 분명한 장단점이 있습니다. 예를 들어, 텍스트 파일을 잘못 구성해 소프트웨어 패키지를 중단시켜 본 적이 없는 Linux 사용자를 찾아보세요.
소프트웨어 프록시, 로드 밸런서, 웹 서버 및 API 게이트웨이 기능을 모두 제공하는 유일한 통합 솔루션인 NGINX는 현대 인터넷 인프라의 핵심 구성 요소입니다. 이러한 인프라는 대부분 Linux 커널을 기반으로 하는 운영 체제 위에 구축됩니다. NGINX는 이 생태계와 이를 지원하는 전문가들의 작업 방식에 부합하기 위해 텍스트 기반 구성에 크게 의존합니다.
F5 NGINX Instance Manager 모듈은 오랫동안 NGINX 관련 구성 오케스트레이션을 위한 대표적인 솔루션으로 자리매김해 왔습니다. 직관적인 사용자 인터페이스와 API를 통해 원격 일괄 구성 관리를 위한 고급 기능을 제공하며, 관련 문서와 안전장치도 갖추고 있습니다. 하지만 개별 NGINX 구성 파일은 코드와 매우 유사하며, 소프트웨어 팀에는 이미 코드를 관리할 수 있는 훌륭한 도구인 Git이 있습니다. Git은 개발팀과 운영팀에 텍스트 파일 워크플로 관리에 특화된 다양한 기능을 제공합니다.
Instance Manager는 Git 및 기타 외부 시스템과의 새로운 통합을 통해 버전 관리, 분산형 기여, 승인 워크플로, 팀 협업과 같은 기능을 제공합니다. GitHub 및 GitLab과 같은 플랫폼은 웹 기반 사용자 인터페이스를 통해 지속적 통합/지속적 배포(CI/CD), 공동 작업, 이슈 추적 및 기타 유용한 기능으로 이 기능 세트를 확장합니다.
이 블로그 게시물에서는 GitHub를 사용하여 NGINX 구성을 관리하고, 변경 사항이 발생할 때마다 해당 구성을 인스턴스에 자동으로 푸시하는 방법을 설명합니다.
인스턴스 관리자 API
Instance Manager는 웹 사용자 인터페이스를 보완하는 다양한 REST API를 제공합니다. 이 API의 주요 이점은 관리 중인 데이터 플레인 인스턴스의 구성 파일을 업데이트할 수 있다는 점입니다. 최근에는 이 기능을 확장하여 구성 업데이트를 파일의 특정 버전에 연결할 수 있도록 했습니다. Git 리포지토리에서 관리되는 구성에는 Git 커밋 해시로 태그를 지정할 수 있습니다. 또한 외부에서 관리되는 구성에 대해, 구성이 외부에서 관리되고 있음을 파일 편집자에게 경고하는 새로운 상태를 Instance Manager에 구현했습니다.
GitHub Actions
GitHub에서는 개발자가 Actions라는 기능을 사용하여 리포지토리에 사용자 지정 배포 파이프라인을 만들 수 있습니다. 사용자는 자체 액션을 정의하거나 YAML 정의를 통해 기존 스크립트를 호출할 수 있습니다. 이러한 파이프라인은 커밋이나 풀 리퀘스트 병합으로 리포지토리가 업데이트될 때와 같이 다양한 방식으로 트리거할 수 있습니다.
이 블로그의 예제에서는 기본 제공되는 GitHub Actions와 Linux 명령어를 활용합니다. 이를 사용하여 Instance Manager API를 통해 NGINX 인스턴스에서 GitHub로 관리되는 NGINX 구성 파일을 업데이트하는 방법을 알아봅니다. 시작하려면 GitHub Docs의 다음 단계에 따라 리포지토리에서 Actions를 실행하기 위한 새 YAML 파일을 만드세요.
Actions 보안 비밀 설정
Instance Manager는 다양한 인증 방식을 지원합니다. 이 예시에서는 기본 인증 방식을 사용하지만, 프로덕션 환경에서는 OIDC 인증을 프로비저닝하는 것이 좋습니다.
Instance Manager 자격 증명을 리포지토리에 저장하는 대신, GitHub에서는 리포지토리 변수로 비밀을 정의할 수 있습니다. 이러한 변수는 Actions 환경에서 액세스할 수 있지만 로그에는 표시되지 않습니다. 다음 단계에 따라 Instance Manager 사용자 이름과 비밀번호 키를 비밀로 저장하면 API 호출을 인증하는 데 사용할 수 있습니다.
여기서는 이러한 변수를 각각 NMS_USERNAME 및 NMS_PASSWORD로 설정했습니다.

Actions 변수 설정
마찬가지로 YAML에서 상수 변수를 정의하는 대신, 이를 분리하여 GitHub 사용자 인터페이스에서 관리하면 편리할 수 있습니다. Variables 페이지에서는 모든 리포지토리 Actions에 적용되는 변수를 정의하는 방법을 확인할 수 있습니다. 이 예제에서는 Instance Manager의 FQDN 또는 IP 주소(NMS_HOSTNAME), NGINX가 실행 중인 시스템의 식별자(SYSTEM_ID), 업데이트할 특정 NGINX 인스턴스의 식별자(INSTANCE_ID)를 정의합니다.

참고: 이 예시에서는 간소화를 위해 이러한 변수를 설정했지만, Instance Manager, System 및 NGINX 식별 정보를 다른 방식으로 관리할 수도 있습니다. 예를 들어, 리포지토리에 각 인스턴스별 구성이 포함된 디렉터리를 만들고 해당 디렉터리의 이름을 시스템 또는 인스턴스 ID로 지정할 수 있습니다. 그런 다음 YAML 또는 Action 스크립트를 수정하여 디렉터리 이름을 읽고 해당 인스턴스의 구성 파일을 업데이트하도록 할 수 있습니다.
NGINX 구성을 업데이트하기 위한 Instance Manager REST API 호출 구조
Instance Manager의 구성 업데이트 REST API 호출이 작동하려면 몇 가지 핵심 구성 요소가 필요합니다. YAML에서 이러한 각 매개변수를 정의하고 올바른 형식으로 API 호출에 포함해야 합니다.
이 예제에서는 단일 인스턴스를 업데이트하는 API 호출을 사용합니다. 하지만 Instance Manager 내에서 인스턴스 그룹을 구성할 수도 있습니다. 이렇게 하면 GitHub에서 새 구성이 푸시될 때마다 그룹의 모든 인스턴스를 업데이트할 수 있습니다. 자세한 내용은 구성 게시 방법 가이드를 참조하세요.
다음은 Instance Manager의 구성 업데이트 REST API 호출에 대한 세부 설명입니다:
https://{INSTANCE MANAGER HOSTNAME}/api/platform/v1/systems/{SYSTEM ID}/instances/{INSTANCE ID}/config'
--header "accept: application/json"
--header "Authorization: Basic {LOGIN CREDENTIALS}"
--header 'Content-Type: application/json'
--data '{
"configFiles": '{
"rootDir": "/etc/nginx",
"files": [{
"contents": "{NGINX CONFIGURATION FILE}",
"name": "{PATH TO CONFIGURATION FILE ON SYSTEM}"
}]
},
"externalIdType": "{SOURCE OF CONFIGS}",
"externalId": "{COMMIT HASH}",
"updateTime": "{TIMESTAMP}"
}'}'
URI 매개변수
- 시스템 식별자 – NGINX가 실행 중인 시스템을 식별하는 고유 키입니다. 이 예시에서는 이 데이터가 GitHub Actions Variables 인터페이스에 정의되어 있습니다.
- NGINX 인스턴스 식별자 – 시스템의 특정 NGINX 인스턴스를 식별하는 고유 키입니다. 이 예시에서는 이 데이터가 GitHub Actions Variables 인터페이스에 정의되어 있습니다.
헤더 매개변수
- Authorization – Instance Manager가 API 호출을 인증하는 데 사용하는 인증 방식 및 Base64로 인코딩된 자격 증명입니다. 이 예에서는 리포지토리에 설정된 보안 비밀의 자격 증명 데이터를 사용하여 기본 인증을 수행합니다.
JSON 데이터 매개변수
- configFiles – 업데이트할 구성 파일의 Base64 인코딩된 내용과 NGINX가 실행 중인 시스템에서 해당 파일의 위치입니다. 또한 NGINX 구성 파일의 루트 디렉터리 경로도 제공해야 하며, 일반적으로 다음과 같이 설정됩니다:
/etc/nginx. - externalIdType – Instance Manager에서 구성 파일의 출처를 식별하는 레이블입니다. 가능한 값은
git또는other입니다. 이 예제에서는 이 매개변수의 값을git으로 하드코딩합니다. - externalId – 구성 파일의 변경 사항을 식별하는 Git 커밋 보안 해시 알고리즘(SHA)입니다.
- updateTime – 현재 날짜와 시간을 포함하는 문자열이며, 형식은
%Y-%m-%dT%H:%M:%SZ입니다.
Base64 인코딩
Instance Manager의 API 사양을 충족하려면 특정 데이터를 Base64 형식으로 인코딩하여 변환해야 합니다. 기존 GitHub Actions에는 이를 수행하는 기본 기능이 없지만, YAML에서 사용할 수 있는 Linux 도구를 활용할 수 있습니다.
Instance Manager 자격 증명
먼저 앞서 보안 비밀로 정의한 Instance Manager 로그인 자격 증명을 참조하여 하나의 문자열로 연결합니다. 그런 다음 해당 문자열을 Base64로 변환하고 Linux 변수(NMS_LOGIN)로 출력한 후, 그 결과를 Actions 러너에서 액세스할 수 있는 사전 정의된 환경 변수(GITHUB_ENV)에 추가합니다.
run: echo "NMS_LOGIN=`echo -n "${{ secrets.NMS_USERNAME }}:${{ secrets.NMS_PASSWORD }}" | base64`" >> $GITHUB_ENV
타임스탬프
Instance Manager API를 사용하려면 특정 API 페이로드와 함께 지정된 형식의 타임스탬프를 전송해야 합니다. Linux date 명령을 사용하여 해당 형식의 타임스탬프를 생성할 수 있습니다. 이전 예제와 마찬가지로 생성한 문자열을 변수로 Linux 환경에 추가합니다.
run: echo "NMS_TIMESTAMP=`date -u +"%Y-%m-%dT%H:%M:%SZ"`" >> $GITHUB_ENV
NGINX 구성
다음으로 관리하려는 NGINX 구성을 리포지토리에 추가합니다. GitHub 리포지토리에 파일을 추가하는 방법은 다양합니다. 자세한 내용은 GitHub 설명서의 이 가이드를 참조하세요를 참조하세요. 이 예시를 따라 하려면 인스턴스의 디렉터리 구조와 동일한 구조를 GitHub 리포지토리에 만들면 됩니다.
아래 YAML 항목은 이전과 마찬가지로 리포지토리에서 구성 파일을 읽고, 해당 내용을 Base64로 인코딩한 다음 그 결과를 환경 변수에 추가합니다.
run: echo "NGINX_CONF_CONFIG_FILE=`cat nginx-server/etc/nginx/nginx.conf | base64 -w 0`" >> $GITHUB_ENV
이 예시에서는 GitHub 리포지토리의 모든 구성 파일에 대해 이 작업을 반복합니다.
모든 요소 통합하기
마지막으로 GitHub의 샘플 참조 구현을 사용하여 지금까지 배운 내용을 실제로 작동하는 YAML 파일로 구성할 수 있습니다. 파일에 정의된 대로 사용자가 커밋 또는 풀 리퀘스트를 통해 리포지토리를 업데이트할 때마다 관련된 모든 GitHub Actions 스크립트가 실행됩니다. YAML의 마지막 항목에서는 curl 명령을 실행하여 적절한 API를 호출하며, 이 호출에는 Instance Manager가 관련된 모든 구성 파일을 업데이트하는 데 필요한 데이터가 포함됩니다.
참고: YAML에서 여러 줄 실행 항목(run: |)을 사용하여 curl 명령을 실행하세요. 이렇게 하면 YAML 인터프리터가 해당 항목의 매개변수 부분에 있는 콜론(“:”)을 텍스트로 처리합니다.
name: Managing NGINX configs with GitHub and GitHub Actions
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the "main" branch
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- name: Set environment variable for NMS API login credentials
run: echo "NMS_LOGIN=`echo -n "${{ secrets.NMS_USERNAME }}:${{ secrets.NMS_PASSWORD }}" | base64`" >> $GITHUB_ENV
- name: Set environment variable for NMS API timestamp
run: echo "NMS_TIMESTAMP=`date -u +"%Y-%m-%dT%H:%M:%SZ"`" >> $GITHUB_ENV
- name: Set environment variable for base64 encoded config file
run: echo "NGINX_CONF_CONFIG_FILE=`cat app-sfo-01/etc/nginx/nginx.conf | base64 -w 0`" >> $GITHUB_ENV
- name: Set environment variable for base64 encoded config file
run: echo "MIME_TYPES_CONFIG_FILE=`cat app-sfo-01/etc/nginx/mime.types | base64 -w 0`" >> $GITHUB_ENV
- name: Set environment variable for base64 encoded config file
run: echo "DEFAULT_CONF_CONFIG_FILE=`cat app-sfo-01/etc/nginx/conf.d/default.conf | base64 -w 0`" >> $GITHUB_ENV
- name: Set environment variable for base64 encoded config file
run: echo "SSL_CONF_CONFIG_FILE=`cat app-sfo-01/etc/nginx/conf.d/ssl.conf | base64 -w 0`" >> $GITHUB_ENV
- name: API call to Instance Manager
run: |
curl --location 'https://${{ vars.NMS_HOSTNAME }}/api/platform/v1/systems/${{ vars.SYSTEM_ID }}/instances/${{ vars.INSTANCE_ID }}/config' --header "accept: application/json" --header "Authorization: Basic ${{ env.NMS_LOGIN }}" --header 'Content-Type: application/json' --data '{"configFiles": {"rootDir": "/etc/nginx","files": [{"contents": "${{ env.NGINX_CONF_CONFIG_FILE }}","name": "/etc/nginx/nginx.conf"},{"contents": "${{ env.MIME_TYPES_CONFIG_FILE }}","name": "/etc/nginx/mime.types"},{"contents": "${{ env.DEFAULT_CONF_CONFIG_FILE }}","name": "/etc/nginx/conf.d/default.conf"},{"contents": "${{ env.SSL_CONF_CONFIG_FILE }}","name": "/etc/nginx/conf.d/ssl.conf"}]},"externalIdType": "git","externalId": "${{ github.sha }}","updateTime": "${{ env.NMS_TIMESTAMP }}"}'
NGINX 참조 구현
파일이 변경된 후 구성 업데이트 API 호출을 실행하는 방법은 여러 가지가 있습니다. GitHub를 사용하는 경우 GitHub Actions가 가장 편리한 방법이지만, GitLab이나 독립형 Git 구현에서는 작동하지 않습니다. 이러한 사용 사례를 지원하기 위해 명령줄에서 실행하거나 사용자 지정 스크립트에서 호출할 수 있는 보조 셸 스크립트 참조 구현을 개발했습니다.
결론적으로, Instance Manager API의 새로운 확장 기능은 구성 업데이트, 롤백 및 버전 기록을 현대적인 분산 방식으로 관리할 수 있는 강력한 도구를 제공합니다. 이 확장 기능을 GitHub와 같은 타사 텍스트 파일 및 코드 관리 플랫폼과 연동하면 직관적인 웹 기반 사용자 인터페이스를 통해 워크플로, CI/CD, 협업 및 이슈 추적 기능을 추가로 활용할 수 있습니다.
여러분의 의견을 들려주세요! 직접 사용해 보시고 댓글을 남기거나 NGINX 커뮤니티 Slack 채널에 참여해 의견을 알려주세요.
관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.