ncloud NKS에서 Nginx Ingress Controller 설치부터 HTTPS 적용하기

2025. 1. 3. 03:36·Kubernetes

이번 포스팅에서는 NKS에서 nginx ingress controller를 설치해서 등록된 도메인을 연결하고, cert-manager와 letsencrypt로 HTTPS를 적용하는 과정을 다룹니다.

 

실행 환경은 `kubectl config`를 통해 생성한 NKS 클러스터에 명령어를 입력가능한 상태입니다.

kubectl config는 이전 포스팅의 마지막 kubectl config 설정 부분을 참고하시면 됩니다.

(2025.01.01 - [Kubernetes] - ncloud NKS로 쿠버네티스 클러스터 구성하기)

 

0. Ingress?

https://kubernetes.io/ko/docs/concepts/services-networking/ingress/

Ingress는 쿠버네티스 클러스터에서 서비스 리소스와 완전히 독립적인 리소스입니다.

Ingress는 프라이빗 클러스터 내부의 서비스를 외부에 노출시키지 않고 라우팅을 할 수 있으며 SSL/TLS 처리와 로드밸런싱 등을 제공합니다.

 

Ingress를 사용하기 위해선 Ingress Controller가 있어야 리소스를 사용할 수 있습니다. 이를 위해 ncloud에서 제공하는 alb-ingress-controller를 이용할 수 있지만 좀 더 섬세한 제어를 위해 Nginx Ingress Controller를 이용하겠습니다.

Nginx Ingress Controller는 L7 로드밸런싱을 쉽게 할 수 있습니다.

1. Nginx Ingress Controller 설치

ncloud 공식 문서에 Ingress 활용 예제에 설치 가이드가 쉽게 설명되어 있습니다.

이 부분을 참고해서 설치하겠습니다.

 

먼저 공식 GitHub에서 지원하는 버전을 확인합니다.

https://github.com/kubernetes/ingress-nginx

 

GitHub - kubernetes/ingress-nginx: Ingress NGINX Controller for Kubernetes

Ingress NGINX Controller for Kubernetes. Contribute to kubernetes/ingress-nginx development by creating an account on GitHub.

github.com

NKS에서 생성한 쿠버네티스 클러스터 버전은 1.29 버전이므로 ingress-nginx 버전은 1.11.3으로 설치하겠습니다.

 

1. 아래 명령어로 ingress-nginx를 설치합니다.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.3/deploy/static/provider/cloud/deploy.yaml

ingress-nginx는 기본적으로 ingress-nginx 네임스페이스에 설치됩니다.

설치되면 NKS 설정 시 등록했던 퍼블릭 로드밸랜서 전용 서브넷에 ingress-nginx-controller 인스턴스가 생성됩니다.

 

2. 아래 명령어로 파드와 서비스를 확인합니다.

# 파드 확인
kubectl get pods -n ingress-nginx

# 실행 결과
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-8w86q        0/1     Completed   0          33h
ingress-nginx-admission-patch-9xsxb         0/1     Completed   1          33h
ingress-nginx-controller-7bf4d86ccc-4mgwj   1/1     Running     0          26h

# 서비스 접속 정보 확인
kubectl get svc -n ingress-nginx

# 실행 결과
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP                                                                PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   198.19.220.90    ingress-ngi-ingress-ngin-bb6c1-101440325-.kr.lb.naverncp.com   80:31580/TCP,443:31172/TCP   33h
ingress-nginx-controller-admission   ClusterIP      198.19.190.226   <none>                                                                     443/TCP                      33h

 

3. Ingress를 설정합니다.

위에서 확인한 ingress-nginx의 EXTERNAL-IP가 외부 주소에 해당하며, `ingress-ngi-ingress-ngin-bb6c1-101440325-.kr.lb.naverncp.com`으로 되어 있습니다.

 

ncloud 콘솔의 Load Balancer 메뉴에서도 확인할 수 있는데요, 로드밸런서가 위치한 서브넷은 이전에 생성해 둔 퍼블릭 로드밸랜서 전용 서브넷에 위치한 것을 확인할 수 있습니다.

 

Ingress 설정에서 URI 기반으로 라우팅을 하는 예시를 보여드리겠습니다.

 

지금 당장은 TLS를 적용하지 않았기 때문에 `nginx.ingress.kubernetes.io/ssl-redirect: 'false'`로 설정해 강제 리다이렉션을 방지합니다.

ingress-nginx 서비스에서 확인한 EXTERNAL IP인 `ingress-ngi-ingress-ngin-bb6c1-101440325-.kr.lb.naverncp.com`를 통해 들어온 요청을 path별로 라우팅을 합니다.

 

아래 메니페스트를 보겠습니다.

