티스토리 뷰

Cloud/Kubernetes

cert-manager with ingress-nginx

Jacob_baek 2023. 2. 13. 23:34

kubernetes에 cert-manager/ingress-nginx를 설치하고 이를 활용하여 ingress에 annotation을 추가하여 cert-manager로 부터 인증서를 가져와 secret으로 저장하고 이를 실 서비스에 사용하는 방법을 알아보자.

cert-manager 설치

다음 helm 명령을 통해 cert-manager를 설치 한다.

jacob@laptop:~ $ helm install cert-manager jetstack/cert-manager \
  -n cert-manager --create-namespace \
  --version v1.11.0 \
  --set installCRDs=true

ingress-nginx 의 letsencrypt issuer를 이용한 cert 관리

ingress-nginx 설치를 하고

jacob@laptop:~ $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml

Let's encrypt로 부터 인증서를 발급받기위해 clusterissuer를 생성한다.
(여기서 issuer는 CA를 위한것이고 clusterissuer가 실제 서비스에 사용될 certificate 발급기관을 위한것이라 보면된다.)

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-nginx
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: dubaek@gmail.com
    privateKeySecretRef:
      name: letsencrypt-nginx
    solvers:
      - http01:
          ingress:
            class: nginx

여기서 email과 http01 하단의 내용을 확인하여 변경해주어야 한다.
아래는 class외에도 podtemplate, serviceType 등에 대한 설명이 있는 링크이니 이를 참고하여 추가한다.

sample nginx deployment 배포 및 ingress

알아두어야 하는 것은 구매한 도메인의 record를 추가해야 한다는것이다.
cert-manager는 http01 / dns01 과 같은 검증 과정을 거친다.
여기서는 http01을 이용하여 domain lookup이 이루어지는지 확인하는 과정을 사용할 것이다.

다음 sample을 배포하여 테스트 해보자.

apiVersion: v1
kind: Namespace
metadata:
  name: ingresstest
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-app
  namespace: ingresstest
  labels:
    app: nginx-app
spec:
  containers:
  - image: nginx
    name: nginx-image
    ports:
    - containerPort: 80
      protocol: TCP
    readinessProbe:
      httpGet:
        path: /
        port: 80
      periodSeconds: 3
      timeoutSeconds: 20
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-svc
  namespace: ingresstest
spec:
  selector:
    app: nginx-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-deploy-ingress
  namespace: ingresstest
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: sample.jacobbaek.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
            service:
              name: nginx-app-svc
              port:
                number: 80
  tls:
    - hosts:
      - sample.jacobbaek.com
      secretName: sample-jacobbaek-cert           # 해당 secret은 cert-manager를 통해 새롭게 생성되어질 secret으로 사전에 생성할 필요가 없다.

dns01을 이용하는 경우라면 TXT record에 대한 검증을 수행해야하여 TXT record를 추가할 수 있는 AWS route53과 같은 서비스에 접근이 가능해야 하고 관련 권한이 존재하는 키가 존재해야 한다. 아래 블로그 및 공식 페이지를 참고해보면 좋을것 같다.

생성된 정보를 확인

다음 crd들을 통해 발급되는 certificate에 대한 확인을 해볼수 있다.

  • certificaterequests : issuer로부터 X.509 인증서를 요청하는데 사용되는 자원이다.
  • order : signed TLS 인증서에 대한 ACME 주문의 전체 사이클을 관리하는 자원이다.
  • certificate : 실제 유지되고 보존되어질 certificate

다음과 같은 과정을 거쳐 certificate을 가져오는것을 확인 할 수 있다.

jacob@laptop:~ $ k get certificaterequests -n ingresstest
NAME                       APPROVED   DENIED   READY   ISSUER              REQUESTOR                                         AGE
sample-jacobbaek-cert-lwzbw   True                True    letsencrypt-nginx   system:serviceaccount:cert-manager:cert-manager   100s

실제 describe를 통해 확인해보면 다음과 같은 event가 수행되었음을 확인 할 수 있다.

jacob@laptop:~ $ k describe certificaterequests -n ingresstest
...
Events:
  Type    Reason              Age   From                                                Message
  ----    ------              ----  ----                                                -------
  Normal  WaitingForApproval  119s  cert-manager-certificaterequests-issuer-venafi      Not signing CertificateRequest until it is Approved
  Normal  WaitingForApproval  119s  cert-manager-certificaterequests-issuer-selfsigned  Not signing CertificateRequest until it is Approved
  Normal  WaitingForApproval  119s  cert-manager-certificaterequests-issuer-vault       Not signing CertificateRequest until it is Approved
  Normal  WaitingForApproval  119s  cert-manager-certificaterequests-issuer-acme        Not signing CertificateRequest until it is Approved
  Normal  WaitingForApproval  119s  cert-manager-certificaterequests-issuer-ca          Not signing CertificateRequest until it is Approved
  Normal  cert-manager.io     119s  cert-manager-certificaterequests-approver           Certificate request has been approved by cert-manager.io
  Normal  OrderCreated        119s  cert-manager-certificaterequests-issuer-acme        Created Order resource ingresstest/sample-jacobbaek-cert-lwzbw-1977632583
  Normal  CertificateIssued   92s   cert-manager-certificaterequests-issuer-acme        Certificate fetched from issuer successfully
jacob@laptop:~ $ k get order -n ingresstest
NAME                                  STATE   AGE
sample-jacobbaek-cert-lwzbw-1977632583   valid   2m48s

발급된 certificate정보를 확인해볼 수 있다.

jacob@laptop:~ $ k get certificate -n ingresstest
NAME                 READY   SECRET               AGE
sample-jacobbaek-cert   True    sample-jacobbaek-cert   2m38s

다음과 같이 renewaalTime도 존재한다.
(실제 이 시점에 갱신이 이루어지는지 한번더 확인해볼 예정)

jacob@laptop:~ $ k get certificate -n ingresstest -o jsonpath='{.items[0].status}' | jq
{
  "conditions": [
    {
      "lastTransitionTime": "2023-02-13T14:00:40Z",
      "message": "Certificate is up to date and has not expired",
      "observedGeneration": 1,
      "reason": "Ready",
      "status": "True",
      "type": "Ready"
    }
  ],
  "notAfter": "2023-05-14T13:00:38Z",
  "notBefore": "2023-02-13T13:00:39Z",
  "renewalTime": "2023-04-14T13:00:38Z",
  "revision": 1
}

검증

실제 생성된 cert 파일을 openssl을 통해 확인해보면 다음과 같이 Let's Encrypt에서 발행한 sample.jacobbaek.com 도메인임을 확인 할 수 있다.

jacob@laptop:~ $ k get secret/sample-jacobbaek-cert -n ingresstest -o jsonpath='{.data.tls\.crt}' | base64 -d > jacobbaek.crt
jacob@laptop:~ $ openssl x509 -noout -text -in jacobbaek.crt | grep CN
        Issuer: C = US, O = Let's Encrypt, CN = R3
        Subject: CN = sample.jacobbaek.com

'Cloud > Kubernetes' 카테고리의 다른 글

Vertical Pods Autoscaler  (0) 2023.02.16
Custom Container Registry with containerd runtime on Kubernetes  (0) 2023.02.13
fluent-bit with azure service  (0) 2023.01.02
Kaniko  (0) 2022.12.26
kubectl debug and koolkit  (0) 2022.04.14
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함