웹사이트 검색

Cert-Manager란 무엇이며 Helm을 사용하여 AWS의 Kubernetes 클러스터에서 SSL 인증서용 Cert-Manager를 설정하는 방법


이 페이지에서

  1. 전제 조건
  2. 무엇을 할 것인가?\n
  3. 클러스터에서 인그레스 컨트롤러 확인\n
  4. 인증 관리자 설정
  5. 샘플 애플리케이션 및 발급자를 위한 개체 정의 파일 만들기\n
  6. 설정 스테이징 및 프로덕션 Lets Encrypt Issuer\n
  7. 샘플 애플리케이션 배포\n
  8. 인그레스 배포
  9. 결론

Cert-Manager는 인증서 관리에 사용되는 컨트롤러입니다. Cert-Manager는 Let’s Encrypt, HashiCorp Vault, Venafi, 단순 서명 키 쌍 또는 자체 서명과 같은 다양한 발급자의 인증서를 발급하는 데 도움을 줄 수 있습니다. Cert-Manager는 인증서를 검증하고 최신 상태인지 확인하며 만료 전에 갱신합니다. Cert-Manager는 아래에 언급된 여러 구성요소로 구성됩니다.

  1. 발급자: 발급자 및 ClusterIssuer는 서명된 인증서를 생성할 수 있는 인증 기관(CA)을 나타내는 Kubernetes의 개체입니다.\n
  2. 인증서: 인증서는 발급자 또는 클러스터 발급자를 참조하는 네임스페이스 리소스이며 갱신되고 최신 상태로 유지됩니다.\n
  3. CertificateRequest: CertificateRequest는 발급자 또는 클러스터 발급자에게 인증서를 요청하는 데 사용되는 네임스페이스 리소스입니다.\n
  4. ACME 주문: 주문은 ACME 발급자를 참조하는 새 CertificateRequest 리소스가 생성되면 생성되는 인증서 요청을 나타냅니다.\n
  5. ACME 챌린지: 주문 리소스가 생성되면 ACME 서버에서 승인되는 각 DNS 이름에 대한 챌린지 리소스가 주문 컨트롤러에 의해 생성됩니다.\n
  6. Webhook: 기본 Cert-Manager 포드와 함께 다른 포드로 배포되며 ValidatingAdmissionWebhook, MutatingAdmissionWebhook 및 CustomResourceConversionWebhook의 3가지 기능이 있습니다.\n
  7. CA 인젝터: 웹후크 유효성 검사, 웹후크 변경, 전환 웹후크에 대한 인증서를 구성하는 데 도움이 됩니다.\n

이 기사에서는 Lets Encrypt 발행자를 사용하여 Cert-Manager를 설정합니다. TLS 인증서를 사용하여 샘플 애플리케이션을 보호하고 Ingress를 사용하여 애플리케이션에 액세스하기 위해 호스트 이름에 HTTPS를 포함합니다. 이를 위해 인증서 리소스가 대신 생성되도록 인그레스에 주석을 추가합니다.

Cert-Manager에 대한 자세한 내용은 여기에서 공식 문서를 참조하십시오. 이 문서의 초점은 Helm을 사용하여 Cert-Manager를 설정하는 데 있으며 사용자가 Cert-Manager와 관련된 개념에 익숙하다고 가정합니다.

전제 조건

  1. AWS 계정(계정이 없는 경우 생성).
  2. Kubernetes 클러스터(Kops를 사용하여 Kubernetes 클러스터를 만들고 자세한 내용을 알아보려면 여기를 클릭하세요.)\n
  3. K8S 클러스터의 Nginx 인그레스 컨트롤러(Nginx 인그레스 컨트롤러 설정 방법을 알아보려면 "인그레스 컨트롤러란 무엇이며 Helm을 사용하여 AWS의 Kubernetes 클러스터에 Nginx 인그레스 컨트롤러를 배포하는 방법"을 검색하십시오.)\n
  4. Helm v3.5.3(Ubuntu 서버에 Helm을 설치하는 방법을 알아보려면 여기를 클릭하세요.)\n
  5. S3 버킷(AWS에서 S3 버킷을 생성하는 방법을 알아보려면 여기를 클릭).\n
  6. 도메인 이름(AWS에 도메인을 등록하는 방법을 알아보려면 여기를 클릭).\n
  7. 관리자 권한이 있는 IAM 역할(AWS에서 IAM 역할을 생성하는 방법을 알아보려면 여기를 클릭).\n

