マルチゾーンのPrivate GKEクラスターを作成してNodePortにLBからつないで公開

慣れたら全部で30分かからないぐらいかな。といってもほぼ待ち時間で、GKEの生成を待ってるのに5分ぐらいで、最後の証明書の生成の待ち時間が15分ぐらい。

## 前置き

Private GKEクラスターを立ててみる。まだ、ちゃんとProductionレベルで動かすような設定は勉強してないので、とりあえずおもちゃみたいな気分で。

GCP周りの操作はgcloudとかTerraformとかを使えば良さそうだなーとは思うけど、今回はGUIでやってみることにする。Terraformとかはまた別で勉強しとく。

LoadBalancerはk8sからはコントロールせずに自分で作ろうと思う。なのでk8sはNodePortまでにしておく。LBのライフサイクルはk8sから切り離して考えたいなと思って。

SSLの証明書はGoogleに管理してもらう。

## 準備

  • プロジェクトを適当な名前で新しく作成した buffering-20190901。最後にプロジェクトごと削除したいから。
  • Google Cloud SDKがインストールされてる(gcloudとkubectl使う)
  • 課金を有効にしてる

## 手順

こうかな。

  1. VPCを作る
  2. GKEを作る
  3. Cloud NATを設定する
  4. サンプルアプリをGKEにデプロイする
  5. LoadBalancer用にFirewallを設定する
  6. LoadBalancer用にStatic IPを作成する
  7. Cloud LoadBalancerを作る

## 1. VPCを作る

デフォルトで作成されてるVPCは使わないので削除した。新しく my-vpc って名前のVPCを作成して、Custom Subnetを東京リージョンに作った。Private Google AccessはOnにしておいた。

f:id:bufferings:20190901085858p:plain

## 2. GKEを作る

Highly available のテンプレートから作った。

f:id:bufferings:20190901094106p:plain

  1. 左側から「Highly available」のテンプレートを選択
  2. 名前を my-gke にした
  3. Regionが us-central1 になってるので asia-northeast1 にした
  4. Number of nodes (per zone)が 3 になってるので 1 にした。合計で3台動くことになる
  5. 下の方にある「Availability, networking, security, and additional features」の部分をクリックして広げて
    1. さっき作成したVPCが選ばれてることを確認
    2. 「Private cluster」にチェックを入れた
    3. 「Master IP range」には 172.16.0.0/28 を入れておいた
    4. 「Enable master authorized networks」に、Masterへのアクセスを許可するIPを設定した方が良いとは思うんだけど、今回は別にいっかと思ってチェックを外しておいた。
    5. 「Stackdriver」の「Enable Stackdriver Kubernetes Engine Monitoring」をチェックしておいた(分かってない)
  6. 「Create」をクリック

これで、5分くらい待てばRegionalでAutoscalingなPrivateクラスターができる。

  • Regionalだと、MasterもNodeも複数Zoneに分散した構成になる。
  • Autoscalingを有効にすると、NodeのCPU使用率とかによって自動でScale Out/InしてくれるNodePoolになる。
  • Privateクラスターは、NodeにGlobalIPを持たせないので外部からのアクセスができない。MasterはGoogleのネットワーク側で管理されていて、外部からのアクセスが可能。

Privateクラスターだと、NodeがGlobalIPを持っていないので、このままだとNodeから外部へのアクセスもできない。ので、Cloud NATを設定する。

## 3. Cloud NATを設定する

東京リージョンを選んで作成する。Cloud Routerがコントロールプレーンとして必要らしいので作成する。

f:id:bufferings:20190901094746p:plain

## 4. サンプルアプリをGKEにデプロイする

これで、GKE上にアプリをデプロイできるので、サンプルアプリをデプロイする。サービスは最初に書いたとおり、NodePortにする。

gcloudでログイン

$ gcloud auth login

GKEのクレデンシャルを取得。リージョンやプロジェクト名は gcloud config で設定してもいい。

$ gcloud container clusters get-credentials my-gke \
    --region asia-northeast1 --project bufferings-20190901

これでkubectlがGKEにつながるようになる。

$ kubectl get node
NAME                                       STATUS   ROLES    AGE   VERSION
gke-my-gke-standard-pool-1-6f5f83d6-vzxn   Ready    <none>   55m   v1.12.8-gke.10
gke-my-gke-standard-pool-1-7cec640a-790g   Ready    <none>   55m   v1.12.8-gke.10
gke-my-gke-standard-pool-1-978f3a3c-6dbc   Ready    <none>   55m   v1.12.8-gke.10

サンプルのアプリをデプロイする。ファイル名は my-nginx.yaml でいいかな。NodePortには 31380 を指定しといた。自動でアサインしても問題ない。

