새소식

AWS/EKS

[EKS Study 7주차] EKS Automation - ACK

  • -

CloudNet@ 팀의 가시다님께서 Leading 하시는 AEWS Study 7주차 스터디 내용 정리

이번 포스팅에서는 kubernetes 에서 AWS Resource API 를 다룰 수 있게 해주는 AWS Controller for Kubernetes (ACK) 대해 알아보겠습니다.

 

1. AWS Controller for Kubernetes (ACK)

 

AWS 리소스를 kubernetes 에서 직접 정의하고 사용할 수 있게 해주는 오픈소스 도구입니다.
AWS 리소스 관리를 위해 k8s Cluster 밖으로 벗어나는 번거로움을 해결하기 위해 만들어졌습니다.

 

https://www.eksworkshop.com/docs/automation/controlplanes/ack/

 

1.1. ACK 를 통해 사용가능한 AWS 서비스

 

ACK 가 지원하는 AWS 서비스 문서

 

Services

Project status of each supported service

aws-controllers-k8s.github.io

23.06.10 기준 현재 총 27가지 서비스를 지원하고 있습니다만,
실제 안정적으로 사용할 수 있는 GA 는 17개 정도로 적긴 합니다.

 

그래도 EC2, IAM, ECR, Lambda, S3, RDS 등 AWS 에서 보편적으로 자주 사용하는 서비스는 GA 니 간단하게 사용하실 때는 불편함이 없을 것 같습니다.

 

1.2. 작동 원리

 

https://aws-controllers-k8s.github.io/community/docs/community/how-it-works/

 

a. k8s user 가 Manifest(CRD) 에 AWS 리소스에 대한 정의를 작성한 후 k8s 의 API Server 호출
b. API Server 는 호출한 User 가 해당 CRD 와 리소스 사용에 대한 권한이 있는 User 인 지 판단
c. 유효한 User 일 경우, API Server 는 etcd 에 해당 CRD 에 대해 기록하고 User 에게 응답
d. etcd 에 기록되는 순간, ACK 컨트롤러가 이를 인지하고 AWS API 와 통신하여 AWS 리소스를 생성

 

2. ACK for S3 실행

 

ACK 는 AWS 리소스 마다 개별 Controller 를 가지고 있으며 Helm 으로 간단하게 설치가 가능합니다.
이번 포스팅에서는 S3 버킷을 관리하는 ACK Controller 를 테스트 해보겠습니다.

 

각각의 ACK Controller Image는 AWS Public ECR 에서 확인하실 수 있습니다.

 

ECR Public Gallery

Amazon ECR Public Gallery is a website that allows anyone to browse and search for public container images, view developer-provided details, and see pull commands

gallery.ecr.aws

 

ACK 의 실행 순서는 컨트롤러에 상관 없이 거의 동일합니다.

a. Helm 설치
b. IRSA 설정
c. AWS 리소스 배포

 

2.1. S3 ACK 설치

 

export SERVICE=s3
export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/$SERVICE-controller/releases/latest | grep '"tag_name":' | cut -d'"' -f4)
export ACK_SYSTEM_NAMESPACE=ack-system
export AWS_REGION=ap-northeast-2
helm install \
    --create-namespace \
    -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller \
    oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart \
    --version=$RELEASE_VERSION \
    --set=aws.region=$AWS_REGION

 

 

2.2. IRSA 설정

 

ACK S3 Controller 에 권장되는 권한은 AWSS3FullAccess 입니다.

 

eksctl create iamserviceaccount \
  --name ack-$SERVICE-controller \
  --namespace ack-system \
  --cluster $CLUSTER_NAME \
  --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3FullAccess`].Arn' --output text) \
  --override-existing-serviceaccounts --approve

 

 

IRSA 설정이 잘 되었다면 rollout 명령어를 통해 기존 S3 Controller 를 대체해줍니다.

kubectl -n ack-system rollout restart deploy ack-$SERVICE-controller-$SERVICE-chart

 

2.3. S3 생성

 

export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
export BUCKET_NAME=my-ack-s3-bucket-$AWS_ACCOUNT_ID
cat << EOF > bucket.yaml
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
  name: $BUCKET_NAME
spec:
  name: $BUCKET_NAME
EOF

kubectl apply -f bucket.yaml

 

버킷 생성 후 AWS 콘솔에서 확인하실 수 있습니다.

 

ACK 로 생성한 버킷은 아래 명령어로 확인 가능합니다.

kubectl get bucket

 

 

2.4. S3 삭제

 

버킷 삭제는 생성과 마찬가지로 명령어 한 줄로 가능합니다.

kubectl delete -f bucket.yaml

 

2.5. ACK for S3 삭제

 

# Helm Uninstall
export SERVICE=s3
helm uninstall -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller

# CRD Remove
kubectl delete -f ~/$SERVICE-chart/crds

# IRSA 제거
eksctl delete iamserviceaccount --cluster myeks --name ack-$SERVICE-controller --namespace ack-system

 

3. Multi Region 에서의 ACK 사용

 

ACK 는 Annotation 을 통해 다른 AWS Region에 리소스를 배포할 수 있습니다.

여기서는 버지니아 북부(us-east-1), 서울(ap-northeast-2) 지역에 VPC 를 동시에 배포해보도록 하겠습니다.

 

3.1. ACK for EC2 설치 (+IRSA)

 

VPC 를 배포하기 위해서는 EC2 Controller 가 필요합니다.

앞서 실습했던 S3 Controller 와 동일한 순서로 설치를 진행합니다.

export SERVICE=ec2
export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/$SERVICE-controller/releases/latest | grep '"tag_name":' | cut -d'"' -f4 | cut -c 2-)
export ACK_SYSTEM_NAMESPACE=ack-system
export AWS_REGION=ap-northeast-2
helm install \
    -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller \
    oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart \
    --version=$RELEASE_VERSION \
    --set=aws.region=$AWS_REGION

 

IRSA 도 진행합니다.

eksctl create iamserviceaccount \
  --name ack-$SERVICE-controller \
  --namespace $ACK_SYSTEM_NAMESPACE \
  --cluster $CLUSTER_NAME \
  --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonEC2FullAccess`].Arn' --output text) \
  --override-existing-serviceaccounts --approve