우리는 무엇을 할 것인가?

  1. 클러스터에서 인그레스 컨트롤러 확인\n
  2. Cert-Manager 설정
  3. 샘플 애플리케이션용 객체 정의 파일 만들기\n
  4. 설정 스테이징 및 프로덕션 Lets Encrypt Issuer\n
  5. 샘플 애플리케이션 배포\n
  6. TLS로 인그레스 개체 배포

클러스터에서 인그레스 컨트롤러 확인

계속하기 전에 클러스터에서 실행 중인 Nginx 인그레스 컨트롤러가 있는지 확인하세요.

kubectl get pods
kubectl get svc

인증서 관리자 설정

Note: I have used Helm binary present at my current location, hence you can see ./helm in screenshots.

Helm v3.5.3을 사용하고 다음 명령을 실행하면 Cert-Manager용 Helm 차트가 설치됩니다.

kubectl create namespace cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.2.0 --set installCRDs=true

위 스크린샷에서 Cert-Manager용 Helm Chart가 설치된 것을 확인할 수 있습니다.

Cert-Manager의 일부로 생성된 포드를 확인합니다.

kubectl get pods -A

\cert-manager\ 네임스페이스에서 3개의 새 포드를 볼 수 있습니다.

샘플 애플리케이션 및 발급자를 위한 객체 정의 파일 만들기

애플리케이션 1용 1-nginx-main-app.yaml 생성

Github 링크: 내 Github 저장소에서 파일을 복사하려면 여기를 클릭하세요.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx-deploy-main
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-main
  template:
    metadata:
      labels:
        run: nginx-main
    spec:
      containers:
      - image: nginx
        name: nginx


---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deploy-main
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    run: nginx-main

애플리케이션 2용 2-nginx-green-app.yaml을 만듭니다.

Github 링크: 내 Github 저장소에서 파일을 복사하려면 여기를 클릭하세요.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx-deploy-green
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-green
  template:
    metadata:
      labels:
        run: nginx-green
    spec:
      volumes:
      - name: webdata
        emptyDir: {}
      initContainers:
      - name: web-content
        image: busybox
        volumeMounts:
        - name: webdata
          mountPath: "/webdata"
        command: ["/bin/sh", "-c", 'echo "<h1>I am <font color=green>GREEN</font></h1>" > /webdata/index.html']
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: webdata
          mountPath: "/usr/share/nginx/html"


---
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deploy-green
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    run: nginx-green          

애플리케이션 3용 3-nginx-blue-app.yaml 생성

Github 링크: 내 Github 저장소에서 파일을 복사하려면 여기를 클릭하세요.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx-deploy-blue
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-blue
  template:
    metadata:
      labels:
        run: nginx-blue
    spec:
      volumes:
      - name: webdata
        emptyDir: {}
      initContainers:
      - name: web-content
        image: busybox
        volumeMounts:
        - name: webdata
          mountPath: "/webdata"
        command: ["/bin/sh", "-c", 'echo "<h1>I am <font color=blue>BLUE</font></h1>" > /webdata/index.html']
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: webdata
          mountPath: "/usr/share/nginx/html"


---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deploy-blue
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    run: nginx-blue

Staging Issuer로 경로 기반 인그레스 규칙을 만들기 위해 4-tls-ingress.yaml을 만듭니다.

Github 링크: 내 Github 저장소에서 파일을 복사하려면 여기를 클릭하세요.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-staging
  name: ingress-resource-3
spec:
  tls:
  - hosts:
    - kops.devopslee.com
    secretName: sample-kubernetes-tls
  rules:
  - host: kops.devopslee.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-deploy-main
          servicePort: 80
      - path: /blue
        backend:
          serviceName: nginx-deploy-blue
          servicePort: 80
      - path: /green
        backend:
          serviceName: nginx-deploy-green
          servicePort: 80

프로덕션 발급자로 경로 기반 인그레스 규칙을 만들기 위해 5-tls-ingress-prod-issuer.yaml을 만듭니다.

Github 링크: 내 Github 저장소에서 파일을 복사하려면 여기를 클릭하세요.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-production
  name: ingress-resource-3
spec:
  tls:
  - hosts:
    - kops.devopslee.com
    secretName: sample-kubernetes-tls
  rules:
  - host: kops.devopslee.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-deploy-main
          servicePort: 80
      - path: /blue
        backend:
          serviceName: nginx-deploy-blue
          servicePort: 80
      - path: /green
        backend:
          serviceName: nginx-deploy-green
          servicePort: 80

