Cloud

Amazon EKS Tutorial - Part.6

Operation CWAL 2021. 3. 22. 22:39

Cluster Autoscaler

이번 시간엔 K8s 클러스터 Worker Node의 갯수를 유동적으로 늘리거나 줄일 수 있는 Cluster Autoscaler에 대해서 알아보자. 이 기능은 AWS가 아닌 Kubernetes에서 진행중인 공식 프로젝트 중 하나이며, 다음과 같은 상황에서 클러스터의 사이즈가 자동으로 조절된다.

  • Resource가 부족하여 Pod을 생성할 수 없는 경우 => 새로운 Worker Node 추가
  • 일정 시간 동안 Resource 사용량이 기준에 못미친 Node 발생 => 해당 Node 제거

Cluster Autoscaler를 설치하기 전, K8s와 AWS의 권한과 관련된 IRSA의 개념을 설명하고 넘어가겠다.  

IRSA

모든 Pod은 ServiceAccount(SA)가 존재하며, 해당 SA에 적절한 Role을 Binding함으로써 K8s 리소스에 대한 접근이 가능하다. 그렇다면 SA를 통해 Pod에서 AWS 서비스를 사용할 수 있을까? 예를 들어, Pod에서 'aws s3 ls' 같은 명령어를 실행하거나, 특정 Auto Scaling Group의 desired count를 늘리는 등의 동작을 생각해볼 수 있다. 상당히 어려워 보이는 이야기같지만 정답을 먼저 말하자면 'Yes'이다. AWS는 IAM Role for ServiceAccount 또는 IRSA라는 서비스를 제공하여, K8s SA와 AWS IAM Role을 매칭하는 방식으로 이 기능을 지원한다. IRSA가 소개되기 전까지는 EKS Node에 IAM Role을 할당하는 방식을 사용하였으나 이는 'Least Privilleges' 원칙에 위배되므로 Deprecated 되었다. 자세한 내용은 AWS User Guide를 참고하길 바란다. 참고로 IRSA는 아래와 같은 프로세스로 동작한다.

 

1. Pod 생성시, K8s API 서버로부터 EKS Pod Identity Webhook으로 Manifest를 전달

2. 해당 Pod에 설정한 ServiceAccount에 'eks.amazonaws.com/role-arn' annotation이 존재할 경우, webhook을 통해 IAM Role 관련 환경변수(AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE)가 Injection된다. 또한 JWT 토큰을 저장할 'aws-iam-token' 볼륨을 Pod에 마운트한다.

3. OIDC로부터 ServiceAccount를 인증, JTW 토큰을 가져와 'AWS_WEB_IDENTITY_TOKEN_FILE' 경로에 저장한다.

4. AWS 리소스 접근시, 'AWS_WEB_IDENTITY_TOKEN_FILE' 경로의 토큰으로 'sts:assume-role-with-web-identity'를 수행하여 IAM Role을 획득한다.

 

실습

실습에 앞서 아래 명령어로 새로운 EKS 클러스터를 생성한다. Cluster Autoscaling 기능을 테스트하기 위해 'workers' nodegroup의 max 값을 5로 설정하였다. 물론 기존 클러스터를 사용하고 싶은 경우, AWS 콘솔이나 eksctl 명령어로 해당 설정을 변경할 수 있다.

eksctl create cluster --name eks-from-eksctl --version 1.19 --region ap-northeast-2 \
--nodegroup-name workers --node-type t3.medium --nodes 2 --nodes-min 1 --nodes-max 5 \
--ssh-access --ssh-public-key eks-access --managed

 

ASG Tag 확인 

Cluster Autoscaler가 ASG의 Desired Count를 변경하기 위해선 해당 ASG에 auto-discovery를 위한 특정 태그 2개가 미리 정의되어야 한다.

k8s.io/cluster-autoscaler/enabled = true
k8s.io/cluster-autoscaler/<YOUR_CLUSTER_NAME> = owned

실제로 'AWS 콘솔 > Auto Scaling Group' 메뉴에서 EKS Nodegroup을 확인하면 아래와 같이 태그가 존재하는 것을 확인할 수 있다.

EKS Managed Nodegroup으로 생성한 경우, 자동으로 위 태그들을 추가하기 때문에 따로 작업할 필요가 없지만 Unmanaged라면 사용자가 직접 추가해줘야 한다.

 

IAM Policy 및 IRSA 추가

Cluster Auto Scaler가 ASG를 접근하기 위해선 아래와 같은 권한들이 필요하다. 'AWS 콘솔 > IAM > Policies' 메뉴에서 아래 내용의 Policy를 추가한다. 필자는 이 Policy의 이름을 'EKSClusterAutoScalerPoilicy'라고 지었다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "autoscaling:DescribeAutoScalingGroups",
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeLaunchConfigurations",
                "autoscaling:DescribeTags",
                "autoscaling:SetDesiredCapacity",
                "autoscaling:TerminateInstanceInAutoScalingGroup",
                "ec2:DescribeLaunchTemplateVersions"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

