🔖

AKS + AGIC で TLS 終端を行う

2024/12/03に公開

個人的な設定方法のメモとして書き散らしておきます。

前提

  • Azure Kubernetes Service (AKS) が既に構築されていること
  • Application Ingress Controller (AGIC) が既に有効化されていること
  • Azure Key Vault が既に構築されていること
  • TLS 証明書は、自己署名証明書を使用すること

手順

初めに TLS 証明書を生成します。

$ mkdir aks-agic-tls
$ cd aks-agic-tls/
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -out aks-ingress-tls.crt -keyout aks-ingress-tls.key -subj "/CN=demo.yuohno.com/O=aks-ingress-tls"
$ ls -l
total 8
-rw-r--r-- 1 yurio yurio 1200 Nov 28 16:45 aks-ingress-tls.crt
-rw------- 1 yurio yurio 1704 Nov 28 16:45 aks-ingress-tls.key

次に Azure Key Vault で扱う証明書は、PFX 形式である必要がある ため、PFX 形式に変換します。
また、パスワードはスキップしています。

$ openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key -out aks-ingress-cert.pfx
Enter Export Password:
Verifying - Enter Export Password:
$ ls -l
total 12
-rw------- 1 yurio yurio 2595 Nov 28 16:46 aks-ingress-cert.pfx
-rw-r--r-- 1 yurio yurio 1200 Nov 28 16:45 aks-ingress-tls.crt
-rw------- 1 yurio yurio 1704 Nov 28 16:45 aks-ingress-tls.key

上記で生成した PFX ファイルを Azure Key Vault にアップロードします。
"キー コンテナー証明書責任者" など、証明書の操作権限を持つロールの割り当てが必要です。

$ az keyvault certificate import --vault-name $AKV_NAME --name aks-ingress-cert --file ./aks-ingress-cert.pfx

それでは Kubernete の操作に移ります。

SecretProviderClass の作成

AKS にて、Secrets Store CSI ドライバー機能を有効化すると、以下のユーザー割り当て マネージド ID が作られますので、
このクライアント ID を控えておきます。

alt text

$ kubectl create namespace ingress
$ export CERT_NAME=aks-ingress-cert
$ export AKV_NAME=<Azure Key Vault 名>
$ export TENANT_ID=<MS Entra ID テナント ID>
$ export CLIENT_ID=<ユーザー割り当て マネージド ID のクライアント ID>
$ cat << EOF | kubectl apply -n ingress -f -
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: azure-tls
spec:
  provider: azure
  secretObjects:
    - secretName: ingress-tls-csi
      type: kubernetes.io/tls
      data: 
        - objectName: $CERT_NAME
          key: tls.key
        - objectName: $CERT_NAME
          key: tls.crt
  parameters:
    usePodIdentity: "false"
    useVMManagedIdentity: "true"
    userAssignedIdentityID: $CLIENT_ID
    keyvaultName: $AKV_NAME
    objects: |
      array:
        - |
          objectName: $CERT_NAME
          objectType: secret
    tenantId: $TENANT_ID
EOF

それでは、この証明書を使って、アプリケーションを公開します。
ポイントとしては、上記で secrets-store-inline の箇所で、一度 Secret としてマウントしています。
これにより、Secret が作成され、その後の Ingress から参照可能になります。

Known Limitations - Secrets Store CSI Driver

The CSI driver is invoked by kubelet only during the pod volume mount.

$ cat << EOF | kubectl apply -n ingress -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aks-helloworld  
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aks-helloworld
  template:
    metadata:
      labels:
        app: aks-helloworld
    spec:
      containers:
      - name: aks-helloworld-one
        image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
        ports:
        - containerPort: 80
        env:
        - name: TITLE
          value: "Welcome to Azure Kubernetes Service (AKS)"
        volumeMounts:
        - name: secrets-store-inline
          mountPath: "/mnt/secrets-store"
          readOnly: true
      volumes:
      - name: secrets-store-inline
        csi:
          driver: secrets-store.csi.k8s.io
          readOnly: true
          volumeAttributes:
            secretProviderClass: "azure-tls"
---
apiVersion: v1
kind: Service
metadata:
  name: aks-helloworld
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    app: aks-helloworld
EOF

コンテナーが稼働していることを確認して、ok ですね。

$ kubectl get deploy -n ingress
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
aks-helloworld   1/1     1            1           28s

次に Ingress リソースを作成します。

$ cat << EOF | kubectl apply -n ingress -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
spec:
  ingressClassName: azure-application-gateway
  tls:
  - hosts:
    - demo.yuohno.com
    secretName: ingress-tls-csi
  rules:
  - host: demo.yuohno.com
    http:
      paths:
      - path: /
        pathType: Exact
        backend:
          service:
            name: aks-helloworld
            port:
              number: 80
EOF

最後に、Ingress リソースの IP アドレスを確認して、curl でアクセスしてみます。

$ kubectl get ingress -n ingress
NAME          CLASS                       HOSTS             ADDRESS       PORTS     AGE
ingress-tls   azure-application-gateway   demo.yuohno.com   xxx.xxx.xxx.xxx   80, 443   10m

下記 TLS 証明書の情報が表示されており、作成した自己証明書の Common Name (CN) および Organization Name (O) が表示されていることを確認します。

yurio@LAPTOP-SK5100ET:~/aks-agic-tls$ curl -v -k --resolve demo.yuohno.com:443:xxx.xxx.xxx.xxx https://demo.yuohno.com
* Added demo.yuohno.com:443:xxx.xxx.xxx.xxx to DNS cache
* Hostname demo.yuohno.com was found in DNS cache
*   Trying xxx.xxx.xxx.xxx :443...
* Connected to demo.yuohno.com (xxx.xxx.xxx.xxx) port 443

...(省略)...

* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / prime256v1 / rsaEncryption
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=demo.yuohno.com; O=aks-ingress-tls
*  start date: Nov 28 07:45:49 2024 GMT
*  expire date: Nov 28 07:45:49 2025 GMT
*  issuer: CN=demo.yuohno.com; O=aks-ingress-tls
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption

...(省略)...

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <link rel="stylesheet" type="text/css" href="/static/default.css">
    <title>Welcome to Azure Kubernetes Service (AKS)</title>

    <script language="JavaScript">
        function send(form){
        }
    </script>

</head>
<body>
    <div id="container">
        <form id="form" name="form" action="/"" method="post"><center>
        <div id="logo">Welcome to Azure Kubernetes Service (AKS)</div>
        <div id="space"></div>
        <img src="/static/acs.png" als="acs logo">
        <div id="form">      
        </div>
    </div>     
</body>
* Connection #0 to host demo.yuohno.com left intact

最後に Azure ポータルを開き、Application Gateway のリソースを確認して、TLS 証明書が登録されていることを確認してみます。

alt text
alt text

登録されていましたね。
ということで検証は以上です。

GitHubで編集を提案
Microsoft (有志)

Discussion