NGINX Plus Sidecar 배포하고 Prometheus 연동하기

이 포스트에서는 쿠버네티스 환경에서 NGINX Plus Sidecar 를 배포하고 해당 메트릭을 Prometheus와 연동하는 방법을 알아봅니다. NGINX Plus는 고급 로드 밸런싱 기능과 모니터링 기능을 제공하여 애플리케이션의 성능을 극대화할 수 있습니다. NGINX Plus Sidecar와 Prometheus를 연동하는 간단한 설정에 대해 알아보세요.

목차

1. NGINX Plus Sidecar란?
2. NGINX Plus Sidecar 배포

2-1. Namespace 생성
2-2. Docker Secret 생성
2-3. ConfigMap 생성
2-4. NGINX Plus Sidecar 가 포함된 서비스 배포
2-5. NGINX Plus Sidecar 배포 확인
3. Prometheus 배포

3-1. Prometheus ConfigMap 배포
3-2. Prometheus 서비스 배포
3-3. Prometheus 배포 확인
4. NGINX Plus Sidecar 메트릭 확인
5. 결론

1. NGINX Plus Sidecar란?

여기서 NGINX Plus Sidecar란 쿠버네티스 환경에서 애플리케이션 컨테이너와 함께 배포되는 NGINX Plus 인스턴스를 의미합니다. Sidecar 패턴은 주 애플리케이션과 보조 서비스(여기서 NGINX Plus)가 동일한 Pod 내에서 실행되도록 하여, 두 컴포넌트 간의 네트워크 통신을 최적화합니다.

2. NGINX Plus Sidecar 배포

먼저 NGINX Plus Sidecar 패턴을 배포하기 위해 NGINX Plus가 필요합니다. 따라서 NGINX Plus Prometheus 모듈을 포함한 Dockerfile을 작성합니다(이 Dockerfile은 debian 기반입니다):

ARG RELEASE=bookworm
FROM debian:${RELEASE}-slim

LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"

RUN --mount=type=secret,id=nginx-crt,dst=nginx-repo.crt \
    --mount=type=secret,id=nginx-key,dst=nginx-repo.key \
    set -x \
    && groupadd --system --gid 101 nginx \
    && useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \
    && apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg2 lsb-release \
    && \
    NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
    NGINX_GPGKEY_PATH=/usr/share/keyrings/nginx-archive-keyring.gpg; \
    export GNUPGHOME="$(mktemp -d)"; \
    found=''; \
    for server in \
        hkp://keyserver.ubuntu.com:80 \
        pgp.mit.edu \
    ; do \
        echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
        gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
    done; \
    test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
    gpg --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH" ; \
    rm -rf "$GNUPGHOME"; \
    apt-get remove --purge --auto-remove -y gnupg2 && rm -rf /var/lib/apt/lists/* \
    && nginxPackages=" \
        nginx-plus \
        nginx-plus-module-njs \
        nginx-plus-module-prometheus \
    " \
    && echo "Acquire::https::pkgs.nginx.com::Verify-Peer \"true\";" > /etc/apt/apt.conf.d/90nginx \
    && echo "Acquire::https::pkgs.nginx.com::Verify-Host \"true\";" >> /etc/apt/apt.conf.d/90nginx \
    && echo "Acquire::https::pkgs.nginx.com::SslCert     \"/etc/ssl/nginx/nginx-repo.crt\";" >> /etc/apt/apt.conf.d/90nginx \
    && echo "Acquire::https::pkgs.nginx.com::SslKey      \"/etc/ssl/nginx/nginx-repo.key\";" >> /etc/apt/apt.conf.d/90nginx \
    && echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://pkgs.nginx.com/plus/debian `lsb_release -cs` nginx-plus\n" > /etc/apt/sources.list.d/nginx-plus.list \
    && mkdir -p /etc/ssl/nginx \
    && cat nginx-repo.crt > /etc/ssl/nginx/nginx-repo.crt \
    && cat nginx-repo.key > /etc/ssl/nginx/nginx-repo.key \
    && apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y $nginxPackages curl gettext-base \
    && apt-get remove --purge -y lsb-release \
    && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx-plus.list \
    && rm -rf /etc/apt/apt.conf.d/90nginx /etc/ssl/nginx \
    && ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80

