Cloud NATが発表されて以降、心待ちにしていたGKEでのセットアップ方法がしれっと公式ドキュメントに追加されていました!!
(いつから公開されていたんでしょうね?自分が気付いてなかっただけとかいうオチもありえますが・・笑)
という訳で、このエントリーではドキュメントを翻訳しながら、実際にKubernetesクラスタを作成していきたいと思います!!ちなみに**Cloud NATがいかに最強か?**という事は下記のエントリーが分かりやすくまとまっているので、一読されることをオススメします。
マネージドNATサービス GCP Cloud NAT がリリースされました - 本日も乙
イントロダクション
このページはCloud NATの設定方法を説明します。Cloud NATをセットアップする前にCloud NAT Overviewも読んでおきましょう。
事前準備
1. IAMパーミッション
roles/compute.networkAdmin ロールは下記の権限を得るために必要です。
- Cloud Router上へのNATゲートウェイの作成
- NAT IPの予約・割り当て
- NATゲートウェイによるIPアドレス変換を適用すべきトラフィックが流れるNATサブネットを指定
2. GCPのセットアップ
- GCPプロジェクトを選択、または作成
- プロジェクトに対して課金が有効になっていることを確認
- Cloud SDKをインストールし、初期化する
今回のチュートリアルのためにk8s-sample-app-20181220
というプロジェクトを作りました。リージョンはasia-northeast1
(東京リージョン)を使います。
# set environment variables
$ PRJ=k8s-sample-app-20181220
$ REGION=asia-northeast1
$ gcloud config set project $PRJ
$ gcloud config list --format='text(core.project)'
core.project: k8s-sample-app-20181220
GKEのセットアップ
Step 1: VPCネットワークとサブネットを作成
既にVPCネットワークとサブネットがあるなら、次のステップに進みましょう。
まずはカスタムモードで新しいVPCネットワークを作成します。
$ NW=custom-network1
$ gcloud compute networks create $NW --subnet-mode custom
NAME SUBNET_MODE BGP_ROUTING_MODE IPV4_RANGE GATEWAY_IPV4
custom-network1 CUSTOM REGIONAL
注意: これはVPCネットワークなので、ネットワークレベルのIPv4アドレスのレンジやゲートウェイIPはありません。
次に、リージョン情報を付けたサブネットを作成しましょう。この例ではasia-northeast1
(東京リージョン)に192.168.1.0/24
のIPアドレスレンジを割り当てます。
$ SUBNW=subnet-asia-northeast1-192
$ gcloud compute networks subnets create $SUBNW \
--network $NW \
--region $REGION \
--range 192.168.1.0/24
NAME REGION NETWORK RANGE
subnet-asia-northeast1-192 asia-northeast1 custom-network1 192.168.1.0/24
Step 2: テスト用に踏み台サーバーを作成
Cloud NATをテストするために、外部IPアドレスを持たないテスト用のVMインスタンスを用意する必要があります。そのインスタンスは外部IPアドレスを持たないため、直接SSHで接続することができません。そこで、まずは外部IPアドレスを持つ踏み台サーバーに接続し、そこから内部IPアドレスを使って目標のインスタンスに接続します。
このステップでは踏み台サーバー用のVMを作成します。(後のステップでテストインスタンスへ接続するために、この踏み台を使います。)
今回はインスタンスのゾーンはasia-northeast1-a
を指定します。
$ ZONE=asia-northeast1-a
$ gcloud compute instances create bastion-1 \
--image-family debian-9 \
--image-project debian-cloud \
--network $NW \
--subnet $SUBNW \
--zone asia-northeast1-a
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
bastion-1 asia-northeast1-a n1-standard-1 192.168.1.2 35.221.81.168 RUNNING
Step 3: プライベートk8sクラスターを作成
enable-private-nodes
を指定することでk8sクラスターをプライベートにできます。
$ gcloud container --project $PRJ clusters create "nat-test-cluster" \
--zone $ZONE \
--username admin \
--cluster-version "1.11.2-gke.26" \
--num-nodes "3" \
--machine-type n1-standard-1 \
--image-type COS \
--disk-type pd-standard \
--disk-size 100 \
--scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" \
--enable-cloud-logging \
--enable-cloud-monitoring \
--enable-private-nodes \
--enable-private-endpoint \
--master-ipv4-cidr 172.16.0.0/28 \
--enable-ip-alias \
--network projects/$PRJ/global/networks/$NW \
--subnetwork projects/$PRJ/regions/$REGION/subnetworks/$SUBNW \
--max-nodes-per-pool "110" \
--enable-master-authorized-networks \
--addons HorizontalPodAutoscaling,HttpLoadBalancing,KubernetesDashboard \
--enable-autoupgrade \
--enable-autorepair
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
nat-test-cluster asia-northeast1-a 1.11.2-gke.26 172.16.0.2 n1-standard-1 1.11.2-gke.26 3 RUNNING
Step 4: SSH接続を許可するためのファイアウォールを作成
$ gcloud compute firewall-rules create allow-ssh \
--network $NW \
--allow tcp:22
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
allow-ssh custom-network1 INGRESS 1000 tcp:22 False
Step 5: ノードへログインし、外部ネットワークから隔離されていることを確認
いずれかのクラスターノード名を取得しましょう。ノード名はgke-nat-test-cluster-default-pool-7d3a845e-c2qf
などです。
$ gcloud compute instances list
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
bastion-1 asia-northeast1-a n1-standard-1 192.168.1.2 35.221.81.168 RUNNING
gke-nat-test-cluster-default-pool-7d3a845e-c2qf asia-northeast1-a n1-standard-1 192.168.1.4 RUNNING
gke-nat-test-cluster-default-pool-7d3a845e-jkt6 asia-northeast1-a n1-standard-1 192.168.1.3 RUNNING
gke-nat-test-cluster-default-pool-7d3a845e-nm15 asia-northeast1-a n1-standard-1 192.168.1.5 RUNNING
Compute EngineのSSHキーをローカルマシンに追加します。
$ ssh-add ~/.ssh/google_compute_engine
踏み台サーバーbastion-1
に接続します。
インスタンスへの初回アクセスの場合はGCPはSSHキーを生成します。
$ gcloud compute ssh bastion-1 --zone $ZONE -- -A
踏み台サーバーからk8sクラスターのいずれかのノード名を指定してSSHで接続します。(この手順だけ公式ドキュメントの"GCLOUD"版で記載漏れがありましたのでご注意を)
ssh gke-nat-test-cluster-default-pool-7d3a845e-c2qf -A
curl
コマンドが入っていればどのノードでも良いのですが、今回はプロンプトからStackdriverエージェント用のコンテナに接続します。
$ docker exec -it $(docker container list | grep stackdriver | awk '{print $1}') /bin/bash
ちなみに、公式ドキュメントではkube-dns
コンテナに入る手順が示されていますが、今回のチュートリアルで使用しているk8sエンジンのバージョン1.11.2-gke.26
ではkube-dns
のコンテナは見つかりませんでした
kube-dnsはCoreDNS
に統合されるらしいので、それが関係していそうです。
CoreDNS is currently a Beta feature in Kubernetes and on course to being graduated to General Availability (GA) for Kubernetes 1.11
Migration from kube-dns to CoreDNS
コンテナ内に入ったら、外部のサイトにアクセスしてみましょう。クラスターがプライベートになっていれば、結果が返って返って来ないはずです。
$ curl example.com
Step 6: Cloud Routerを使ってNATを設定する
次に、Cloud NATを使うインスタンスと同じリージョンにCloud Routerを作成する必要があります。Cloud NATはVM上にNAT情報を保存するためだけに使われます。実際のNATゲートウェイの一部としては使われません。
この設定により、リージョンに属する全てのインスタンスが、プライマリおよびエイリアスIP範囲のためにCloud NATを使うことができるようになります。また、NATゲートウェイのための外部IPアドレスを自動で割り当てます。その他のオプションはgcloud command-line interfaceのドキュメントを参照してください。
注記: Cloud NATはNATの設定情報をグルーピングするためだけにCloud Routerを使います。(コントロール側)Cloud NATはCloud RouterにBGP(Border Gateway Protocol)の利用や、ルーティング追加の命令は出しません。また、NATのトラフィックはCloud Routerを通過しません。(データ側)
Cloud Routerを作成します。
$ gcloud compute routers create nat-router \
--network $NW \
--region $REGION
NAME REGION NETWORK
nat-router asia-northeast1 custom-network1
routerに設定を追加します。
$ gcloud compute routers nats create nat-config \
--router-region $REGION \
--router nat-router \
--nat-all-subnet-ip-ranges \
--auto-allocate-nat-external-ips
Step 7: 再度インターネットアクセスを試行
NAT設定が反映されるのに長いと3分程度かかることもあるため、再度インターネットアクセスを試みる前に少し待つ必要があります。
もし、先程ログインしたコンテナに入ったままなら、再接続を行い、curlコマンドを実行しましょう。
$ curl example.com
<!doctype html>
<html>
<head>
<title>Example Domain</title>
...
...
</body>
</html>
今度はHTMLがレスポンスとして返って来たはずです。
これでプライベートクラスターからNATゲートウェイを経由して外部ネットワークに接続できたことが確認できましたね!!
最後にチュートリアルのプロジェクトを削除しておきましょう。
$ gcloud projects delete $PRJ
以上でチュートリアルは終了です。
まとめ
動作確認のための手順を除くと、非常に少ない設定でGKEにCloud NATを組み込むことができましたね!
Cloud NATが登場するまでは、NATゲートウェイ用のGCEインスタンスを自前で用意して、ルーティング設定を行う必要がありました。この構成では、NATゲートウェイのインスタンスが単一障害点になったり、帯域のボトルネックになったりしていました。しかし、マネージドなCloud NATを使うことで、NATインスタンス自体が無くなり、レイテンシやスループットが安定するようになります。これらの要因で、既存のオンプレや他のパブリッククラウドと組み合わせることに踏み切れなかった方も一度、導入を検討してみてはいかがでしょうか!?
それではCloud NATで快適なクラウドライフを〜!!