GKE Autopilot modeをお試しする

### はじめに
こんにちは、いりすです。最近、バーチャル肉体を手に入れたけど直後にPCが壊れて悲しい思いをしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/2ac6bbe5-8a56-03e9-e340-8820cc34f88a.png)

さて、最近、GKEのAutopilot modeがリリースされました。
https://cloud.google.com/blog/ja/products/containers-kubernetes/introducing-gke-autopilot
https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview?hl=ja

従来のnodeのスペックを自分で設定するものと異なり、nodeをgoogleにフルマネージドされたものとなっております。

それまでnode側を意識しなければならなかったGKEの運用がpodのみを考えれば良くなり、エンジニアがアプリケーション開発に注力できるような機能だと感じております。

特に、`GCPUG Tokyo GKE Day March 2021`にて、Autopilot modeが従来のモードとどう違うか、実装の詳細などが解説されており、非常にオススメです。
https://gcpug-tokyo.connpass.com/event/205839/

今回の記事では、GKE Autopilot modeでクラスタを立ててサンプルアプリケーションを構築して、機能お試しをします。

### 流れ
みんな大好きGKEのチュートリアルをautopilot modeでやるよ。
https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=ja

- autopilot modeでclusterを作るよ
- GCRにイメージをpushするよ
- GKEにデプロイするよ
- デプロイしたclusterがどんな感じか見るよ

### GKE Autopilotを試すよ

#### Clusterを作るよ
GCPコンソールのGKEサービス画面にて、クラスタ`作成`ボタンを押下、`標準` or `Autopilot` かを聞かれるので、Autopilotの`構成`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/ad5b8b66-2dd3-af5f-9fac-e90df7e060c1.png)

クラスタ作成時の設定画面が出てきます。standardで存在したノードの設定などがなくなりシンプルになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/0f563b2e-9984-6a03-6640-89de2e0a3241.png)

※ standardとの比較
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/bb46ce3f-b7fb-8180-d753-945deedcdebb.png)

今回はお試しなので、そのまま`作成`を押下します。

GCPへのRESTリクエストはこんな感じで、`autopilot.enable=true` が追加されてます。

```
POST https://container.googleapis.com/v1beta1/projects/[PROJECT_ID]/locations/us-central1/clusters
{
  "cluster": {
    "name": "[cluster name]",
    "masterAuth": {
      "clientCertificateConfig": {}
    },
    "network": "projects/[PROJECT_ID]/global/networks/default",
    "addonsConfig": {
      "httpLoadBalancing": {},
      "horizontalPodAutoscaling": {},
      "kubernetesDashboard": {
        "disabled": true
      }
    },
    "subnetwork": "projects/[PROJECT_ID]/regions/us-central1/subnetworks/default",
    "networkPolicy": {},
    "ipAllocationPolicy": {
      "useIpAliases": true,
      "clusterIpv4CidrBlock": "/17",
      "servicesIpv4CidrBlock": "/22"
    },
    "masterAuthorizedNetworksConfig": {},
    "networkConfig": {
      "enableIntraNodeVisibility": true
    },
    "privateClusterConfig": {},
    "verticalPodAutoscaling": {
      "enabled": true
    },
    "shieldedNodes": {
      "enabled": true
    },
    "releaseChannel": {
      "channel": "REGULAR"
    },
    "clusterTelemetry": {
      "type": "ENABLED"
    },
    "notificationConfig": {
      "pubsub": {}
    },
    "initialClusterVersion": "1.18.12-gke.1210",
    "location": "us-central1",
    "autopilot": {
      "enabled": true
    }
  }
}
```

---

※ `gcloud`コマンドで作成する場合は以下のようになってます。

```bash
gcloud container clusters create-auto [cluster name]
```

---

できた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/0bc6b167-cad6-7b6f-4371-ec88bc9e03ef.png)

### GCRにpush
tutorialの手順に従う
https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=ja

- 事前準備:

```bash
gcloud services enable containerregistry.googleapis.com
gcloud auth configure-docker
```

- pushする

```bash
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/hello-app
export PROJECT_ID=project-id
docker build -t gcr.io/${PROJECT_ID}/hello-app:v1 .
docker push gcr.io/${PROJECT_ID}/hello-app:v1
```

### clusterにデプロイ

consoleで作成したため、ローカルのkubeconfigに登録されてないので、GKE上から取得します。

```bash
gcloud container clusters get-credentials autopilot-cluster-1
kubectl config get-contexts # 確認
```

deploymentの作成

```bash
kubectl create deployment autopilot-cluster-1 --image=gcr.io/${PROJECT_ID}/hello-app:v1
```

