はじめに
前回投稿したGCP記事で紹介したGKEクラスタのCIDR設計について、深堀りした記事になります。
1-5. 共有VPC上のGKEクラスタのセカンダリCIDR設計
事象: オンプレ環境と接続する1つの共有VPC上にproduction, stagingなど複数プロジェクトを相乗りさせる場合、各プロジェクトで利用するセカンダリCIDRの設計が必要。
対応: GKEで必要なセカンダリCIDRを本腰入れて設計しました。スタンダードなこれと言った解はなく、必要な環境数、オンプレ環境から割り当てられたIP範囲から適宜設計する必要があります。
記載通りですが、GKEクラスタを構築する際に、実際に設計した内容を元に制約や設計のポイントを紹介したいと思います。
GKEとは
コンテナ化されたアプリケーションをデプロイするための、本番稼働に対応したマネージド型環境です。
https://cloud.google.com/kubernetes-engine/
CIDRとは
Classless Inter-Domain Routing(CIDR、サイダー)は、インターネット上のルーターにおけるルーティングテーブルの肥大化速度を低減させるための機構であり、ISPや組織にクラスA、B、Cを全部ではなく部分的に割り当てることでIPアドレスの浪費を防ぐ機構である。CIDR記法でアドレスを記述でき、アドレスの集約的表現が可能で、アドレスブロックの委譲も容易である。
「CIDR」の読みは「サイダー」とするのが一般的である
https://ja.wikipedia.org/wiki/Classless_Inter-Domain_Routing
CIDR記法は 10.0.0.0/8
、172.16.0.0/12
、 192.168.0.0/16
といったIPアドレスとビット数を指定する方法です。
詳細は次項で説明していきますが、ある条件でGKEクラスタを構築すると、このCIDR設計が必須になってきます
前提
アーキテクチャ設計上の要件と、GKEクラスタの制約の2つが設計上の考慮事項となります。
アーキクチャ設計上の要件
今回GKEクラスタを構築する上で2つの前提がありました。
※オンプレ環境とインターネットVPNで繋ぐため1つのVPCを複数環境で利用したかったのと、セキュリティポリシーから外部アクセス禁止となっていたためです。
共有VPCとは
共有VPCとは、あるホストとなるプロジェクトのVPCを、複数のGCPプロジェクトがリソースとして利用できるようになる機能です。これにより、サブネット、ルート、ファイアウォールなどのネットワーク リソースを集中管理しながら、インスタンスの作成や管理などの管理責任をサービス プロジェクト管理者に委任できます。
以下は前回投稿したGCP記事で紹介した構成図です。Shared VPCと書かれた領域にある、Subnetをサービスと呼ばれる別GCPプロジェクトが利用しています。
VPC Peeringとの違いはいくつかありますが、ホストとなるプロジェクト側でファイアウォールルールなどを集中管理できる点などが異なります(今回はこの点が重視し共有VPCを選択しました)
限定公開クラスタとは
限定公開クラスタでは、ノードに RFC 1918 の内部 IP アドレスのみがあるため、ワークロードが公共のインターネットから隔離されるようになります。
https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters
引用文そのままですが、限定公開クラスタの設定を行うと、各GKEノードにPublic IPを付与せずGKEクラスタを構築できます。セキュリティ要件からこちらの設定が必須となりました。
GKEクラスタの制約
- 共有VPC上にGKEクラスタ構築する制約
クラスタのポッドとサービスに使用するサブネットとセカンダリCIDRを指定する必要があります。
https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-shared-vpc#verify_usable_subnets - パブリックエンドポイントへのアクセスが制限された限定公開クラスタによる制約
クラスタマスターが使用する /28 分の RFC 1918 アドレス範囲を指定する必要があります。
https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters#public_master - セカンダリCIDRの上限によるクラスタ数の制約
ポッドとサービスに対して割り当てるセカンダリCIDRですが、1サブネット内に設定可能なセカンダリCIDR数に上限があり、この上限数/2が構築可能なクラスタ数になります。
https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-shared-vpc#notes_about_secondary_ranges
私が構築した時点ではセカンダリCIDRの上限は5つだったためクラスタの上限は2つでしたが、現在はセカンダリCIDRの上限は30まで拡張されており15クラスタまで作成可能なのでさほど設計上の制約にはならないかもしれません。
※日本語ドキュメントはまだ5のままにですが英語では30になっています(2019/10/17時点)
実際に設計してみる
本編です。
前項の制約から1GKEクラスタに対して 3つのCIDR(ポッド、サービス、マスタ)を割り当てる必要 が出てきました。またこれらは 同一の共有VPC上に構築するため構築される全てのプロジェクトをまたいで全てのCIDRが被ってはいけない という制約もあります。
この辺りに注意してCIDR設計したいと思います。
1. 全体の設計方針
設定上はプロジェクトが異なればポッドやサービスのCIDRは全く異なる範囲や体系で設定可能です。
ですが、各プロジェクト(環境)毎に設計のポリシーを合わせるために全プロジェクトに対してポッド、サービス、マスタ別にCIDRを概念的に割り当て、そこから各プロジェクトごとに実際のCIDRを割り当てるといった設計方針をとりました。
2. ポッド&サービスCIDR
2.1. 共有VPC上の全プロジェクトに対するCIDR
こちらは172.16.0.0/12(クラスB)を概念的に割り当てました。
GKEのポッド&サービスに割り当て可能なCIDRはRFC 1918 ブロック(10.0.0.0/8、172.16.0.0/12、または 192.168.0.0/16)の制約があります。
https://cloud.google.com/kubernetes-engine/docs/how-to/routes-based-cluster#pod_address_range
10.0.0.0/8はGCP環境以外も含めたシステム全体で利用しているのと、192.168.0.0/16は後述のマスタのアドレス範囲に利用するためクラスB(172.16.0.0/12)を選択しました。
なお基本的にはクラスBの範囲を使うことができますが、公式ドキュメントには172.17.0.0/16
を利用できない旨の記載があります。
該当範囲を指定してもクラスタ構築時にエラーとなるわけではないのでご注意下さい。
Restrictions
Private clusters have the following restrictions:
You cannot use a cluster master, node, Pod, or Service IP range that overlaps with 172.17.0.0/16.
https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters#restrictions
2.2. 各プロジェクトにおけるCIDR
こちらに対してはさらに3段階の概念でCIDRを設計しました。
- プロジェクト毎のCIDR
- ポッド/サービス毎のCIDR
- クラスタ毎のCIDR
まずプロジェクトごとのCIDRですが、全体でいくつのプロジェクトを作成するかを設計します。
本番、ステージングはよくある環境ですが、他に非機能テスト、開発時の機能検証用を想定すると4面、これに加えて実データ使ったデモ環境、並行して動かす別バージョン環境・・などを考慮し最大7断面を想定しました。
これによって172.16.0.0/12以下に3bit加えて以下のCIDRが割当たります。
環境 | CIDR |
---|---|
本番 | 172.18.0.0/15 |
ステージング | 172.20.0.0/15 |
非機能 | 172.22.0.0/15 |
・・・ | ・・・ |
※172.16.0.0/15は前述の172.17.0.0/16を含むため利用しませんでした。
次にポッド/サービスですが、これは2値のため次の1bitを割り当てます
環境 | CIDR | 種別 | CIDR |
---|---|---|---|
本番 | 172.16.0.0/15 | ポッド | 172.18.0.0/16 |
サービス | 172.19.0.0/16 | ||
ステージング | 172.18.0.0/15 | ポッド | 172.20.0.0/16 |
サービス | 172.21.0.0/16 | ||
非機能 | 172.20.0.0/15 | ポッド | 172.22.0.0/16 |
サービス | 172.23.0.0/16 | ||
・・・ | ・・・ | ・・・ | ・・・ |
そして最後に実際にクラスタに割り当てるCIDRに分割します。
ここは実際に構築するクラスタ数に応じて細分化します。
環境 | CIDR | 種別 | CIDR | クラスタ | CIDR |
---|---|---|---|---|---|
本番 | 172.16.0.0/15 | ポッド | 172.18.0.0/16 | クラスタA | 172.18.0.0/18 |
ポッド | クラスタB | 172.18.64.0/18 | |||
サービス | 172.19.0.0/16 | クラスタA | 172.19.0.0/18 | ||
サービス | クラスタB | 172.19.64.0/18 | |||
ステージング | 172.18.0.0/15 | ポッド | 172.20.0.0/16 | クラスタA | 172.20.0.0/18 |
ポッド | クラスタB | 172.20.64.0/18 | |||
サービス | 172.21.0.0/16 | クラスタA | 172.21.0.0/18 | ||
サービス | クラスタB | 172.21.64.0/18 | |||
非機能 | 172.20.0.0/15 | ポッド | 172.22.0.0/16 | クラスタA | 172.22.0.0/18 |
ポッド | クラスタB | 172.22.64.0/18 | |||
サービス | 172.23.0.0/16 | クラスタA | 172.23.0.0/18 | ||
サービス | クラスタB | 172.23.64.0/18 | |||
・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ |
なお前述の1環境2クラスタの制限(2019/10/17時点では制約が緩和され15クラスタまで可能なはず)から以下のような切り方も出来たのですが、
環境 | CIDR | 種別 | CIDR | クラスタ | CIDR |
---|---|---|---|---|---|
本番 | 172.16.0.0/15 | ポッド | 172.16.0.0/16 | クラスタA | 172.18.0.0/17 |
ポッド | クラスタB | 172.18.128.0/17 | |||
サービス | 172.17.0.0/16 | クラスタA | 172.19.0.0/17 | ||
サービス | クラスタB | 172.19.128.0/17 | |||
・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ |
以下の理由で/18のアドレス範囲としました。
- 今後制約が緩んだ時の拡張性を持たせる
- クラスタ再作成を覚悟すれば、後で拡張可能であろうという前提です
- /18で切ったアドレス範囲内でポッドとサービスの数は十分足りる
2.3. アドレスに対する意味付け
ここまでのアドレス設計と並行して、アドレスから容易に環境や用途を判断できるように考慮しました。
今回のアドレス設計ではアドレスの2か所に意味を持たせています。
アドレス体系:172.XXX.YYY.0/18
- XXXの箇所で環境を表す
本番(18,19)、ステージング(20,21)・・・ - XXXの箇所で種別を表す
偶数がポッド、奇数がサービスとなっています。 - YYYの箇所にはクラスタ。
クラスタA(0)、クラスタB(64)
3. マスタCIDR
3.1. 共有VPC上の全プロジェクトに対するCIDR
こちらは192.168.0.0/16(クラスC)を概念的に割り当てました。
これは10.0.0.0/8(クラスA)の一部をプライマリCIDRで利用していたのと172.16.0.0/12(クラスB)をポッドとサービスのセカンダリCDIRで利用していたためです。
また制約上/28のCDIRを割り当てればよいため、クラスCのアドレス範囲で十分と判断しました。
3.2. 各プロジェクトにおけるCIDR
こちらに対しては2段階の概念でアドレス範囲を設定しました。
- プロジェクト毎のCIDR
- クラスタ毎のCIDR
ただし、アドレス範囲を無駄なくキレイには使わずに、分かりやすさを考慮して以下のアドレス範囲を割り当てています。
環境 | クラスタ | CIDR |
---|---|---|
本番 | クラスタA | 192.168.16.0/28 |
クラスタB | 192.168.17.0/28 | |
ステージング | クラスタA | 192.168.32.0/28 |
クラスタB | 192.168.33.0/28 | |
非機能 | クラスタA | 192.168.48.0/28 |
クラスタB | 192.168.49.0/28 | |
・・・ | ・・・ | ・・・ |
3.3. アドレスに対する意味付け
ここでもアドレスから容易に環境や用途を判断できるように考慮しました。
今回のアドレス設計ではアドレスの2か所に意味を持たせています。
アドレス体系:192.168.XXX.0/28
- XXXの箇所で環境を表す
本番(16,17)、ステージング(32,33)・・・ - XXXの箇所でクラスタを表す
偶数がクラスタA、奇数がクラスタBとなっています。
4. 全体サマリ
全体のアドレスをまとめると以下になります。
環境 | クラスタ | 種別 | CIDR |
---|---|---|---|
本番 | クラスタA | ポッド | 172.18.0.0/18 |
サービス | 172.19.0.0/18 | ||
マスター | 192.168.16.0/28 | ||
クラスタB | ポッド | 172.18.64.0/18 | |
サービス | 172.19.64.0/18 | ||
マスター | 192.168.17.0/28 | ||
ステージング | クラスタA | ポッド | 172.20.0.0/18 |
サービス | 172.21.0.0/18 | ||
マスター | 192.168.32.0/28 | ||
クラスタB | ポッド | 172.20.64.0/18 | |
サービス | 172.21.64.0/18 | ||
マスター | 192.168.33.0/28 | ||
・・・ | ・・・ | ・・・ | ・・・ |
あとがき
今回は実際に設計した事例を元にGCP上の制約や設計時に考えたことを紹介させて頂きました。
この辺りの設計は制約や重視するポイントで結構変わってくるのでこれと言った正解はありませんが、1つの例として構築の際にお役に立てれば幸いです。