😺

cert-managerとRoute53を使ったTLS証明書の作成

に公開

概要

以前に投稿した「オンプレ環境でk8s環境の構築(v1.34)」で構築したkubernetesクラスタ上
でweb apiなどを動作させる際に、traefikやnginxなどのIngressをリバースプロキシとして使用することが多いかと思います。
上記の場合に、cert-managerとRoute53を使ってLet's Encryptで作成したワイルドカード証明書を使ったTLS通信を実現する方法を解説します。

参考にした記事

下記Qiitaの記事を参考に、環境やバージョン差異があってそのままでは動作しなかった箇所を修正させていただきました。
Kubernetes cert-managerでRoute53で作成したドメインの証明書を作成し、Ingressで利用する。

前提条件

今回の記事の内容を実施するにあたって、下記が前提条件となります。
使用するドメインについては、Route53に管理を委譲できるものであればどこで取得しても問題ないはずです。筆者はお名前.comで取得したドメインを使用しています。

  • ドメインを所有している
  • awsアカウントを作成していて、Route53でドメインを管理している

cert-managerのインストール

下記コマンドを実行して、helmでcert-managerをインストールします。

helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.18.2 \
  --set installCRDs=true \
  --set 'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=8.8.8.8:53\,1.1.1.1:53}'

ポイントとしては、「helm install」のオプションで「--set 'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53}'」をつけていることです。
オンプレクラスターの名前解決に使用するLAN内のDNSサーバーと、Let's Encryptから参照するRoute53の両方に同じドメインを登録することになりますが、このオプションを付けておかないと証明書発行に必要になるtxtレコードの参照でLAN内のDNSサーバーを参照してしまい、証明書の作成に失敗するためです。

issuerの作成

Route53にLet's EncryptのDNS検証で必要になるtxtレコードを作成するための準備をします。
まずは、公式ドキュメントに沿ってIAMを作成してください。
cert-manager Route53

上記手順で作成したIAMのシークレットアクセスキーをkubernetesのシークレットに登録します。

kubectl -n cert-manager create secret generic prod-route53-credentials-secret --from-literal=secret-access-key=<SECRET_ACCESS_KEY>

次に、下記のyamlを作成してClusterIssuerを作成します。

lets-encrypt-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-issuer
spec:
  acme:
    # stagingで試して、問題なく証明書ができたらprodで再実行
    # server: https://acme-v02.api.letsencrypt.org/directory
    server: https://acme-staging-v02.api.letsencrypt.org/directory # staging
    email: <YOUR_MAIL>
    privateKeySecretRef:
      name: letsencrypt-issuer
    solvers:
      - selector:
          dnsZones:
            - "example.net"
        dns01:
          route53:
            region: ap-northeast-1
            hostedZoneID: <Route53 Zone ID>
            accessKeyID: <ACCESS_KEY> // アクセスキー
            secretAccessKeySecretRef:
              name: prod-route53-credentials-secret
              key: secret-access-key

kubectl apply実行後に、ステータスに問題がなければ大丈夫です。

kubectl describe clusterissuer
・・・
Status:
  Acme:
    Last Private Key Hash:  xxxxxxxxxxxxxxxxxxx
    Last Registered Email:  <YOUR_MAIL>
  Conditions:
    Last Transition Time:  2025-09-20T02:08:00Z
    Message:               The ACME account was registered with the ACME server
    Observed Generation:   1
    Reason:                ACMEAccountRegistered
    Status:                True
    Type:                  Ready
・・・

IngressでTLS証明書を使用する場合は特定のアノテーションを付けることで自動で作成出来ますが、動作確認のため、今回は手動で作成してみます。
下記yamlファイルを作成してapplyすると証明書が作成されます。

certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-net # 任意の名前に変更
spec:
  secretName: example-net-tls # 任意の名前に変更
  duration: 2160h # 90d
  renewBefore: 360h # 15d
  commonName: "*.example.net" # 任意の名前に変更
  isCA: false
  usages:
    - server auth
    - client auth
  dnsNames:
    - example.net # 使用するドメインに変更
    - "*.example.net" # commonNameに設定したものと合わせる
  # Issuer references are always required.
  issuerRef:
    name: letsencrypt-issuer
    kind: ClusterIssuer

下記コマンドで、問題なく証明書が作成されているか確認出来ます。

kubectl get certificate
NAME            READY   SECRET              AGE
example-net    True    example-net-tls     10d

まとめ

今回はcert-managerとRoute53を使ってLet's Encryptの証明書を作成する方法をまとめました。
かなりざっくりとまとめた内容ですが、少しでも参考になれば幸いです。

Discussion