TerraformとGoogle Cloudでやらかした話
はじめに
やあみんな、技術の食いつき虫Reiだよ:v:!
- Microsoft Learn Student Ambassador
- GiTHub Campus Expert
- Google Developer Student Club Nagoya Lead
- 普段はSREとインフラとセキュリティをやってるよ(開発できるけどね)
- コミュニティ運営してるよ!(ぜひGDSCNagoyaやGitHub Student Communityに入ってね!)
ぜひフォローしてね
https://linktr.ee/Rei_suzuki
きっかけ
インターン先で検証してた際にはまったことがあったので、メモがてら残しておきます。
この記事の対象者
- terraformを使ってる方
- Google Cloudを使っている方
- 細かい仕様が好きな人
本題
結論
Terraformを使ってIaC(Infrastructure as Code)をする際に、対象のクラウドの仕様の細かい仕様を公式ドキュメントでしっかりと見ようねという話です
実際にやったこと
環境
- terraform 1.6.1
- terraform-provider-google 5.2.0
やりたかったこと
上記の図のようにCertificate Managerにあるセルフマネージド証明書をロードバランサーにアタッチしようとTerraformのコードを書こうとしてた。
なぜか?
- 元々Certificate Managerを使わない従来の方法で今まで行っていた
- Certificate Managerに移行する検討をしたい
- terraform-provider-google 5.2.0にて、何やらそれについて追加があったぽいぞ(後述)
詳しい変更点
5.2.0
...
BUG FIXES:
...
compute: added certificate_manager_certificates field to google_compute_target_https_proxy resource (#16179)
...
リリースノートにはこう記載されてました
詳しいPull Request
terraform-provider-googleのドキュメントを見に行きます
おお!確かにある!
resource "google_compute_target_https_proxy" "default" {
name = "target-http-proxy"
url_map = google_compute_url_map.default.id
certificate_manager_certificates = ["//certificatemanager.googleapis.com/${google_certificate_manager_certificate.default.id}"] # [google_certificate_manager_certificate.default.id] is also acceptable
}
certificate_manager_certificatesの詳しい説明を見ると
英語の説明
(Optional) URLs to certificate manager certificate resources that are used to authenticate connections between users and the load balancer. Currently, you may specify up to 15 certificates. Certificate manager certificates do not apply when the load balancing scheme is set to INTERNAL_SELF_MANAGED. sslCertificates and certificateManagerCertificates fields can not be defined together. Accepted format is //certificatemanager.googleapis.com/projects/{project}/locations/{location}/certificates/{resourceName} or just the self_link projects/{project}/locations/{location}/certificates/{resourceName}
簡単に日本語で言うと
- 最大15個指定できるよ
- ロードバランサーのスキームが INTERNAL_SELF_MANAGEDの場合は、適用されないよ
- sslCertificatesと一緒に定義できないよ
- フォーマットは
- //certificatemanager.googleapis.com/projects/{project}/locations/{location}/certificates/{resourceName}
- projects/{project}/locations/{location}/certificates/{resourceName}
そもそもどうなっていたの?
resource "google_compute_target_https_proxy" "default" {
name = "test-proxy"
url_map = google_compute_url_map.default.id
ssl_certificates = [google_compute_ssl_certificate.default.id]
}
resource "google_compute_ssl_certificate" "default" {
name = "my-certificate"
private_key = file("path/to/private.key")
certificate = file("path/to/certificate.crt")
}
このような感じで、セルフマネージド証明書を証明書リソースとしてアップロードしてから、グローバル外部アプリケーション ロードバランサーにアタッチしてました。
詳しいドキュメント
なので、書き直すとしたら
resource "google_compute_target_https_proxy" "default" {
name = "target-http-proxy"
url_map = google_compute_url_map.default.id
certificate_manager_certificates = ["//certificatemanager.googleapis.com/${google_certificate_manager_certificate.default.id}"]
}
resource "google_certificate_manager_certificate" "default" {
name = "my-certificate"
scope = "ALL_REGIONS"
self_managed {
pem_certificate = file("test-fixtures/cert.pem")
pem_private_key = file("test-fixtures/private-key.pem")
}
}
の公式ドキュメントに書いてある通りに記述すればよいと思ってました(これが一番の間違い)
terraform plan が問題なかったが、terraform applyを実行した際、エラー が起きました!
Error creating TargetHttpsProxy:googleapi:
Error 400: Invalid value for field 'resource.sslCertificates[0]':
Cloud certificate reference is not supported for TargetHttpsProxy creation.,Invalid
Details: |
[|
{ |
"@type":"type.googleapis.com/google.rpc.BadRequest",|
"fieldViolations":[|
{|
"description":"certificate \"projects/11111/locations/global/certificates/sample-cert\" has invalid scope ",|
"field":"certificates"|
}
]
}
]
どんな解決を試みたか
- 上記のドキュメントで関連するしっかりとリファレンスを見る
- 実際のGitHubのリポジトリを見に行き、齟齬がないか見てみる
- リリースされてから2週間ばかりだったので、同じようなエラーをissuesで探す
- terraform のデバッグログをみる
- Google Cloudで関連するドキュメントを見る(APIの仕様まで)
- terraform のバージョンアップをする
しかしながら,解決に至らず…
そこで、実際にドキュメントにあるコードをCloud Shellで動きを確認することにしました。
ドキュメントにあるコードは動いたので、差分に注目しました。
というのも、気になってた部分がありました。
自分の環境だと、ロードバランサーのスキームが EXTERNAL_MANAGED だけど、ドキュメントにある例には、INTERNAL_MANAGED
ロードバランサーのスキームについて
ここに注目しました
自分の環境だと
- 証明書マップを作成
- 証明書マップエントリを追加
- ロードバランサーにアタッチ
ドキュメントにあるのは、
- セルフマネージド証明書をアップロードして、ロードバランサーに直接添付する
待てよ,terraform-provider-googleのほうには、
- ロードバランサーのスキームが INTERNAL_SELF_MANAGEDの場合は、適用されないよ
と書いてあったはず(これが罠)
ということは、certificate_manager_certificatesは、グローバル外部アプリケーション ロードバランサでは使えない??
実際には、
- グローバル外部アプリケーション ロードバランサ(EXTERNAL_MANAGED)
- 従来のアプリケーション ロードバランサ(EXTERNAL)
- グローバル外部プロキシ ネットワーク ロードバランサ(EXTERNAL)
はだめで、
- クロスリージョンの内部アプリケーション ロードバランサ(INTERNAL_MANAGED)
- リージョン外部アプリケーション ロードバランサ(EXTERNAL_MANAGED)
- リージョン内部アプリケーション ロードバランサ(INTERNAL_MANAGED)
は大丈夫
ややこしい
やらかしポイント
- Certificate Manager をロードバランサーにアタッチのところの理解があいまいだった
- プロバイダーのドキュメントを信用しすぎた(純粋)
- 間違っているわけではない
- ドキュメントしっかりと読む
まとめ
SREっぽいことをやっていて、クラウド業務に携わっていると、
サードパーティーツールとクラウドのドキュメントが違うことが結構あったりするので、退屈しないですね(検証のしがいがある)
また深夜テンションのまま書いているので、誤字脱字、また認識の違いがあれば、ぜひご連絡ください!
Discussion