STOPSIGNAL SIGQUIT

CMD ["nginx", "-g", "daemon off;"]

해당 Dockerfile을 빌드하여 이미지를 생성합니다:

DOCKER_BUILDKIT=1 docker build --no-cache -t nginxplus --secret id=nginx-crt,src=</path/to/your/nginx-repo.crt> --secret id=nginx-key,src=</path/to/your/nginx-repo.key> .

NGINX Plus를 Docker에 배포하는 자세한 방법은 아래 포스트를 참조하세요.

2-1. Namespace 생성

이 가이드에서는 3개의 namespace에 있는 각각 서비스에 NGINX Plus Sidecar를 주입합니다. 따라서 3개의 namespace를 생성합니다:

# kubectl create namespace ns1
# kubectl create namespace ns2
# kubectl create namespace ns3

2-2. Docker Secret 생성

NGINX Plus 이미지를 불러오기 위해 Docker Secret을 각 namespace에 생성합니다.

# kubectl create secret docker-registry nginxplus -n ns1 \
  --docker-username=<docker-username>  \
  --docker-password=<docker-password> \
  --docker-email=<docker-email>

# kubectl create secret docker-registry nginxplus -n ns2 \
  --docker-username=<docker-username>  \
  --docker-password=<docker-password> \
  --docker-email=<docker-email>

# kubectl create secret docker-registry nginxplus -n ns3 \
  --docker-username=<docker-username>  \
  --docker-password=<docker-password> \
  --docker-email=<docker-email>

2-3. ConfigMap 생성

NGINX Plus Sidecar의 설정을 구성합니다. 여기서는 Apache 서비스로 프록시하는 구성입니다:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-plus-config
  namespace: ns1
data:
  nginx.conf: |

    user  nginx;
    worker_processes auto;

    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;

    load_module modules/ngx_http_js_module.so;

    events {
        worker_connections  1024;
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        js_import /usr/share/nginx-plus-module-prometheus/prometheus.js;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;
        sendfile        on;
        keepalive_timeout  65;

        upstream ns1 {
          zone ns1 64k;
          server localhost:80;  # Apache Server
        }

        server {
          listen 8080;

          location / {
            proxy_pass http://ns1;
          }
          location /api/ {
            api write=on;
          }
          location = /metrics {
            js_content prometheus.metrics;
          }
        }
    }

위와 같은 ConfigMap 리소스를 각각 ns2, ns3에도 배포합니다. 이에 대한 리소스는 아래를 yaml을 클릭하세요.

이제 각각의 ConfigMap 리소스를 배포합니다:

# kubectl apply -f ns1_np_config.yaml
# kubectl apply -f ns2_np_config.yaml
# kubectl apply -f ns3_np_config.yaml

2-4. NGINX Plus Sidecar가 포함된 서비스 배포

이 가이드에서는 기본 서비스를 Apache로 사용합니다. 이제 각각의 namespace에 NGINX Plus Sidecar가 포함된 서비스를 생성합니다(namespace ns1):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ns1-deploy
  namespace: ns1
spec:
  selector:
    matchLabels:
      app: ns1-deploy
  template:
    metadata:
      labels:
        app: ns1-deploy
    spec:
      imagePullSecrets:
      - name: nginxplus                    # 섹션 2-2에서 생성한 secret 
      containers:
      - name: ns1-container1
        image: httpd                       # Apache 서비스
        ports:
        - containerPort: 80
      - name: nginx-plus
        image: <NGINX Plus Images:Tag>  # 섹션 2에서 배포한 NGINX Plus Image:tag 로 변경
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/nginx.conf   # 해당 경로로 마운트
          subPath: nginx.conf                # nginx.conf만 마운트
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-plus-config

