AKS - Azure Key Vault, Nginx Ingress TLS 연동
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
이 글에서는 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://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/