Automatic Certificate Management Environment (ACME) プロトコルは、X.509 証明書の取得と更新のプロセスを自動化します。ACME プロトコルにより、認証局 (CA) はドメインの所有権を自動的に検証し、そのドメインの証明書を発行できます。Let's Encrypt は、ACME プロトコルを使用して、ほとんどの Web ブラウザーで信頼される証明書を発行する非営利のパブリック CA です。このトピックでは、cert-manager と Let's Encrypt を使用して、ブラウザーで信頼される HTTPS 証明書を ASM イングレスゲートウェイに発行する方法について説明します。
前提条件
-
v1.16 以降の Service Mesh (ASM) インスタンスに追加された Container Service for Kubernetes (ACK) クラスター。詳細については、「ASM インスタンスへのクラスターの追加」および「ASM インスタンスのアップグレード」をご参照ください。
-
イングレスゲートウェイがデプロイされ、ポート 80 と 443 が公開されていること。詳細については、「イングレスゲートウェイの作成」をご参照ください。
-
ASM インスタンスに関連付けられたクラスターに httpbin アプリケーションがデプロイされていること。詳細については、「httpbin アプリケーションのデプロイ」をご参照ください。
-
cert-manager がインストールされていること。詳細については、「cert-manager のインストール」をご参照ください。
-
ASM イングレスゲートウェイで Ingress API サポートが有効になっていること。詳細については、「ステップ 1:Ingress API アクセスの有効化」をご参照ください。
cert-manager における ACME
cert-manager を使用すると、ACME Issuer コンポーネントが ACME プロトコルをサポートする CA サーバーにユーザーアカウントを登録します。ACME Issuer を作成すると、cert-manager は ACME サーバーと安全に通信するために使用される秘密鍵を生成します。Let's Encrypt のようなパブリック CA からの証明書は、ほとんどの Web ブラウザーでデフォルトで信頼されます。これは、ユーザーが Web サイトにアクセスすると、ブラウザーがサイトの SSL/TLS 証明書を自動的に信頼することを意味します。パブリック CA の主な目的は、サーバーがドメインの正当な所有者であることをブラウザーに証明することです。これを行うために、CA は証明書を発行する前に、申請者が実際にドメインをコントロールしていることを検証する必要があります。ACME プロトコルの詳細については、「Automatic Certificate Management Environment」をご参照ください。
チャレンジの解決
チャレンジとは、ACME プロトコルがドメインの所有権を検証する方法です。証明書発行のプロセス中に、ACME サーバーはクライアントに特定のチャレンジを完了するよう要求します。これにより、ドメインの正当な所有者のみがその証明書を取得できるようになり、ドメインのなりすましを防ぎ、セキュリティを強化します。cert-manager は、HTTP-01 と DNS-01 という 2 つの主要なチャレンジタイプをサポートしています。
-
HTTP-01 チャレンジでは、サーバー上の特定の URL に検証キーを含むファイルを配置することで、所有権を証明する必要があります。この URL は公開アクセス可能で、証明書を要求しているドメインを含んでいる必要があります。ACME サーバーがこのパスからキーを正常に取得すると、ドメインが検証されたと見なされます。これを簡素化するために、cert-manager はプロセスを自動化します。HTTP-01 チャレンジを設定すると、cert-manager はクラスターの Ingress リソースを一時的に調整して、検証リクエストを小規模な Web サービスにルーティングします。このサービスは、必要な検証キーを ACME サーバーに提示します。
-
DNS-01 チャレンジでは、検証キーを含む特定の DNS TXT レコードを作成することで、所有権を証明する必要があります。レコードが DNS システム全体に伝播した後、ACME サーバーは DNS ルックアップを実行してドメインの所有権を検証できます。必要な権限が付与されていれば、cert-manager は必要な TXT レコードを自動的に作成し、DNS プロバイダーに送信して DNS-01 チャレンジを解決できます。
本番環境では、ご利用の認証局が ACME プロトコルをサポートしているかどうかを確認する必要があります。サポートしている場合、ASM イングレスゲートウェイは cert-manager を介して CA から証明書を自動的に取得できます。たとえば、Sectigo は ACME プロトコルをサポートしており、同様の原理で動作します。
ステップ 1:パブリックドメインの準備
Let's Encrypt を使用して証明書を発行するには、ASM イングレスゲートウェイを指すパブリックドメインが必要です。具体的な手順については、ご利用の DNS プロバイダーのドキュメントをご参照ください。Alibaba Cloud DNS を使用する場合は、「DNS レコードの追加」をご参照ください。Let's Encrypt の詳細については、「クイックスタート」をご参照ください。
ステップ 2:Let's Encrypt Issuer リソースの作成
-
データプレーンクラスターの KubeConfig を使用して、次のリソースを作成します。
apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: letsencrypt-prod-issuer namespace: istio-system spec: acme: email: 'te**@mail.com' # このフィールドはオプションですが、推奨されます。ACME サーバーは、このメールアドレスを使用して証明書に関する重要なお知らせを送信する場合があります。 privateKeySecretRef: name: letsencrypt-prod server: https://acme-v02.api.letsencrypt.org/directory solvers: - http01: ingress: ingressClassName: istio上記の Issuer リソースは、
ingressClassNameがistioの Ingress API を使用するhttp01ソルバーを指定しています。次のステップでは、このソルバーがどのように機能するかを説明します。説明cert-manager は Ingress API と Gateway API の両方のソルバーをサポートしています。ASM も両方の API をサポートしています。この例では Ingress API を使用します。
-
Issuer が準備完了になるまで待ちます。次のコマンドを実行して、そのステータスを確認します。
kubectl -n istio-system get issuer letsencrypt-prod-issuer想定される出力:
NAME READY AGE letsencrypt-prod-issuer True 8m3s
ステップ 3:証明書の発行
-
データプレーンクラスターの KubeConfig を使用して、次のリソースを作成します。
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: istio-ingressgateway-certs namespace: istio-system spec: dnsNames: - ${YOUR_DOMAIN} # 例:test.com issuerRef: group: cert-manager.io kind: Issuer name: letsencrypt-prod-issuer secretName: istio-ingressgateway-certs -
Certificate が準備完了になるまで待ちます。次のコマンドを実行して、そのステータスを確認します。
kubectl -n istio-system get certificate istio-ingressgateway-certs想定される出力:
NAME READY SECRET AGE istio-ingressgateway-certs True istio-ingressgateway-certs 59m
証明書発行のプロセス
Certificate リソースを作成した後、cert-manager は指定された Issuer を使用してドメインの証明書を発行します。このプロセス中に、設定されたソルバーがアクティブになります。
Let's Encrypt は、HTTP-01 チャレンジを使用して、証明書を要求しているサーバーがドメインを所有していることを確認します。これを行うために、Let's Encrypt はドメインに HTTP リクエストを送信し、検証を完了するために有効な応答を受け取ることを期待します。この例では、イングレスゲートウェイには httpbin アプリケーションのルーティングルールしかなく、チャレンジに関する特定の設定はありません。Let's Encrypt は実際にチャレンジリクエストを送信するのでしょうか?そして、どのように応答されるのでしょうか?
次のコマンドを実行してゲートウェイログを確認し、Let's Encrypt がチャレンジリクエストを送信したかどうかを判断できます。
kubectl -n istio-system logs ${GATEWAY_POD_NAME} | grep letsencrypt | tail -1
ログから、ゲートウェイが Let's Encrypt からのリクエストを受信し、正常に処理したことがわかります。Issuer が ingressClassName を istio として設定されていたため、cert-manager は同じ ingressClassName を持つ一時的な Ingress リソースを自動的に作成します。この Ingress リソースは、チャレンジリクエストを cert-manager ソルバーに転送し、検証を完了させます。
Certificate リソースが準備完了になった後、kubectl -n istio-system get ingress を実行しても一時的な Ingress リソースは表示されません。これは、証明書が正常に発行されると、cert-manager が Ingress、Service、Deployment などのソルバー関連リソースを自動的に削除するためです。
ステップ 4:証明書の検証
-
次の Gateway リソースを作成して、ステップ 3 で生成された証明書をゲートウェイのポート 443 に設定します。詳細については、「Istio ゲートウェイの管理」をご参照ください。
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: httpbin-https namespace: default spec: selector: istio: ingressgateway servers: - hosts: - ${YOUR_DOMAIN} port: name: https number: 443 protocol: HTTPS tls: credentialName: istio-ingressgateway-certs mode: SIMPLE -
既存の httpbin-vs 仮想サービスを次のように変更します。詳細については、「仮想サービスの管理」をご参照ください。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin-vs namespace: default spec: gateways: - httpbin - httpbin-https # この行を追加します。 hosts: - '*' http: - name: test route: - destination: host: httpbin.default.svc.cluster.local port: number: 8000 -
ブラウザーで
https://${YOUR_DOMAIN}にアクセスします。ブラウザーのアドレスバーで、鍵の
アイコンをクリックします。「この接続は安全です」というメッセージが表示され、ブラウザーがこの証明書を信頼していることを示します。