Cloud NATをGKEで使ってみる

はじめに

こんにちわ!ノハナでGKEをいじいじしている野村と申します。
一緒にGKEをいじいじしたいなと思う方はこちらにお問い合わせくださいネ!
twitterやってるので気軽に話しかけてくださいませ!
@junpayment

〜宣伝終了〜

Cloud NAT

GCP上でのマネージドなNATサービスCloud NATのbetaがリリースされました。

【追記 2018/12/05】
GAになりました!
https://cloud.google.com/nat/docs/release-notes#november_30_2018

弊社ではGKEを導入していることもあり、早速GKE上で試してみようと思いましたが公式にそこまで特化した手順が無いみたいです。
GCEに設置する手順ならあるんですけどねー。

というわけで自分でやってみました!

Cloud NATとは?

GCPのマネージドなNATです。

クラスタ内のアウトバウンドなアクセスのゲートウェイとして設置することができます。
外部サービスへアクセスする際に自ホストの外向けIPアドレスを固定したいなどに使えると思います。

Cloud NATが登場する以前はこんな手順でGCEにNATゲートウェイをデプロイする方法がありましたが、自前でメンテナンスする必要があるためめんどくさかったのです。

Cloud NATを導入することで、マネージドならではの恩恵を受けることができますね!

マネージドならではといえば、Cloud NATは負荷に応じてスケールします。
https://cloud.google.com/nat/docs/overview#cloud_nat_benefits

Cloud NATが適用されるアクセス

Cloud NATが適用されるトラフィックはざっくり下記のような感じです。

  • アタッチしたnetworkのアウトバウンドのトラフィックのみを一括して対象にします
  • VMやk8sのpodのタグ指定とかではなくnetwork(or subnetwork)を一括対象
  • プライベート(External IPを持ってないVM)が対象
  • 独自実装NATを使っている場合は適用外

つまりCloud NATを適用するにはsubnetworkが必要だということです。
また、そのsubnetworkに属するVMはパブリックIPを持っていてはいけません。

Cloud NATを使うにあたって満たすべきGKE側の要件

上記を踏まえてGKE側ではどんな要件を満たすべきなのか書いてみます。

  • Cloud NATがアタッチされたnetwork and subnetwork を使用すること
  • External IPを持たないnodeを持つこと

k8sのnodeにExternal IPを持たせないためには、対象クラスタをprivate clusterに設定する必要があります。
private cluster

ポイント
private clusterにした場合、k8sのapiサーバもプライベートになるので、踏み台などを経由したりしない限りは、気軽にkubectlを実行することができなくなり、日常のオペレーションに支障をきたす恐れがあります。

そのため、マスターノードをpublicに晒すということを後述します。

手順onGKE

Cloud NAT側の用意

公式の手順に法ってnetwork, subnetwork, router, natまで作る
https://cloud.google.com/nat/docs/using-nat

なので下記を実施
Step 1: Create a VPC network and subnet

gcloud compute networks create custom-network1 \
    --subnet-mode custom
gcloud compute networks subnets create subnet-us-central-192 \
   --network custom-network1 \
   --region us-central1 \
   --range 192.168.1.0/24

Step 6: Create a Cloud Router

gcloud alpha compute routers create nat-router \
    --network custom-network1 \
    --region us-central1

Step 7: Add a NAT configuration to the Cloud Router

gcloud alpha compute routers nats create nat-test-config \
    --router-region us-central1 \
    --router nat-router \
    --nat-all-subnet-ip-ranges \
    --auto-allocate-nat-external-ips

すでに取得しているstaticなExternal IPを指定する場合はこちら

gcloud alpha compute routers nats create nat-test-config \
    --router-region us-central1 \
    --router nat-router \
    --nat-all-subnet-ip-ranges \
    --nat-external-ip-pool=external-ip-hoge

ここまで設定したらこんな感じになってるはず。

GKE環境を作る

作ったnetwork, subnetworkに属したGKEクラスタを作成します。

デフォルトと違う項目は下記の通りです。

  • Region, network, subnetworkは前手順で作ったCloud NATのものを設定
  • Private clusterにチェック

private cluster だとデフォルトだと外から一切マスターノードにアクセスできなくなります。
そのため、下記設定でアクセス可能にします。

おそらく、踏み台経由で kubectl しますよとかいう人には不要

  • Access master using.... にチェック
    • Master IP rangeRFC 1918な任意のCIDRを設定
  • Enable master authorized... にチェック
    • Name は任意。Networkに任意のアクセス元ホストのCIDRを設定

      アクセス元の制限をしない場合は0.0.0.0/0を設定。
      IAMで制御する方が利便性とセキュリティを同時に確保できるのとで僕個人的にはこちらがオススメです。外部CIツールなどと連携する際も便利です。

コンソールの設定画面

ここまで設定すればこのようになっていると思います。

疎通確認

適当なイメージをデプロイして確認します。

gcloud beta container clusters get-credentials cluster-3 --region us-central1 --project lotus-production
kubectl run example --restart=Never --image centos:7 -- sh -c "while true; do  sleep 1000; done"
kubectl get po
NAME      READY     STATUS    RESTARTS   AGE
example   1/1       Running   0          1h

作ったpod上で自分の外向けIPを取得するサイトに向けてcurlします。

kubectl exec -it example curl httpbin.org/ip
{
    origin: 35.188.94.3
}

static ip指定してない場合
ここで取得したIPがVPC -> External IPに存在しないことを確認したらOK

static ip指定している場合
ここで取得したIPが想定のものであることを確認したらOK

手順は以上です。お疲れ様でした!

気になるところ

まだbetaなので、ちょいちょい気になるところがあります。
僕が気になったのは、アタッチしたはずのExternal IPがin use by: Noneになっているんですよね。

間違って別のものにアタッチしないように気をつけたりしましょうね!

それでは良いコンテナライフを!