最初こんな感じで`Unschedulable`で失敗しますが

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/fde1823b-e770-7b79-faf5-2a2a29e97e26.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/590db0ed-75b3-e634-beea-953960833118.png)

ちょっと待つとOKになります :relaxed:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/64dfcc1e-c67a-d5f6-70a0-55ec7871771c.png)

#### podのwebappの動作確認(kubectl exec, kubectl port-forward)

チュートリアルではこの後browseしますが、そのままだと面白くないので、kubectl execしてrequestを飛ばしてみたり、port forwardingしてアプリを見てみます。

kubectlしてrequestしてみる: 

```
$ wget -O - localhost:8080
Connecting to localhost:8080 ([::1]:8080)
writing to stdout
Hello, world!
Version: 1.0.0
```

port forwardingしてみる: 

```
$ kubectl port-forward pod/autopilot-pod-1-759dc8b678-nzcr6 8080:8080
$ curl localhost:8080
Hello, world!
Version: 1.0.0
Hostname: autopilot-pod-1-759dc8b678-nzcr6
```

うむ。

### デプロイしたclusterがどんな感じか見るよ

まず、GCEを見てみます。

```
$ gcloud compute instances list

NAME        ZONE               MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
instance-2  asia-northeast1-b  e2-micro                   10.0.0.2                  RUNNING
```

standard modeではnodeがGCEに紐づいてましたが、autopilot modeではユーザーの見られない場所に置かれてるようです。（過去に作ったインスタンスしかなかった）

次にnodeを見てみましょう。

```
$ kubectl get node
NAME                                                 STATUS   ROLES    AGE     VERSION
gk3-autopilot-cluster-1-default-pool-59f96323-2tgn   Ready    <none>   3h23m   v1.18.12-gke.1210
gk3-autopilot-cluster-1-default-pool-d800e826-0082   Ready    <none>   17m     v1.18.12-gke.1210
gk3-autopilot-cluster-1-default-pool-d800e826-v0z4   Ready    <none>   3h23m   v1.18.12-gke.1210
```

比較的新しく作成されたnodeを見てましょう

```
kubectl describe gk3-autopilot-cluster-1-default-pool-d800e826-0082
```

labelや、どのくらいリソースが使われてるかといったシステムの情報が見えます。

```
Labels:             addon.gke.io/node-local-dns-ds-ready=true
                    beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=e2-medium
                    beta.kubernetes.io/os=linux
                    cloud.google.com/gke-boot-disk=pd-standard
                    cloud.google.com/gke-netd-ready=true
                    cloud.google.com/gke-nodepool=default-pool
                    cloud.google.com/gke-os-distribution=cos
                    cloud.google.com/machine-family=e2
                    failure-domain.beta.kubernetes.io/region=us-central1
                    failure-domain.beta.kubernetes.io/zone=us-central1-a
                    iam.gke.io/gke-metadata-server-enabled=true
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=gk3-autopilot-cluster-1-default-pool-d800e826-0082
                    kubernetes.io/os=linux
                    node.kubernetes.io/instance-type=e2-medium
                    topology.gke.io/zone=us-central1-a
                    topology.kubernetes.io/region=us-central1
                    topology.kubernetes.io/zone=us-central1-a
...
System Info:
  Machine ID:                 2fb79a32d388c3d0a9d98329351bbc38
  System UUID:                2fb79a32-d388-c3d0-a9d9-8329351bbc38
  Boot ID:                    2926e9e0-eeb2-4a52-bf42-cdc97d5fbd15
  Kernel Version:             5.4.49+
  OS Image:                   Container-Optimized OS from Google
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.4.1
  Kubelet Version:            v1.18.12-gke.1210
  Kube-Proxy Version:         v1.18.12-gke.1210
PodCIDR:                      10.8.0.128/26
PodCIDRs:                     10.8.0.128/26
...
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                   Requests      Limits
  --------                   --------      ------
  cpu                        828m (88%)    600m (63%)
  memory                     2403Mi (85%)  2698Mi (95%)
  ephemeral-storage          1Gi (2%)      1Gi (2%)
  hugepages-2Mi              0 (0%)        0 (0%)
  attachable-volumes-gce-pd  0             0
```

#### nodeのInstanceっぽい場所にping,sshしてみる。

Internal IPの情報があるので、同じネットワークにインスタンスを立ててアクセスしてみましょう。

```
Addresses:
  InternalIP:   10.128.0.5
```

