· Vojtech Svoboda · Kubernetes  · 6 min čtení

PV na EKS clusteru s pouze Fargate nody

Jak vytvořit persistent volume v EKS clusteru s pouze Fargate nody a na co si dát pozor.

Jak vytvořit persistent volume v EKS clusteru s pouze Fargate nody a na co si dát pozor.

Na první pohled se může zdát, že nastavení persistent volume (PV) na Fargate-only EKS clusteru v AWS není problém. Ve skutečnosti je ale potřeba si dát pozor na několik důležitých detailů a omezení. V tomto článku si projdeme klíčové body a funkční řešení.


Úvodem

Tento článek chceme udržet stručný, ale nejprve je potřeba vysvětlit, co je to Fargate.

AWS Fargate je technologie, která umožňuje spouštět kontejnery (na ECS, EKS nebo dokonce Lambda funkce) bez nutnosti spravovat virtuální stroje pod nimi. Využívá konceptu microVM, kde každý workload (task v ECS nebo Pod v EKS) běží ve vlastním izolovaném VM. To je to, čemu AWS říká „serverless“.

Tyto microVM nejsou spravovány jako EC2 instance. Jako uživatelé k nim nemáme žádný přístup ani možnost správy, což je jednou z hlavních výhod serverless přístupu.

Existují ale i nevýhody. Například workloady se spouští pomaleji, protože je nejprve nutné vytvořit instanci pod nimi. Oproti spuštění Podů na již běžících EC2 nodech to může znamenat znatelné zpoždění (někdy až dvě minuty).

Dalším důležitým omezením je, že microVM nepodporují všechny funkce EC2. Konkrétně nepodporují připojení EBS disků. To se stává zásadním problémem ve chvíli, kdy chcete v Kubernetes clusteru používat Persistent Volumes – a právě tomu se tento článek věnuje.

Jak nastavit funkční PV

Jak tedy toto omezení obejít a zajistit, aby Fargate-only EKS cluster fungoval s persistentními volumes? Po prostudování AWS dokumentace jsme narazili na několik míst, která nejsou příliš dobře vysvětlena. Níže najdete krok za krokem postup, který tyto mezery vyplňuje.

Prerekvizity

Budete potřebovat:

  • helm
  • kubectl
  • EKS cluster s Fargate profilem a administrátoský přístup
  • AWS uživatele s dostatečnými oprávněními pro vytvoření a správu EFS a IAM

Pro účely tohoto článku předpokládáme, že AWS účet obsahuje:

  • VPC s CIDR 10.0.0.0/16
  • Tři privátní subnety (10.0.0.0/24, 10.0.1.0/24, 10.0.2.0/24)
  • Tři veřejné subnety (10.0.3.0/24, 10.0.4.0/24, 10.0.5.0/24)
  • Subnety rozložené do tří Availability Zones
  • EKS cluster nasazený v privátních subneteche

V celém návodu používáme region us-east-1.

EFS

I když EBS na Fargate použít nelze, EFS je podporované a představuje doporučené řešení pro persistentní úložiště ve Fargate-only EKS clusterech. EFS má sice vyšší latenci než EBS, ale v tomto setupu jde o jedinou podporovanou možnost persistentního sdíleného úložiště (kromě objektových úložišť).

Nejprve vytvoříme EFS filesystem:

aws efs create-file-system \
  --tags Key=Name,Value=my-efs \
  --region us-east-1

Následně vytvoříme security group pro mount targety:

aws ec2 create-security-group \
  --group-name efs-sg \
  --description efs \
  --vpc-id vpc-XXXX

Poté vytvoříme mount targety v každém privátním subnetu, ke kterým bude EKS cluster přistupovat:

aws efs create-mount-target \
  --file-system-id fs-<ID of the EFS created earlier> \
  --subnet-id subnet-private-1 \
  --security-groups sg-<ID of the security group created earlier>

aws efs create-mount-target \
  --file-system-id fs-<ID of the EFS created earlier> \
  --subnet-id subnet-private-2 \
  --security-groups sg-<ID of the security group created earlier>

aws efs create-mount-target \
  --file-system-id fs-<ID of the EFS created earlier> \
  --subnet-id subnet-private-3 \
  --security-groups sg-<ID of the security group created earlier>

Nakonec – a tento krok je velmi důležitý – je nutné přidat v security group ingress pravidla pro NFS (port 2049) z privátních subnetů. Tato pravidla musí být přiřazena security group mount targetů EFS:

aws ec2 authorize-security-group-ingress \
  --group-id sg-<ID of the security group created earlier> \
  --protocol tcp \
  --port 2049 \
  --cidr 10.0.0.0/24

aws ec2 authorize-security-group-ingress \
  --group-id sg-<ID of the security group created earlier> \
  --protocol tcp \
  --port 2049 \
  --cidr 10.0.1.0/24

aws ec2 authorize-security-group-ingress \
  --group-id sg-<ID of the security group created earlier> \
  --protocol tcp \
  --port 2049 \
  --cidr 10.0.2.0/24

AWS IAM role pro service account

