GCP のロードバランサーに無料の SSL 証明書を gcloud コマンドで設定してみる


こんにちは。
開発チームのワイルド担当、まんだいです。

本日はタイトル通り、先日追加されたフルマネージドかつ無料の SSL 証明書を、ロードバランサーに適用できるようになったので試してみたいと思います。
昨今 SSL 化が必須の流れになってきていて、 SSL 証明書の費用も無視できなくなってきましたので、これはかなり嬉しい方もおられるんじゃないでしょうか。

 

いつから GCP の ロードバランサーに無料の SSL 証明書が発行できるようになっていたのか

そもそも GCP の ELB に 無料の SSL 証明書を適用できるようになっていたのをご存知だったでしょうか?
2018年10月にローンチされた機能で、私自身恥ずかしながら気づいていませんでした。

AWS に AWS Certificate Manager という機能が追加されたのは2016年1月とかなり前なので時期的な問題ではかなり差が開いていますが、機能的にはシンプルで世の中のスタンダードに寄り添った形なので、個人的には好感が持てるなと思いました。

 

GCP の無料 SSL 証明書の中身はどうなっているのか

GCP の SSL 証明書は GCP のコンソールを確認すればすぐに分かりますが、 Let’s Encrypt 経由で発行されています。

Let’s Encrypt といえば、証明書の更新サイクルが3ヶ月と短いため、サーバーに更新スクリプトを組み込んで定期実行するのがセオリーです。
これだけなんですが、これがパブリッククラウドのロードバランサーとなると途端に話はややこしくなります。

GCP では、この更新作業にまつわる機能の全てをロードバランサー側に用意して、快適かつ簡単に SSL を利用できる環境を用意したと言えます。

また、 証明書を発行するには、 SSL 証明書を適用する予定のドメインの DNS が SSL 証明書を置くロードバランサーに設定された IP アドレスを指している必要があります。
この縛りのため、適用直後は外部公開している状態でも SSL が効いていない状態がちょっとの間発生します。

 

gcloud コマンドで設定してみる

ロードバランサーに SSL 証明書を置くのは gcloud コマンドから実行可能です。

まずは、 gcloud コマンド自身をバージョンアップしておきましょう。
調べたところによると、220.0.0以降のバージョンなら、問題ないようでしたが念の為、最新にしておきましょう。

gcloud components update

 

gcloud コマンドは頻繁にアップデートされるため、何かしらの更新はあるんじゃないかと思います。

アップデートが終わったら、早速コマンドで SSL 証明書を作成してみます。
今回は SSL 証明書の名前を test-example-ssl 、 SSL 証明書を作成するドメインを、 test.example.com として、 SSL 証明書を作成してみましょう。

gcloud beta compute ssl-certificates create test-example-ssl \
    --domains test.example.com
