コラム
EBS CSI driverをEKSアドオンとして導入してみた
-
TAG
EKS -
UPDATE
2022/09/27
こんにちは。DX事業部の宮國です。
EBS CSI driver関連のアップデート状況は
EBS CSI driverを試す前に、なぜEKSでAWSのストレージサービスを組み合わせたくなるのか、おさらいしてみたいと思います。
Pod(Kubernetesにおけるコンテナの最小実行単位・1つ以上のコンテナで構成)は、Pod内にディスク領域を持ちますが、一時的なものであるためPodの削除と同時にデータは消失してしまいます。
hostpathを使ってノードのボリュームにデータを保持するという考え方もありますが、ノード自体も破棄可能なものとしてとらえるのが自然ですし、
永続化が必要なデータに関しては、Kubernetesクラスタとは分離してデータを保存することが望ましいです。
したがって、外部ストレージと連携した永続ボリュームを利用したくなります。
- StorageClass(SC)
- PVの作成に使用するためのストレージの仕様を定義するリソース
- ※Provisionerで、どのボリュームプラグイン(ボリュームを作成、管理するための拡張機能)を使うか定義する。
- PersistentVolume(PV)
- 永続ボリュームを表すリソース
- PersistnetVolumeClaim(PVC)
- 永続ボリュームの割り当てを要求するリソース
これらを適切に定義することによって、外部のストレージサービスから永続ボリュームを切り出します。
StorageClassで利用可能なProvisionerは多種多様ですが、EKSを利用していると、AWSのストレージサービスを使いたくなります。
ノードとして利用しているEC2にアタッチするストレージとしてはEBS、EFSが代表的です。
AZに限定されず、何かと使い勝手が良いEFSをプロジェクトでは利用しているのですが、今回はEBSの記事なので、ここからは便宜上、EBSの話に絞っていきます。
KubernetesからEBSを利用したい。というニーズは大分前からありました。
そのため、EBSを利用するためのボリュームプラグインはin-tree(コードロジックがKubernetesに組み込まれる形で開発)で開発されてきました。(kubernetes.io/aws-ebs)
しかし、現在(2022/9)は、このin-treeのボリュームプラグインを利用することは推奨されていません。※EKS Kubernetes 1.23を利用している場合、CSIMigrationAWS機能が有効になっているため、利用することはないはずです。
Podから永続ボリュームとしてEBSを利用する場合、EBS CSI driverが必要になってきます。
CSIとは
CSIという言葉を前置きなしに使っているので、CSIについても軽く触れます。
CSI(Container Storage Interface)は、Kubernetesなどのコンテナオーケストレーションと、任意のブロックおよびファイルストレージシステムを繋ぐための標準化されたインタフェースです。
先ほどEBS用のプラグインがin-treeで開発されていたことについて触れた通り、かつてKubernetesで永続ボリュームを提供するための、ストレージのProvisioner毎のコードは、Kubernetesプロジェクトのコードに含まれていました。
しかしこの状態では、ストレージプラグイン開発者がボリュームプラグインのバグを修正したいだけでも、Kubernetesのリリースプロセスに合わせる必要がある。リリースが複雑になる。といった問題を抱えていました。
CSIが登場し、Kubernetesで利用可能になったことで、ストレージプラグイン開発者がKubernetesのソースに組み込まずにストレージ関連の機能を実装し、機能を提供することが可能となりました。
CSIに準拠したdriverは、ベンダや機種ごとにストレージの仕様が異なっていても、統一的なマニフェストファイルの書き方で利用できるようになっています。
EBS CSI driverも、
EKSからEBSを利用する場合、このEBS CSI driverを使う必要があります。
EKSアドオンとは
前置きがとても長いことを自覚しています。最後にEKSアドオンについて触れさせてください。
用語の説明、歴史の振り返りがないと、なぜEBS CSI driverをEKSアドオンで入れたくなるのかわからないと思ったからです。
現時点(2022/9)では以下のアドオンが対応しています。
- Amazon VPC CNI plugin for Kubernetes
- CoreDNS
- kube-proxy
- ADOT
- Amazon EBS CSI
実際の所、EKSをプロジェクトで利用しようと思うと、ロードバランサを使いたい、ノードをスケーリングしたい、ファイルシステムを使いたい、監視用のメトリクスサーバやagentを入れたい。などなどのニーズから色々なアドオンを入れたくなります。
これらのアドオンを入れてメンテナンスするためには、それぞれのアドオンのGitHubリポジトリを覗いてインストールし、リリースノートを確認し、マニフェストファイルを管理していく必要があります。
デフォルトの状態から何か値をいじるのであれば、差分を管理していく必要もあります。
AWSのリソースに対して何か指示をするのであれば、IAMポリシーを定義する必要がありますし、途中で必要なポリシーが変わる可能性もあるので、ソース管理の対象になるでしょう。
このように、たくさんのアドオンを入れるとその分マニフェストファイル管理、運用、アップデート作業が大変になるので、できるだけシンプルに、楽に管理をしたいところです。
パッケージマネージャーであるHelmを利用する事でも幾分楽になりますが、EKSアドオンはAWSにサポートされている分、それ以上の運用容易性向上の可能性を秘めているかもしれません。
そこで、今回はEBS CSI driver をEKSアドオンとして入れてみたいと思います。(前置きおしまい)
EKSアドオンでEBS CSI driverをいれてみた
それでは実際に導入してみたいと思います。
EKSクラスタへの接続環境としてCloud9を利用します。
セットアップはEKS workshopをベースにしているので、ここでの説明は省略します。(※今もなお、メンテナンスされていて素晴らしい学習コンテンツだと思います。)
クラスタ作成
現時点(2022/9)の最新バージョンであるEKS 1.23でクラスタを作成します。
クラスタ構築にはeksctlを利用します。
基本的にマニフェストファイルを利用する前提で記載していきますが、オプションとして渡すこともできますし、むしろ手軽です。(実運用を想定した時にマニフェストファイル化した方がいいと考えているので、マニフェストファイルでやっています。)
以下のようなeksctl用のマニフェストファイルを用意して、クラスタを作成します。
eks.yaml
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ebs-test-cluster region: us-west-2 version: "1.23" iam: withOIDC: true managedNodeGroups: - name: nodegroup instanceType: m5.large desiredCapacity: 1 privateNetworking: true
eksctl create cluster -f eks.yaml
クラスタが正しく作成されたことを確認します。
$ eksctl get cluster NAME REGION EKSCTL CREATED ebs-test-cluster us-west-2 True $ eksctl get nodegroup --cluster ebs-test-cluster CLUSTER NODEGROUP STATUS CREATED MIN SIZE MAX SIZE DESIRED CAPACITY INSTANCE TYPE IMAGE ID ASG NAME TYPE ebs-test-cluster nodegroup ACTIVE 2022-09-26T09:24:22Z 1 1 1m5.large AL2_x86_64 eks-nodegroup-d0c1bc8e-4bcf-22b4-b43d-af143697e7ff managed $ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-162-107.us-west-2.compute.internal Ready <none> 3m33s v1.23.9-eks-ba74326
OIDCプロバイダーが作成されていることを確認します。
oidc_id=$(aws eks describe-cluster --name ebs-test-cluster --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
aws iam list-open-id-connect-providers | grep $oidc_id "Arn": "arn:aws:iam::<account-id>:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/HOGEHOGE"
IAMロール作成
EBS CSI driverでは、ユーザに代わってAWSのAPIの呼び出しを行うため、IAM アクセス許可が必要です。したがって、IAMポリシーを定義する必要があります。
今までアドオンに必要なIAMポリシーは自ら作って管理する必要がありましたが、EBS CSI driver用のIAMポリシーがサービスロールとして提供されているので、そちらを使う事ができます。おそらくEKSアドオンとしてサポートされたからでしょう。
以下のようなyamlを用意します。ServiceAccountは後で作成するので、role-onlyで作成します。
eks-policy.yaml
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ebs-test-cluster region: us-west-2 version: "1.23" iam: withOIDC: true serviceAccounts: - metadata: name: ebs-csi-controller-sa namespace: kube-system attachPolicyARNs: - "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy" roleName: AmazonEKS_EBS_CSI_DriverRole roleOnly: true
eksctl create iamserviceaccount -f eks-policy.yaml --approve
$ eksctl get iamserviceaccount --cluster ebs-test-cluster NAMESPACE NAME ROLE ARN kube-system aws-node arn:aws:iam::<account-id>:role/eksctl-ebs-test-cluster-addon-iamserviceacco-Role1-1NLMN0MSW3P25 kube-system ebs-csi-controller-sa arn:aws:iam::<account-id>:role/AmazonEKS_EBS_CSI_DriverRole
EBS CSI driverの追加
EKSアドオンとしてEBS CSI driverをクラスタに適用します。
eks-addon.yaml
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ebs-test-cluster region: us-west-2 version: "1.23" iam: withOIDC: true addons: - name: aws-ebs-csi-driver serviceAccountRoleARN: "arn:aws:iam::<account-id>:role/AmazonEKS_EBS_CSI_DriverRole"
eksctl create addon -f eks-addon.yaml
EKSアドオンとしてEBS CSI driverが管理されていることが確認できます。
$ eksctl get addon --name aws-ebs-csi-driver --cluster ebs-test-cluster NAME VERSION STATUS ISSUES IAMROLE UPDATE AVAILABLE aws-ebs-csi-driver v1.11.2-eksbuild.1 ACTIVE 0 arn:aws:iam::<account-id>:role/AmazonEKS_EBS_CSI_DriverRole
また、EBS CSI driver関連のリソースが作成されていることが確認できます。
$ kubectl get sa -n kube-system | grep ebs ebs-csi-controller-sa 1 3m58s ebs-csi-node-sa 1 3m58s $ kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE aws-node-r9vmm 1/1 Running 0 65m coredns-57ff979f67-7ppgt 1/1 Running 0 74m coredns-57ff979f67-zl4bg 1/1 Running 0 74m ebs-csi-controller-d76cfdc66-672dn 6/6 Running 0 4m37s ebs-csi-controller-d76cfdc66-mxdf9 6/6 Running 0 5m7s ebs-csi-node-xnmns 3/3 Running 0 5m7s kube-proxy-thqfv 1/1 Running 0 65m
以上でEBSを利用する準備が整いました。通常のやり方でEKSにアドオンを導入するより、かなり手順が少ない事がうかがえると思います。
動作確認
実際にサンプルアプリを適用してpodからEBSが利用可能になったかどうか試していきたいと思います。
ここからは、公式ブログに準拠しながらやっていきます。
まずStorageClassを確認すると、Provisionerがkubernetes.io/aws-ebsとなっているStorageClassが適用されていることが確認できます。(あくまでEKS 1.23時点です)これがin-treeのボリュームプラグインです。
$ kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 84m
provisionerとしてEBS CSI driverが指定されたStorageClassを新たに作成します。
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: gp3 allowVolumeExpansion: true provisioner: ebs.csi.aws.com volumeBindingMode: WaitForFirstConsumer parameters: type: gp3
$ kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 94m gp3 ebs.csi.aws.com Delete WaitForFirstConsumer true 4s
次にPVCを作成します。
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-csi spec: accessModes: - ReadWriteOnce storageClassName: gp3 resources: requests: storage: 1Gi
$ kubectl apply -f ebs-test/pvc-csi.yaml persistentvolumeclaim/pvc-csi created $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-csi Pending gp3 7s
PVCがPendingになっているのは、VolumeBindingMode が WaitForFirstConsumer(Podが作成された時にPVを生成してバインドする仕様)であるためです。
次にPodを作成します。
apiVersion: v1 kind: Pod metadata: name: app-gp3 spec: containers: - name: app image: centos command: ["/bin/sh"] args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"] volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim: claimName: pvc-csi
$ kubectl apply -f ebs-test/pod-csi.yaml pod/app-gp3 created
各種ステータスを確認すると、PVが生成されていること、PVCがバウンドされていること、Podがrunningになっていること、PodからEBSがマウントされていることが確認できます。
$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-c2001a90-a1d2-453c-a238-096af6fe87e2 1Gi RWO Delete Bound default/pvc-csi gp3 1s $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-csi Bound pvc-c2001a90-a1d2-453c-a238-096af6fe87e2 1Gi RWO gp3 3m20s $ kubectl get pod NAME READY STATUS RESTARTS AGE app-gp3 1/1 Running 0 47s $ kubectl exec -it app-gp3 -- cat /data/out.txt Mon Sep 26 10:58:29 UTC 2022 Mon Sep 26 10:58:34 UTC 2022 Mon Sep 26 10:58:39 UTC 2022 Mon Sep 26 10:58:44 UTC 2022 Mon Sep 26 10:58:49 UTC 2022 Mon Sep 26 10:58:54 UTC 2022
マネジメントコンソールからEBSを確認すると、gp3のEBSが作成されていることが確認できます。
動作確認は以上です。
まとめ
このように、EKSアドオンを利用してEBS CSI driverを適用することで、簡単に導入することができました。
一通りやってみての感想ですが、EBS CSI driver単体だけで考えたらぜひEKSアドオンを利用したいな。と思いました。
デフォルトのパラメータから特にいじる事が無ければ、とても楽だと思いました。
一方で、実運用で今すぐ使いたいかと考えると疑問でした。
1つ目の理由は、EKSアドオンとして管理できるアドオンが限られているからです。
コンテナロードマップを見ても、AWS Load Balancer Controller、EFS CSI driver、Calico、Cluster Autoscaler等よく使われるアドオンはまだEKSアドオン対応の見通しが立っていません。
このアドオンはEKSアドオンで管理して、このアドオンはHelmで管理して、このアドオンはkubectlで適用して、というようなばらつきがあると、運用が複雑になってしまいます。
2つめの理由は、デフォルトのパラメータから何か変えたい時にかえってややこしそうだからです。
EKSアドオンが管理しているパラメータを変更した場合、その後のEKSアドオンの更新によって再度アドオンのデフォルトに戻されてしまいます。
変更可能なパラメータだとしても、変更には気を使うと思います。
Helmでもそれなりにマニフェストファイル管理の見通しは良くなるので、
Chartを取得して、修正したい値を変えて適用してあげる方が、マニフェストファイル管理やデフォルトとの差分の管理が楽なのではないかなと感じました。
デフォルトの設定から特に変えないのであれば、アドオン管理がかなり省力化できると思いますし、EKSアドオンのコンセプトは素敵なので、今後の発展に期待したいと思いました。
今回は以上です。
-
PICK UP
ピックアップ
-
ピックアップコンテンツがありません
-
RANKING
人気の記事
-
ARCHIVE
アーカイブ
-
- July 2024 (1)
- January 2024 (1)
- December 2023 (2)
- June 2023 (2)
- May 2023 (1)
- April 2023 (1)
- March 2023 (2)
- February 2023 (2)
- January 2023 (1)
- December 2022 (2)
- October 2022 (2)
- September 2022 (2)