# Controller 재실행
kubectl -n $ACK_SYSTEM_NAMESPACE rollout restart deploy ack-$SERVICE-controller-$SERVICE-chart

 

3.2. 리소스 Yaml 에 Annotation 추가

 

ACK 로 Multi Region 에 리소스를 배포하는 방법은 2가지가 있습니다.

1가지는 리소스 Yaml 에 직접 Region 과 관련한 Annotation 을 추가하는 것이고,
다른 1가지는 k8s Namespace 에 Annotation 을 추가해 Region 을 강제하는 것입니다.

 

이번에는 리소스 Yaml 파일에 Annotation 을 추가해보겠습니다.

metadata:
  annotations:
    services.k8s.aws/region: <AWS_REGION>

다음과 같이 us-east-1, ap-northeast-2 에 VPC를 만드는 Yaml 파일을 생성합니다.

cat <<EOF > vpc.yaml
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: VPC
metadata:
  name: vpc-ue1
  annotations:
    services.k8s.aws/region: us-east-1
spec:
  cidrBlocks: 
  - 10.0.0.0/16
  enableDNSSupport: true
  enableDNSHostnames: true
  tags:
    - key: Name
      value: vpc-ack-ue1
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: VPC
metadata:
  name: vpc-an2
  annotations:
    services.k8s.aws/region: ap-northeast-2
spec:
  cidrBlocks: 
  - 10.0.0.0/16
  enableDNSSupport: true
  enableDNSHostnames: true
  tags:
    - key: Name
      value: vpc-ack-an2
EOF
kubectl apply -f vpc.yaml

 

배포 후 AWS 콘솔에서 확인해봅니다.

각 리전에 배포된 것을 알 수 있습니다.

 

다음 실습을 위해 리소스를 삭제합니다.

 

kubectl delete -f vpc.yaml

 

3.3. Namespace 에 Annotation 추가

 

이번에는 Namespace 에 Annotation 을 추가하여 해당 Namespace 에 배포되는 리소스의 리전을 특정해보겠습니다.
만약 ACK 를 사용한다면, 이 방법이 더 유용할 것으로 판단됩니다.

 

다음과 같이 네임스페이스를 2개 생성하되, 각각 us-east-1 , ap-northeast-2 어노테이션을 달아줍니다.

cat <<EOF > ack-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ue1
  annotations:
    services.k8s.aws/default-region: us-east-1
---
apiVersion: v1
kind: Namespace
metadata:
  name: an2
  annotations:
    services.k8s.aws/default-region: ap-northeast-2
EOF

kubectl apply -f ack-ns.yaml
kubectl describe ns an2 ue1

 

 

VPC 배포

VPC 와 관련된 Yaml 파일을 생성하여 각각의 Namespace 에 배포해봅니다.

cat <<EOF > vpc2.yaml
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: VPC
metadata:
  name: vpc-ue1
  namespace: ue1
spec:
  cidrBlocks: 
  - 10.0.0.0/16
  enableDNSSupport: true
  enableDNSHostnames: true
  tags:
    - key: Name
      value: vpc2-ack-ue1
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: VPC
metadata:
  name: vpc-an2
  namespace: an2
spec:
  cidrBlocks: 
  - 10.0.0.0/16
  enableDNSSupport: true
  enableDNSHostnames: true
  tags:
    - key: Name
      value: vpc2-ack-an2
EOF
kubectl apply -f vpc2.yaml

 

각 Region 에 배포된 VPC 를 확인해봅니다.

kubectl get vpc -A

 

 

실습 후 리소스를 삭제합니다.

kubectl delete -f vpc2.yaml

 

4 ACK Drift 관리

 

Terraform 이나 CloudFormation 을 사용하다보면, 실제 AWS 환경과 IaC 코드가 일치하지 않아 문제가 많이 발생합니다.
ACK 를 통해서 AWS 리소스를 생성하고 관리할 때도 Drift 관리가 중요할 것입니다.

 

k8s 클러스터 외부에서 AWS 리소스의 환경 변화가 있을 때 ACK 가 어떻게 반응하는 지 살펴보겠습니다.

 

기본적으로 모든 ACK 컨트롤러는 10시간 마다 Drift 를 감지 시도를 진행합니다.
그 후, 사전에 적용된 yaml spec 내용에 따라 원상복구를 시도하게 됩니다.

 

ACK 컨트롤러의 values.yaml 에서 아래 리소스를 수정하면 Drift 감지 시간을 변경할 수 있습니다.

reconcile:
    defaultResyncPeriod: 1800 # 30 minutes (in seconds)
    resourceResyncPeriods:
        Bucket: 1800 # 30 minutes (in seconds)

 

 


참고 문서

 

 

 

Contents

포스팅 주소를 복사했습니다