新着情報: プロジェクトの最新情報については TwitterMastodonでご確認ください。

Azure Kubernetes Service (AKS) への cert-manager のデプロイと、Let's Encrypt を使用した HTTPS ウェブサイトの証明書の署名

最終検証日: 2024年1月11日

このチュートリアルでは、Azure Kubernetes Service (AKS) に cert-manager をデプロイして構成する方法、HTTPS Web サーバーをデプロイしてインターネット上で公開する方法を学習します。クライアントが HTTPS ウェブサイトに安全に接続できるように、Let's Encrypt から署名された証明書を取得するように cert-manager を構成する方法を学習します。ワークロード ID フェデレーションを使用して Azure に認証を行い、Let's Encrypt DNS-01 チャレンジプロトコル を Azure DNS と共に使用するように cert-manager を構成します。

Microsoft Azure: Microsoft が提供するクラウドコンピューティングサービスのスイート。
Kubernetes: サーバー上で動作します。コンテナ化されたアプリケーションのデプロイ、スケーリング、および管理を自動化します。
cert-manager: Kubernetes 内で動作します。TLS/SSL 証明書を取得し、証明書の有効性と最新の状態を維持します。
Let’s Encrypt: インターネットサービスです。短期間有効な無料の SSL 証明書を生成できます。

パート1

このチュートリアルの最初の部分では、cert-manager を使用して Web サーバーの SSL 証明書を作成し、Azure Kubernetes クラスタ上に HTTPS ウェブサイトをデプロイするために必要な基本事項を学習します。ウェブサイトの DNS ドメインを作成し、Azure Kubernetes クラスタを作成し、cert-manager をインストールし、SSL 証明書を作成し、インターネット上のクライアントからの HTTPS 要求に応答する Web サーバーをデプロイします。ただし、パート 1 の SSL 証明書はテスト目的のみです。

パート 2 では、Let's Encrypt と Azure DNS を使用して、本番環境で使用できる信頼できる SSL 証明書を作成するように cert-manager を構成する方法を学習します。

Azure CLI (az) の構成

まだ行っていない場合は、Azure CLI (az) をダウンロードしてインストールしてください。

azコマンドの対話型使用の設定

az init

まだ行っていない場合はログインしてください

az login

デフォルトのリソースグループと場所の設定

export AZURE_DEFAULTS_GROUP=your-resource-group # ❗ Your Azure resource group
export AZURE_DEFAULTS_LOCATION=eastus2 # ❗ Your Azure location.

ℹ️ az バージョン >=2.40.0 が必要です。az version を実行して現在のバージョンを表示してください。

ℹ️ az init を実行する際、プロンプトで「対話型操作向けに最適化」を選択してください。

ℹ️ az login を実行すると、https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize で Web ブラウザが開きます。Web ブラウザでログインを続行し、ターミナルに戻ってください。

📖 Azure コマンドラインインターフェース (CLI) のドキュメント をお読みください。

📖 az のデフォルト設定の詳細については、CLI 構成値と環境変数 をお読みください。

公開ドメイン名の作成

このチュートリアルでは、公開アクセス可能なドメイン名を持つ HTTPS ウェブサイトをデプロイするため、既にドメインを持っている場合を除き、ドメインを登録する必要があります。任意のドメイン名登録業者 を使用して、サイトのドメイン名を登録できます。ここでは、Gandi という登録業者を使用し、このチュートリアルのために安価なドメイン名を登録します。cert-manager-tutorial-22.site というドメイン名を使用しますが、独自のドメイン名を選択する必要があります。

ドメイン名がわかったら、環境変数に保存します。

export DOMAIN_NAME=cert-manager-tutorial-22.site # ❗ Replace this with your own DNS domain name

そして、Azure DNS にゾーンとして追加します。

az network dns zone create --name $DOMAIN_NAME

