こちらの記事は、2019年5月に公開された『 Completely Private GKE Clusters with No Internet Connectivity 』の和訳になります。
はじめに
Google Kubernetes Engine(GKE)クラスターをインターネットアクセスから分離する理由はいくつかありますが、主な理由はセキュリティです。多くの金融機関、政府機関、および同様の機関が、Google Cloud Platform(GCP)でワークロードを実行しています。
この投稿では、インターネットへのアクセスをブロックする、隔離されたネットワークでGKEクラスターを立ち上げるために必要な手順を説明します。
#TL;DR
- プライベートGoogleアクセスを有効にしてGKEクラスターのVPCとサブネットを作成します。
- 送信時に0.0.0.0/0(全指定)でブロックするファイアウォールのルールでVPCをロックダウンし、Googleヘルスチェックからの受信を許可し、Googleヘルスチェック、制限されたAPI、およびGKEプライベートマスター範囲への送信を許可します。
- VPCで自動的に作成されたデフォルトルートを削除します(ネクストホップとしてデフォルトインターネットゲートウェイを指定しているルール)。デフォルトのインターネットゲートウェイを介してGoogle Restricted API(199.36.153.4/30)に到達するためのルートを作成します。
- 次のCloud DNSの変更を行い、ゾーンをVPCにアタッチします。
-
- .googleapis.comからrestrict.googleapis.comを引くためのCNAMEレコード、restricted.googleapis.comから199.36.153.4/30を引くためのAレコードをもつ、プライベートDNSゾーンgoogleapis.comを作成します。
-
- .gcr.ioからgcr.ioを引くためのCNAMEレコード、gcr.ioから199.36.153.4/30を引くためのAレコードをもつプライベートDNSゾーンgcr.ioを作成します。
- プライベートノードとプライベートマスターでGKEクラスターを作成します。
#段階的な展開
以降で利用可能なTerraformコード
##VPCとサブネットを作成する
クラスターを作成する前に、クラスターに使用する環境にVPCとサブネットが必要です。それぞれのクラスターに3つのサブネットがあります。
- ノードレンジ:GKEワーカーノードはこのサブネットに存在します。
- クラスターレンジ:GKEはこの範囲を取得し、ノード間で分割します。デフォルトでは、各ノードはこの範囲から/ 24を取得しますが、 フレックスポッドCIDRを使用してカスタマイズできます。
- サービスレンジ:クラスター内で実行されるクラスターIPサービスに使用されます。
クラスタとサービスのレンジは、ノードのプライマリレンジに対するセカンダリレンジとして構成されます。セカンダリレンジは、クラスターでエイリアスIPを構成するために使用されます。これにより、より良いSDNインテグレーションを実現します。これらの理由により、他の方法を使用せずに、別名IPサブネットを使用することをお勧めします。
gcloud compute networks create gke-no-internet-network \
--subnet-mode custom \
--bgp-routing-mode global
gcloud compute networks subnets create priv-cluster-01 \
--network gke-no-internet-network \
--range 10.10.10.0/24 \
--region us-central1 --enable-flow-logs \
--enable-private-ip-google-access \
--secondary-range services=10.10.11.0/24,pods=10.1.0.0/16
##ファイアウォールのルールを作成する
VPCが作成されたら、それをロックダウンして、インターネットへのあらゆるタイプのアクセスを防止しましょう。デフォルトではすべての出力トラフィックが許可されているため、このトラフィックをブロックするルールを作成する必要があります。
gcloud compute firewall-rules create deny-egress \
--action DENY \
--rules all \
--destination-ranges 0.0.0.0/0 \
--direction EGRESS \
--priority 1100 \
--network gke-no-internet-network
次に、ヘルスチェックを実行するGoogleのIPアドレスへの入力/出力を許可しましょう。これらはGCPがノードが正常にスピンアップしたことを認識し、将来のロードバランサーまたはイングレスサービスのために許可される必要があります。
gcloud compute firewall-rules create allow-healthcheck-ingress \
--action ALLOW \
--rules tcp:80,tcp:443 \
--source-ranges 130.211.0.0/22,35.191.0.0/16 \
--direction INGRESS \
--network gke-no-internet-network
gcloud compute firewall-rules create allow-healthcheck-egress \
--action ALLOW \
--rules tcp:80,tcp:443 \
--destination-ranges 130.211.0.0/22,35.191.0.0/16 \
--direction EGRESS \
--network gke-no-internet-network
また、制限されたGoogle APIのVIPへトラフィックを許可する必要があります。これは、Googleサービスとの通信に使用され、GKE APIと通信するために必要です。
gcloud compute firewall-rules create allow-google-apis-egress \
--action ALLOW \
--rules all \
--destination-ranges 199.36.153.4/30 \
--direction EGRESS \
--network gke-no-internet-network
この次の出力ルールは、GKEワーカーノードから、ステップ#5で作成されるマスターノードへのトラフィックを許可します。クラスターを作成する前にこのルールを作成する必要があります。そうしないと、ワーカーノードがマスターノードに到達できなくなります。ここでは出力ルールのみが必要です。入力ルールは、クラスターの作成中にGCPによって自動的に作成されます。
gcloud compute firewall-rules create allow-master-node-egress \
--action ALLOW \
--rules tcp:443,tcp:10250 \
--destination-ranges 172.16.0.0/28 \
--direction EGRESS \
--network gke-no-internet-network
注:このVPCは現在、0.0.0.0/0へのすべての出力をブロックしています。内部IP空間(10.0.0.0/8、172.16.0.0/20、192.168.0.0/16)に向かうトラフィックには、クラスターがそれらのIPに到達できるようにするための追加の出力ルールが必要になります。
デフォルトルートを削除し、Google APIへのルートを作成する
VPCを作成すると、ネクストホップがdefault-internet-gateway
としてインターネットへのデフォルトルート(0.0.0.0/0)が自動的に作成されます。インターネットへのパスを削除するために、このルートを削除する必要があります。GUIを使用して削除するのが最も簡単です。
次に、VPCでルートを作成して、制限されたGoogle APIサブネットにトラフィックを送信します。プライベートGoogle APIにアクセスするための要件に従って、ネクストホップをdefault-internet-gateway
として設定する必要があります 。
「インターネットゲートウェイ」と言っても、実際にはトラフィックをインターネットに送信しません。サブネットで有効にしたプライベートGoogleアクセス機能のおかげで、トラフィックはGoogle APIへのプライベート内部パスを辿るようにルーティングされます。
gcloud compute routes create google-apis \
--destination-range 199.36.153.4/30 \
--next-hop-gateway default-internet-gateway \
--network gke-no-internet-network
##Google APIおよびGCR.ioのDNSゾーンを作成します
次のステップとして、googleapis.com
のVPCでDNSをカスタマイズします。googleapis.com
はパブリックIPにて解決されるため、restricted.googleapis.com
を使用する必要があります。
このURLは、GCPネットワーク内でアクセス可能な特定の範囲199.36.153.4/30に解決されます(前の手順でルートを作成した範囲と同じです)。GKEワーカーノードを正常に起動するためには、googleapis.com
の代わりにrestricted.googleapis.com
を使用する必要があります。
これは、GCP内のプライベートクラウドDNS機能を使用して実施できます。まず、Cloud DNSでgoogleapis.com
のプライベートゾーンを作成します。
ゾーンが作成されたら、restricted.googleapis.com
を指す* .googleapis.com
のCNAMEレコードを追加します。この作業を行うためにはもう1つのレコード、restricted.googleapis.com
の制限付きVIP IPを指すAレコードが必要です。
gcloud dns managed-zones create google-apis \
--description "private zone for Google APIs" \
--dns-name googleapis.com \
--visibility private \
--networks gke-no-internet-network
gcloud dns record-sets transaction start --zone google-apis
gcloud dns record-sets transaction add restricted.googleapis.com. \
--name *.googleapis.com \
--ttl 300 \
--type CNAME \
--zone google-apis
gcloud dns record-sets transaction add "199.36.153.4" \
"199.36.153.5" "199.36.153.6" "199.36.153.7" \
--name restricted.googleapis.com \
--ttl 300 \
--type A \
--zone google-apis
gcloud dns record-sets transaction execute --zone google-apis
GCR.ioドメインに対して同様の設定を行い、コンテナレジストリに到達するためにトラフィックを制限されたGoogle APIサブネットに送信する必要があります。これらの変更がないと、GKEクラスターは、必要なすべてのコンテナをプルダウンできないため、正常に起動しません。
gcloud dns managed-zones create gcr-io \
--description "private zone for GCR.io" \
--dns-name gcr.io \
--visibility private \
--networks gke-no-internet-network
gcloud dns record-sets transaction start --zone gcr-io
gcloud dns record-sets transaction add gcr.io. \
--name *.gcr.io \
--ttl 300 \
--type CNAME \
--zone gcr-io
gcloud dns record-sets transaction add "199.36.153.4" "199.36.153.5" "199.36.153.6" "199.36.153.7" \
--name gcr.io \
--ttl 300 \
--type A \
--zone gcr-io
gcloud dns record-sets transaction execute --zone gcr-io
GKEクラスターを作成する
ネットワークといくつかのサブネットができたので、プライベートGKEクラスターを作成しましょう。クラスターを作成するときに調整する箇所は多数ありますが、プライベートIPのみを使用してワーカーノードとマスターノードを作成するために必要なものはわずかです。次の設定を確認します。
- VPCネイティブの有効化
- プライベートクラスタノードの有効化
- 外部IPアドレスを使用したマスターへのアクセスを無効化
gcloud beta container clusters create private-gke-cluster \
--zone "us-central1-a" \
--enable-private-nodes \
--enable-private-endpoint \
--master-ipv4-cidr "172.16.0.0/28" \
--enable-ip-alias \
--network "projects/<project_id>/global/networks/gke-no-internet-network" \
--subnetwork "projects/<project_id>/regions/us-central1/subnetworks/priv-cluster-01" \
--cluster-secondary-range-name "pods" \
--services-secondary-range-name "services" \
--enable-master-authorized-networks
#プライベートクラスタがデプロイされました!
すべてがプランどおりに進んだ場合、クラスターはすべてのワークロードとサービスが正常な状態で起動するはずです。この記事の設定で問題が発生した場合は、Twitterでご連絡ください。お手伝いさせていただきます。
#Terraform
本記事の手順をスキップしてすぐに起動したい場合は、次のGithubリポジトリで利用可能なterraform構成ファイルがあります。
翻訳協力
Author: Andrey Kumanov
Thank you for letting us share your knowledge!
記事選定: @takitakis
翻訳/技術監査: @aoharu / @azumana
Markdown化: @aoharu