---
apiVersion: v1
kind: Service
metadata:
  name: ns1-svc
  namespace: ns1
  labels:
    app: ns1-deploy1
spec:
  clusterIP: 10.110.0.1      # prometheus에서 메트릭 수집을 위해 clusterIP 할당
  ports:
  - name: http-ho-svc-port1
    port: 80
    targetPort: 8080
  selector:
    app: ns1-deploy

위와 같은 서비스를 각각 ns2, ns3에도 배포합니다. 이에 대한 리소스는 아래를 yaml을 클릭하세요.

이제 각각의 서비스를 배포합니다:

# kubectl apply -f ns1_sidecar_service.yaml
# kubectl apply -f ns2_sidecar_service.yaml
# kubectl apply -f ns3_sidecar_service.yaml

2-5. NGINX Plus Sidecar 배포 확인

현재 배포된 Pod는 다음과 같습니다:

# kubectl get pods -n ns1
NAME                          READY   STATUS    RESTARTS   AGE
ns1-deploy-6bb4876bdc-mcdwq   2/2     Running   0          105m

# kubectl get pods -n ns2
NAME                          READY   STATUS    RESTARTS   AGE
ns2-deploy-66df57f599-8k744   2/2     Running   0          105m

# kubectl get pods -n ns3
NAME                          READY   STATUS    RESTARTS   AGE
ns3-deploy-7f7589594c-c8gnq   2/2     Running   0          106m

현재 배포된 ConfigMap은 다음과 같습니다:

# kubectl get cm -n ns1
NAME                DATA   AGE
kube-root-ca.crt    1      2d19h
nginx-plus-config   1      2d19h

# kubectl get cm -n ns2
NAME                DATA   AGE
kube-root-ca.crt    1      2d19h
nginx-plus-config   1      2d19h

# kubectl get cm -n ns3
NAME                DATA   AGE
kube-root-ca.crt    1      2d19h
nginx-plus-config   1      2d19h

현재 배포된 Service는 다음과 같습니다.

# kubectl get svc -n ns1
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
ns1-svc   ClusterIP   10.110.0.1   <none>        80/TCP    109m

# kubectl get svc -n ns2
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
ns2-svc   ClusterIP   10.110.0.2   <none>        80/TCP    126m

# kubectl get svc -n ns3
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
ns3-svc   ClusterIP   10.110.0.3   <none>        80/TCP    125m

이제 각 서비스의 clusterIP/metrics 를 요청하여 NGINX Plus의 메트릭이 나타나는지 확인합니다:

# curl 10.110.0.1/metrics

# HELP nginxplus_workers_mem_rss Resident set size (pss), physical memory NGINX workers are using, including shared libraries
# TYPE nginxplus_workers_mem_rss counter
nginxplus_workers_mem_rss 14815232
# HELP nginxplus_workers_mem_private Private memory used by NGINX workers, does not include shared libraries
# TYPE nginxplus_workers_mem_private counter
nginxplus_workers_mem_private 9793536
...

각각 10.110.0.1/metrics, 10.110.0.2/metrics, 10.110.0.3/metrics 를 요청했을 때, 메트릭이 모두 나타난다면 정상입니다.

3. Prometheus 배포

위에서 확인한 NGINX Plus Sidecar의 메트릭을 확인 후, 이 메트릭을 Prometheus로 넘겨주기 위해 Prometheus를 배포합니다. 여기서 Prometheus에 관한 리소스는 “monitoring” namespace에 배포합니다.

# kubectl create namespace monitoring

3-1. Prometheus ConfigMap 배포

위에서 확인한 NGINX Plus Sidecar의 메트릭을 Prometheus로 넘겨주기 위해 ConfigMap 리소스를 사용하여 prometheus.yml을 생성합니다(prom-config.yaml):

