前提
- 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 と連携して使えば解決!
具体的な方法
- VPC を作る
- サブネットを作る
- External Static IP を払い出す
- ルーターを作る
- Cloud NAT を作る
- クラスタを作る
- 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 compute routers nats create ${nat_name}\
--region=${region}\
--router=${router_name}\
--nat-external-ip-pool="${external_ip_name}"\
--nat-custom-subnet-ip-ranges="${subnet_name}"
- 変数部分は環境に合わせて指定
-
--nat-external-ip-pool="${external_ip_name}"
- --auto-allocate-nat-external-ips で自動払出するか、割り当てる IP を列挙する
-
--nat-custom-subnet-ip-ranges="${subnet_name}"
- --nat-all-subnet-ip-ranges や --nat-primary-subnet-ip-ranges でネットワーク内全てのサブネットまたは primary 全てを範囲とするか、 NAT を使う IP 帯を列挙する
(2020-01-24) (@zawataki さんからのご指摘) alpha じゃなくなり
--nat-external-ip-pool
--nat-custom-subnet-ip-ranges
の指定方法が変わっていたので更新
クラスタを作る
$ 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}"
}