16
12

More than 3 years have passed since last update.

EKSでEFSファイルシステムを永続ボリュームとして利用する

Last updated at Posted at 2019-09-18

はじめに

ここ2ヶ月ほどEKS/Kubernetesを触っています。

アプリケーションをコンテナ化する以上、コンテナは状態をなるべく持たず状態はデータベースやオブジェクトストレージに保存するようにするのがベストプラクティスですが、どうしてもファイルシステムにファイルを保存したいという場合はあるのではないでしょうか。

そういった場合、KubernetesのPersistent Volumeの仕組みを使うとPodに非揮発性のファイルシステムをマウントすることができます。
ただ、マウント対象のファイルシステムは自分で用意しないといけません。

マウント対象としてはいくつか選べるのですが、複数のPodから同時に読めて状態を共有できるようにするにはNFSファイルシステムをマウントするのがよいと思われます。

そこで、マネージドNFSファイルシステムであるAmazon EFSのファイルシステムをEKSクラスタで利用しようとしました。
EKSもEFSもAWSのマネージドサービスだし楽勝だろ、と思っていたら意外とハマったので、手順を共有して苦しむ人が減ればと思います。

EFSファイルシステムを作成する

AWSコンソールからEFSファイルシステムを作成します。

このとき、EKSのワーカーノードが存在するサブネットすべてをマウントターゲットに追加し、またそれぞれセキュリティグループをEKSが勝手に作成するセキュリティグループを設定しておきます。

こちらのクイックスタートをつかっていれば、xxx-NodeSecurityGroup-yyyみたいな名前のセキュリティグループができているかと思いますが、それです。

sc-2019-09-18 21.55.42.jpg

ワーカーノードのIAMロール

EKSワーカーノードのロールに1で作ったEFSボリュームに関するポリシーを追加します。こちらもクイックスタートを使っていると、xxx-NodeInstanceRole-yyyという名前になっているかと。

こちらのロールに、さきほど作成したEFSファイルシステムの「リスト・読み込み・書き込み」の権限が付与されていればOKです。

50bac8bd-88f9-478b-a0d5-b302239b7f99.png

efs-provisioner の設定

EFSをKubernetesの永続ボリュームとして使うには、efs-provisionerを使う必要があります。

しかし、これがREADMEの通りに手順をたどっても動かせないという罠があります。
リポジトリのサンプルマニフェストの記述が間違っているからです。。😡

こちらのIssueに解決策が載っていました。

ただマウントしたいだけなら、


https://github.com/kubernetes-incubator/external-storage/blob/master/aws/efs/deploy/manifest.yaml

の2つをapplyする必要がありますが、両方とも修正する必要があります。

まずrbac.yamlですが、よくわからないRoleとClusterRoleの使い分けがありますが、ClusterRoleに一本化しましょう。また、サービスロールの記述も追加しないといけません。

rbac.yaml
---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: efs-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]

---

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-efs-provisioner
subjects:
  - kind: ServiceAccount
    name: efs-provisioner
    namespace: development # ClusterRoleBindingの指定はネームスペースごと
roleRef:
  kind: ClusterRole
  name: efs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io

---

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: development # ServiceAccountの指定もネームスペースごと
  name: efs-provisioner

そして、manifest.yamlは、Deploymentのところにネームスペースとサービスアカウントを追記します。

manifest.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  namespace: development # この記述もネームスペースごと
  name: efs-provisioner
  spec:
    serviceAccount: efs-provisioner
    containers:
      - name: efs-provisioner
        image: quay.io/external_storage/efs-provisioner:latest

ディレクトリ分割

前の手順までで、Podの永続ボリュームとしてEFSファイルシステムを利用できるようになります。

適当なEC2インスタンスをたててEFSファイルシステムをマウントしてみるとわかるのですが、manifest.yamlのPersistentVolumeClaimごとにディレクトリが切られて、各Podからはその中しか見られないようになっています。
なので、1つのEFSファイルシステムを複数のPodで相乗り利用する場合は、共通のStorageClassを利用するPersistentVolumeClaimを複数定義すればよいです。

おわりに

これでEKSクラスタ上で動くPodの永続ボリュームとしてEFSファイルシステムを利用できるようになりました。
EKSもEFSもAWSの製品なのでありがちなユースケースなのではないかと思うのですが、意外とドンピシャな情報がなかったので、参考になればと思います。

16
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
12