Dále musíme vytvořit IAM roli, která bude navázána na Kubernetes service account. Tato role umožní EFS CSI driver controlleru vytvářet a spravovat EFS access pointy.

Celý proces je popsán v AWS dokumentaci, ale pro úplnost jej uvádíme i zde.

Nejprve zjistíme OIDC issuer ID clusteru:

export cluster_name=my-cluster
aws eks describe-cluster \
  --name $cluster_name \
  --query "cluster.identity.oidc.issuer" \
  --output text

Poté vytvoříme IAM roli, která povolí AssumeRoleWithWebIdentity:

cat <<EOF > aws-efs-csi-driver-trust-policy.json
{
  "Version":"2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:kube-system:efs-csi-*",
          "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
EOF

aws iam create-role \
  --role-name AmazonEKS_EFS_CSI_DriverRole \
  --assume-role-policy-document file://"aws-efs-csi-driver-trust-policy.json"

Nakonec k roli připojíme potřebnou politiku (AmazonEFSCSIDriverPolicy):

aws iam attach-role-policy \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
  --role-name AmazonEKS_EFS_CSI_DriverRole

Po dokončení konfigurace na straně AWS můžeme přejít k instalaci CSI controlleru. Service account se vytvoří automaticky během instalace pomocí Helm.

CSI controller

Pokud objekt CSIDriver v clusteru neexistuje, vytvoříme jej ručně:

apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
  name: efs.csi.aws.com
spec:
  attachRequired: false

I když lze EFS CSI driver nainstalovat jako EKS add-on, v případě Fargate-only clusterů jsme s tímto přístupem narazili na problémy. Proto v tomto návodu používáme self-managed instalaci pomocí Helm.

helm repo add aws-efs-csi-driver \
  https://kubernetes-sigs.github.io/aws-efs-csi-driver/
helm repo update aws-efs-csi-driver

helm upgrade --install aws-efs-csi-driver \
  --namespace kube-system \
  --set controller.replicaCount=1 \
  --set controller.serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn=<ARN of the created IAM role> \
  --set controller.containerSecurityContext.privileged=false \
  --set node.enabled=false \
  aws-efs-csi-driver/aws-efs-csi-driver

Zde je vysvětlení některých zvolených konfigurací:

  • replicaCount je nastaveno na 1, protože jde o ukázkovou instalaci a vysoká dostupnost není nutná.
  • Anotace role-arn zajišťuje, že service account controlleru použije správnou IAM roli.
  • node.enabled=false vypíná node daemonset, který na Fargate není podporován.
  • privileged=false je nutné, protože privilegované kontejnery nejsou na Fargate povoleny, a nemá negativní dopad na funkčnost controlleru.

Storage class

Dále vytvoříme storage class, která používá EFS CSI driver a dříve vytvořený filesystem.

Používáme provisioning mód efs-ap, který umožňuje dynamické vytváření a mazání PersistentVolumeClaimů v Kubernetes. Každý PVC má vlastní EFS access point a změny se do EFS propisují velmi rychle.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  fileSystemId: fs-<ID of EFS>
  provisioningMode: efs-ap
  directoryPerms: '700'

A to je vše! Nyní, když máme veškeré konfigurace připravené můžeme otestovat, že se nám PVC a PV vytvoří.

Testování setupu

Po dokončení všech kroků můžeme konfiguraci otestovat.

Nejprve vytvoříme PersistentVolumeClaim, který využívá námi vytvořenou StorageClass:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: poc-app-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 1Gi

Poté vytvoříme dva Pody, abychom otestovali sdílené úložiště. Použijeme příklady od AWS:

kubectl apply -f \
  https://raw.githubusercontent.com/aws-samples/eks-efs-share-within-fargate/refs/heads/master/scripts/epic04/pod1.yaml

kubectl apply -f \
  https://raw.githubusercontent.com/aws-samples/eks-efs-share-within-fargate/refs/heads/master/scripts/epic04/pod2.yaml

Jakmile jsou oba Pody spuštěné, můžete se připojit do libovolného z nich a zkontrolovat adresář /data. Měli byste vidět soubory vytvořené oběma Pody, což potvrzuje funkčnost sdíleného persistentního úložiště.

Závěr

Úspěšně jsme nakonfigurovali persistentní úložiště pomocí EFS pro Fargate-only EKS cluster. Přestože je řešení v principu jednoduché, existuje mnoho kroků, kde může drobná chyba vést k velmi matoucím problémům.

Chyba, u které bylo nejtěžší zjistit, kde se nachází příčina problému, byla následující:

kubelet MountVolume.MountDevice failed for volume "poc-app-pv" :
kubernetes.io/csi: attacher.MountDevice failed to create newCsiDriverClient:
driver name efs.csi.aws.com not found in the list of registered CSI drivers

Tato chybová hláška jasně nepopisuje skutečnou příčinu problému. V našem případě byla příčina v nesprávně nastavených nebo chybějících ingress pravidlech security group u EFS mount targetů. Povolení NFS provozu (port 2049) ze všech relevantních privátních subnetů problém vyřešilo.

Zpět na blog