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

AWS Elastic Kubernetes Service (EKS) 上に cert-manager をデプロイし、Let's Encrypt を使用して HTTPS ウェブサイトの TLS 証明書に署名する

最終検証日: 2024年9月9日

このチュートリアルでは、AWS Elastic Kubernetes Service (EKS) 上に cert-manager をデプロイおよび設定する方法、HTTPS ウェブサーバーをデプロイしてインターネット上で利用可能にする方法を学習します。クライアントが HTTPS ウェブサイトに安全に接続できるように、Let's Encrypt から署名された証明書を取得するように cert-manager を設定する方法を学習します。AWS Route53 DNS で Let's Encrypt DNS-01 チャレンジプロトコル を使用するように cert-manager を設定します。専用の Kubernetes ServiceAccount トークン を使用して Route53 に認証します。

パート 1

このチュートリアルの最初の部分では、cert-manager を使用してウェブサーバーの SSL 証明書を作成する AWS Elastic Kubernetes Service (EKS) クラスタ上に HTTPS ウェブサイトをデプロイするために必要な基本事項を学習します。ウェブサイトの DNS ドメインを作成し、EKS クラスタを作成し、cert-manager をインストールし、TLS 証明書を作成し、インターネット上のクライアントからの HTTPS 要求に応答するウェブサーバーをデプロイします。パート 1 の TLS 証明書はテスト目的のみです。パート 2 では、Let's Encrypt と Route53 DNS を使用して、本番環境で使用できる信頼できる証明書を作成するように cert-manager を設定する方法を学習します。

AWS CLI (aws) の設定

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

awsコマンドを対話的に使用する設定

aws configure

デフォルトの出力形式とリージョンを設定する

export AWS_DEFAULT_OUTPUT=json # ❗ Use JSON output for this tutorial
export AWS_DEFAULT_REGION=us-west-2 # ❗ Your AWS region.

📖 AWS CLI の設定AWS CLI の構成 を読んで、aws の設定についてさらに学習してください。

パブリックドメイン名の作成

このチュートリアルでは、パブリックにアクセス可能なドメイン名を持つ HTTPS ウェブサイトをデプロイするため、既に持っている場合を除き、ドメインを登録する必要があります。サイトのドメイン名を登録するには、任意の ドメイン名レジストラ を使用できます。たとえば、Gandi を使用して、このチュートリアルの目的のために安価なドメイン名を登録できます。

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

export DOMAIN_NAME=example.com # ❗ Replace this with your own DNS domain name

そして、AWS Route53 にゾーンとして追加します。

aws route53 create-hosted-zone --caller-reference $(uuidgen) --name $DOMAIN_NAME

作成されたゾーンの詳細はコンソールに出力されます。

{
"Location": "https://route53.amazonaws.com/2013-04-01/hostedzone/Z0984294TRL0R8AT3SQA",
"HostedZone": {
"Id": "/hostedzone/Z0984294TRL0R8AT3SQA",
"Name": "cert-manager-aws-tutorial.richard-gcp.jetstacker.net.",
"CallerReference": "77274711-b648-4da5-81b7-74512897d0db",
"Config": {
"PrivateZone": false
},
"ResourceRecordSetCount": 2
},
"ChangeInfo": {
"Id": "/change/C04685872DX6N6587E1TL",
"Status": "PENDING",
"SubmittedAt": "2024-09-03T16:29:11.960000+00:00"
},
"DelegationSet": {
"NameServers": [
"ns-1504.awsdns-60.org",
"ns-538.awsdns-03.net",
"ns-278.awsdns-34.com",
"ns-1765.awsdns-28.co.uk"
]
}
}

ドメインレジストラの管理パネルにログインし、ドメインの NS レコードを、Route53 でホストされているゾーンの 権威DNSサーバー のDNS名と一致するように設定します。aws route53 create-hosted-zone の出力にある NameServers を参照するか、後でネームサーバーを見つけることができます。

HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name --dns-name $DOMAIN_NAME --query "HostedZones[0].Id" --output text)
aws route53 get-hosted-zone --id ${HOSTED_ZONE_ID}

dig を使用して NS レコードの階層を「トレース」することにより、NS レコードが更新されたことを確認できます。

dig $DOMAIN_NAME ns +trace +nodnssec

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

📖 Gandi.net のドキュメントにある DNS レコードの更新方法 を読んでください。または、ご自身のドメイン名レジストラの同等のドキュメントを参照してください。

EKS Kubernetes クラスタの作成

開始するには、EKS を使用して Kubernetes クラスタを作成しましょう。EKS クラスタを作成する最も簡単な方法は、eksctl を使用することです。eksctl をダウンロードしてインストールしてください。

クラスタの名前を選択し、環境変数に保存します。

export CLUSTER=test-cluster-1

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

eksctl create cluster \
--name $CLUSTER \
--nodegroup-name node-group-1 \
--node-type t3.small \
--nodes 3 \
--nodes-min 1 \
--nodes-max 3 \
--managed \
--spot

これにより、新しいクラスタの認証情報を使用して kubectl 構成ファイルが更新されます。

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