ドメイン登録業者のコントロールパネルにログインし、ドメインの NS レコードを、Azure の 権威 DNS サーバー の DNS 名と一致するように設定します。これらは、Azure でホストされている DNS ゾーンの NS レコードを検索することで見つけることができます。

az network dns zone show --name $DOMAIN_NAME --output yaml

ローカルの DNS リゾルバーを使用するのではなく、dig を使用して NS レコードの階層を「トレース」することで、NS レコードが更新されたことを確認できます。

dig $DOMAIN_NAME ns +trace +nodnssec

⏲ NS レコードが親ゾーンで更新されるまで、1 時間以上かかる場合があり、NS レコードを更新する前に DNS 名を検索した場合、DNS リゾルバーサーバーのキャッシュから古い NS レコードが置き換えられるまで時間がかかる場合があります。

📖 Gandi.net のドキュメントにある DNS レコードの更新方法 をお読みになるか、ご自身のドメイン名登録業者の同等のドキュメントを参照してください。

Kubernetes クラスタの作成

始めましょう。Microsoft Azure に Kubernetes クラスタを作成します。クラスタの名前を選択する必要があります。ここでは「test-cluster-1」を使用します。環境変数に保存します。

export CLUSTER=test-cluster-1

次に、次のコマンドを使用してクラスタを作成します。

az aks create \
--name ${CLUSTER} \
--node-count 1 \
--node-vm-size "Standard_B2s" \
--load-balancer-sku basic

新しいクラスタの資格情報を使用して kubectl config ファイルを更新します。

az aks get-credentials --admin --name "$CLUSTER"

クラスタに接続できることを確認します。

kubectl get nodes -o wide

⏲ クラスタの作成には 4~5 分かかります。

💵 クラウド料金を最小限に抑えるため、このコマンドでは、低コストの仮想マシンとロードバランサーを使用して 1 ノードのクラスタを作成します。

⚠️ このクラスタは学習目的でのみ適しており、本番環境での使用には適していません。

📖 料金節約のヒントについては、Azure で低コストで Kubernetes を実行する方法 をお読みください。

cert-manager のインストール

これで、cert-manager をインストールして構成できます。

次のように helm を使用して cert-manager をインストールします。

helm repo add jetstack https://charts.jetstack.io --force-update
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.16.1 \
--set crds.enabled=true

これにより、cert-manager という新しい名前空間に、3 つのデプロイメントといくつかのサービスとポッドが作成されます。また、RBAC ロールやカスタムリソース定義など、さまざまなクラスタスコープのサポートリソースもインストールされます。

インストールされたリソースの一部は、次のように表示できます。

kubectl -n cert-manager get all

そして、次のように kubectl explain を使用して、カスタムリソース定義 (cert-manager の API) を調べることができます。

kubectl explain Certificate
kubectl explain CertificateRequest
kubectl explain Issuer

📖 cert-manager のその他のインストール方法 についてお読みください。

📖 証明書と発行者 について詳しくお読みください。

テスト ClusterIssuer と証明書の作成

これで、最初の証明書を作成する準備ができました。これは自己署名証明書ですが、後で Let's Encrypt 署名証明書に置き換えます。

# clusterissuer-selfsigned.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned
spec:
selfSigned: {}

🔗 clusterissuer-selfsigned.yaml

kubectl apply -f clusterissuer-selfsigned.yaml

次に、envsubst を使用して、選択したドメイン名を次の証明書テンプレートに代入します。

# certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: www
spec:
secretName: www-tls
privateKey:
rotationPolicy: Always
commonName: www.$DOMAIN_NAME
dnsNames:
- www.$DOMAIN_NAME
usages:
- digital signature
- key encipherment
- server auth
issuerRef:
name: selfsigned
kind: ClusterIssuer

🔗 certificate.yaml

envsubst < certificate.yaml | kubectl apply -f -

🔗 envsubst がまだインストールされていない場合は、envsubst の Go 実装をダウンロードしてインストールできます。

cmctl status certificate を使用して、証明書のステータスを確認します。

cmctl status certificate www