다음은 Cluster Autoscaler를 위한 ServiceAccount와 IAM Role을 생성하고, 둘을 IRSA로 엮어야 한다. 다행히도 eksctl은 이 과정을 매우 간단하게 처리해주는 기능도 제공해주고 있다. 우선 인증을 위한 OIDC를 생성하고, 그 다음 IRSA를 처리하도록 하자. 명령어는 다음과 같다.

eksctl utils associate-iam-oidc-provider \
            --region=ap-northeast-2 \
            --cluster=eks-from-eksctl \
            --approve

eksctl create iamserviceaccount \
                --name eks-cluster-autoscaler \
                --namespace kube-system \
                --cluster eks-from-eksctl \
                --attach-policy-arn arn:aws:iam::199137616366:policy/EKSClusterAutoScalerPoilicy \
                --approve \
                --region ap-northeast-2
  • --name: Cluster Autoscaler에서 사용할 ServiceAccount 이름
  • --namespace: kube-system namespace에 해당 ServiceAccount를 생성해야 한다
  • --cluster: IRSA 적용할 EKS Cluster 이름
  • --attach-policy-arn: 위에서 생성한 IAM Policy의 ARN을 입력한다
  • --approve: --dry-run이 아닌 실제 수행
  • --region: EKS Cluster가 위치한 Region

여기까지 진행했다면 IAM Role과 ServiceAccount가 아래처럼 생성되어야 한다.

IAM Role
ServiceAccount

 

Cluster Autoscaler 설치

Cluster Autoscaler는 Helm 차트를 통해 쉽게 설치 가능하다. 우선 현재 클러스터 환경에 맞게 values 파일(overrides.yaml)을 아래 내용으로 추가한다.

awsRegion: ap-northeast-2
rbac:
  create: true
  serviceAccount:
    create: false
    name: eks-cluster-autoscaler
autoDiscovery:
  clusterName: eks-from-eksctl
  enabled: true

다음 명령어로 Cluster Autoscaler를 kube-system namespace에 설치할 수 있다.

helm install cluster-autoscaler \
    stable/cluster-autoscaler \
    --namespace kube-system \
    --values overrides.yaml

제대로 생성되었는지 확인해보자.

 

테스트

다음과 같이 spec상으로 많은 리소스를 요구하는 Deployment를 정의한다. 당장은 replica 1개로만 배포하며, 이후 'kubectl scale' 명령어로 10개까지 늘렸을 때, Worker Node도 같이 증가하는지 확인하고자 한다. 참고로 현재 Worker는 단 2개만 존재하는 상태다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-scaling
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-scaling
  template:
    metadata:
      labels:
        service: test-scaling
        app: test-scaling
    spec:
      containers:
      - image: nginx
        name: test-scaling
        resources:
          limits:
            cpu: 2500m
            memory: 2500Mi
          requests:
            cpu: 1400m
            memory: 1400Mi

 

이제 replica를 10개로 늘려보겠다. 리소스 부족으로 배치할 수 있는 Worker가 없기 때문에 대부분의 Pod이 바로 생성되진 못하고 새로운 worker node가 추가되기 전까진, Pending 상태로 남아있게 된다.

kubectl scale --replicas=10 deployment/test-scaling

이 상태에서 'AWS 콘솔 > EC2 > Instances' 메뉴를 확인해보면 3개의 Instance가 생성 중임을 확인할 수 있다. 

1~2분 정도 더 기다린 뒤, 'kubectl get no' 명령어로 K8s Worker Node를 체크해보았다.

현재 클러스터에 총 5개의 Worker Node가 존재하며 3개는 Cluster Autoscaler에 의해 새로 추가된 것을 알 수 있다. 그리고 4개 정도의 Pod이 생성되지 못한채 아직 Pending 상태로 남아있지만, Nodegroup의 max가 5로 설정되어 있기 때문에 그 이상은 추가할 수 없다.

 

마치며...

설명한 것처럼 Cluster Autoscaler는 Cloud 환경에서 Kubernetes를 구축하였을 때의 강점을 최대한으로 보여주는 기능 이다. 또한 나중에 설명할 HPA(Horizontal Pod Autoscaler)와의 시너지 효과를 통해 많은 작업량도 유동적으로 처리할 수 있기 때문에 Kubernetes 사용자라면 꼭 알아두길 바란다.

 

참고

 

 

'Cloud' 카테고리의 다른 글

Amazon RDS - 개요  (0) 2021.11.05
Container Vs. VM  (0) 2021.06.26
Amazon EKS Tutorial - Part.5  (0) 2021.03.20
Amazon EKS Tutorial - Part.4  (0) 2021.03.17
Amazon EKS Tutorial - Part.3  (0) 2021.03.16