`/api/v1`으로 시작하는 경로는 backend-svc 서비스로 라우팅 합니다. 그 외 `/`으로 시작하는 경로는 frontend-svc 서비스로 라우팅 합니다. `/` 보다 먼저 처리돼야 하므로 백엔드 서비스가 가장 최상단에 있습니다.

# my-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: 'false'
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /api/v1
            pathType: Prefix
            backend:
              service:
                name: backend-svc
                port:
                  number: 8080
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-svc
                port:
                  number: 80

 

4. Ingress를 생성합니다.

kubectl apply -f ./my-ingress.yaml

 

이후 생성된 ingress를 확인합니다.

kubectl get ingress

# 실행 결과
NAME            CLASS   HOSTS   ADDRESS                                                         PORTS  
ingress-nginx   nginx   *       ingress-ngi-ingress-ngin-bb6c1-101440325-.kr.lb.naverncp.com    80, 443

 

curl 또는 Postman으로 API 호출이 정상적으로 되는지 확인할 수 있습니다.

curl ingress-ngi-ingress-ngin-bb6c1-101440325.kr.lb.naverncp.com/api/v1/users

2. 도메인 연결하기

구매한 도메인은 ncloud의 Global DNS+에 등록이 먼저 되어있어야 합니다.

레코드 추가를 눌러 A 레코드를 등록합니다.

LB VPC를 선택하고, 위에서 생성한 ingress 로드 밸런서를 선택하고 추가를 눌러 등록합니다.

몇 분 시간이 지나면 배포가 되니 기다립시다.

3. cert-manager, letsencrypt로 TLS 설정하기 (HTTPS)

cert-manager와 letsencrypt를 이용해 TLS를 설정하고, ingress-nginx 설정으로 HTTPS를 적용합니다.

cert-manager 공식 문서에서 튜토리얼을 기반으로 정리했습니다.

 

Ingress를 통해 cert-manager가 인증을 하는 방식은 아래 이미지와 같습니다.

https://cert-manager.io/docs/usage/ingress/

cert-manager는 Ingress에 annotation을 다는 것만으로도 TLS 인증을 처리할 수 있도록 합니다.

3-1. cert-manager 설치

아래 명령어로 cert-manager를 설치합니다.

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.16.2/cert-manager.yaml

cert-manager는 `cert-manager` 네임스페이스에 설치됩니다.

 

설치 후 네임스페이스를 확인합니다.

3개의 파드가 모두 `Running`상태가 될 때 까지 잠시 기다립시다. `cert-manager-webhook` 파드가 올라오기까지 시간이 조금 걸립니다.

kubectl get pods --namespace cert-manager

# 실행 결과
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-5c6866597-zw7kh               1/1     Running   0          2m
cert-manager-cainjector-577f6d9fd7-tr77l   1/1     Running   0          2m
cert-manager-webhook-787858fcdb-nlzsq      1/1     Running   0          2m

 

3-2. ClusterIssuer 생성

Issuer는 ACME(Automatic Certificate Management Environment)이며, 오픈 소스를 지원합니다.

인증 방식은 `http01`로 수행하며, `dns01`을 이용할 수도 있습니다.

  • `http01` 방식은 ACME 서버가 도메인 소유권을 확인하기 위해 HTTP 요청으로 키 값을 검증하는 방식입니다. 퍼블릭 도메인인 경우에만 사용할 수 있습니다.
  • `dns01` 방식은 ACME 서버가 DNS 조회 시 TXT 레코드를 참조해 인증서에 대한 도메인을 소유하고 있는지 확인하는 방식입니다. DNS TXT 레코드에 특정 키 값을 수동으로 설정해야 합니다.

더 자세한 내용은 이 링크를 참고해주세요.

 

1. ClusterIssuer 매니페스트를 작성합니다. `email` 부분만 사용할 이메일로 바꿔서 작성하면 됩니다.

저는 `dns01` 방식은 DNS TXT 레코드를 수동으로 설정해야 하는 불편함이 있어 `http01` 방식을 사용했습니다.

# cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: 이메일을 입력하세요
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx

 

2. 아래 명령어로 ClusterIssuer를 생성합니다.

kubectl apply -f ./cluster-issuer.yaml

3-3. ingress-nginx 수정

위에서 작성했던 ingress-nginx 메니페스트를 수정합니다. (my-ingress.yaml)

  • `nginx.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS":443}]'`를 추가해 80, 443 포트를 리스닝합니다.
  • `nginx.ingress.kubernetes.io/ssl-redirect: 'false'`부분을 `nginx.ingress.kubernetes.io/ssl-redirect: 'true'`로 변경하거나 제거합니다. (해당 애너테이션 기본값은 `true`입니다.)
  • 애너테이션에 `cert-manager.io/cluster-issuer: letsencrypt-prod`를 추가합니다.
    입력하는 이름은 위에서 생성한
    ClusterIssuer 이름입니다.