apiVersion: v1
kind: Service
metadata:
  name: my-nginx-service
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    nodePort: 31380
    port: 8080
    targetPort: 80
  selector:
    app: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deployment
spec:
  selector:
    matchLabels:
      app: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

これを適用して

$ kubectl apply -f my-nginx.yaml
service/my-nginx-service created
deployment.apps/my-nginx-deployment created

作成されてることを確認したら

$ kubectl get svc,po
NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes         ClusterIP   10.201.0.1     <none>        443/TCP          43m
service/my-nginx-service   NodePort    10.201.1.148   <none>        8080:31380/TCP   9s

NAME                                       READY   STATUS    RESTARTS   AGE
pod/my-nginx-deployment-5796dcf6c4-bxjw8   1/1     Running   0          9s
pod/my-nginx-deployment-5796dcf6c4-rz87d   1/1     Running   0          8s

Port Forwardingで確認しておく

$ kubectl port-forward svc/my-nginx-service 8888:8080
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80

これで、localhost:8888をブラウザで開くとnginxにつながる。

f:id:bufferings:20190901103304p:plain

## 5. LoadBalancer用にFirewallを設定する

k8s側でNodePortじゃなくてLBサービスを使えばFirewallも自動で設定してくれるんだけど、自分でLBを作るのでFirewallも自分で設定する必要がある。

### LB → NodePort

さっきNodePortを 31380 にしたからそこへのアクセスを許可する。

次のページに書いてあるように、LBからのアクセスは 130.211.0.0/2235.191.0.0/16 のレンジからのアクセスを許可する。

https://cloud.google.com/load-balancing/docs/https/#firewall_rules

TargetのTagは、既にGKE生成時に自動的に作成されている設定と同じものを入れておいた。

f:id:bufferings:20190901105035p:plain

### LB → Health Check

それともうひとつ、LBからNodeへのHealthCheckを許可しないといけない。これは各Nodeのポート 10256 でパスが /healthz で動いてるので、そこを通す。NodePortのやつに混ぜても良かったんだけど、別で作っておいた。

f:id:bufferings:20190901105618p:plain

## 6. LoadBalancer用にStatic IPを予約する

LB用なのでRegionalじゃなくてGlobalで予約する。

f:id:bufferings:20190901112812p:plain

「Reserve」ボタンを押すとIPが予約される。

今回僕が予約できたのは 35.244.157.110 だったので、これをLBから使う。LBを作成するときにHTTPSアクセスのための証明書を自動設定したいので、自分で持ってるドメインに登録しておく。

my-gke.shiiba.dev でこのIPアドレスを登録しておいた。

$ nslookup my-gke.shiiba.dev
Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
Name:   my-gke.shiiba.dev
Address: 35.244.157.110

## 7. Cloud LoadBalancerを作る

ということで、最後にLBを作る。種類は「HTTP(S) Load Balancing」

f:id:bufferings:20190901113700p:plain

LBはBackend、Rule、Frontendの3つの設定があって、Frontendがリクエストをインターネットから受ける部分、それをRuleで処理して、Backendに流す、という感じ。

BackendにGKEのNodePortを設定して、FrontendでSSLの設定をする。Ruleは特に設定せずに受けたリクエストを全部GKEに流すことにする。

### Backend

対象はInstance Groupで、PortはNodePortに指定した 31380

f:id:bufferings:20190901115243p:plain

Regional Clusterにしたので、各ZoneにInstance Groupが作られてる。なので、各ZoneのInstance Groupに対して同じ設定をする。

Backendに対するHealthCheckは新規作成する。これがPort 10256 で、パスが /healthz

f:id:bufferings:20190901115500p:plain

### Frontend

HTTPSのフロントエンドを作成する。IPアドレスには、さっき予約したIPアドレスを指定する。

f:id:bufferings:20190901120119p:plain

Certificateの部分で「Create a new certificate」を選んで、証明書の作成と管理をGoogleにやってもらうようにする。

f:id:bufferings:20190901120315p:plain

ドメインの部分にさっき設定しておいた my-gke.shiiba.dev を指定しておいた。これで「Let's Encrypt」の証明書発行などをGoogleがやってくれる。

### Create

全部終わったら、Createボタンを押して15分ぐらい待つ。LBが作成されて、証明書のStatusがACTIVEになってから、5分ぐらい待つと、つながるようになる。

f:id:bufferings:20190901122231p:plain

(∩´∀`)∩ワーイ

## プロジェクトを削除

楽しんだら忘れずにプロジェクトとDNSの設定を削除しておしまい!