成功すると、秘密鍵と署名付き証明書は www-tls という名前のシークレットに保存されます。cmctl inspect secret www-tls を使用して、シークレットの Base64 エンコードされた X.509 コンテンツをデコードできます。

$ cmctl inspect secret www-tls
...
Valid for:
DNS Names:
- www.cert-manager-tutorial-22.site
URIs: <none>
IP Addresses: <none>
Email Addresses: <none>
Usages:
- digital signature
- key encipherment
- server auth
...

サンプル Web サーバーをデプロイします

次に、「hello world!」で HTTPS リクエストに応答する単純な Web サーバーをデプロイします。SSL/TLS キーと証明書は、www-tls シークレットをボリュームとして使用し、そのコンテンツをPod内のhello-appコンテナのファイルシステムにマウントすることで、Web サーバーに提供されます。

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloweb
labels:
app: hello
spec:
selector:
matchLabels:
app: hello
tier: web
template:
metadata:
labels:
app: hello
tier: web
spec:
containers:
- name: hello-app
image: us-docker.pkg.dev/google-samples/containers/gke/hello-app-tls:1.0
imagePullPolicy: Always
ports:
- containerPort: 8443
volumeMounts:
- name: tls
mountPath: /etc/tls
readOnly: true
env:
- name: TLS_CERT
value: /etc/tls/tls.crt
- name: TLS_KEY
value: /etc/tls/tls.key
volumes:
- name: tls
secret:
secretName: www-tls

🔗 deployment.yaml

kubectl apply -f deployment.yaml

インターネットからの接続をWebサーバーPodにルーティングできるように、Kubernetes LoadBalancerサービスを作成する必要もあります。次のKubernetesサービスを作成すると、一時的なパブリックIPアドレスを持つAzureロードバランサーも作成されます。

# service.yaml
apiVersion: v1
kind: Service
metadata:
name: helloweb
annotations:
service.beta.kubernetes.io/azure-dns-label-name: $AZURE_LOADBALANCER_DNS_LABEL_NAME
spec:
ports:
- port: 443
protocol: TCP
targetPort: 8443
selector:
app: hello
tier: web
type: LoadBalancer

🔗 service.yaml

LoadBalancerサービスの一意のDNS名を作成し、適用します。

export AZURE_LOADBALANCER_DNS_LABEL_NAME=lb-$(uuidgen) # ❗ The label must start with a lowercase ASCII letter
envsubst < service.yaml | kubectl apply -f -

2~3分以内に、パブリックIPアドレスがプロビジョニングされたロードバランサーが作成されます。

kubectl get service helloweb

サンプル出力

$ kubectl get service helloweb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloweb LoadBalancer 10.0.141.1 20.114.151.62 443:30394/TCP 7m15s

表示されるEXTERNAL-IPはユーザーごとに異なり、LoadBalancerサービスを再作成するたびに異なる可能性がありますが、azure-dns-label-nameでサービスに注釈を付けたため、安定したDNSホスト名が関連付けられます。この安定したDNSホスト名は、DNS CNAMEレコードを作成することで、選択した$DOMAIN_NAMEのエイリアスとして使用できます。

az network dns record-set cname set-record \
--zone-name $DOMAIN_NAME \
--cname $AZURE_LOADBALANCER_DNS_LABEL_NAME.$AZURE_DEFAULTS_LOCATION.cloudapp.azure.com \
--record-set-name www

www.$DOMAIN_NAMEがロードバランサーの一時的なパブリックIPアドレスに解決されることを確認します。

$ dig www.$DOMAIN_NAME A
...
;; QUESTION SECTION:
;www.cert-manager-tutorial-22.site. IN A
...
;; ANSWER SECTION:
www.cert-manager-tutorial-22.site. 3600 IN CNAME lb-ec8776e1-d067-4d4c-8cce-fdf07ce48260.eastus2.cloudapp.azure.com.
lb-ec8776e1-d067-4d4c-8cce-fdf07ce48260.eastus2.cloudapp.azure.com. 10 IN A 20.122.27.189
...