Created [https://www.googleapis.com/compute/beta/projects/hogehoge-xxxxxx/global/sslCertificates/test-example-ssl].
NAME              TYPE     CREATION_TIMESTAMP             EXPIRE_TIME  MANAGED_STATUS
test-example-ssl  MANAGED  2019-04-01T03:12:53.962-07:00               PROVISIONING
    test.example.com: PROVISIONING

 

現在の様子を確認するには、「 gcloud beta compute ssl-certificates list 」コマンドを使用します。

gcloud beta compute ssl-certificates list
NAME              TYPE     CREATION_TIMESTAMP             EXPIRE_TIME                    MANAGED_STATUS
www-example-ssl   MANAGED  2019-03-01T23:33:53.360-08:00  2019-05-30T23:41:52.000-07:00  ACTIVE
    www.example.com: ACTIVE
test-example-ssl  MANAGED  2019-04-01T03:12:53.962-07:00                                 PROVISIONING
    test.example.com: PROVISIONING

 

www-example-ssl は少し前に作成済みのもので、既に有効になっています。
test-example-ssl はというとプロビジョニングしている、と出ていますが、このまま放っておくと最終的にエラーになります。
test.example.com の A レコードに書かれている IP アドレスが、これから作成するロードバランサーを向いていないからですね。
こちらももプロビジョニングが完了したら、 MANAGED_STATUS の部分が ACTIVE に変わります。

 

ロードバランサーに SSL 証明書を適用する

それでは、プロビジョニングができた SSL 証明書をロードバランサーに適用していくのですが、肝心のロードバランサーがないので新たにロードバランサーを作成するところから始めていきます。
少し手順が多いですが、挫けずに行きましょう!

 

インスタンスグループの作成

インスタンスグループを作成します。
ここでは、インスタンスを入れる入れ物を作ります。

gcloud compute instance-groups unmanaged create example-instance-group \
    --zone=us-east1-b
Created [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/zones/us-east1-b/instanceGroups/example-instance-group].
NAME                    LOCATION    SCOPE  NETWORK  MANAGED  INSTANCES
example-instance-group  us-east1-b  zone                     0

 

インスタンスグループには、オートスケールやインスタンステンプレートといった機能を簡単に利用できるマネージドインスタンスグループと、そういった機能を持たないアンマネージドインスタンスグループの2種類があります。

今回は、そういった機能が不要なので、アンマネージドインスタンスグループとして作成します。

作成した全てのインスタンスグループを確認するコマンドは以下のとおりです。

gcloud compute instance-groups list
NAME                    LOCATION           SCOPE  NETWORK  MANAGED  INSTANCES
default-group           asia-northeast1-b  zone   default  No       1
example-instance-group  us-east1-b         zone   default  No       1

 

インスタンスグループにインスタンスを追加

作成したインスタンスグループにインスタンスを追加していきます。
今回は example-web01 インスタンスがある us-east1 リージョンのゾーン B に作成します。

gcloud compute instance-groups unmanaged add-instances example-instance-group \
    --instances example-web01 \
    --zone us-east1-b
Updated [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/zones/us-east1-b/instanceGroups/example-instance-group].

 

インスタンスグループに追加されたインスタンスを確認するには、以下のコマンドを使用します。

gcloud compute instance-groups describe example-instance-group --zone [region-zone]
creationTimestamp: '2019-04-05T00:13:10.372-07:00'
description: ''
fingerprint: hogehoge
id: 'xxxxxxxxxxxxxxxx'
kind: compute#instanceGroup
name: example-instance-group
namedPorts:
- name: http
  port: 80
network: https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/networks/default
selfLink: https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/zones/us-east1-b/instanceGroups/example-instance-group
size: 1
subnetwork: https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/regions/us-east1/subnetworks/default
zone: https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/zones/us-east1-b

 

 

インスタンスグループのポートマッピングを設定する

インスタンスグループの待受ポートを設定します。
ここでは HTTP (80番)ポートを開けてみます。

gcloud compute instance-groups unmanaged set-named-ports example-instance-group \
    --named-ports http:80 \
    --zone us-east1-b
Updated [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/zones/us-east1-b/instanceGroups/example-instance-group].

 

–named-ports オプションは、カンマ区切りで複数設定することができます。

 

ヘルスチェックの作成

ヘルスチェックは、指定した URL にアクセスして行う死活監視です。
この後に設定するバックエンドサービスに紐付ける機能で、200番が返ってくれば、機能していると判断します。

ここでは、80番ポートに対するヘルスチェックを作成してみます。

gcloud compute health-checks create http example-check \
    --port 80
Created [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/healthChecks/http-basic-check].
NAME           PROTOCOL
example-check  HTTP

 

ヘルスチェックについては、今回のように SSL 証明書付きのロードバランサーであっても、ヘルスチェックの通信はロードバランサーからインスタンス間なので、 HTTP のヘルスチェックでいいようです。

 

バックエンドサービスを作成

バックエンドサービスは、複数のインスタンスグループをまとめる役割を持ちます。
インスタンスグループも同じようにインスタンスをまとめる役割を持ちますが、バックエンドサービスは、この後に出てくる URL マップで URL のパターンごとに転送先を変える場合の単位になります。

ヘルスチェックは、バックエンドサービス内のインスタンスグループが待ち受けるポートのヘルスチェックを指定します。

gcloud compute backend-services create example-backend \
    --protocol HTTP \
    --health-checks example-check \
    --global
Created [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/backendServices/example-backend].
NAME             BACKENDS  PROTOCOL
example-backend            HTTPS

 

 

バックエンドサービスにインスタンスグループを紐付ける

先程作成したバックエンドサービスに、インスタンスグループを追加していきます。
バックエンドサービスは、インスタンスグループを最小単位として登録できます。

gcloud compute backend-services add-backend example-backend \
    --balancing-mode UTILIZATION \
    --max-utilization 0.8 \
    --capacity-scaler 1 \
    --instance-group example-instance-group \
    --instance-group-zone us-east1-b \
    --global
Updated [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/backendServices/example-backend].

 

バックエンドサービス内の各インスタンスグループにバランシングするために、 GCP では、2つのバランシングモードが用意されています。

 

UTILIZATION

CPU 使用率を基準に負荷を分散させます。マシンリソースを有効に使いたい場合は、このモードがおすすめです。
また、 –max-utilization の値を越えた場合にオートスケールが実行されるので、0.8であれば CPU 使用率が80%を越えたときにオートスケールが実行されます。

 

RATE

リクエスト/秒( RPS ) を基準負荷分散させます。サービスのレスポンスを安定させたい場合は、こちらのモードがおすすめです。
–target-load-balancing-utilization で指定したパーセンテージを越えたリクエストを受けている場合に、オートスケールが実行されます。

どちらのモードも –max-num-replicas オプションでオートスケールが起動するインスタンスの最大数を指定できます。

 

URLマップの作成

GCP の負荷分散の仕組みは、TCP ベース、コンテンツベースの2種類あります。

GCP のドキュメントには、クロスリージョン負荷分散という仕組みもありますが、設定の形はコンテンツベースの発展形という内容です(詳しい話は省きます)。

コンテンツベースの場合、GCP のコンソールの負荷分散のページでロードバランサーとして表示されているのが、この URL マップです。

URL マップは、その名の通り、 URL のパターンから複数のバックエンドサービスへのルーティングを行います。
この機能を使えば、ウェブサービス全体の機能の粒度を小さくすることでマイクロサービス化することができますね。

gcloud compute url-maps create example-url-map \
    --default-service example-backend
Created [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/urlMaps/example-url-map].
NAME             DEFAULT_SERVICE
example-url-map  backendServices/example-backend

 

今回は単一のバックエンドサービスしか持たない URL マップなので、ルーティングの記述はありません。
URL マップでルーティングするには、パスマッチャーというパスに応じたルーティングを作成して、オブジェクトを作成して URL マップに追加していきます。

パスマッチャーは今回の記事から少し離れてしまうため、ここでは説明を省きます。
気になる方は英語になりますが、公式ドキュメントを参照してください。

 

ターゲットプロキシの作成

ターゲットプロキシは、 URL マップと SSL 証明書を紐付ける役目を持ちます。

gcloud compute target-https-proxies create example-https-proxy \
    --url-map example-url-map \
    --ssl-certificates test-example-ssl
Created [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/targetHttpsProxies/example-https-proxy].
NAME                 SSL_CERTIFICATES  URL_MAP
example-https-proxy  test-example-ssl  example-url-map

 

 

IP アドレスの作成

次にロードバランサーで使用する IP アドレスを作成します。

gcloud compute addresses create example-ip --ip-version=IPV4 --global
Created [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/addresses/example-ip].

 

現在使用している IP アドレスを確認するには、以下のコマンドを使用します。

gcloud compute addresses list
NAME           ADDRESS/RANGE    TYPE  PURPOSE  NETWORK  REGION           SUBNET  STATUS
default-web01  xxx.xxx.xxx.xxx                          asia-northeast1          IN_USE
example-ip     xxx.xxx.xxx.xxx                                                   RESERVED

 

 

フロントエンドサービスの追加

最後に、外部と URL マップを繋ぐフロントエンドサービスを作成します。

gcloud compute forwarding-rules create example-frontend \
    --address xxx.xxx.xxx.xxx \
    --global \
    --target-https-proxy example-https-proxy \
    --ports 443
Created [https://www.googleapis.com/compute/v1/projects/hogehoge-xxxxxx/global/forwardingRules/example-frontend].

 

フロントエンドサービスでグローバル IP とポート、ターゲットプロキシの紐づけを行います。

以上でロードバランサーに無料の SSL 証明書を適用することができました。

 

まとめ

ロードバランサーに SSL 証明書を適用する記事を、と思ったのですが、ほとんどがロードバランサーを作成する内容になってしまったなと反省しています。逆に言うと出来上がっているロードバランサーに対してなら SSL 証明書を適用するのは、非常に簡単だということではないかと思います。

ロードバランサーを立ち上げるための手順が意外に多く、最初はどの順で作っていけばよいのか分からなくなってしまいますので、改めて順番を整理してみます。

  1. インスタンスグループを作成する
  2. インスタンスグループに対してポートを追加する
  3. ヘルスチェックを作成する
  4. バックエンドサービスを作成する
  5. バックエンドサービスにインスタンスグループを追加する
  6. URL マッピングを作成する
  7. ターゲットプロキシを作成する
  8. IPアドレスを作成する
  9. フロントエンドサービスを作成する

これに SSL 証明書を作成する手順を追加するわけですが、ターゲットプロキシを作成するまでの間のどこかで行えば問題ないようです。
また、 SSL 証明書は作成後すぐに利用できるわけではなく、プロビジョニングに少し時間が掛かるため、余裕を持って作業を行ったほうがいいでしょう。

 
以上です。


この記事をかいた人

About the author