Google Cloud Certificate ManagerでTLS証明書の取得に苦戦した
1.はじめに
弊社のエンジニアメンバー増加に伴い、チーム専用の「ステージング環境」を新たに作成する必要がありました。
このプロセスで出会った問題とその解決方法について話します。
2.経緯(やろうとしたこと)
今回作成したステージング環境は、Google Kubernetes Engine(GKE)というサービスを使用しています。
GKE内の同一クラスター上で、それぞれのチームが「namespace」という区切りを使って自分たちのステージング環境を持っています。その中で自分が作成したのは、図1の赤枠部分です。
すでにある手順通りに作業を進めました。作業のポイントを抜粋すると以下の通りです。
作業手順
1. 諸々の設定(Serviceの作成や静的IPアドレスの取得など)
2. IngressとCertificate Managerを設定
(ingress.yamlとmanaged-certificate.yamlをapply)
3. アプリケーションをデプロイ
4. DNS設定
3.問題(遭遇したエラー)
遭遇したエラーは以下の通りです。404エラーが発生し、「保護されていない通信」が表示されました。これをクリックすると、「証明書が無効です」というメッセージが出現しました。
4.調査から解決まで
4-1.各種設定の調査
問題のエラーについて調べ、SSL/TLS証明書が原因である可能性が高いと判断しました。そして、今回の作業でSSL/TLS証明書の取得に関連しているCertificate Managerの設定を確認しました。
項目 | ステータス | 説明 |
---|---|---|
マネージドステータス | PROVISIONING | マネージド証明書が作成され、Google Cloud は認証局と連携して証明書に署名します。 |
ドメインステータス | FAILED_NOT_VISIBLE | ドメインの証明書のプロビジョニングが完了していません。 |
これらのステータスから、TLS証明書が適切に取得されていないことが明らかになりました。
4-2.関連技術の理解、整理
現在、自分の遭遇しているエラーとその状況を正確に把握するため、今回のエラーに関連していそうな技術について、それぞれ調べました。
4-2-1.それぞれの用語について理解する
DNS、TLS/SSL証明書の役割など、理解が曖昧なものについて簡単に整理しました。
DNS(Domain Name System)とは
DNSとは、example.comのようなドメイン名とIPアドレスとを紐づけることを指します。
また、ユーザーがPCのURLにexample.comを入力すると、それに対応したIPアドレスを返してくれるのが、DNSサーバーです。
SSL(Secure Socket Layer)証明書とは
SSL証明書の役割は、主に以下の2つです。
1.認証局(第三者機関)によるサーバーの実在証明
2.クライアントとサーバー間の通信の暗号化
また、TLS(Transport Layer Security)証明書は、SSL証明書をバージョンアップしたものです。
4-2-2.Certificate Managerについて理解する
今回の作業の中でCertificate Managerがどのような役割を果たしているか整理しました。
Certificate Managerの役割は、TLS(SSL)証明書の取得/更新管理を自動で行うことです。
GKEにおいては、Ingress と同じ Namespace に ManagedCertificate オブジェクトを作成し、外部ロードバランサに、TLS(SSL)証明書を設定することができます。その結果、ユーザーと外部ロードバランサでHTTPS通信が可能なります。
これを冒頭の構成図に組み込むと、以下のようになります。
以下が該当のコードです。
managed-certificate.yamlとingress.yamlのそれぞれでドメイン名(team-example.com)を指定しています。
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: team-example-managed-certificate
namespace: team-example
spec:
domains:
- team-example.com
ingress.yamlのnetworking.gke.io/managed-certificates の部分で、Certificate Managerを指定しています。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: team-example-ingress
namespace: team-example
annotations:
kubernetes.io/ingress.global-static-ip-name: team-example-static-ip
networking.gke.io/managed-certificates: team-example-managed-certificate
spec:
rules:
- host: team-example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: nginx
port:
number: 80
4-3.仮説を立てる
上記の前提条件と作業手順を踏まえ、以下の仮説を立てました。
仮説:
今回の作業は「3.経緯」に記載の手順で行いました。その際、ドメイン名を取得していない状態で、手順2.のmanaged-certificateとingressの設定を行いましたが、その時点で存在しないドメイン名に対し、証明書を発行しようとしたので、認証は得られなかったのではないか。
作業手順
1. 諸々の設定(Serviceの作成や静的IPアドレスの取得など)
2. IngressとCertificate Managerを設定 ←この時点でドメイン名取得が前提だった。
(ingress.yamlとmanaged-certificate.yamlをapply)
3. アプリケーションをデプロイ
4. DNS設定
よって、ドメイン名の取得ができている現在、再度TLS証明書の申請をすれば、取得できるはず。
4-4.解決方法
仮説を根拠にmanaged-certificate と ingressを再度applyする。
すると写真の通り、マネージドステータス、ドメインステータスが共にActiveになり、サイトにアクセスできるようになりました👏
結論としては、以下の順番で作業すれば、エラーは起きなかったはずです。
なお、DNSの設定には時間がかかる場合があります。
作業手順
1. 諸々の設定(Serviceの作成や静的IPアドレスの取得など)
2. DNS設定
3. IngressとCertificate Managerを設定
(ingress.yamlとmanaged-certificate.yamlをapply)
4. アプリケーションをデプロイ
5.おわりに
今回のエラーは、TLS(SSL)証明書、ドメイン名、DNSなどのwebの基礎知識、そしてCertificate Managerの役割を理解していれば、起こらなかった、もしくは簡単に解決できるものでした。
改めて、自分が使用する技術への理解が大事だと感じました。
今回のエラーを通して多くのこと学べました。このようなタスクを任せてもらえたことに感謝です🙏
株式会社クロスビットでは、デスクレスワーカーのためのHR管理プラットフォームを開発しています。
一緒に開発を行ってくれる各ポジションのエンジニアを募集中です。
6.参考リンク
Discussion