Posted at

Google Cloud の Cloud NAT を使って GKE の External IP を固定化してみた


前提


  • GKE は Kubernetes をベースとした Container as a Service です。

  • そのためクラスタには node-pools があり、 pod はこのリソースを使用して起動します。

  • node-pools はスケーリングすることを前提として存在するため、外部と通信するための External IP は変動するものと思った方が良いです。

  • ただそうすると IP アドレスによるアクセス制限をしている外部サービスとの連携に困ります。

  • そこでこれまでなら自力で Gateway サーバーを立ててそれを介して通信するようにしていました。


tl;dr


  • JST 2018-10-11 に Google Cloud / Cloud NAT という NAT サービスがベータリリースされました。

  • これを GKE と連携して使えば解決!


具体的な方法


  1. VPC を作る

  2. サブネットを作る

  3. External Static IP を払い出す

  4. ルーターを作る

  5. Cloud NAT を作る

  6. クラスタを作る

  7. pod 立てて External IP を調べてみる


VPC を作る

$ gcloud compute networks create ${vpc_name}\

--project=${project_id}\
--bgp-routing-mode=regional\
--subnet-mode=custom


  • 変数部分は環境に合わせて指定


  • --bgp-routing-mode


    • global でも良いけど今回はリージョンに閉じた話なので regional




  • --subnet-mode


    • auto は勝手にサブネット作って煩わしいので使わない

    • legacy は古い方式で Cloud NAT とか使えない

    • やりたいことやるだけなら custom で手動設定




サブネットを作る

$ gcloud compute networks subnets create ${subnet_name}\

--project=${project_id}\
--region=${region}\
--network=${vpc_name}\
--range=${subnet_range}


  • 変数部分は環境に合わせて指定



    • --range=${subnet_range} は RFC1918 のお好きな IP 帯




External Static IP を払い出す

$ gcloud compute addresses create ${external_ip_name}\

--region=${region}


  • 変数部分は環境に合わせて指定


ルーターを作る

$ gcloud compute routers create ${router_name}\

--region=${region}\
--network=${vpc_name}\
--asn=65001


  • 変数部分は環境に合わせて指定


  • --asn=65001


    • 自律システム番号(ASN)

    • ネットワーク内で一意な 64512 〜 65534 または 4200000000 〜 4294967294 の範囲で決めろとのこと




Cloud NAT を作る

$ gcloud alpha compute routers nats create ${nat_name}\

--region=${region}\
--router=${router_name}\
--nat-external-ip-pool="${external_ip}"\
--nat-custom-subnet-ip-ranges="${subnet_range}"


  • 変数部分は環境に合わせて指定


  • --nat-external-ip-pool="${external_ip}"



    • --auto-allocate-nat-external-ips で自動払出するか、割り当てる IP を列挙する




  • --nat-custom-subnet-ip-ranges="${subnet_range}"



    • --nat-all-subnet-ip-ranges--nat-primary-subnet-ip-ranges でネットワーク内全てのサブネットまたは primary 全てを範囲とするか、 NAT を使う IP 帯を列挙する




クラスタを作る

$ gcloud container clusters create ${gke_cluster_name}\

--project=${project_id}\
--zone=${zone}\
--network=${vpc_name}\
--subnetwork=${subnet_name}\
--enable-ip-alias\
--enable-private-nodes\
--master-ipv4-cidr=172.16.0.0/28\
--enable-master-authorized-networks\
--master-authorized-networks=0.0.0.0/0\
--no-enable-legacy-authorization\
--no-enable-basic-auth\
--no-issue-client-certificate


  • 変数部分は環境に合わせて指定

  • 細かくは割愛


  • --network=${vpc_name}--subnetwork=${subnet_name} で Cloud NAT の対象サブネットを指定する

  • node-pools が External IP を持っていないことが Cloud NAT を使用する条件なので --enable-private-nodes にする

  • External IP がないと kubectl で操作に困るようなのでマスターエンドポイントへのアクセスを --enable-master-authorized-networks で出来るようにする



    • --master-authorized-networks=0.0.0.0/0 で指定したアクセス元だけ許可される




pod 立てて External IP を調べてみる

$ kubectl run tmp-pod -it --rm --image=${image} -n ${namespace} --restart=Never -- curl httpbin.org/ip

{
"origin": "${external_ip}"
}