eks 및 efs 연동 테스트

https://catalog.us-east-1.prod.workshops.aws/workshops/9c0aa9ab-90a9-44a6-abe1-8dff360ae428/ko-KR

EKS

AWS CLI

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
apt install unzip -y
unzip awscliv2.zip
sudo ./aws/install

aws configure

aws configure

EKS 클러스터 생성

root관리자 계정말고 별도의 계정으로 진행합니다. 안그러면 IAM설정에 어려움이 있을수있음.

ubuntu 22.04 서버를 Bastion으로 사용함.

Terraform 등 IaC구성시 주의사항

# 배포시 서브넷 태그 key:value 설정 중요
- key = kubernetes.io/role/elb
- value = 1

Kubectl Install

curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.31.2/2024-11-15/bin/linux/amd64/kubectl
chmod +x kubectl && mv kubectl /usr/local/bin/kubectl

eksctl 설치

아래의 명령어를 통해, 최신의 eksctl 바이너리를 다운로드 합니다.

curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

바이너리를 /usr/local/bin으로 옮깁니다.

sudo mv -v /tmp/eksctl /usr/local/bin

아래의 명령어를 통해 설치 여부를 확인합니다.

eksctl version

eksctl을 사용하여 EKS 클러스터 생성하기
eksctl을 사용하여 아무 설정 값을 주지 않고 이 명령어(eksctl create cluster)를 실행하면 default parameter로 클러스터가 배포됩니다.

vim ~/eks-demo-cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: eks-demo # 생성할 EKS 클러스터명
  region: ap-northeast-2 # 클러스터를 생성할 리전
  version: "1.30"

vpc:
  cidr: "10.0.0.0/16" # 클러스터에서 사용할 VPC의 CIDR
  nat:
    gateway: HighlyAvailable

managedNodeGroups:
  - name: node-group # 클러스터의 노드 그룹명
    instanceType: m5.large # 클러스터 워커 노드의 인스턴스 타입
    desiredCapacity: 3 # 클러스터 워커 노드의 갯수
    volumeSize: 20  # 클러스터 워커 노드의 EBS 용량 (단위: GiB)
    privateNetworking: true
    iam:
      withAddonPolicies:
        imageBuilder: true # Amazon ECR에 대한 권한 추가
        albIngress: true  # albIngress에 대한 권한 추가
        cloudWatch: true # cloudWatch에 대한 권한 추가
        autoScaler: true # auto scaling에 대한 권한 추가
        ebs: true # EBS CSI Driver에 대한 권한 추가
        efs: true # by.sdjo add-test

cloudWatch:
  clusterLogging:
    enableTypes: ["*"]

iam:
  withOIDC: true
EOF
eksctl create cluster -f eks-demo-cluster.yaml

클러스터 생성후 확인

kubectl get no
kubectl get po -A

jq설치

apt install jq -y

웹콘솔 EKS 접근제어 추가

EKS에 IAM 역할 매핑

eksctl create iamidentitymapping --cluster eks-demo --arn arn:aws:iam::448559955338:user/demo --group system:masters --username admin

# root적용
eksctl create iamidentitymapping --cluster eks-demo --arn arn:aws:iam::448559955338:user/root --group system:masters --username admin

ConfigMap 등록확인

mapUsers항목에 추가되어있는 것이 확인 되어야한다.

root@aws-bastion:~# kubectl edit cm aws-auth -n kube-system
# 직접 configmap에 등록하는 방법도 있다.
apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::고유계정아이디번호:role/eksctl-eks-demo-nodegroup-node-gro-NodeInstanceRole
      username: system:node:{{EC2PrivateDNSName}}
  mapUsers: |
    - groups:
      - system:masters
      userarn: arn:aws:iam::고유계정아이디번호:user/demo
      username: admin
    # 웹콘솔 EKS 접근제어 추가를 실행하지않고,
    # 직접 configmap에 입력하는 것도 가능하다.  
    - groups:
      - system:masters
      userarn: arn:aws:iam::고유계정아이디번호:root
      username: admin

EKS 삭제(옵션)

eksctl delete cluster --name eks-demo --region ap-northeast-2

Elastic File System

https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEFSCSIDriverPolicy.html

https://kschoi728.tistory.com/94

EFS 준비

vpc_id 정보 필요 cicd_range 정보 필요(ex: 10.0.0.0/16).

보안그룹생성

security_group_id=$(aws ec2 create-security-group \
–group-name MyEfsSecurityGroup \
–description “My EFS security group” \
–vpc-id $vpc_id \
–output text)

보안그룹 2049 포트 추가

EFS 생성

file_system_id=$(aws efs create-file-system \
    --region ap-northeast-2 \
    --performance-mode generalPurpose \
    --query 'FileSystemId' \
    --output text)

마운트 타겟설정을 위한 정보 확인

aws ec2 describe-subnets \
    --filters "Name=vpc-id,Values=$vpc_id" \
    --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \
    --output table

노드가 있는 서브넷에 마운트 타겟 지정

aws efs create-mount-target \
    --file-system-id $file_system_id \
    --subnet-id subnet-0d8be3835fe60e983 \
    --security-groups $security_group_id
    
