Azure

AKS - Azure Key Vault, Nginx Ingress TLS 연동

shj4895 2024. 3. 26. 16:11

AKS 환경에서 Azure Key Vault, Nginx Ingress 를 연동하여 TLS 통신을 테스트 하는 글이다.

 

먼저 AKS, Key Vault가 배포되어 있어야 한다. 또한 AKS 클러스터 생성 시 "비밀 저장소 CSI 드라이버 사용"이 활성화 되어 있어야 하고, AKS Managed ID에 Key Vault 접근 권한이 부여되어 있어야 한다. 이 부분은 아래 링크를 참고하여 따라하면 된다.

https://learn.microsoft.com/ko-kr/azure/aks/csi-secrets-store-driver

https://learn.microsoft.com/ko-kr/azure/aks/csi-secrets-store-identity-access#access-with-managed-identity

 

이 글에서는 Self-Signed 인증서가 아닌 실제 도메인을 소유하고 있어 Let's Encrypt로 발행한 인증서를 사용하였다.


1. pem 파일을 pfx로 변환

현재 가지고 있는 인증서 파일 확장자가 .pem 이므로 openssl 명령어를 활용해서 pfx로 변환하였다.

$ openssl pkcs12 -export -in <cert_pem> -inkey <키 파일명> -out <pfx파일명>

 

2. Azure Key Vault에 인증서 업로드

변환한 pfx 파일을 Key Vault에 업로드

az keyvault certificate import --vault-name <AKV_NAME> -n <CERT_NAME> -f <PFX_NAME>.pfx

 

3. 네임스페이스 생성

$ kubectl create ns nginx-tls-test

 

4. SecretProviderClass 생성

아래 yaml 파일 생성하고 kubectl apply -f 명령어로 Secret ProviderClass 생성

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: azure-tls
  namespace: nginx-tls-test
spec:
  provider: azure
  secretObjects:                            # secretObjects defines the desired state of synced K8s secret objects
    - secretName: ingress-tls-csi
      type: kubernetes.io/tls
      data: 
        - objectName: hj-pfx1              #kv에 올린 인증서 이름과 동일하게 맞춰야됨
          key: tls.key
        - objectName: hj-pfx1
          key: tls.crt
  parameters:
    usePodIdentity: "false"
    useVMManagedIdentity: "true"          # Set to true for using managed identity
    userAssignedIdentityID: <MID의 Client ID>   # Set the clientID of the user-assigned managed identity to use
    keyvaultName: <Azure Key Vault 이름>        # Set to the name of your key vault
    cloudName: ""                         # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud
    objects:  |
      array:
        - |
          objectName: hj-pfx1             # kv에 올린 인증서 이름
          objectType: secret              # object types에는 secret, key, cert이 있지만 인증서의 crt와 key를 가져오려면 secret 타입으로 지정해야됨.
          objectVersion: ""               # [OPTIONAL] object versions, default to latest if empty
    tenantId: <Tenant ID>                # The tenant ID of the key vault

 

배포 

$ kubectl apply -f secretproviderclass.yaml

 

5. Nginx Ingress Controller의 Helm 설치 및 인증서 연동

먼저 values.yaml 파일을 작성하여 helm chart 설치시에 필요한 설정값을 기입한다.

controller:
  extraVolumes:
      - name: secrets-store-inline
        csi:
          driver: secrets-store.csi.k8s.io
          readOnly: true
          volumeAttributes:
            secretProviderClass: "azure-tls" #이전에 생성한 SecretProviderClass의 이름
  extraVolumeMounts:
      - name: secrets-store-inline
        mountPath: "/mnt/secrets-store"
        readOnly: true

 

 

작성한 values.yaml 파일을 적용시켜 Nginx Ingress를 설치, 인증서 연동을 한다. Helm 설치 명령어는 Azure 공식 사이트에 있는 명령어로 진행하니 에러가 많이 발생하여 필요 없는 부분은 지웠다.

$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
$ helm repo update

$ helm install ingress-nginx/ingress-nginx  --generate-name  \
--namespace nginx-tls-test  \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
--set controller.service.externalTrafficPolicy=Local \
-f values.yaml

 

배포 되었는지 확인

$ kubectl get secret -A
$ kubectl get svc -n nginx-tls-test

 

6. 테스트용 환경 구성

테스트용 deploy, svc 생성

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nginx        #nginx ingress에 인증서를 사용할 것이기 때문에 deploy에 연동할 필요 없음
  namespace: nginx-tls-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        env:
        - name: TITLE
          value: "AKS Nginx Ingress Demo"

---
apiVersion: v1
kind: Service
metadata:
  name: test-nginx-svc
  namespace: nginx-tls-test
spec:
  type: ClusterIP
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: test-nginx

 

배포 되었는지 확인

$ kubectl get pod -n nginx-tls-test
$ kubectl get svc -n nginx-tls-test

 

7. Ingress 생성

실제 소유하고 있는 도메인을 입력해서 인그레스를 생성한다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
  namespace: nginx-tls-test
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - <Domain Name>
    secretName: ingress-tls-csi
  rules:
  - host: <Domain Name>
    http:
      paths:
      - path: /
        pathType: Prefix      
        backend:
          service:
            name: test-nginx-svc
            port:
              number: 80

 

 

아래 명령어로 Ingress Controller의 Public IP를 조회하여 hosts 파일을 변조하거나 도메인 호스팅 사이트에 A 레코드를 생성하여 테스트 하면 된다.

$ kubectl get svc -n nginx-tls-test

 

 

8. 인증서 갱신

 

Azure Key Valut에 등록된 인증서를 SecretProviderClass를 통해 연동했을 경우 아래 링크를 참고하여 갱신했음.  

 

https://secrets-store-csi-driver.sigs.k8s.io/known-limitations#how-to-fetch-the-latest-content-with-release-v0014-and-earlier-or-without-auto-rotation-feature-enabled

 


 

참고

https://learn.microsoft.com/ko-kr/azure/aks/csi-secrets-store-nginx-tls

https://darkstart.tistory.com/109?category=871909

https://elfinlas.github.io/letsencrypt/211105_letscert-fail/