DNSが正しく、ロードバランサーが動作し、hello world Webサーバーが実行されている場合、curlまたはWebブラウザを使用して接続できるようになります。

curl --insecure -v https://www.$DOMAIN_NAME

⚠️ デフォルトでは自己署名証明書を拒否するため、curlの--insecureオプションを使用しました。後で、Let's Encryptによって署名された信頼できる証明書の作成方法について学習します。

証明書に期待されるDNS名があり、自己署名されていることを確認する必要があります。

...
* Server certificate:
* subject: CN=www.cert-manager-tutorial-22.site
* start date: Jan 4 15:28:30 2023 GMT
* expire date: Apr 4 15:28:30 2023 GMT
* issuer: CN=www.cert-manager-tutorial-22.site
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
...
Hello, world!
Protocol: HTTP/2.0!
Hostname: helloweb-55cb4cd887-tjlvh

📖 サービスを使用してアプリケーションを公開する方法の詳細をご覧ください。

📖 Azure Kubernetes Service (AKS)ロードバランサーでパブリックIPアドレスとDNSラベルを使用する方法の詳細をご覧ください。

パート2

パート1では、テスト証明書を作成しました。ここでは、cert-managerを構成してLet's EncryptとAzure DNSを使用して、本番環境で使用できる信頼できる証明書を作成する方法について学習します。証明書のドメイン名を所有していることをLet's Encryptに証明する必要があり、その方法の1つは、そのドメインに特別なDNSレコードを作成することです。これは、DNS-01チャレンジタイプとして知られています。

cert-managerはAzure DNS APIを使用してDNSレコードを作成できますが、最初にAzureに認証する必要があります。現在、最も安全な認証方法は、ワークロードIDフェデレーションを使用することです。この方法の利点は、cert-managerがAzureへの認証に一時的なKubernetes ServiceAccountトークンを使用し、トークンをKubernetesシークレットに保存する必要がないことです。