apiVersion: v1
kind: ConfigMap
metadata:
  name: prom-config
  namespace: monitoring
data:
  prometheus.yml: |

    scrape_configs:
      - job_name: nginxplus-target       # 해당 job 이름을 nginxplus-target으로 설정
        honor_timestamps: true           # 해당 메트릭의 타임스탬프 활성화
        scrape_interval: 5s              # 메트릭 수집 주기
        scrape_timeout: 5s               # 메트릭 수집 timeout
        metrics_path: /metrics           # metrics 수집을 위한 경로
        scheme: http                     # HTTP를 사용하여 메트릭 수집
        follow_redirects: true           # 리다이렉션 활성화
        static_configs:
          - targets: ['10.110.0.1:80']
          - targets: ['10.110.0.2:80']
          - targets: ['10.110.0.3:80']

위와 같이 구성 후 배포합니다:

# kubectl apply -f prom-config.yaml

3-2. Prometheus 서비스 배포

생성한 ConfigMap 설정을 마운트하는 Prometheus 서비스를 생성합니다(prometheus.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: prom-deploy
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: prom-deploy
  template:
    metadata:
      labels:
        app: prom-deploy
    spec:
      containers:
      - name: prom-container
        image: prom/prometheus
        ports:
          - containerPort: 9090
        volumeMounts:
        - name: prom-config
          mountPath: /etc/prometheus/prometheus.yml
          subPath: prometheus.yml
      volumes:
      - name: prom-config
        configMap:
          name: prom-config
---
apiVersion: v1
kind: Service
metadata:
  name: prom-svc
  namespace: monitoring
spec:
  ports:
  - name: prom-port
    port: 80
    targetPort: 9090
    nodePort: 30090
  selector:
    app: prom-deploy
  type: NodePort

이 예시에서는 간단한 테스트이기 때문에 NodePort Type을 사용했습니다. 작성한 Deployment와 Service 리소스를 배포합니다:

$ kubectl apply prometheus.yaml

3-3. Prometheus 배포 확인

다음 명령어를 사용하여 정상적으로 배포되었는지 확인합니다:

# kubectl get pods -n monitoring 
NAME                           READY   STATUS    RESTARTS   AGE
prom-deploy-6d59ddffd6-bkjmz   1/1     Running   0          7m28s

# kubectl get svc -n monitoring 
NAME       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
prom-svc   NodePort   10.96.48.191   <none>        80:30090/TCP   7m29s

4. NGINX Plus Sidecar 메트릭 확인

이제 Prometheus UI에서 NGINX Plus Sidecar의 메트릭을 확인합니다. 이 예시에서는 Prometheus를 NodePort 30090으로 배포하였기 때문에 30090 포트로 접속합니다:

우측 지구본 모양의 Metrics Explorer 아이콘을 클릭하여 nginxplus 와 관련된 메트릭이 나타난다면 정상적으로 NGINX Plus Sidecar와 Prometheus가 연동된 것입니다.

/targets?search= 엔트포인트를 검색하면 연결된 NGINX Plus Sidecar 정보를 확인할 수 있습니다:

5. 결론

이번 포스트에서는 NGINX Plus Sidecar와 Prometheus를 연동하는 간단한 방법을 소개했습니다.

NGINX Plus Sidecar와 Prometheus의 연동은 애플리케이션의 성능 모니터링을 강화합니다. 실시간 메트릭 수집을 통해 트래픽 패턴을 분석하고, 문제 발생 시 빠르게 대응할 수 있습니다. 또한, Grafana와 같은 시각화 도구와 통합하여 직관적인 대시보드를 제공함으로써 운영 효율성을 높이고, 최적의 사용자 경험을 보장할 수 있습니다.

NGINX Plus Sidecar를 직접 사용해 보시려면 30일 무료 평가판을 신청하거나 NGINX STORE에 연락하여 논의하십시오.

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

* indicates required