Google Kubernetes Engine (GKE)へのcert-managerのデプロイと、Let's Encryptを使用したIngressへのSSL証明書の生成
最終検証日: 2022年7月15日
このチュートリアルでは、Google Kubernetes Engine (GKE)へのcert-managerのデプロイと設定方法を学習します。Let's Encryptから署名されたSSL証明書を取得し、HTTP-01チャレンジを使用してcert-managerを設定する方法を学習します。最後に、その証明書を使用してパブリックドメイン名を持つHTTPSウェブサイトを運用する方法を学習します。
Google Cloud: Googleによるクラウドコンピューティングサービスのスイートです。
Kubernetes: サーバー上で動作します。コンテナ化されたアプリケーションのデプロイ、スケーリング、および管理を自動化します。
cert-manager: Kubernetes内で動作します。TLS/SSL証明書を取得し、証明書が有効で最新の状態であることを保証します。
Let’s Encrypt: インターネットサービスです。無料の短期間有効なSSL証明書の生成を可能にします。
まず、Kubernetes (GKE)クラスタを作成し、サンプルウェブサーバーをデプロイします。次に、ウェブサイトのパブリックIPアドレスとパブリックドメイン名を作成します。IngressとGoogle Cloudロードバランサーを設定して、インターネットクライアントがHTTPを使用してウェブサーバーに接続できるようにします。最後に、cert-managerを使用してLet's EncryptからSSL証明書を取得し、ロードバランサーがその証明書を使用するように設定します。このチュートリアルの最後には、https://
URLを使用してインターネットからウェブサイトに接続できるようになります。
前提条件
💻 Google Cloudアカウント
Google Cloudアカウントが必要です。登録にはクレジットカードまたは銀行口座の情報が必要です。Google Cloudの開始方法ページにアクセスして、手順に従ってください。
💵 Google Cloudを初めて使用する場合は、Google Cloud無料プログラムを利用できる場合があります。これは、Google Cloudを探索して評価するための300ドルの無料クラウド請求クレジットを含む90日間のトライアル期間を提供します。
💻 ドメイン名
ドメイン名と、そのドメインでDNSレコードを作成する機能が必要です。Google Domainsから12ドルのドメイン名を取得します。Google Domainsは、多くの可能な「ドメイン名レジストラ」の1つです。NameCheapとGoDaddyは、他の2つのよく知られたレジストラです。
💵 ドメイン名を購入したくない場合は、このチュートリアルをIPアドレスを使用してウェブサイトとSSL証明書を提供するように適応させることも可能です。
💻 ソフトウェア
また、ラップトップに次のソフトウェアをインストールする必要があります。
- gcloud: Google Cloudリソースの作成と管理のためのツールセットです。
- kubectl: Kubernetesクラスタを設定できるKubernetesコマンドラインツールです。
- curl: HTTPおよびHTTPSを使用してウェブサーバーに接続するためのコマンドラインツールです。
ℹ️
gcloud components install kubectl
を実行してkubectl
を迅速にインストールしてみてください。
0. Google Cloudプロジェクトでgcloud
を設定する
Google Cloudアカウントを持っていない場合、以下のコマンドでアカウントを作成します。
gcloud init
次の質問に「yes」と答える必要があります。
Do you want to configure a default Compute Region and Zone? (Y/n)? Y
コマンドを実行した後、プロジェクト名、デフォルトリージョン、デフォルトゾーンが表示されます。
出力例
* Commands that require authentication will use firstname.lastname@example.com by default* Commands will reference project `your-project` by default* Compute Engine commands will use region `europe-west1` by default* Compute Engine commands will use zone `europe-west1-b` by default
このチュートリアルでは、gcloud init
の実行時に選択されたプロジェクト名を PROJECT
変数で参照します。$PROJECT
がコマンドに表示される場合は、(1) コマンドを実行する前に変数を手動で置き換えるか、(2) シェルセッションで変数をエクスポートする必要があります。これは、このチュートリアルに記載されているコマンドで発生するすべての環境変数に適用されます。
(2) の方法を使用するため、gcloud init
で出力された情報を使用して環境変数をエクスポートしてから続行する必要があります。
export PROJECT=your-project # Your Google Cloud project ID.export REGION=europe-west1 # Your Google Cloud region.
1. Kubernetesクラスタの作成
開始するには、Google CloudにKubernetesクラスタを作成します。クラスタの名前を選択する必要があります。ここでは「test-cluster-1」を使用します。環境変数に保存しましょう。
export CLUSTER=test-cluster-1
次に、次のコマンドを使用してクラスタを作成します。
gcloud container clusters create $CLUSTER --preemptible --num-nodes=1
kubectlのGoogle Kubernetes Engine認証プラグインを設定します。
gcloud components install gke-gcloud-auth-pluginexport USE_GKE_GCLOUD_AUTH_PLUGIN=Truegcloud container clusters get-credentials $CLUSTER
クラスタに接続できることを確認します。
kubectl get nodes -o wide
⏲ クラスタの作成には4〜5分かかります。
💵 クラウド料金を最小限に抑えるために、このコマンドは、通常の仮想マシンよりも安価なプリエンプティブ仮想マシンを使用する1ノードクラスタを作成します。
2. サンプルウェブサーバーのデプロイ
「hello world!」でHTTPリクエストに応答する非常にシンプルなウェブサーバーをデプロイします。
kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0
また、接続をウェブサーバーPodにルーティングできるように、Kubernetesサービスを作成する必要があります。
kubectl expose deployment web --port=8080
ℹ️ これらのkubectl命令型コマンドは、可読性と簡潔さのために使用されています。YAMLマニフェストと
kubectl apply -f
を代わりに使用しても構いません。ℹ️
kubectl expose
で作成されたサービスは、ClusterIP
タイプ(デフォルト)になり、クラスタ内のコンポーネントからのみアクセスできます。後で、クラスタ外部のクライアントがサービスを利用できるようにするIngressを作成します。🔰 サービスを使用してアプリケーションを公開する方法の詳細を参照してください。
3. 静的外部IPアドレスの作成
このチュートリアルは、HTTP01チャレンジメカニズムを使用してLet's Encrypt SSL証明書を持つパブリックにアクセスできるHTTPSウェブサイトを作成する方法について説明しているため、Let's Encryptと他のインターネットクライアントの両方がウェブサイトに接続できるように、パブリックIPアドレスが必要です。
Google CloudでパブリックIPアドレスを作成するのは簡単で、後でそれをウェブサイトのドメイン名とGoogle Cloudロードバランサーに関連付けます。ロードバランサーは、インターネットクライアントからのHTTP(S)接続を受け入れ、クラスタ内で実行されているウェブサーバーにリクエストをプロキシします。
グローバル静的IPアドレスを次のように作成します。
gcloud compute addresses create web-ip --global
新しいIPアドレスがリストされていることを確認する必要があります。
gcloud compute addresses list
⚠️ 本チュートリアルで使用している外部HTTP(S)ロードバランサーの前提条件として、
グローバル
IPアドレスを作成する必要があります。💵 グローバル静的IPアドレスは、プレミアムネットワークサービスティアでのみ利用可能であり、エフェメラルおよび標準パブリックIPアドレスよりも高価です。
🔰 Google Cloudのネットワークサービスティアの詳細については、こちらをご覧ください。
🔰 Google Cloudでの静的外部IPアドレスのリザーブの詳細については、こちらをご覧ください。
最後に、IPアドレスを環境変数に保存して、後で使用します。以下のコマンドでIPアドレスを表示します。
gcloud compute addresses describe web-ip --format='value(address)' --global
次に、出力をコピーして環境変数に保存します。
export IP_ADDRESS=198.51.100.1 # Replace with your IP address
4. ウェブサイトのドメイン名を作成する
ウェブサイトにはドメイン名が必要であり、Let's EncryptはSSL証明書に署名する前にドメインを確認するため、ドメイン名はインターネットからアクセス可能である必要があります。
クレジットカードを使用して安価なドメイン名を購入します。https://domains.google.comにアクセスし、検索ボックスに何かを入力します。例として、デプロイする例となるコンテナの名前がhello-app
であるため、hello-app.com
を検索しました。最も重要なのは、ドメイン名を価格でソートすることです。
hello-app.com
は2,800ドルと高価なので選択せず、最上位のheyapp.net
を選択します。良さそうですね!次に、カートボタンをクリックします。次の画面で、自動更新を無効にします。毎年このドメインの料金を支払いたくないからです。
ドメイン名が分かったら、それを環境変数に保存します。
export DOMAIN_NAME=heyapp.net
次に、上記で作成したIPアドレスをポイントする新しいA
レコードを作成する必要があります。https://domains.google.com/registrarに戻り、ドメイン(ここではheyapp.net
)を開き、左側のメニューで「DNS」をクリックします。「カスタムレコード」が表示されます。タイプA
の新しいレコードを追加し、「データ」に前の手順のIPアドレスを入力します。最上位ドメイン名を構成しているので、「ホスト名」は空のままにしておく必要があります。
🔰 Cloudflare DNSチュートリアルのDNS Aレコードとは?についてはこちらをご覧ください。
ℹ️ ウェブサイトのドメイン名を作成することは必須ではありません。IPアドレスを使用して接続し、後でドメイン名ではなくIPアドレスのSSL証明書を作成できます。何らかの理由でドメイン名を作成できない場合は、このセクションをスキップして、以下の手順をIPアドレスを使用するように適応できます。
ℹ️ すべてのGoogle Cloudアドレスには、
51.159.120.34.bc.googleusercontent.com
のような自動生成されたリバースDNS名が付いていますが、親ドメインgoogleusercontent.com
にはCAAレコードがあり、Let's Encryptがサブドメインの証明書に署名することを防ぎます。Let's EncryptのドキュメントのCertificate Authority Authorization (CAA)を参照してください。
5. Ingressを作成する
まだウェブサイトにアクセスできません。ウェブサーバーはKubernetesクラスタ内で実行されていますが、インターネットクライアントが接続できるルートまたはプロキシはまだありません!ここで、Kubernetes Ingressオブジェクトを作成します。Google Cloudでは、これにより、インターネットクライアントがKubernetesクラスタ内で実行されているウェブサーバーにアクセスできるようにする、さまざまなサービスが作成されます。
最初に、SSLレイヤーを追加する前に基本的な接続をテストできるように、HTTP(HTTPSではない)Ingressを作成します。
ingress.yaml
というファイルに以下のYAMLをコピーして適用します。
# ingress.yamlapiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: web-ingressannotations:# This tells Google Cloud to create an External Load Balancer to realize this Ingresskubernetes.io/ingress.class: gce# This enables HTTP connections from Internet clientskubernetes.io/ingress.allow-http: "true"# This tells Google Cloud to associate the External Load Balancer with the static IP which we created earlierkubernetes.io/ingress.global-static-ip-name: web-ipspec:defaultBackend:service:name: webport:number: 8080
kubectl apply -f ingress.yaml
これにより、前に作成したIPアドレスに関連付けられたGoogle HTTP(S)ロードバランサーが作成されます。進行状況と作成されているリソースを確認できます。
kubectl describe ingress web-ingress
4〜5分以内に、すべてのロードバランサーコンポーネントの準備が整い、DNS名に接続して、前にデプロイしたhello-worldウェブサーバーからの応答を確認できるようになります。
curl http://$DOMAIN_NAME
出力例
Hello, world!Version: 1.0.0Hostname: web-79d88c97d6-t8hj2
この時点で、クラスタ内のPodで実行されているhello-worldウェブサーバーにHTTPトラフィックを転送するGoogleロードバランサーができました。
⏲ ロードバランサーコンポーネントの作成と構成、およびインターネットクライアントへのウェブサーバーのルーティングには、4〜5分かかります。時間がかかる場合は、トラブルシューティングセクションを参照してください。
🔰 Ingressアノテーションを使用したHTTP(S)ロードバランサーへの静的IPアドレスの使用方法についてはこちらをご覧ください。
🔰 GKEの外部Ingressアノテーションの概要についてはこちらをご覧ください。
🔰 GKEでの外部HTTP(S)ロードバランシングによるIngressのトラブルシューティングについてはこちらをご覧ください。
ℹ️ GKE Ingressには、
gce
クラスとgce-internal
クラスの2つのIngressクラスがあります。gce
クラスは外部ロードバランサーをデプロイし、gce-internal
クラスは内部ロードバランサーをデプロイします。クラスを指定せずにIngressリソースを作成すると、デフォルトでgce
になります。⚠️ Kubernetes Ingressのドキュメントとは異なり、
Ingress.Spec.IngressClassName
フィールドではなく、kubernetes.io/ingress.class
アノテーションを使用する必要があります。ingress-gce #1301とingress-gce #1337を参照してください。
6. cert-managerをインストールする
いよいよ、ウェブサイトのSSL証明書の作成を開始する準備ができました。最初に、cert-managerをインストールする必要があります。以下のようにkubectl
を使用して簡単にインストールします。
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.1/cert-manager.yaml
これにより、3つのDeploymentと、cert-manager
という新しい名前空間にある多数のServiceとPodが作成されます。また、RBACロールやカスタムリソース定義など、さまざまなクラスタスコープのサポートリソースもインストールされます。
インストールされたリソースの一部は、次のように表示できます。
kubectl -n cert-manager get all
そして、以下のようにkubectl explain
を使用して、カスタムリソース定義(cert-managerのAPI)を調べることができます。
kubectl explain Certificatekubectl explain CertificateRequestkubectl explain Issuer
🔰 cert-managerのその他のインストール方法についてはこちらをご覧ください。
🔰 証明書と発行者の詳細についてはこちらをご覧ください。
7. Let's Encryptステージング用の発行者を作成する
発行者は、証明書に署名する方法をcert-managerに指示するカスタムリソースです。この場合、発行者はLet's Encryptステージングサーバーに接続するように構成され、ドメイン名のLet's Encrypt証明書のクォータを使い果たすことなく、すべてをテストできます。
ℹ️ Let's Encryptは、Automatic Certificate Management Environment(ACME)プロトコルを使用しているため、以下の構成は
acme
というキーの下にあります。
issuer-lets-encrypt-staging.yaml
というファイルに以下のコンテンツを保存し、email
フィールドをメールアドレスに変更して適用します。
# issuer-lets-encrypt-staging.yamlapiVersion: cert-manager.io/v1kind: Issuermetadata:name: letsencrypt-stagingspec:acme:server: https://acme-staging-v02.api.letsencrypt.org/directoryemail: <email-address> # ❗ Replace this with your email addressprivateKeySecretRef:name: letsencrypt-stagingsolvers:- http01:ingress:name: web-ingress
kubectl apply -f issuer-lets-encrypt-staging.yaml
ℹ️ メールアドレスは、Let's Encryptが期限切れの30日前に証明書の更新を通知するためにのみ使用されます。cert-managerで証明書の更新中に問題が発生した場合にのみ、このメールを受け取ります。
発行者のステータスを確認できます。
kubectl describe issuers.cert-manager.io letsencrypt-staging
出力例
Status:Acme:Last Registered Email: firstname.lastname@example.comUri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/60706744Conditions:Last Transition Time: 2022-07-13T16:13:25ZMessage: The ACME account was registered with the ACME serverObserved Generation: 1Reason: ACMEAccountRegisteredStatus: TrueType: Ready
ℹ️ Let's Encrypt本番発行者には、非常に厳格なレート制限があります。実験や学習をしていると、これらの制限に簡単に達することがあります。そのため、Let's Encryptステージング発行者から始め、問題なく動作することを確認したら、本番発行者に切り替えます。
⚠️ 次の手順では、ステージング発行者から開始するため、信頼されていない証明書に関する警告が表示されますが、これは完全に予想されることです。
🔰 ACME発行者の構成の詳細についてはこちらをご覧ください。
8. SSL用にIngressを再構成する
前にIngressを作成し、HTTPを使用してウェブサーバーに接続できることを確認しました。ここでは、そのIngressをHTTPS用に再構成します。
まず、Google Cloud Ingressコントローラーの問題を回避するための簡単な方法として、SSL証明書の空のシークレットを**Ingressの再構成の前に**作成して適用します。
# secret.yamlapiVersion: v1kind: Secretmetadata:name: web-ssltype: kubernetes.io/tlsstringData:tls.key: ""tls.crt: ""
kubectl apply -f secret.yaml
ℹ️ これは、ingress-gceコントローラーが、最終的にSSL証明書を含むシークレットを最初に検出しない限り、転送ルールを更新しないという、鶏と卵の問題に対する回避策です。しかし、Let's Encryptは、cert-managerがIngressに追加し、ingress-gceコントローラーによってGoogle Cloud転送ルールに変換される必要がある特別な
.../.well-known/acme-challenge/...
URLを取得しない限り、SSL証明書に署名しません。🔰 Kubernetesシークレットとその使用方法の詳細についてはこちらをご覧ください。
ここで、Ingressに変更を加えて適用します。
--- a/ingress.yaml+++ b/ingress.yaml@@ -7,7 +7,12 @@ metadata:kubernetes.io/ingress.class: gcekubernetes.io/ingress.allow-http: "true"kubernetes.io/ingress.global-static-ip-name: web-ip+ cert-manager.io/issuer: letsencrypt-stagingspec:+ tls:+ - secretName: web-ssl+ hosts:+ - $DOMAIN_NAMEdefaultBackend:service:name: web
kubectl apply -f ingress.yaml
これにより、完了までに数分かかる可能性のある複雑な一連の操作がトリガーされます。これらの手順の一部は2〜3分かかりますが、最初は失敗する可能性があります。cert-managerとingress-gce(Google Cloud Ingressコントローラー)は定期的に再調整されるため、最終的にはすべて成功するはずです。
最終的に、すべてのピースが揃ったら、curl を使用してウェブサイトへの HTTPS 接続を確認できるようになります。
curl -v --insecure https://$DOMAIN_NAME
HTTPS接続が確立されているが、SSL証明書が信頼されていないことがわかります。そのため、この段階では--insecure
フラグを使用します。
出力例
* Server certificate:* subject: CN=www.example.com* start date: Jul 14 08:52:29 2022 GMT* expire date: Oct 12 08:52:28 2022 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.
⏲ SSL証明書が署名され、Google Cloudロードバランサーによって読み込まれるまで、5~10分待つ必要があります。時間がかかる場合は、トラブルシューティングセクションを参照してください。
ℹ️ アノテーション
cert-manager.io/issuer: letsencrypt-staging
を追加すると、cert-manageringress-shim
の注意を引くIngressに印が付けられ、以前に作成した発行者を参照する新しい証明書が作成されます。🔰 詳細については、Ingressリソースの保護をお読みください。
🔰 GKEでIngressに証明書を指定する方法については、こちらをご覧ください。
9. 本番環境対応のSSL証明書の作成
Let's Encryptステージングサーバーで全てが動作するようになったので、本番サーバーに切り替えて、信頼できるSSL証明書を取得できます。
Let's Encrypt本番発行者を作成して適用します。
# issuer-lets-encrypt-production.yamlapiVersion: cert-manager.io/v1kind: Issuermetadata:name: letsencrypt-productionspec:acme:server: https://acme-v02.api.letsencrypt.org/directoryemail: <email-address> # ❗ Replace this with your email addressprivateKeySecretRef:name: letsencrypt-productionsolvers:- http01:ingress:name: web-ingress
kubectl apply -f issuer-lets-encrypt-production.yaml
次に、本番発行者を使用するようにIngressアノテーションを更新します。
kubectl annotate ingress web-ingress cert-manager.io/issuer=letsencrypt-production --overwrite
これにより、cert-managerはLet's Encrypt本番CAによって署名された新しいSSL証明書を取得し、web-ssl
シークレットに格納します。約10分以内に、この新しい証明書がGoogle Cloudロードバランサーに同期され、安全なHTTPSを使用してウェブサイトに接続できるようになります。
curl -v https://$DOMAIN_NAME
出力例
...* Server certificate:* subject: CN=www.example.com* start date: Jul 14 09:44:29 2022 GMT* expire date: Oct 12 09:44:28 2022 GMT* subjectAltName: host "www.example.com" matched cert's "www.example.com"* issuer: C=US; O=Let's Encrypt; CN=R3* SSL certificate verify ok....Hello, world!Version: 1.0.0Hostname: web-79d88c97d6-t8hj2
また、エラーや警告なしに、ウェブブラウザでhttps://$DOMAIN_NAME
にアクセスすることもできます。
これでチュートリアルは終了です。cert-managerがKubernetes IngressとクラウドIngressコントローラーとどのように統合されるかを理解しました。cert-managerを使用して無料のLet's Encrypt SSL証明書を取得する方法を学びました。そして、証明書がクラウドベースのロードバランサーによってどのように使用され、インターネットクライアントからのSSL接続を終了し、HTTPSリクエストをKubernetesクラスタで実行されているウェブサーバーに転送するかを確認しました。
💵 このチュートリアルで作成したすべてのリソースを削除し、クラウド料金を削減する方法については、クリーンアップセクションをお読みください。
🔰 このチュートリアルで説明されている手順で問題が発生した場合は、トラブルシューティングセクションをお読みください。
クリーンアップ
チュートリアルを完了したら、次の手順に従って、クラスタ、ドメイン名、静的IPアドレスを削除してクリーンアップできます。
# Delete the cluster and all the Google Cloud resources related to the Ingress that it containsgcloud container clusters delete $CLUSTER# Delete the domain namegcloud dns record-sets delete $DOMAIN_NAME --zone $ZONE --type A# Delete the static IP addressgcloud compute addresses delete web-ip --global
トラブルシューティング
このチュートリアルでIngressオブジェクトを作成または更新すると、多くの時間がかかる可能性のある一連の複雑な操作がトリガーされます。これらの手順の中には、2〜3分かかり、最初は失敗するものの、cert-managerまたはGoogle Ingressコントローラーが再調整されると、後で成功するものもあります。簡単に言うと、Ingressを作成または変更した後5〜10分待って、kubectl describe ingress web-ingress
を実行したときにいくつかのエラーや警告が表示されることを期待する必要があります。
cert-managerとingress-gce(Google Cloud Ingressコントローラー)によって実行される操作の概要を次に示します。
- cert-managerはLet's Encryptに接続し、SSL証明書の署名要求を送信します。
- Let's Encryptは、「チャレンジ」で応答します。これは、cert-managerがターゲットウェブサイトの既知の場所に利用可能にする必要がある一意のトークンです。これは、そのウェブサイトとドメイン名の管理者であることを証明します。
- cert-managerは、Let's Encryptチャレンジトークンを提供する一時的なWebサーバーを含むPodをデプロイします。
- cert-managerは、Let's Encryptからのリクエストをその一時的なWebサーバーにルーティングする
rule
を追加して、Ingressを再構成します。 - Google Cloud Ingressコントローラーはその新しいルールを使用して外部HTTPロードバランサーを再構成します。
- Let's Encryptは接続し、期待されるチャレンジトークンを受信し、SSL証明書に署名してcert-managerに戻します。
- cert-managerは、署名されたSSL証明書を
web-ssl
という名前のKubernetesシークレットに格納します。 - Google Cloud Ingressコントローラーは、署名された証明書と関連する秘密鍵をGoogle Cloud証明書にアップロードします。
- Google Cloud Ingressコントローラーは、アップロードされたSSL証明書を提供するように外部ロードバランサーを再構成します。
Ingressと関連イベントの確認
kubectl describe
を使用して、Ingress構成と関連するすべてのイベントを表示します。IPアドレスが正しいこと、TLSとHostのエントリがウェブサイトに選択したドメイン名と一致することを確認します。ingress-gce
は、管理するGoogle Cloudコンポーネントごとにイベントを作成することに注意してください。また、これらのコンポーネントのIDを参照するアノテーションを追加することもあります。cert-managerも、Ingressオブジェクトを調整するときにイベントを作成し、作成したIngressのCertificateオブジェクトの詳細を含めます。
$ kubectl describe ingress web-ingressName: web-ingressLabels: <none>Namespace: defaultAddress: 34.120.159.51Ingress Class: <none>Default backend: web:8080 (10.52.0.13:8080)TLS:web-ssl terminates www.example.comRules:Host Path Backends---- ---- --------* * web:8080 (10.52.0.13:8080)Annotations: cert-manager.io/issuer: letsencrypt-stagingingress.kubernetes.io/backends: {"k8s1-01784147-default-web-8080-1647ccd2":"HEALTHY"}ingress.kubernetes.io/forwarding-rule: k8s2-fr-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/https-forwarding-rule: k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/https-target-proxy: k8s2-ts-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/ssl-cert: k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174ingress.kubernetes.io/target-proxy: k8s2-tp-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/url-map: k8s2-um-1lt9dzcy-default-web-ingress-yteotwe4kubernetes.io/ingress.allow-http: truekubernetes.io/ingress.class: gcekubernetes.io/ingress.global-static-ip-name: web-ipEvents:Type Reason Age From Message---- ------ ---- ---- -------Normal CreateCertificate 28m cert-manager-ingress-shim Successfully created Certificate "web-ssl"Normal Sync 28m loadbalancer-controller UrlMap "k8s2-um-1lt9dzcy-default-web-ingress-yteotwe4" updatedWarning Sync 24m (x16 over 28m) loadbalancer-controller Error syncing to GCP: error running load balancer syncing routine: loadbalancer 1lt9dzcy-default-web-ingress-yteotwe4 does not exist: googleapi: Error 404: The resource 'projects/your-project/global/sslCertificates/k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-e3b0c44298fc1c14' was not found, notFoundNormal Sync 34s (x16 over 65m) loadbalancer-controller Scheduled for sync
cmctlを使用して、証明書とその関連リソースの状態を表示する
ℹ️ まだインストールしていない場合は、
cmctl
をインストールしてください。
証明書を作成すると、cert-managerは、それぞれに証明書の署名プロセスの状態に関する情報が含まれている一時的なリソースのコレクションを作成します。これらについては、証明書ライフサイクルセクションで詳しく説明しています。cmctl status
コマンドを使用して、これらのすべてのリソースと関連するすべてのイベントとエラーメッセージの詳細を表示します。
次のような一時的なエラーが表示される場合があります。
$ cmctl status certificate web-sslName: web-sslNamespace: defaultCreated at: 2022-07-14T17:30:06+01:00Conditions:Ready: False, Reason: MissingData, Message: Issuing certificate as Secret does not contain a private keyIssuing: True, Reason: MissingData, Message: Issuing certificate as Secret does not contain a private keyDNS Names:- www.example.comEvents:Type Reason Age From Message---- ------ ---- ---- -------Normal Issuing 4m37s cert-manager-certificates-trigger Issuing certificate as Secret does not contain a private keyNormal Generated 4m37s cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "web-ssl-8gsqc"Normal Requested 4m37s cert-manager-certificates-request-manager Created new CertificateRequest resource "web-ssl-dblrj"Issuer:Name: letsencrypt-stagingKind: IssuerConditions:Ready: True, Reason: ACMEAccountRegistered, Message: The ACME account was registered with the ACME serverEvents: <none>error: 'tls.crt' of Secret "web-ssl" is not setNot Before: <none>Not After: <none>Renewal Time: <none>CertificateRequest:Name: web-ssl-dblrjNamespace: defaultConditions:Approved: True, Reason: cert-manager.io, Message: Certificate request has been approved by cert-manager.ioReady: False, Reason: Pending, Message: Waiting on certificate issuance from order default/web-ssl-dblrj-327645514: "pending"Events:Type Reason Age From Message---- ------ ---- ---- -------Normal cert-manager.io 4m37s cert-manager-certificaterequests-approver Certificate request has been approved by cert-manager.ioNormal OrderCreated 4m37s cert-manager-certificaterequests-issuer-acme Created Order resource default/web-ssl-dblrj-327645514Normal OrderPending 4m37s cert-manager-certificaterequests-issuer-acme Waiting on certificate issuance from order default/web-ssl-dblrj-327645514: ""Order:Name: web-ssl-dblrj-327645514State: pending, Reason:Authorizations:URL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3008789144, Identifier: www.example.com, Initial State: pending, Wildcard: falseChallenges:- Name: web-ssl-dblrj-327645514-2671694319, Type: HTTP-01, Token: TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro, Key: TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro.f4bppCOm-jXasFGMKjpBE5aQlhiQBeTPIs0Lx822xao, State: pending, Reason: Waiting for HTTP-01 challenge propagation: did not get expected response when querying endpoint, expected "TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro.f4bppCOm-jXasFGMKjpBE5aQlhiQBeTPIs0Lx822xao" but got: Hello, world!Version: 1... (truncated), Processing: true, Presented: true
これは、cert-managerが、一時的なチャレンジWebサーバーが予想されるURLで到達可能かどうかを確認するための事前チェックを実行しているためです。最初は到達できません。cert-managerは一時的なWebサーバーのデプロイに時間がかかり、Ingressコントローラーは新しいHTTPルーティングルールの設定に時間がかかるためです。最終的には、証明書が準備完了になり、署名されていることがわかります。
$ cmctl status certificate web-sslName: web-sslNamespace: defaultCreated at: 2022-07-14T17:30:06+01:00Conditions:Ready: True, Reason: Ready, Message: Certificate is up to date and has not expiredDNS Names:- www.example.comEvents:Type Reason Age From Message---- ------ ---- ---- -------Normal Issuing 31m cert-manager-certificates-trigger Issuing certificate as Secret does not contain a private keyNormal Generated 31m cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "web-ssl-8gsqc"Normal Requested 31m cert-manager-certificates-request-manager Created new CertificateRequest resource "web-ssl-dblrj"Normal Issuing 26m cert-manager-certificates-issuing The certificate has been successfully issuedIssuer:Name: letsencrypt-stagingKind: IssuerConditions:Ready: True, Reason: ACMEAccountRegistered, Message: The ACME account was registered with the ACME serverEvents: <none>Secret:Name: web-sslIssuer Country: USIssuer Organisation: (STAGING) Let's EncryptIssuer Common Name: (STAGING) Artificial Apricot R3Key Usage: Digital Signature, Key EnciphermentExtended Key Usages: Server Authentication, Client AuthenticationPublic Key Algorithm: RSASignature Algorithm: SHA256-RSASubject Key ID: a51e3621f5c1138947810f27dce425b33c88cb16Authority Key ID: de727a48df31c3a650df9f8523df57374b5d2e65Serial Number: fa8bb0b603ca2cdbfdfb2872d05ee52cda10Events: <none>Not Before: 2022-07-14T16:34:52+01:00Not After: 2022-10-12T16:34:51+01:00Renewal Time: 2022-09-12T16:34:51+01:00
SSL証明書がGoogle Cloudにコピーされていることを確認する
cert-managerが署名された証明書を受け取ると、web-ssl
シークレットに格納され、これによりGoogle Cloud IngressコントローラーがそのSSL証明書をGoogle Cloudにコピーするようにトリガーされます。gcloud
コマンドを使用して、証明書を確認できます。
$ gcloud compute ssl-certificates listNAME TYPE CREATION_TIMESTAMP EXPIRE_TIME MANAGED_STATUSk8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174 SELF_MANAGED 2022-07-14T09:37:06.920-07:00 2022-10-12T08:34:51.000-07:00
そして、その内容を表示し、属性を確認することができます。
$ gcloud compute ssl-certificates describe k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174 --format='value(certificate)' \| openssl x509 -in - -noout -text...Certificate:Data:Version: 3 (0x2)Serial Number:04:9f:47:f1:cb:25:37:9b:86:a3:ef:bf:2e:77:3b:45:fc:1aSignature Algorithm: sha256WithRSAEncryptionIssuer: C = US, O = Let's Encrypt, CN = R3ValidityNot Before: Jul 14 17:11:15 2022 GMTNot After : Oct 12 17:11:14 2022 GMTSubject: CN = www.example.com
Google Cloud転送ルールの確認
IngressオブジェクトにTLS節を追加した後、最終的にSSL接続の転送ルールが表示されます。
$ gcloud compute forwarding-rules describe k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4 --globalIPAddress: 34.120.159.51IPProtocol: TCPcreationTimestamp: '2022-07-14T09:37:12.362-07:00'description: '{"kubernetes.io/ingress-name": "default/web-ingress"}'fingerprint: oBTg7dRaIqI=id: '2303318464959215831'kind: compute#forwardingRulelabelFingerprint: 42WmSpB8rSM=loadBalancingScheme: EXTERNALname: k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4networkTier: PREMIUMportRange: 443-443selfLink: https://www.googleapis.com/compute/v1/projects/your-project/global/forwardingRules/k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4target: https://www.googleapis.com/compute/v1/projects/your-project/global/targetHttpsProxies/k8s2-ts-1lt9dzcy-default-web-ingress-yteotwe4