ℹ️ cert-manager >= v1.11.0 は、Azure DNSを使用したACME(Let's Encrypt)DNS-01でワークロードIDフェデレーションをサポートしています。以前のバージョンのcert-managerは、このチュートリアルでは説明していない他の認証メカニズムをサポートしています。

📖 Azure DNSでACME発行者を構成する他の方法について説明しています。

AzureワークロードID機能のインストール

Azure AKSのワークロードID機能は比較的新しい(執筆時点)ものであり、デフォルト以外の機能を有効にする必要があります。

AKSクラスタで高度なワークロードIDフェデレーション機能を構成するために必要なAzure CLI AKSプレビュー拡張機能をインストールします。

az extension add --name aks-preview

このデモのAKSクラスタに必要なEnableWorkloadIdentityPreview機能フラグを登録します。

az feature register --namespace "Microsoft.ContainerService" --name "EnableWorkloadIdentityPreview"
# It takes a few minutes for the status to show Registered. Verify the registration status by using the az feature list command:
az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/EnableWorkloadIdentityPreview')].{Name:name,State:properties.state}"
# When ready, refresh the registration of the Microsoft.ContainerService resource provider by using the az provider register command:
az provider register --namespace Microsoft.ContainerService

📖 EnableWorkloadIdentityPreview機能フラグの登録の詳細をご覧ください。

クラスタの再構成

次に、前に作成したクラスタでワークロードIDフェデレーション機能を有効にします。

az aks update \
--name ${CLUSTER} \
--enable-oidc-issuer \
--enable-workload-identity # ℹ️ This option is currently only available when using the aks-preview extension.

Azure Kubernetes Service (AKS)クラスタにワークロードIDをデプロイして構成する方法の詳細については、--enable-workload-identity機能に関する情報をご覧ください。

cert-managerの再構成

Azure Workload Identity Webhookの注意書きとして、cert-managerコントローラーPodとServiceAccountにラベルを付けます。これにより、cert-managerコントローラーPodに、Azureへの認証に使用されるKubernetes ServiceAccountトークンを含む追加のボリュームが作成されます。

ラベルは、以下のHelm値ファイルを使用して構成できます。

# values.yaml
podLabels:
azure.workload.identity/use: "true"
serviceAccount:
labels:
azure.workload.identity/use: "true"

🔗 values.yaml

existing_cert_manager_version=$(helm get metadata -n cert-manager cert-manager | grep '^VERSION' | awk '{ print $2 }')
helm upgrade cert-manager jetstack/cert-manager \
--reuse-values \
--namespace cert-manager \
--version $existing_cert_manager_version \
--values values.yaml

新しくロールアウトされたcert-manager Podには、いくつかの新しい環境変数が設定され、AzureワークロードID ServiceAccountトークンがプロジェクションボリュームとして含まれます。

kubectl describe pod -n cert-manager -l app.kubernetes.io/component=controller
Containers:
...
cert-manager-controller:
...
Environment:
...
AZURE_CLIENT_ID:
AZURE_TENANT_ID: f99bd6a4-665c-41cf-aff1-87a89d5c62d4
AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/azure/tokens/azure-identity-token
AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/
Mounts:
/var/run/secrets/azure/tokens from azure-identity-token (ro)
Volumes:
...
azure-identity-token:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3600

📖 KubernetesのAzure ADワークロードIDにおけるミューテーションアドミッションWebhookの役割について説明しています。

📖 cert-manager Helmチャートでカスタマイズできる他の値について説明しています。

AzureマネージドIDの作成

cert-managerがLet's Encryptを使用して証明書を作成する場合、DNSレコードを使用して、証明書内のDNSドメイン名を制御していることを証明できます。cert-managerがAzure APIを使用してAzure DNSゾーンのレコードを操作するには、Azureアカウントが必要です。使用するアカウントの最適なタイプは「マネージドID」と呼ばれます。このアカウントにはパスワードやAPIキーが付属しておらず、人間ではなくマシンによる使用を目的としています。

マネージドIDの名前を選択します。

export USER_ASSIGNED_IDENTITY_NAME=cert-manager-tutorials-1 # ❗ Replace with your preferred managed identity name

マネージドIDを作成します。

az identity create --name "${USER_ASSIGNED_IDENTITY_NAME}"

DNSゾーンレコードを変更する権限を付与します。

export USER_ASSIGNED_IDENTITY_CLIENT_ID=$(az identity show --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -o tsv)
az role assignment create \
--role "DNS Zone Contributor" \
--assignee $USER_ASSIGNED_IDENTITY_CLIENT_ID \
--scope $(az network dns zone show --name $DOMAIN_NAME -o tsv --query id)

📖 マネージドIDとその使用方法の概要については、AzureリソースのマネージドIDとは何かを参照してください。

📖 「DNSゾーンコントリビューター」ロールについては、Azure組み込みロールを参照してください。

フェデレーションIDの追加

次に、特定のKubernetes ServiceAccountトークン、特に特定のKubernetesクラスタからのServiceAccountトークン、およびcert-manager ServiceAccountに関連付けられているトークンのみをAzureが信頼するように構成します。cert-managerは、短命のKubernetes ServiceAccountトークンを使用してAzureに認証し、前の手順で作成したマネージドIDを偽装できます。

最初に、cert-managerコントローラーで使用されるKubernetes ServiceAccountの名前と名前空間を含む次の環境変数をエクスポートします。

export SERVICE_ACCOUNT_NAME=cert-manager # ℹ️ This is the default Kubernetes ServiceAccount used by the cert-manager controller.
export SERVICE_ACCOUNT_NAMESPACE=cert-manager # ℹ️ This is the default namespace for cert-manager.

次に、その「サブジェクト」(Kubernetes ServiceAccountの識別名)とその「発行者」(JWT署名証明書およびその他のメタデータをダウンロードできるURL)を指定して、cert-manager Kubernetes ServiceAccountを信頼するようにマネージドIDを構成します。

export SERVICE_ACCOUNT_ISSUER=$(az aks show --resource-group $AZURE_DEFAULTS_GROUP --name $CLUSTER --query "oidcIssuerProfile.issuerUrl" -o tsv)
az identity federated-credential create \
--name "cert-manager" \
--identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \
--issuer "${SERVICE_ACCOUNT_ISSUER}" \
--subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}"