Lets Encrypt 스테이징 발급자를 위한 staging_issuer.yaml 생성

Github 링크: 내 Github 저장소에서 파일을 복사하려면 여기를 클릭하세요.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # Email address used for ACME registration
    email: your-email-id-here
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Name of a secret used to store the ACME account private key
      name: letsencrypt-staging-private-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

Lets Encrypt Production Issuer를 위한 production_issuer.yaml 생성

Github 링크: 내 Github 저장소에서 파일을 복사하려면 여기를 클릭하세요.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-production
spec:
  acme:
    # Email address used for ACME registration
    email: your-email-id-here
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Name of a secret used to store the ACME account private key
      name: letsencrypt-production-private-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

여기 내 Github 저장소에서 이 모든 파일을 찾을 수 있습니다.

설정 스테이징 및 프로덕션 Lets Encrypt Issuer

Staging 및 Production Cluster Issuer를 모두 설치합니다.

각색:

스테이징에는 \서버: https://acme-staging-v02.api.letsencrypt.org/directory\가 있습니다.

kubectl logs cert-manager-56f5c44b5d-jn46m -n cert-manager -f
kubectl apply -f cluster-issuer/staging_issuer.yaml

이렇게 하면 "letsencrypt-staging-private-key"라는 암호가 생성됩니다.

kubectl get secret letsencrypt-staging-private-key -n cert-manager -o json

생산:

프로덕션에는 "서버: https://acme-v02.api.letsencrypt.org/directory"가 있습니다.

kubectl logs cert-manager-56f5c44b5d-jn46m -n cert-manager -f
kubectl apply -f cluster-issuer/production_issuer.yaml

이렇게 하면 "letsencrypt-production-private-key"라는 암호가 생성됩니다.

kubectl get secret letsencrypt-production-private-key -n cert-manager -o json

샘플 애플리케이션 배포

3개의 샘플 애플리케이션을 배포해 보겠습니다.

kubectl apply -f sample-app/1-nginx-main-app.yaml
kubectl apply -f sample-app/2-nginx-green-app.yaml
kubectl apply -f sample-app/3-nginx-blue-app.yaml
Check the deployments, pods, and services created by the above commands.
kubectl get deployments
kubectl get pods kubectl
get service

인그레스 배포

먼저 Staging Issuer와 함께 Ingress를 배포해 보겠습니다.

kubectl apply -f sample-app/4-tls-ingress.yaml
kubectl get ingress
kubectl describe ingress ingress-resource-3

인그레스 리소스가 생성된 후 인그레스의 TLS 섹션에 대한 인증서를 발급하기 위해 백그라운드에서 발생한 모든 일을 확인할 수 있습니다.

kubectl get certificate -A
kubectl get certificaterequests.cert-manager.io -A
kubectl get orders.acme.cert-manager.io -A
kubectl get challenges.acme.cert-manager.io -A
kubectl get certificate  -o json | grep secretName
kubectl get secret sample-kubernetes-tls -o yaml

이제 HTTPS를 통해 애플리케이션에 액세스할 수 있지만 Lets Encrypt 발급자의 스테이징 환경을 사용했기 때문에 "이 사이트에 대한 연결이 안전하지 않습니다"라는 경고가 표시됩니다.

프로덕션 발급자와 함께 인그레스를 배포합니다.

이제 스테이징을 사용하여 인그레스를 삭제하고 프로덕션 발급자를 가리키는 새 인그레스를 생성해 보겠습니다.

kubectl delete -f sample-app/4-tls-ingress.yaml
kubectl apply -f sample-app/5-tls-ingress-prod-issuer.yaml
kubectl get ingress
kubectl describe ingress ingress-resource-3

이번에는 애플리케이션에 액세스하려고 하면 "이 사이트에 대한 연결이 안전하지 않습니다"라는 경고가 표시되지 않습니다.

결론

이 기사에서는 Kubernetes 클러스터에서 Cert-Manager를 설정하는 단계를 살펴보았습니다. 샘플 애플리케이션을 배포하고 경로 기반 인그레스를 통해 트래픽을 라우팅했으며 Lets Encrypt 클러스터 발급자가 발급한 인증서를 사용하여 HTTPS와의 연결을 보호했습니다. 먼저 Lets Encrypt Staging 환경을 사용하여 인증서를 발급한 다음 Lets Encrypt 프로덕션 환경을 사용했습니다.