# aws efs create-mount-target --file-system-id fs-063a6530ca2136ccd --subnet-id subnet-0f3597d15e5b81e54 --security-groups sg-0b20e9324374526b3
# aws efs create-mount-target --file-system-id fs-063a6530ca2136ccd --subnet-id subnet-021a7807e53666d22 --security-groups sg-0b20e9324374526b3
# aws efs create-mount-target --file-system-id fs-063a6530ca2136ccd --subnet-id subnet-0e1302992f7b3c987 --security-groups sg-0b20e9324374526b3

AmazonEFSCSIDriverPolicy 등록

# https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEFSCSIDriverPolicy.html
# 이 내용이 안되면 2번째 참고자료 참고해서 해볼것
# iam-policy-example.json
{
  "Version" : "2012-10-17",
  "Statement" : [
    {
      "Sid" : "AllowDescribe",
      "Effect" : "Allow",
      "Action" : [
        "elasticfilesystem:DescribeAccessPoints",
        "elasticfilesystem:DescribeFileSystems",
        "elasticfilesystem:DescribeMountTargets",
        "ec2:DescribeAvailabilityZones"
      ],
      "Resource" : "*"
    },
    {
      "Sid" : "AllowCreateAccessPoint",
      "Effect" : "Allow",
      "Action" : [
        "elasticfilesystem:CreateAccessPoint"
      ],
      "Resource" : "*",
      "Condition" : {
        "Null" : {
          "aws:RequestTag/efs.csi.aws.com/cluster" : "false"
        },
        "ForAllValues:StringEquals" : {
          "aws:TagKeys" : "efs.csi.aws.com/cluster"
        }
      }
    },
    {
      "Sid" : "AllowTagNewAccessPoints",
      "Effect" : "Allow",
      "Action" : [
        "elasticfilesystem:TagResource"
      ],
      "Resource" : "*",
      "Condition" : {
        "StringEquals" : {
          "elasticfilesystem:CreateAction" : "CreateAccessPoint"
        },
        "Null" : {
          "aws:RequestTag/efs.csi.aws.com/cluster" : "false"
        },
        "ForAllValues:StringEquals" : {
          "aws:TagKeys" : "efs.csi.aws.com/cluster"
        }
      }
    },
    {
      "Sid" : "AllowDeleteAccessPoint",
      "Effect" : "Allow",
      "Action" : "elasticfilesystem:DeleteAccessPoint",
      "Resource" : "*",
      "Condition" : {
        "Null" : {
          "aws:ResourceTag/efs.csi.aws.com/cluster" : "false"
        }
      }
    }
  ]
}

정책을 생성합니다.

aws iam create-policy \
--policy-name AmazonEKS_EFS_CSI_Driver_Policy \
--policy-document file://iam-policy-example.json

정책 연결

https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/efs-csi.html#efs-install-driver

다음 명령을 실행하여 eksctl로 IAM 역할을 만들 수 있습니다. my-cluster를 클러스터 이름으로 바꾸고 AmazonEKS_EFS_CSI_DriverRole을 역할의 이름으로 바꿉니다.

export cluster_name=my-cluster
export role_name=AmazonEKS_EFS_CSI_DriverRole
eksctl create iamserviceaccount \
    --name efs-csi-controller-sa \
    --namespace kube-system \
    --cluster $cluster_name \
    --role-name $role_name \
    --role-only \
    --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
    --approve
TRUST_POLICY=$(aws iam get-role --role-name $role_name --query 'Role.AssumeRolePolicyDocument' | \
    sed -e 's/efs-csi-controller-sa/efs-csi-*/' -e 's/StringEquals/StringLike/')
aws iam update-assume-role-policy --role-name $role_name --policy-document "$TRUST_POLICY"

CSI-DRIVER 배포

https://docs.aws.amazon.com/eks/latest/userguide/creating-an-add-on.html#_create_add_on_eksctl

쿠버네티스 1.30버전에서 배포가능한 Addon조회

eksctl utils describe-addon-versions --kubernetes-version 1.30 | grep AddonName

애드온별 사용가능한 버전 확인

eksctl utils describe-addon-versions --kubernetes-version 1.30 --name name-of-addon | grep AddonVersion

애드온 배포

eksctl create addon --cluster $CLUSTER_NAME --name aws-efs-csi-driver --version latest --service-account-role-arn arn:aws:iam::$ACCOUNT_ID:role/AmazonEKS_EFS_CSI_DriverRole --force
eksctl delete addon --cluster eks-demo --name aws-efs-csi-driver

드라이버삭제(옵션)

eksctl delete addon --cluster eks-demo --name aws-efs-csi-driver

동적 스토리지클래스, example/storageClass.yaml

# https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: efs-sc
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: fs-063a6530ca2136ccd
  directoryPerms: "700"
  gidRangeStart: "1000" # optional
  gidRangeEnd: "2000" # optional
  basePath: "/dynamic_provisioning" # optional
  subPathPattern: "${.PVC.namespace}/${.PVC.name}" # optional
  ensureUniqueDirectory: "true" # optional
  reuseAccessPoint: "false" # optional

example/pod.yaml

# https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: efs-app
spec:
  containers:
    - name: app
      image: centos:latest
      command:
        - /bin/sh
      args:
        - "-c"
        - "while true; do echo $(date -u) >> /data/out; sleep 5; done"
      volumeMounts:
        - name: persistent-storage
          mountPath: /data
  volumes:
    - name: persistent-storage
      persistentVolumeClaim:
        claimName: efs-claim