매니페스트

# my-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS":443}]'
    nginx.ingress.kubernetes.io/ssl-redirect: 'true'
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - dev2.mydomain.com
      secretName: mydomain-cert
  ingressClassName: nginx
  rules:
    - host: dev2.mydomain.com
      http:
        paths:
          - path: /api/v1
            pathType: Prefix
            backend:
              service:
                name: backend-svc
                port:
                  number: 8080
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-svc
                port:
                  number: 80

 

매니페스트 변경 사항 적용

변경 사항을 적용합니다.

kubectl apply -f ./my-ingress.yaml

 

만약 변경이 잘 적용되지 않는다면 ingress-nginx-controller를 재시작합니다.

kubectl rollout restart deployment ingress-nginx-controller -n ingress-nginx

 

클러스터에서 Certificate 및 Secret 리소스 확인

아래 명령어로 cert-manager가 생성한 certificate 리소스를 확인할 수 있습니다.

kubectl get certificate -o wide

# 실행 결과
NAME        READY   SECRET      ISSUER             STATUS                                          AGE
dev2-cert   True    dev2-cert   letsencrypt-prod   Certificate is up to date and has not expired   1h

 

아래 명령어로 위의 인증서를 Secret으로 등록된 것을 확인할 수 있습니다.

kubectl get secret
NAME             TYPE                DATA   AGE
dev2-cert        kubernetes.io/tls   2      27h

 

이제 TLS 적용이 완료되어 인증서가 유효함을 확인할 수 있습니다.

추가. CORS 설정

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS":443}]'
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "https://dev2.mydomain.com"
    nginx.ingress.kubernetes.io/cors-allow-methods: "HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-headers: "Authorization, Content-Type, X-Refresh-Token, Cache-Control"
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
# 이하 생략

만약 CORS 설정이 필요하면 Ingress에서 처리할 수 있습니다. 그 외에도 annotation을 활용해 기존 Nginx에서 사용했던 설정들을 대체할 수 있으니 이 링크를 확인하시면 됩니다.

 

참고

  • https://kubernetes.io/ko/docs/concepts/services-networking/ingress/
  • https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-ingress-guide-nginx-example.html

 

도움이 되셨길 바라며, 읽어주셔서 감사합니다.

'Kubernetes' 카테고리의 다른 글

쿠버네티스에서 MySQL dump 하기 (uuid 필드를 사용할 때)  (0) 2025.02.28
쿠버네티스에서 트래픽 유실 없는 무중단 배포 적용하기  (1) 2025.01.06
ncloud NKS로 쿠버네티스 클러스터 구성하기  (0) 2025.01.01
[k8s] 쿠버네티스 핵심 개념  (0) 2024.09.11
[k8s] 쿠버네티스 시작하기  (0) 2024.09.11
'Kubernetes' 카테고리의 다른 글
  • 쿠버네티스에서 MySQL dump 하기 (uuid 필드를 사용할 때)
  • 쿠버네티스에서 트래픽 유실 없는 무중단 배포 적용하기
  • ncloud NKS로 쿠버네티스 클러스터 구성하기
  • [k8s] 쿠버네티스 핵심 개념
옐리yelly
옐리yelly
전시회에서 도슨트를 따라다니며 작품 해설을 들으면 더 재밌었던 기억들이 있습니다. 글로 더 재밌는 개발이 되도록 노력하고 있습니다.
  • 옐리yelly
    개발 갤러리
    옐리yelly
  • 전체
    오늘
    어제
    • 모든 글 보기 (82)
      • Project (22)
      • Java (4)
      • Spring (6)
      • Kubernetes (6)
      • Docker (2)
      • JPA (2)
      • Querydsl (2)
      • MySQL (8)
      • ElasticSearch (7)
      • DevOps (4)
      • Message Broker (3)
      • Git & GitHub (2)
      • Svelte (1)
      • Python (8)
        • Python Distilled (4)
        • Anaconda (1)
        • Django (0)
        • pandas (3)
      • Algorithm (1)
      • Computer Science (0)
      • 내 생각 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    blue-green 배포
    Python
    argocd
    데드락
    devops
    비사이드
    nks
    gitops
    k8s
    예약 시스템
    포텐데이
    ncloud
    프로젝트
    리팩토링
    JPA
    pymysql
    svelte
    RabbitMQ
    pandas
    커넥션 풀
    querydsl
    Project
    MySQL
    OOP
    성능 테스트
    Spring
    elasticsearch
    Message Broker
    docker
    dataframe
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
옐리yelly
ncloud NKS에서 Nginx Ingress Controller 설치부터 HTTPS 적용하기
상단으로

티스토리툴바