Microsoft IDプラットフォームのドキュメントでワークロードIDフェデレーションについて説明しています。

Let's Encrypt ステージング環境用 ClusterIssuer の作成

ClusterIssuer は、cert-manager に証明書の署名方法を指示するカスタムリソースです。この場合、ClusterIssuer は Let's Encrypt ステージングサーバーに接続するように設定され、ドメイン名の Let's Encrypt 証明書クォータを使い果たすことなく、すべてをテストできます。

clusterissuer-lets-encrypt-staging.yaml という名前のファイルに次の内容を保存し、email フィールドをあなたのメールアドレスに変更して適用します。

# clusterissuer-lets-encrypt-staging.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: $EMAIL_ADDRESS
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- dns01:
azureDNS:
resourceGroupName: $AZURE_DEFAULTS_GROUP
subscriptionID: $AZURE_SUBSCRIPTION_ID
hostedZoneName: $DOMAIN_NAME
environment: AzurePublicCloud
managedIdentity:
clientID: $USER_ASSIGNED_IDENTITY_CLIENT_ID

🔗 clusterissuer-lets-encrypt-staging.yaml

ご覧のように、clusterissuer-lets-encrypt-staging.yaml にはいくつかの変数が含まれており、適用する前に値を入力する必要があります。ほとんどは本チュートリアルの前段階で定義されていますが、以下の設定が必要です。

export EMAIL_ADDRESS=<email-address> # ❗ Replace this with your email address
export AZURE_SUBSCRIPTION=<your-subscription-or-billing-account> # ❗ Replace this with your Azure account name

次に、envsubst を使用して変数を埋め、kubectl apply にパイプします。

export AZURE_SUBSCRIPTION_ID=$(az account show --name $AZURE_SUBSCRIPTION --query 'id' -o tsv)
envsubst < clusterissuer-lets-encrypt-staging.yaml | kubectl apply -f -

ClusterIssuer のステータスを確認できます。

kubectl describe clusterissuer letsencrypt-staging

出力例

Status:
Acme:
Last Registered Email: firstname.lastname@example.com
Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/77882854
Conditions:
Last Transition Time: 2022-11-29T13:05:33Z
Message: The ACME account was registered with the ACME server
Observed Generation: 1
Reason: ACMEAccountRegistered
Status: True
Type: Ready

ℹ️ Let's Encrypt は Automatic Certificate Management Environment (ACME) プロトコルを使用しているため、上記の構成は acme というキーの下にあります。

ℹ️ メールアドレスは、Let's Encrypt が期限切れの 30 日前に証明書の更新を通知するためにのみ使用されます。cert-manager で証明書の更新中に問題が発生した場合にのみ、このメールを受信します。

ℹ️ Let's Encrypt の本番発行者には非常に厳しいレート制限があります。実験や学習をしていると、簡単にこれらの制限に達することがあります。そのため、Let's Encrypt ステージング発行者から開始し、正常に動作することを確認してから本番発行者に移行します。

📖 ACME Issuer の設定の詳細については、こちらをご覧ください。

Let's Encrypt を使用した証明書の再発行

ステージング ClusterIssuer を使用するように証明書をパッチします。

kubectl patch certificate www --type merge -p '{"spec":{"issuerRef":{"name":"letsencrypt-staging"}}}'

これにより、cert-manager が証明書の更新を開始します。cmctl を使用して確認してください。

cmctl status certificate www
cmctl inspect secret www-tls

