概要
GKEで稼働しているサービスで、コスト・パフォーマンス最適化のために昨年末に東京リージョンでGAとなったN4インスタンスへの利用を検討していて、 N4インスタンスに変更する際のハマリポイントを整理します。
マシンタイプの切り替え方法
マシンタイプを切り替える方法は、主に下記2つがあります。
- 既存のNodePoolのマシンタイプを変更する方法
- 新しく使うマシンタイプを設定したNodePoolを新規で作り、kubectl cordon, drainにより旧NodePoolのNodeから段階的にPodを追い出す方法
ここでは、切り替え次の可用性などを考慮して、2番の方法で検証を進めました。
N4に変える際のポイント
N4から、従来のstandardが使えなくなり、ストレージがhyperdiskのみにしか対応しておりません。 https://cloud.google.com/compute/docs/general-purpose-machines?hl=ja#supported_disk_types_for_n4
これに関係して、一部のStatefulSetリソースに関連したPodが起動せず、eventを確認すると下記のエラーが出ていました。
AttachVolume.Attach failed for volume "pvc-hoge" : rpc error: code = InvalidArgument desc = ControllerPublish not permitted on node "projects/dummy/zones/asia-northeast1-a/instances/gke-dummy-instance-abc" due to backoff condition FailedAttachVolume ...
AttachVolume.Attach failed for volume "pvc-hoge" : rpc error: code = InvalidArgument desc = Failed to Attach: failed when waiting for zonal op: rpc error: code = InvalidArgument desc = operation operation-xxx failed (UNSUPPORTED_OPERATION): [pd-standard, n4-standard-4] features are not compatible for creating instance.
設定内容は下記のyamlマニフェストに記載の通りです。
GKEクラスター内で稼働しているStatefulSetが、StatefulSetに紐づくPersistentVolumeClaimでstandardのストレージクラスを設定しており、N4インスタンスでサポートされなくなったことによりPodの起動時にVolumeを割り当てられなくなったことによりエラーが発生していました。
volumeClaimTemplates: - metadata: name: dummy-app-data labels: app.kubernetes.io/name: dummy-app app.kubernetes.io/instance: test app.kubernetes.io/component: dummy-app spec: storageClassName: standard # ここでstandardを指定する accessModes: - ReadWriteOnce resources: requests: storage: 10Gi
StatefulSetリソースの仕組み上、リソースを登録すると、StatefulSetは作成されたPodに紐づくVolumeを作成するためのPersisitentVolumeClaim(PVC)リソースを作成します。
StatefulSetは直接ボリュームを作成するわけではなく、このPVCリソースの情報をもとに、各KubernetesクラスターでサポートされているPersisitentVolume(PV)が作成されます。
StatefulSetの仕組みについては公式ドキュメントをご確認ください。
同様のエラーに対するGoogleCloudのissue Compute VM Instance (n4-standard-16) with attached... - Google Cloud Community
このボリュームのタイプを指定したものがStorageClassというKubernetesのリソースで、各プロバイダーで固有のストレージタイプを定義して割り当てることができます。
GKEにおけるStorageClassの利用については下記のドキュメントを確認ください https://cloud.google.com/kubernetes-engine/docs/concepts/persistent-volumes?hl=ja
standardストレージからhyperdiskへのデータの移行
ここで、N4インスタンスを利用するにあたり、Hyperdiskストレージを使うように設定します。 主な手順は以下の通りです。
- standardストレージのスナップショットを作成
- hyperdiskストレージを作成する際に、スナップショットファイルを指定して起動する
- hyperdisk用のStorageClassを作成する
- 上記のStorageClassを使うようにしたPersistentVolumeリソースを作成する
- 上記のPersistentVolumeに合致するPVCを作成し、Podに割り当てる 既存の永続ディスクを PersistentVolume として使用する | Google Kubernetes Engine (GKE) | Google Cloud
既存のStatefulSetで新しいPersistentVolumeを紐づけるには
StatefulSetの仕様により、稼働済みのStatefulSetに対して上述したvolumeClaimTemplatesを使うように変更することはできません。
そのため、新しいStatefulSetリソースを用意して、volumeClaimTemplatesの設定で新しいStorageClassを指定して作成する必要があります。
詳細は別途記事にまとめます。
まとめ
GKEにおいてN4マシンタイプを利用する際の注意点として下記の問題があります。
- N4インスタンスでは従来のPersistentDiskやローカルSSDを利用できず、Hyperdiskの
Hyperdisk Balanced
というストレージブロックしか利用できない- これに伴い、StatefulSetなど、Volumeにstorageクラスなどを割り当てている場合はPod起動時にボリューム割り当てエラーがでてしまいPodが起動できない
上記の点に対処できれば、それ以外の問題は特になく、以前より新しい世代のcpuを使ったVMへの切り替えにより、クラスターのリソースのコストパフォーマンスを改善できるため、利点が上回るかと思います。
思わぬ問題もあるかもしれないため、当然のことですがマシンタイプ切り替えの際は開発環境などで十分にテストすることが重要です。