```
$ ping 10.128.0.5
PING 10.128.0.5 (10.128.0.5) 56(84) bytes of data.
64 bytes from 10.128.0.5: icmp_seq=1 ttl=64 time=2.09 ms
64 bytes from 10.128.0.5: icmp_seq=2 ttl=64 time=0.322 ms
64 bytes from 10.128.0.5: icmp_seq=3 ttl=64 time=0.351 ms
64 bytes from 10.128.0.5: icmp_seq=4 ttl=64 time=0.376 ms
64 bytes from 10.128.0.5: icmp_seq=5 ttl=64 time=0.561 ms
64 bytes from 10.128.0.5: icmp_seq=6 ttl=64 time=0.379 ms
64 bytes from 10.128.0.5: icmp_seq=7 ttl=64 time=0.395 ms
64 bytes from 10.128.0.5: icmp_seq=8 ttl=64 time=0.271 ms
64 bytes from 10.128.0.5: icmp_seq=9 ttl=64 time=0.412 ms
^C
--- 10.128.0.5 ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 181ms
rtt min/avg/max/mdev = 0.271/0.572/2.086/0.540 ms
$ ssh 10.128.0.5
...
[user name]@10.128.0.5: Permission denied (publickey).
```

pingは通ったけど、さすがにsshはできなかったｗ

#### `gcloud ssh`してみる

じゃあ、`gcloud ssh`はどうかを試してみます。
network内のすべてのリソースにTCP IAPをONにして、`gcloud ssh`してみましょう。
（なんかインスタンスを閲覧できない時点で無理な気がするけど）

- IAP用のfirewall設定を追加

https://cloud.google.com/iap/docs/using-tcp-forwarding?hl=ja

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/0acc4cca-a173-74ec-8e8c-11382753aa07.png)

普通のインスタンスへは接続できた。

```
$ gcloud compute ssh  instance-3
...
irisu@instance-3:~$
```

nodeにはどうかな？
そもそもインスタンス名とzoneがわからないので、describeにあるかを調べてみます。

```
ProviderID:                   gce://[PROJECT_ID]/us-central1-a/gk3-autopilot-cluster-1-default-pool-d800e826-0082
```

こいつっぽいです。
zoneは`us-central1-a`で、instance名は`gk3-autopilot-cluster-1-default-pool-d800e826-0082`なので、gcloud sshで入ってみましょう。

```
$ gcloud config set compute/zone us-central1-a
$ gcloud compute ssh gk3-autopilot-cluster-1-default-pool-d800e826-0082
ERROR: (gcloud.compute.ssh) Could not fetch resource:
 - The resource 'projects/[PROJECT_ID]/zones/us-central1-a/instances/gk3-autopilot-cluster-1-default-pool-d800e826-0082' was not found
```

ですよねー

### なんか使ってて詰まったところとか

#### そういえば、nodeの権限ってどうなってるの

サービスアカウントを厳しくする（primitive roleはsecurityに引っかかるので、間違って権限を変えたり）と、image pullで失敗した過去があったので、今回も実験してみます。

`Default compute service account`のサービスアカウントをCompute Adminにして、再度deployしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/25ad78c7-0171-7909-d87e-73c177766e35.png)


docker imageを新しくして、deployすることでGCRからpullできなくてpodが作成できなくなるはずです。

```
docker tag gcr.io/${PROJECT_ID}/hello-app:v1 gcr.io/${PROJECT_ID}/hello-app:v2
docker push gcr.io/${PROJECT_ID}/hello-app:v2
kubectl create deployment autopilot-pod-2 --image=gcr.io/${PROJECT_ID
}/hello-app:v2
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/b0dad2c5-9349-e83e-10a2-868a50f61aae.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/c5202e51-f4bc-5262-5578-570e015098cf.png)

nodeを管理しているGCEは`Default compute service account`を使ってるので無闇にいじると変なところで詰まります。
(ここら辺って公式に出てるのかな、だれか知ってたら教えてください :bow:  )

### おわりに

以上になります。

GKEのautopilot modeをお試しするためにチュートリアルをやってみたり、nodelessのnodeを見たり、nodeに乗り込もうとしてdenyされたりしました。

GKE autopilotを使うことで今まで管理していたnodeの管理を考えることなく利用でき、cloud runのように、よりアプリケーションに注力できそうな感じです。

実際に製品としての利用事例としてはPLAID様の事例が非常に参考になります。

https://tech.plaid.co.jp/ml_realtime_inference_with_gke_autopilot/

ただ、nodeがmanagedになったので、今までできたnodeのsysctlとかはできなくなったので、大規模なアプリへの適用などは工夫が必要に思えます。

個人的には内部アプリやお遊びで作るアプリを立てたりする場にカジュアルに使えそうでぜひ導入していきたいです。

あと、terraformで管理したいマンなので、terraform対応が待ち遠しいです。

おしまい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299097/1f0eecb9-3425-c5b0-2177-d8c7ed11ec9f.png)
じゃあねー