最後に、新しい証明書が発行されたら、Web サーバーを再起動して使用します。

kubectl rollout restart deployment helloweb

再度 Web サイトに接続できるようになりますが、今回は Let's Encrypt ステージング証明書が表示されます。

$ curl -v --insecure https://www.$DOMAIN_NAME
...
* Server certificate:
* subject: CN=www.cert-manager-tutorial-22.site
* start date: Jan 5 12:41:14 2023 GMT
* expire date: Apr 5 12:41:13 2023 GMT
* issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Artificial Apricot R3
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
...
Hello, world!
Protocol: HTTP/2.0!
Hostname: helloweb-9b8bcdd56-6rxm8

⚠️ ここでは、Let's Encrypt ステージング発行者によって信頼されていない証明書が作成されるため、curl の --insecure オプションを再度使用しました。次に、Let's Encrypt 本番発行者によって署名された信頼できる証明書を作成する方法を学習します。

本番環境対応証明書の作成

Let's Encrypt ステージングサーバーで正常に動作するようになったので、本番サーバーに切り替え、信頼できる証明書を取得できます。

ステージング ClusterIssuer YAML をコピーしてサーバー URL と名前を変更し、Let's Encrypt 本番 Issuer を作成して適用します。

# clusterissuer-lets-encrypt-production.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: $EMAIL_ADDRESS
privateKeySecretRef:
name: letsencrypt-production
solvers:
- dns01:
azureDNS:
resourceGroupName: $AZURE_DEFAULTS_GROUP
subscriptionID: $AZURE_SUBSCRIPTION_ID
hostedZoneName: $DOMAIN_NAME
environment: AzurePublicCloud
managedIdentity:
clientID: $USER_ASSIGNED_IDENTITY_CLIENT_ID

🔗 clusterissuer-lets-encrypt-production.yaml

envsubst < clusterissuer-lets-encrypt-production.yaml | kubectl apply -f -

ClusterIssuer のステータスを確認します。

kubectl describe clusterissuer letsencrypt-production

本番 ClusterIssuer を使用するように証明書をパッチします。

kubectl patch certificate www --type merge -p '{"spec":{"issuerRef":{"name":"letsencrypt-production"}}}'

これにより、cert-manager が証明書の更新を開始します。cmctl を使用して確認してください。

cmctl status certificate www
cmctl inspect secret www-tls

最後に、新しい証明書が発行されたら、Web サーバーを再起動して使用します。

kubectl rollout restart deployment helloweb

これで、--insecure フラグなしで Web サーバーに安全に接続できるようになり、Web ブラウザでサイトにアクセスすると、URL の横に南京錠 (🔒) 記号が表示されます。

curl -v https://www.$DOMAIN_NAME
...
* Server certificate:
* subject: CN=cert-manager-tutorial-22.site
* start date: Nov 30 15:41:40 2022 GMT
* expire date: Feb 28 15:41:39 2023 GMT
* subjectAltName: host "www.cert-manager-tutorial-22.site" matched cert's "www.cert-manager-tutorial-22.site"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
...

このチュートリアルはこれで終了です。Azure AKS に cert-manager をデプロイする方法、Azure DNS を使用した DNS-01 プロトコルで Let's Encrypt 署名付き証明書を発行するように設定する方法、Azure のワークロード ID フェデレーションについて、および Kubernetes ServiceAccount トークンを使用して Azure に認証するように cert-manager を設定する方法を学習しました。

クリーンアップ

チュートリアルを完了したら、以下のようにクラスター、ドメイン名、マネージド ID を削除してクリーンアップできます。

az aks delete --name $CLUSTER
az network dns zone delete --name $DOMAIN_NAME
az identity delete --name $USER_ASSIGNED_IDENTITY_NAME

次のステップ

📖 その他の cert-manager チュートリアル入門ガイド をご覧ください。

📖 Azure DNS を使用した cert-manager ACME Issuer の設定の詳細については、こちらをご覧ください。