kubectl get nodes -o wide

⏲ クラスタの作成には 15~20 分かかります。理由は、EKS クラスタ作成時間の短縮 を参照してください。

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

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

cert-manager のインストール

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

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

helm install cert-manager cert-manager \
--repo https://charts.jetstack.io \
--namespace cert-manager \
--create-namespace \
--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
revisionHistoryLimit: 1
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-aws-tutorial.richard-gcp.jetstacker.net
URIs: <none>
IP Addresses: <none>
Email Addresses: <none>
Usages:
- digital signature
- key encipherment
- server auth
...

サンプルウェブサーバーのデプロイ

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

# 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

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

# service.yaml
apiVersion: v1
kind: Service
metadata:
name: helloweb
spec:
ports:
- port: 443
protocol: TCP
targetPort: 8443
selector:
app: hello
tier: web
type: LoadBalancer

🔗 service.yaml

kubectl apply -f service.yaml

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

kubectl get service helloweb

サンプル出力

$ kubectl get service helloweb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloweb LoadBalancer 10.100.175.247 ae25d292150aa4e3e90e6c25376f9a7d-496307726.us-west-2.elb.amazonaws.com 443:32184/TCP 6m

ユーザーごとにEXTERNAL-IPは異なり、LoadBalancerサービスを再作成するたびに変わる可能性がありますが、安定したDNSホスト名が付与されます。

ℹ️ 既定では、EKSはクラスタ内のLoadBalancerサービスに対して、クラシックロードバランサーをレガシークラウドプロバイダーロードバランサーコントローラーを使用して作成します。これは、追加のソフトウェアや設定を必要としないため、このチュートリアルでは便利です。しかしながら、AWSクラウドプロバイダーロードバランサーコントローラーはレガシーであり、現在は重大なバグ修正のみが行われていますEKSベストプラクティスガイド参照)。代わりにAWSロードバランサーコントローラーの使用を検討してください。

ロードバランサーの安定したDNSホスト名は、選択した$DOMAIN_NAMEwwwレコードのエイリアスとして、Route53のエイリアスレコードを作成することで使用できます。

HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name --dns-name $DOMAIN_NAME --query "HostedZones[0].Id" --output text)
ELB_CANONICAL_HOSTED_ZONE_NAME=$(kubectl get svc helloweb --output=jsonpath='{ .status.loadBalancer.ingress[0].hostname }')
aws elb describe-load-balancers --query "LoadBalancerDescriptions[?CanonicalHostedZoneName == '$ELB_CANONICAL_HOSTED_ZONE_NAME'] | [0]" \
| jq '{
"Comment": "Creating an alias record",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "www.\($DOMAIN_NAME)",
"Type": "A",
"AliasTarget": {
"HostedZoneId": .CanonicalHostedZoneNameID,
"DNSName": .CanonicalHostedZoneName,
"EvaluateTargetHealth": false
}
}
}
]
}' \
--arg DOMAIN_NAME "${DOMAIN_NAME}" \
| aws route53 change-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID --change-batch file:///dev/stdin

ℹ️ このタスクの詳細については、ELBロードバランサーへのトラフィックルーティングを参照してください。

ℹ️ このスクリプトは、DNS名と照合することでKubernetesサービスのELBを取得するために、JMESPathクエリを使用しています。

📖 ロードバランサーのDNSレコードを管理する別の方法として、ExternalDNSがあります。ExternalDNSは、公開されたKubernetesサービスとIngressをDNSプロバイダーと同期します。詳細については、AWS上のKubernetesクラスタ内でのExternalDNSの使用を参照してください。

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

$ dig www.$DOMAIN_NAME A
...
;; QUESTION SECTION:
;www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net. IN A
;; ANSWER SECTION:
www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net. 60 IN A 34.212.236.229
www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net. 60 IN A 44.232.234.71
www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net. 60 IN A 35.164.69.198

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

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

⚠️ curlの--insecureオプションを使用しました。これは、そうでなければcurlが生成した信頼できない証明書を拒否するためです。後で、Let's Encryptによって署名された信頼できる証明書の作成方法について説明します。

証明書が期待されるDNS名を持ち、自己署名されていることを確認してください。

...
* Server certificate:
* subject: CN=www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net
* start date: Sep 4 08:43:56 2024 GMT
* expire date: Dec 3 08:43:56 2024 GMT
* issuer: CN=www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
...
Hello, world!
Protocol: HTTP/2.0!
Hostname: helloweb-55cb4cd887-tjlvh

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

パート2

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

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

📖 AWS Route53 DNSを使用してACME発行者を構成する他の方法についてご確認ください。

クラスタのIAM OIDCプロバイダーを作成する

eksctl utils associate-iam-oidc-provider --cluster $CLUSTER --approve

ℹ️ 詳細については、クラスタのIAM OIDCプロバイダーの作成を参照してください。

IAMポリシーの作成

