概要 #
リージョン外部 ALB で、公開の Google マネージド証明書を使うとします。選べるのは Certificate Manager の DNS 認証です。
Compute Engine のマネージド証明書は使えません。自己管理証明書なら別途使えます。
Compute Engine Google-managed SSL certificates aren’t supported for regional external Application Load Balancers, regional internal Application Load Balancers, or cross-region internal Application Load Balancers.
残るのは Certificate Manager です。認証方式は DNS認証とLB認証の2つで、どちらを選ぶかで証明書を用意できるタイミングが変わります。
ただしリージョン証明書で使えるのは DNS 認証だけです。 この記事では、比較のためにグローバル外部ALBで LB 認証も試します。
両方を同じプロジェクトに作り、発行までを実測しました。29分の時点では両方 FAILED でした。
対象読者 #
- Terraform で Google Cloud のロードバランサを作ったことがある
terraform applyの出力を読める
扱わないもの #
- Terraform と Google Cloud の入門
- 自己管理証明書、private PKI
- Cloud Armor、URL マップの詳細
証明書の発行と、ロードバランサへの取り付けに絞ります。
検証すること #
- 発行が完了するまで実際にどれくらいかかるか
- ロードバランサが無くても発行できるか
- リージョンとグローバルで DNS 認証の中身は同じか
- 証明書が ACTIVE になれば TLS は張れるのか
- Cloud Logging に何が残るか
前提環境 #
- Google Cloud CLI、Terraform
- Billing が有効な検証用 Google Cloud Project
- 親ドメインから、サブドメインを Cloud DNS へ委任できること
- 検証時のバージョン:Terraform 1.14.3、google 7.x
委任しないと DNS 認証の CNAME が引けません。証明書は待っても発行されません。
使用するTerraformコード #
2つの認証方式 #
flowchart TB
subgraph DNS["DNS認証"]
D1["DNS認証を作る"]
D2["_acme-challenge の CNAME を置く"]
D3["証明書が発行される"]
D4["ロードバランサに付ける"]
D1 --> D2 --> D3 --> D4
end
subgraph LB["LB認証"]
L1["ロードバランサを作る"]
L2["A レコードを LB の IP に向ける"]
L3["証明書が発行される"]
L1 --> L2 --> L3
end
DNS認証は証明書が先、LB認証はロードバランサが先です。移行のときはこの順序が効きます。
構成 #
3つ並べます。
A. DNS認証 + リージョン証明書 -> リージョン外部ALB regional.<domain>
B. LB 認証 + グローバル証明書 -> グローバル外部ALB global.<domain>
C. DNS認証 + リージョン証明書 -> どこにも繋がない nolb.<domain>
C は A レコードもロードバランサも作りません。DNS認証が配信経路と無関係かどうかを見るためです。
バックエンドは VM 1台で、ゾーン NEG を A と B で共用します。
認証方式の選び方は「何を用意できるか」で決まる #
| DNS認証 | LB認証 | |
|---|---|---|
| 必要なもの | _acme-challenge の CNAME |
ドメインを配信するすべてのIPで同じ証明書に443で到達できること |
| SAN の上限 | 100 | 5 |
| 対応するLB | グローバル / クラシック / リージョン / クロスリージョン | グローバル / クラシックのみ |
LB認証は「そのホスト名でロードバランサが応答していること」を認証条件にします。ロードバランサが先に要ります。
委任直後と委任済みで発行時間に差が出た #
A と B を作り、親ドメインから委任した直後の記録です。
0秒 regional=AUTHORIZING global=AUTHORIZING
29分20秒 regional=FAILED global=FAILED
38分20秒 regional=AUTHORIZED global=FAILED
38分53秒 regional=ACTIVE global=FAILED
40分35秒 regional=ACTIVE global=ACTIVE
29分20秒の時点で両方 FAILED になっています。 ここで見ていたら、設定を疑って作り直していたはずです。
これはドメイン認証の状態(authorizationAttemptInfo[].state)です。証明書そのものの managed.state が FAILED になった場合は発行を諦めた状態で、作り直しが要ります。同じ FAILED でも意味が違います。
そのあと C を、同じゾーンに追加しました。
0秒 PROVISIONING/AUTHORIZING
220秒 PROVISIONING/AUTHORIZED
252秒 ACTIVE/AUTHORIZED
4分12秒です。同じプロジェクト、同じゾーン、同じ手順で9倍以上の差が出ました。
違いは、委任してからの経過時間だけです。1回目は委任した直後で、権威ネームサーバの切り替わりを待っていました。2回目はすでに引ける状態でした。
「証明書の発行には最大24時間」という記述を見かけます。ただしこの測定では、DNS の伝播と Certificate Manager・CA 側の処理を切り分けていません。 どちらがどれだけ効いたかは言えないので、発行処理単体の所要時間や上限についてはここでは結論を出しません。
ロードバランサが無くても発行できる #
C は A レコードもロードバランサも作っていません。
$ dig +short A nolb.<domain>
(何も返らない)
$ gcloud compute forwarding-rules list --format="value(name)"
tf-adv-cm27-global-fr
tf-adv-cm27-regional-fr
それでも 4分12秒で ACTIVE になりました。DNS認証は配信経路と無関係に発行できます。
LB認証では原理的にできません。認証の条件は、証明書を関連付けたロードバランサの構成が済んでいて、そのホスト名の A / AAAA が返すすべての IP でポート 443 からその証明書を使えることだからです。AAAA の取り違え、証明書の未関連付け、443 の未開放は、いずれも失敗の原因になります。
この違いは移行のときに効きます。既存サイトをロードバランサへ載せ替える場合、DNS認証なら切り替え前に証明書を用意できます。
LB認証だと、ロードバランサを立てて DNS を向けるまで証明書が発行されません。切り替えと証明書の準備を同時にやることになります。
リージョンとグローバルでCNAMEの名前が違う #
同じ「DNS認証」でも中身が違いました。
| global(今回) | リージョン | |
|---|---|---|
| 種別 | FIXED_RECORD |
PER_PROJECT_RECORD |
| CNAME | _acme-challenge.<domain> |
_acme-challenge_<接尾辞>.<domain> |
CNAME の名前は location ではなく種別で決まります。 global では PER_PROJECT_RECORD も選べます。今回 global に FIXED_RECORD を使ったので、この組み合わせになりました。
一方、リージョンで FIXED_RECORD を指定すると弾かれます。
description: FIXED_RECORD type is not supported in this environment
subject: FIXED_RECORD
type: DATA_INVALID
公式にも書かれています。
For regional Google-managed certificates, you can create only the
PER_PROJECT_RECORDtype of DNS authorization.
_acme-challenge を決め打ちで書いたコードは、リージョンでは動きません。 認証リソースの出力から取れば、どちらでも動きます。
resource "google_dns_record_set" "acme_challenge_regional" {
name = google_certificate_manager_dns_authorization.regional.dns_resource_record[0].name
type = google_certificate_manager_dns_authorization.regional.dns_resource_record[0].type
ttl = 300
managed_zone = google_dns_managed_zone.delegated.name
rrdatas = [google_certificate_manager_dns_authorization.regional.dns_resource_record[0].data]
}
エラー文言が原因を指していない #
「存在しない」と言われるが、存在する #
global に作った DNS 認証を、リージョン証明書に渡してみました。
ERROR: INVALID_ARGUMENT: dns authorization doesn't exist
- field: managed.dns_authorizations[0]
認証は存在します。location が違うだけです。
$ gcloud certificate-manager dns-authorizations describe ... --location=global
projects/.../locations/global/dnsAuthorizations/... FIXED_RECORD
公式の記述と対応しています。
You can’t use global DNS authorizations with regional certificates.
「使えない」ではなく「無い」と出るので、リソース名の打ち間違いを疑ってしまいます。
「非対応」ではなく「見つからない」と出る #
Compute Engine のマネージド証明書をリージョン ALB に付けようとした結果です。
ERROR: Could not fetch resource:
- The resource 'projects/.../regions/asia-northeast1/sslCertificates/...' was not found
作成自体はできます。グローバル資源だからです。付けようとすると regions/<region>/sslCertificates/ を探しに行き、そこには無い、という順で失敗します。
この出力が直接示すのは「そのリージョンパスに資源が無い」ことだけです。 リージョン SSL 証明書が Google-managed に非対応であること自体は仕様で確かめます。観測と仕様は分けて読みます。
冒頭の「リージョンALBでは非対応」を知らないと、この文面からはたどり着けません。
証明書がACTIVEでも、まだTLSは張れない #
リージョン側は、ACTIVE の直後から通りました。
$ curl -o /dev/null -w '%{http_code} %{ssl_verify_result}\n' https://regional.<domain>/
200 0
subject=CN = regional.<domain>
issuer=C = US, O = Google Trust Services, CN = WR3
notBefore=Sep 5 23:52:56 2026 GMT
notAfter=Dec 5 00:48:52 2026 GMT
ssl_verify_result が 0 なので、検証も通っています。有効期間は90日です。
グローバル側は違いました。
$ curl https://global.<domain>/
curl: (35) error:0A000126:SSL routines::unexpected eof while reading
証明書は ACTIVE です。それでも TLS が張れません。さらに121秒待つと 200 になりました。
似た記述がCompute Engine のマネージド SSL 証明書のページにあります。
After the certificate and domain statuses are active, it can take up to 30 minutes for your load balancer to begin using your Google-managed SSL certificate.
ただしこれは Certificate Manager の証明書についての記述ではありません。 121秒は今回の観測値で、上限を示すものでもありません。
いずれにせよ、「証明書ができた」と「繋がる」は別です。
取り付け方がリージョンとグローバルで違う #
| 取り付け先 | |
|---|---|
| リージョン | ターゲットプロキシに直接(certificate_manager_certificates) |
| グローバル | 証明書マップ経由(certificate_map) |
リージョン側はこう書きます。
resource "google_compute_region_target_https_proxy" "regional" {
name = "tf-adv-cm27-regional-proxy"
region = var.region
url_map = google_compute_region_url_map.regional.id
certificate_manager_certificates = [google_certificate_manager_certificate.regional.id]
}
併用の可否は上下で違います。 リージョン側の certificate_manager_certificates は ssl_certificates と同時に指定できません。
sslCertificates and certificateManagerCertificates can’t be defined together.
グローバル側の certificate_map は ssl_certificates と同時に設定できます。その場合はマップが優先され、Compute Engine の証明書は無視されます。
今回の検索では発行の経過を確認できなかった #
管理操作は残ります。
$ gcloud logging read 'protoPayload.serviceName="certificatemanager.googleapis.com"' --freshness=4h
CreateDnsAuthorization projects/.../dnsAuthorizations/tf-adv-cm27-dnsauth-regional
CreateCertificate projects/.../certificates/tf-adv-cm27-cert-nolb
...
→ 18 件
発行の経過は、今回の検索では見つかりませんでした。
$ gcloud logging read 'textPayload=~"ACTIVE|AUTHORIZ|PROVISION"' --freshness=3h
→ 0 件
この条件は textPayload しか見ていません。 jsonPayload や protoPayload は別のフィールドなので、この検索だけでは経過ログが存在しないとは言い切れません。
今回は describe を定期的に呼び出して状態を追いました。
describe を繰り返して authorizationAttemptInfo を見るしかありません。
$ gcloud certificate-manager certificates describe <NAME> --location=<REGION> --format="yaml(managed)"
managed:
authorizationAttemptInfo:
- attemptTime: '2026-09-06T00:48:54Z'
domain: regional.<domain>
state: AUTHORIZED
state: ACTIVE
つまずいたところ #
API有効化の直後は失敗する #
google_project_service で Certificate Manager API を有効化し、同じ apply で証明書を作ろうとして落ちました。
Certificate Manager API has not been used in project ... before or it is disabled.
"reason": "SERVICE_DISABLED"
google_project_service は、有効化オペレーションの完了と、Service Usage 上で ENABLED になるまでは待ちます。ただしそれは、そのサービスで実際に操作できるようになったことの確認ではありません。 depends_on は作成順序を決めるだけで、利用可能になるまでを保証しません。
今回はもう一度 apply すれば通りました。ただし1回の観測なので、必ず再 apply で通るとまでは言えません。
capacity_scaler を省くとplanが落ちる(リージョン版) #
Error: managed backend service must have at least one non-zero capacity_scaler for backends
google_compute_region_backend_service で EXTERNAL_MANAGED を使うと、plan の検証に引っかかりました。
API の省略時の既定は 1 です。 明示を求めているのは provider 側の検証で、グローバル版の google_compute_backend_service には既定値があります。
backend {
group = google_compute_network_endpoint_group.backend.id
balancing_mode = "RATE"
max_rate_per_endpoint = 100
capacity_scaler = 1.0
}
まとめ #
実測した結果を並べます。
| 項目 | 結果 |
|---|---|
| 発行までの時間(委任直後) | 38分53秒 |
| 発行までの時間(委任済み) | 4分12秒 |
途中の FAILED |
あり。29分20秒から9分間 |
| LB無しでの発行 | できる(DNS認証) |
| リージョンのDNS認証 | PER_PROJECT_RECORD 強制 |
| 証明書ACTIVE後のTLS | グローバルはさらに121秒 |
| 発行経過のログ | 0件 |
時間がかかるのは DNS の伝播でした。 2回目が4分で終わったことが、それを示しています。委任を先に済ませておけば、証明書の発行自体は待つほどのものではありません。
FAILED という表示だけで再作成を判断しないことが、この検証で一番の収穫でした。29分で諦めていたら、原因のない作り直しをしていたはずです。
ただし待てば直るとは限りません。 公式のトラブルシューティングは、認証の失敗理由として CNAME の不一致やロードバランサの設定不備を挙げています。failureReason と details を見て、設定に問題があれば直します。
どのフィールドが失敗したのかも確かめます。managed.state の FAILED は作り直しが要ります。
認証方式は、証明書をいつ用意したいかで決まります。ロードバランサを立てる前に用意しておきたいなら DNS認証しかありません。リージョンALBを使う場合は、そもそも Certificate Manager 一択です。
参考資料 #
- Certificate Manager overview
- Deploy a regional Google-managed certificate with DNS authorization
- Deploy a global Google-managed certificate with load balancer authorization
- DNS authorizations
- Google-managed SSL certificates (Compute Engine)
- Proxy-only subnets for Envoy-based load balancers
- google_certificate_manager_certificate
- google_certificate_manager_dns_authorization
- google_compute_region_target_https_proxy