Kubernetesについては、AWSではEKS、オンプレではkubeadmを使ってきましたが、そういえばGKEは一度も使ったことがない。ということで、少し触ってみました。
目次
クラスタの作成
GCPのコンソールから、"Kubernetes Engine" -> "クラスタ"をクリック。
初回の場合はAPIを有効化します。
"作成"をクリック。
クラスタの作成には2種類の方法があります。"GKE Autopilot"は、worker nodeをGCP側で管理してくれて勝手にスケーリングなどが行われるというようなものみたい。EKS Fargetみたいな感じですかね(Fargate触ったことないし、知らんけど)。とりあえず"GKE Standard"を選択します。
ここから作成するクラスタの設定を行っていきます。今回はあまり細かい設定は行わずにほぼデフォルトでクラスタ作って試してみるつもりなのですが、どのような設定項目があるのかは順に見ていきたいと思います。
クラスタの基本
まず、基本設定となる”クラスタの基本”。
”クラスタの基本”では、
- クラスタ名
- ロケーション(ゾーン、リージョン)
- コントロールプレーンのバージョン
が指定できます。コントロールプレーンは、バージョン指定か、Googleのリリースチャンネルで指定できるみたい。
各リリースチャンネルごとのリリーススケジュールやサポートポリシーはこちら。
あと、右にあるクラスタセットアップガイドを使うと、それぞれの用途のおすすめの設定でクラスタ設定がカスタマイズされるみたい。今回は使わないけど。
ノードプール
次にノードプール。左のメニューから"default-pool"をクリックします。
ノードプールは、EKSでいうノードグループと同じもの。デフォルトで、クラスタに必ず1つ作成されます。"default-pool"はデフォルトの名前ってことですね。ここでは、
- ワーカーノードのノード数
- 自動スケーリング
- 自動アップグレード・修復
などが設定できる。"自動アップグレード"、"自動修復"はグレーアウトしてるけど、コントロールプレーンのバージョン指定で"リリースチャンネル"を指定している場合は必須で、"静的バージョン"を指定している場合にOFFにもできるみたい。まあ"静的バージョン"を選択するぐらいなので、自動でアップグレードされたら困るということですね。"自動修復"は基本的にOFFにすることはないだろうけど。
ノード
ノードプールはさらにサブメニューがあります。まず"ノード"。
ここはワーカーノードとなるGoogle Compute Engineのインスタンスの指定ですね。
- インスタンスイメージの種類
- インスタンスのマシンタイプ(CPU/メモリ)
- ディスクサイズ
- プリエンプティブルノードの有効・無効
- 1ノードあたりのPod数
あたりが設定できる。Kubernetesとして特に重要そうと思ったのは、"イメージの種類"、"1ノードあたりのPod数"あたりかな。
"イメージの種類"では、
- cos
- コンテナランタイムとしてDockerを使う、コンテナ最適化OS
- cos_containerd
- コンテナランタイムとして containerd を使う、コンテナ最適化OS。デフォルト。
- ubuntu
- コンテナランタイムとして Docker を使う。OSはUbuntu
- ubuntu_containerd
- コンテナランタイムとして containerd を使う。OSはUbuntu
あたりが選べるようです。書いてないけどWindowsコンテナも使えるみたい。
"1PodあたりのPod数"は"110"が最大みたいで、これ以上増やすことはできなかった。
オーバーライドできるとあるけど、多分減らすほうにってことかな。EKSだとEC2インスタンスタイプでこのあたりは決まるので、より大きいインスタンスタイプを選択すれば増やすことができるんだけど、マシンタイプ変えても変わらなかった。小さいマシンタイプでたくさんのPodを上げてもしょうがない気もするけど、小さなPodがたくさん必要になるようなケースで大きいマシンタイプを選ばざるを得なくてリソース無駄、ということを考えるとどっちもどっちかなという気がする。
セキュリティ
"セキュリティ"では、サービスアカウントの設定とノードの保護を行えるみたい。ただし、ここで言うサービスアカウントはKubernetesのサービスアカウントじゃなくて、GCPのサービスアカウントっぽい。なのでEKSだとノードとなるインスタンスに割り当てるIAMロールに近いと思う。IAM Roles for Service Accounts みたいなものはたぶんWorkload Identityというやつかな?
メタデータ
"メタデータ"は、その名の通り、メタデータの設定です。ラベルやtaintなどのメタデータを設定できます。
クラスタの詳細設定
ここからはクラスタのより詳細な設定です。この辺はサラッと。
自動化
"自動化"は、アップデートやメンテナンスやスケジュールウインドウを設定したりする感じですね。あとは、スケールアップ・スケールアウトあたり。
ネットワーキング
"ネットワーキング"は、VPC周りの設定など。Node Local DNSCacheの有効化とかもここで出来ちゃうみたい。
セキュリティ
Cloud KMSを使ったsecretの暗号化とか。Workload Identityもここで有効にできるみたいですね。
メタデータ
ここはGCPにおけるメタデータ、つまりAWSのタグと同じようなものだと思う。
特徴量
"特徴量"っていうこの名前、全然ピンとこないけど、主に他の機能と連携するような部分って感じがする。
- Cloud Logging/Cloud Monitoringなどの有効有無
- Copute Engine永続ディスクのCSIドライバの有効有無
あたりはデフォルトでオンになってるみたいですね。
クラスタを作成してみる
とりあえず、今回はお試しなので、"クラスタの基本”で、
- クラスタ名を適当に。今回は"demo-cluster-01"にします。
- ロケーション。東京リージョンのゾーンのうち一つを選択、今回は、"asia-northeast-1a"を選択。
だけを設定して一番下の「作成」をクリックします。
クラスタ作成中です。ちょっと時間がかかります。
できました。
クラスタへの操作
クラスタへの操作はCloud Shellを使います。
ためしにkubectlを叩いてみます。
$ which kubectl /usr/bin/kubectl $ kubectl get node The connection to the server localhost:8080 was refused - did you specify the right host or port?
ということでCloud Shell側には何も設定されていませんね。クラスタにアクセスするための認証情報を取得します。
$ gcloud container clusters get-credentials demo-cluster-01 --zone asia-northeast1-a
実行すると以下のように承認が求められますので、承認します。
認証情報が取得されて、kubeconfigの設定が行われたようです。
Fetching cluster endpoint and auth data. kubeconfig entry generated for demo-cluster-01.
ではkubectlを実行してみましょう。
$ kubectl config get-clusters NAME gke_sample-e2d18_asia-northeast1-a_demo-cluster-01 $ kubectl get node NAME STATUS ROLES AGE VERSION gke-demo-cluster-01-default-pool-aae0737e-cnfl Ready <none> 16m v1.20.9-gke.701 gke-demo-cluster-01-default-pool-aae0737e-jgn2 Ready <none> 16m v1.20.9-gke.701 gke-demo-cluster-01-default-pool-aae0737e-qn5p Ready <none> 16m v1.20.9-gke.701 $ kubectl get all --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system pod/event-exporter-gke-67986489c8-w2bv2 2/2 Running 0 17m kube-system pod/fluentbit-gke-656xn 2/2 Running 0 17m kube-system pod/fluentbit-gke-8pvzp 2/2 Running 0 17m kube-system pod/fluentbit-gke-kxxhs 2/2 Running 0 17m kube-system pod/gke-metrics-agent-9fkqh 1/1 Running 0 17m kube-system pod/gke-metrics-agent-9pg8j 1/1 Running 0 17m kube-system pod/gke-metrics-agent-j5nb8 1/1 Running 0 17m kube-system pod/kube-dns-autoscaler-844c9d9448-7fl8m 1/1 Running 0 17m kube-system pod/kube-dns-b4f5c58c7-9rkgx 4/4 Running 0 17m kube-system pod/kube-dns-b4f5c58c7-dk664 4/4 Running 0 17m kube-system pod/kube-proxy-gke-demo-cluster-01-default-pool-aae0737e-cnfl 1/1 Running 0 17m kube-system pod/kube-proxy-gke-demo-cluster-01-default-pool-aae0737e-jgn2 1/1 Running 0 16m kube-system pod/kube-proxy-gke-demo-cluster-01-default-pool-aae0737e-qn5p 1/1 Running 0 17m kube-system pod/l7-default-backend-56cb9644f6-9rwvr 1/1 Running 0 17m kube-system pod/metrics-server-v0.3.6-9c5bbf784-ntxgs 2/2 Running 0 16m kube-system pod/pdcsi-node-7rg44 2/2 Running 0 17m kube-system pod/pdcsi-node-8pb8b 2/2 Running 0 17m kube-system pod/pdcsi-node-qqwtr 2/2 Running 0 17m kube-system pod/stackdriver-metadata-agent-cluster-level-658b89df-7hzbb 2/2 Running 0 17m NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default service/kubernetes ClusterIP 10.76.0.1 <none> 443/TCP 18m kube-system service/default-http-backend NodePort 10.76.10.142 <none> 80:31187/TCP 17m kube-system service/kube-dns ClusterIP 10.76.0.10 <none> 53/UDP,53/TCP 17m kube-system service/metrics-server ClusterIP 10.76.10.52 <none> 443/TCP 17m NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system daemonset.apps/fluentbit-gke 3 3 3 3 3 kubernetes.io/os=linux 17m kube-system daemonset.apps/gke-metrics-agent 3 3 3 3 3 kubernetes.io/os=linux 17m kube-system daemonset.apps/gke-metrics-agent-windows 0 0 0 0 0 kubernetes.io/os=windows 17m kube-system daemonset.apps/kube-proxy 0 0 0 0 0 kubernetes.io/os=linux,node.kubernetes.io/kube-proxy-ds-ready=true 17m kube-system daemonset.apps/metadata-proxy-v0.1 0 0 0 0 0 cloud.google.com/metadata-proxy-ready=true,kubernetes.io/os=linux 17m kube-system daemonset.apps/nvidia-gpu-device-plugin 0 0 0 0 0 <none> 17m kube-system daemonset.apps/pdcsi-node 3 3 3 3 3 kubernetes.io/os=linux 17m kube-system daemonset.apps/pdcsi-node-windows 0 0 0 0 0 kubernetes.io/os=windows 17m NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE kube-system deployment.apps/event-exporter-gke 1/1 1 1 17m kube-system deployment.apps/kube-dns 2/2 2 2 17m kube-system deployment.apps/kube-dns-autoscaler 1/1 1 1 17m kube-system deployment.apps/l7-default-backend 1/1 1 1 17m kube-system deployment.apps/metrics-server-v0.3.6 1/1 1 1 17m kube-system deployment.apps/stackdriver-metadata-agent-cluster-level 1/1 1 1 17m NAMESPACE NAME DESIRED CURRENT READY AGE kube-system replicaset.apps/event-exporter-gke-67986489c8 1 1 1 17m kube-system replicaset.apps/kube-dns-autoscaler-844c9d9448 1 1 1 17m kube-system replicaset.apps/kube-dns-b4f5c58c7 2 2 2 17m kube-system replicaset.apps/l7-default-backend-56cb9644f6 1 1 1 17m kube-system replicaset.apps/metrics-server-v0.3.6-57bc866888 0 0 0 17m kube-system replicaset.apps/metrics-server-v0.3.6-886d66856 0 0 0 17m kube-system replicaset.apps/metrics-server-v0.3.6-9c5bbf784 1 1 1 16m kube-system replicaset.apps/stackdriver-metadata-agent-cluster-level-55bf669657 0 0 0 17m kube-system replicaset.apps/stackdriver-metadata-agent-cluster-level-658b89df 1 1 1 17m
クラスタでnodeが3台、その上でいろいろなpodが動いているのがわかりますね。
podを立ててみる。
ではpodを立ててみます。以下のマニフェストで。
$ kubectl apply -f https://gist.githubusercontent.com/kun432/e29dd1c14f28806ed3acb1f6c66322c1/raw/e09fcd368634377485d2d9cd92ed14131ba793b3/sample-deployment.yaml deployment.apps/bootcamp-deployment created $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES bootcamp-deployment-8d6697479-mpszh 1/1 Running 0 2m11s 10.72.0.6 gke-demo-cluster-01-default-pool-aae0737e-jgn2 <none> <none> bootcamp-deployment-8d6697479-n8755 1/1 Running 0 2m12s 10.72.0.5 gke-demo-cluster-01-default-pool-aae0737e-jgn2 <none> <none> bootcamp-deployment-8d6697479-rgkbr 1/1 Running 0 2m11s 10.72.1.4 gke-demo-cluster-01-default-pool-aae0737e-cnfl <none> <none> $ kubectl get deployment -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR bootcamp-deployment 3/3 3 3 2m41s bootcamp gcr.io/google-samples/kubernetes-bootcamp:v1 app=bootcamp
ローカルでアクセスできるか確認してみましょう。gcloudのプレビュー機能とkubectl port-forwardを使うとコンソールからWebアクセスをかんたんに試せます。Cloud Shellの以下のアイコンをクリックするとメニューが表示されます。
デフォルトだと8080で待ち受けてpodに流すようになっているようです。今回使っているkubernetes-bootcampのpodはport8080で待ち受けるようにハードコードされてるのでこうなります。
$ kubectl port-forward deployment/bootcamp-deployment 8080:8080 Forwarding from 127.0.0.1:8080 -> 8080
この状態で、プレビュー機能から"ポート8080でプレビュー"をクリックします。
ブラウザの別タブが立ち上がって、podにアクセスできてるのがわかりますね。
serviceを立ててみる
クラウドにおけるKubernetesマネージドサービスの良さはクラウドの機能と連携できるところですが、特にLoadBalancer Serviceが使えることだと思っています。以下のマニフェストを適用してみます。
適用してみます。
$ kubectl apply -f https://gist.githubusercontent.com/kun432/d94323661719fc06e13e1e75f7e91848/raw/2698bbdc94b1820efb4c0bc3fbfd8dc4e9a16acb/bootcamp-service.yaml service/bootcamp-service created $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE bootcamp-service LoadBalancer 10.76.3.220 <pending> 8888:30080/TCP 6s kubernetes ClusterIP 10.76.0.1 <none> 443/TCP 106m
作成したサービスのEXTERNAL-IPが"pending"になっていますが、しばらく待つとこうなります。
$ kubectl get serviceNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE bootcamp-service LoadBalancer 10.76.3.220 XXX.XXX.XXX.XXX 8888:30080/TCP 49s kubernetes ClusterIP 10.76.0.1 <none> 443/TCP 107m
XXX...にはグローバルなIPアドレスが付与されていると思います。これにさきほどのserviceのマニフェストにあるspec.ports[].port
で指定しているポート8888を付与してブラウザでアクセスしてみましょう。
GCPのリソースはどうなっているかも確認してみましょう。メニューから、"ServicesとIngress"をクリックすると、LoadBalancerが起動してグローバルIPアドレスが割り振られているのがわかると思います。
service名をクリックするとより詳細な情報が見れます。serviceのCluster IPも見えますし、紐付いているdeploymentやpodも見えますね。
まとめ
一通り触ってみましたが、とてもわかりやすいですね。Kubernetesのマネージドサービスは以前はGKE一択と言われてたのも納得できますね。仕事で使うことはなさそうですが、これからKubernetesをはじめる、クラウドでやってみたい、という場合にはGKEのほうがわかりやすいのではないでしょうか。あくまでも個人の印象ですが。