aws iam create-policy \
--policy-name cert-manager-acme-dns01-route53 \
--description "This policy allows cert-manager to manage ACME DNS01 records in Route53 hosted zones. See https://cert-manager.dokyumento.jp/docs/configuration/acme/dns01/route53" \
--policy-document file:///dev/stdin <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "route53:GetChange",
"Resource": "arn:aws:route53:::change/*"
},
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/*"
},
{
"Effect": "Allow",
"Action": "route53:ListHostedZonesByName",
"Resource": "*"
}
]
}
EOF

ℹ️ このIAMポリシーの詳細については、cert-manager ACME DNS01 Route53設定ドキュメントを参照してください。

IAMロールの作成とKubernetesサービスアカウントへの関連付け

次のコマンドは3つのタスクを実行します。

  1. cert-manager名前空間に新しい専用のKubernetes ServiceAccountを作成し、
  2. 前の手順のポリシーで定義された権限を持つ新しいAWSロールを構成します。
  3. このEKSクラスタ内の新しい専用のKubernetes ServiceAccountのトークンを持つクライアントのみがロールを想定できるようにロールを構成します。
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
eksctl create iamserviceaccount \
--name cert-manager-acme-dns01-route53 \
--namespace cert-manager \
--cluster ${CLUSTER} \
--role-name cert-manager-acme-dns01-route53 \
--attach-policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/cert-manager-acme-dns01-route53 \
--approve

ℹ️ 詳細については、KubernetesサービスアカウントへのIAMロールの割り当てを参照してください。

cert-managerがServiceAccountトークンを作成するための権限を付与する

cert-managerは、前の手順で作成したKubernetes ServiceAccountのJWTトークンを生成するための権限が必要です。cert-manager名前空間に次のRBACロールとロールバインディングを適用します。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-acme-dns01-route53-tokenrequest
namespace: cert-manager
rules:
- apiGroups: ['']
resources: ['serviceaccounts/token']
resourceNames: ['cert-manager-acme-dns01-route53']
verbs: ['create']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cert-manager-acme-dns01-route53-tokenrequest
namespace: cert-manager
subjects:
- kind: ServiceAccount
name: cert-manager
namespace: cert-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cert-manager-acme-dns01-route53-tokenrequest

🔗 rbac.yaml

kubectl apply -f rbac.yaml

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:
route53:
region: ${AWS_DEFAULT_REGION}
role: arn:aws:iam::${AWS_ACCOUNT_ID}:role/cert-manager-acme-dns01-route53
auth:
kubernetes:
serviceAccountRef:
name: cert-manager-acme-dns01-route53

🔗 clusterissuer-lets-encrypt-staging.yaml

clusterissuer-lets-encrypt-staging.yamlには、適用前に記入する必要がある変数がいくつかあります。ほとんどはこのチュートリアルの前の方で定義されていますが、次のものを設定する必要があります。

export EMAIL_ADDRESS=<email-address> # ❗ Replace this with your email address

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

export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
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: 2024-09-04T15:41:18Z
Message: The ACME account was registered with the ACME server
Observed Generation: 1
Reason: ACMEAccountRegistered
Status: True
Type: Ready

ℹ️ Let's Encryptは自動証明書管理環境(ACME)プロトコルを使用しているため、上記の構成はacmeというキーの下にあります。

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

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

📖 ACME発行者の構成について詳しくはご確認ください。

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

再度ウェブサイトに接続できるようになりますが、今回は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

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

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

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

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

# 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:
route53:
region: ${AWS_DEFAULT_REGION}
role: arn:aws:iam::${AWS_ACCOUNT_ID}:role/cert-manager-acme-dns01-route53
auth:
kubernetes:
serviceAccountRef:
name: cert-manager-acme-dns01-route53

🔗 clusterissuer-lets-encrypt-production.yaml

export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
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=www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net
* start date: Sep 4 19:32:24 2024 GMT
* expire date: Dec 3 19:32:23 2024 GMT
* subjectAltName: host "www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net" matched cert's "www.cert-manager-aws-tutorial.richard-gcp.jetstacker.net"
* issuer: C=US; O=Let's Encrypt; CN=R11
* SSL certificate verify ok.
...

これで、このチュートリアルの終わりです。AWS EKSへのcert-managerのデプロイ方法、およびRoute53 DNSを使用したDNS-01プロトコルでLet's Encrypt署名証明書を発行するようにcert-managerを構成する方法を学習しました。サービスアカウントのIAMロール(IRSA)について学習し、Kubernetes ServiceAccountトークンを使用してAWS Route53に対してcert-managerを認証するように構成する方法を学習しました。

クリーンアップ

チュートリアルを完了したら、以下の手順に従ってEKSクラスタとRoute53ホストゾーンを削除してクリーンアップできます。

eksctl delete cluster --name $CLUSTER
HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name --dns-name $DOMAIN_NAME --query "HostedZones[0].Id" --output text)
aws route53 delete-hosted-zone --id ${HOSTED_ZONE_ID}

IAMポリシー、ロール、およびIDプロバイダーは、AWS Web UIから手動で削除できます。

次のステップ

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

📖 Route53 DNSを使用したcert-manager ACMEイッシューアーの構成について詳しくお読みください。