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 証明書を適用するのは、非常に簡単だということではないかと思います。
ロードバランサーを立ち上げるための手順が意外に多く、最初はどの順で作っていけばよいのか分からなくなってしまいますので、改めて順番を整理してみます。
- インスタンスグループを作成する
- インスタンスグループに対してポートを追加する
- ヘルスチェックを作成する
- バックエンドサービスを作成する
- バックエンドサービスにインスタンスグループを追加する
- URL マッピングを作成する
- ターゲットプロキシを作成する
- IPアドレスを作成する
- フロントエンドサービスを作成する
これに SSL 証明書を作成する手順を追加するわけですが、ターゲットプロキシを作成するまでの間のどこかで行えば問題ないようです。
また、 SSL 証明書は作成後すぐに利用できるわけではなく、プロビジョニングに少し時間が掛かるため、余裕を持って作業を行ったほうがいいでしょう。
以上です。