nayoungs
항상 끈기있게
nayoungs
  • 분류 전체보기 (274)
    • Cloud (21)
      • AWS (15)
      • Azure (3)
      • NCP (2)
      • GCP (1)
    • DevOps (68)
      • Docker (16)
      • Kubernetes (50)
      • CICD (2)
    • IaC (25)
      • Ansible (17)
      • Terraform (8)
    • Certification (4)
    • 금융 IT (5)
    • AI (3)
    • Linux (47)
    • 미들웨어 (5)
    • Programming (7)
      • GoLang (3)
      • Spring (4)
    • CS (25)
      • 네트워크 (17)
      • 운영체제 (5)
      • Web (1)
      • 개발 상식 (2)
      • 데이터베이스 (0)
    • Algorithm (59)
      • 프로그래머스 (36)
      • 백준 (18)
      • 알고리즘 정리 (5)
    • ETC (5)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
nayoungs

항상 끈기있게

DevOps/Kubernetes

[Kubernetes] AWS EKS : Cluster Autoscaling 및 Container Insights 설정

2022. 6. 6. 22:19
728x90

 

📌Index

  • Cluster AutoScaling
  • 수동 스케일링
  • 자동 스케일링
  • CloudWatch Container Insight



✔️ Cluster AutoScaling

Kubernetes의 Cluster Autoscaling

Kubernetes는 Cluster AutoScaler를 통해 동적으로 인프라를 확장할 수 있다.

Kubernetes Cluster Autoscaler는 Pod가 실패하거나 다른 노드로 다시 예약될 때 클러스터의 노드 수를 자동으로 조정하며, Pod의 리소스 요청에 따라 클러스터의 노드를 추가하거나 제거한다.

만약 리소스 부족으로 인해 스케줄링 대기 상태(Pending)의 Pod가 존재하는 경우 Cluster AutoScaler가 노드를 추가한다.

추가 시, 설정한 Min, Max 값을 넘어가지 않도록 구성할 수 있다.



https://swalloow.github.io/eks-autoscale/

 

EKS AutoScaler

EKS의 AutoScaler는 AWS의 Auto Scaling Group을 활용한다.

ASG는 주기적으로 현재 상태를 확인하고 Desired State로 변화하는 방식으로 동작한다.

사용자는 클러스터 노드 수를 제한하는 Min, Max 값을 지정할 수 있다.



✔️ 수동 스케일링

eksctl scale 명령어를 사용하여, 노드를 수동으로 오토스케일링이 가능하다.

$ eksctl scale nodegroup --name [노드그룹명] --cluster [클러스터명] [flags]

flags 확인

$ eksctl scale nodegroup --cluster myeks-custom --help
Scale a nodegroup

Usage: eksctl scale nodegroup [flags]

Aliases: nodegroup, ng

General flags:
      --cluster string       EKS cluster name
  -n, --name string          Name of the nodegroup to scale
  -f, --config-file string   load configuration from a file (or stdin if set to '-')
  -N, --nodes int            desired number of nodes (required) (default -1)
  -M, --nodes-max int        maximum number of nodes (default -1)
  -m, --nodes-min int        minimum number of nodes (default -1)
  -r, --region string        AWS region. Defaults to the value set in your AWS config (~/.aws/config)
      --timeout duration     maximum waiting time for any long-running operation (default 25m0s)

AWS client flags:
  -p, --profile string         AWS credentials profile to use (defaults to value of the AWS_PROFILE environment variable)
      --cfn-role-arn string    IAM role used by CloudFormation to call AWS API on your behalf
      --cfn-disable-rollback   for debugging: If a stack fails, do not roll it back. Be careful, this may lead to unintentional resource consumption!

Common flags:
  -C, --color string   toggle colorized logs (valid options: true, false, fabulous) (default "true")
  -d, --dumpLogs       dump logs to disk on failure if set to true
  -h, --help           help for this command
  -v, --verbose int    set log level, use 0 to silence, 4 for debugging and 5 for debugging with AWS debug logging (default 3)

 

예시

Desired number of nodes(원하는 노드의 수)를 수정해보자.

현재 노드 그룹의 상태는 다음과 같고,

$ eksctl get nodegroup --cluster myeks-custom
CLUSTER         NODEGROUP       STATUS  CREATED                 MIN SIZE        MAX SIZE        DESIRED CAPACITY       INSTANCE TYPE    IMAGE ID        ASG NAME                                                TYPE
myeks-custom    myeks-ng1       ACTIVE  2022-06-05T14:41:31Z    2               4               3                      t3.medium        AL2_x86_64      eks-myeks-ng1-8ac09a28-288f-6ab0-5ff3-f759aa3af27a      managed

다음 명령을 통해 Desired number of nodes를 2로 수정할 수 있다.

eksctl scale nodegroup --name myeks-ng1 --cluster myeks-custom --nodes 2

DESIRED가 2로 변경된 것을 확인할 수 있다.

$ eksctl get nodegroup --cluster myeks-custom
CLUSTER         NODEGROUP       STATUS  CREATED                 MIN SIZE        MAX SIZE        DESIRED CAPACITY       INSTANCE TYPE    IMAGE ID        ASG NAME                                                TYPE
myeks-custom    myeks-ng1       ACTIVE  2022-06-05T14:41:31Z    2               4               2                      t3.medium        AL2_x86_64      eks-myeks-ng1-8ac09a28-288f-6ab0-5ff3-f759aa3af27a      managed



 

✔️ 자동 스케일링

AWS EKS AutoScaling 공식문서에 따라 진행해보자.

클러스터는 다음 yaml 파일로 생성하였고, IAM 정책 및 역할 생성까지 충족된 상태이다.

 

myeks.yaml

apiVersion: eksctl.io/v1alpha5 
kind: ClusterConfig 

metadata:
  name: myeks-custom #cluster 이름
  region: ap-northeast-2 
  version: "1.22"

# 가용영역 지정
availabilityZones: ["ap-northeast-2a", "ap-northeast-2b",  "ap-northeast-2c"]

#IAM 계정을 만들어 연결
iam:
  withOIDC: true #OIDC(OpenID Connect) : eks입장에서 AWS IAM은 외부인증서버이기 때문에 OIDC를 true로 하지 않으면 
                 #                       AWS 계정과 eks 계정은 완전히 별개이다.
  serviceAccounts: #SA 계정 생성 -> 이후 addon 추가할 때 필요
    - metadata:
        name: aws-load-balancer-controller #SA 계정 이름
        namespace: kube-system
      wellKnownPolicies:
        awsLoadBalancerController: true #계정에 권한 부여 : ingress를 만들 때 사용
    - metadata:
        name: ebs-csi-controller-sa #SA 계정 이름
        namespace: kube-system
      wellKnownPolicies:
        ebsCSIController: true #계정에 권한 부여 : ebs
    - metadata: 
        name: cluster-autoscaler #SA 계정 이름
        namespace: kube-system
      wellKnownPolicies:
        autoScaler: true #계정에 권한 부여

# Managed Node Groups : worker node 그룹
managedNodeGroups: #여러개 세팅 가능
  # On-Demand Instance
  - name: myeks-ng1
    instanceType: t3.medium
    minSize: 2
    desiredCapacity: 3 #cluster 오토스케일링된다
    maxSize: 4
    privateNetworking: true #기본적으로 EC2는 public에 배치된다(앞서 EXTERNAL-IP 부여된 것 확인했었다)
                            #외부에 노출되는 것은 위험하기 때문에 private 배치애햐한다
    ssh:
      allow: true 
      publicKeyPath: ./keypair/myeks.pub  #접속할 ssh 키
    availabilityZones: ["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c"]
    iam:
      withAddonPolicies: #IAM 계정 정책
        autoScaler: true
        albIngress: true
        cloudWatch: true #로그를 남기기 위해
        ebs: true

# Fargate Profiles
fargateProfiles:
  - name: fg-1
    selectors:
    - namespace: dev
      labels:
        env: fargate
        
        
# CloudWatch Logging
cloudWatch:
  clusterLogging:
    enableTypes: ["*"]

 

먼저 Cluster Autoscaler YAMl 파일을 다운로드한다.

curl -o cluster-autoscaler-autodiscover.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml

 

다음으로 cluster-autoscaler-autodiscover.yaml에서 <YOUR CLUSTER NAME>을 클러스터명으로 수정한다.

앞선 클러스터 yaml 파일에서 확인할 수 있듯이 본 실습에서는 myeks-custom이다.

 

163: - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/myeks-custom

그리고 수정 사항을 적용한다.

 

kubectl apply -f cluster-autoscaler-autodiscover.yaml

cluster-autoscaler가 배포된 것을 확인할 수 있다.

 

$ kubectl get po -n kube-system
NAME                                  READY   STATUS    RESTARTS   AGE
...
cluster-autoscaler-66d46c46d4-2vsz8   1/1     Running   0          2m19s
...

다음 명령어를 실행했을 때, annotation이 정상적으로 들어가 있기 때문에 따로 수정할 필요는 없다.

만약 설정이 안 되어있다면 annotaion을 반드시 설정해주자.

 

kubectl describe sa cluster-autoscaler -n kube-system

 

다음으로 deployment에 cluster-autoscaler.kubernetes.io/safe-to-evict annotaion을 추가한다.

 

kubectl -n kube-system edit deployment.apps/cluster-autoscaler

spec.template.metadata.annotations

...
spec:
...
  template:
    metadata:
      annotations:
        cluster-autoscaler.kubernetes.io/safe-to-evict: "false" #추가하기
...

spec.containers.command의 <YOUR CLUSTER NAME>를 클러스터의 이름(myeks-custom)으로 교체하고 다음 옵션을 추가한다.

  • --balance-similar-node-groups
  • --skip-nodes-with-system-pods=false
      - command:
        - ./cluster-autoscaler
        - --v=4
        - --stderrthreshold=info
        - --cloud-provider=aws
        - --skip-nodes-with-local-storage= "false"
        - --expander=least-waste
        - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/myeks-custom #클러스터명 수정
        - --balance-similar-node-groups #옵션 추가
        - --skip-nodes-with-system-pods=false #옵션 추가

 

다음으로 웹 브라우저의 GitHub에서 Cluster Autoscaler [릴리스(releases)] 페이지를 열고 클러스터의 Kubernetes 메이저 및 마이너 버전과 일치하는 최신 Cluster Autoscaler 버전을 검색하여,

해당 버전으로 image를 수정한다. 현시점(2022.6)에서는 v1.22.2이다.

 

kubectl set image deployment cluster-autoscaler -n kube-system cluster-autoscaler=k8s.gcr.io/autoscaling/cluster-autoscaler:v1.22.2

 

Cluster Autoscaler를 deploy 한 후에 로그를 확인하여 제대로 동작하는지 확인한다.

 

kubectl -n kube-system logs -f deployment.apps/cluster-autoscaler

 

 

💻 실습

다음과 같이 deployment myweb-deploy를 생성한다.

 

sample.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb:alpine
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 200m
              memory: 200M
            limits:
              cpu: 200m
              memory: 200M
kubectl create -f sample.yaml

현재 파드가 2개인 것을 확인할 수 있다.

$ kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
myweb-deploy-5c4cbfd766-kjfzr   1/1     Running   0          40s
myweb-deploy-5c4cbfd766-mlj9f   1/1     Running   0          40s

다음과 같이 deployment의 replicase를 10으로 수정한다.

kubectl scale deploy myweb-deploy --replicas=10

현재 노드는 2개가 존재하고, 파드를 확인해보면 다음과 같다.

$ kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
myweb-deploy-5c4cbfd766-2php6   0/1     Pending   0          4s
myweb-deploy-5c4cbfd766-2xhzz   1/1     Running   0          4s
myweb-deploy-5c4cbfd766-2zx99   1/1     Running   0          4s
myweb-deploy-5c4cbfd766-77zsk   1/1     Running   0          4s
myweb-deploy-5c4cbfd766-9b7np   1/1     Running   0          4s
myweb-deploy-5c4cbfd766-fg92v   1/1     Running   0          10s
myweb-deploy-5c4cbfd766-rv66k   0/1     Pending   0          4s
myweb-deploy-5c4cbfd766-rwxnw   1/1     Running   0          4s
myweb-deploy-5c4cbfd766-wmxm8   1/1     Running   0          10s
myweb-deploy-5c4cbfd766-xmrvp   0/1     Pending   0          4s

cpu 리소스가 부족하여, 노드에 배치되지 못한 Pending 상태의 파드가 있는 것이다.

$ eksctl get nodegroup --cluster myeks-custom
CLUSTER         NODEGROUP       STATUS  CREATED                 MIN SIZE        MAX SIZE        DESIRED CAPACITY       INSTANCE TYPE    IMAGE ID        ASG NAME                                                TYPE
myeks-custom    myeks-ng1       ACTIVE  2022-06-05T14:41:31Z    2               4               2                      t3.medium        AL2_x86_64      eks-myeks-ng1-8ac09a28-288f-6ab0-5ff3-f759aa3af27a      managed

pending 상태의 파드를 임의로 한 개 선택하여 kubectl describe 명령어로 Events를 보면

2 Insufficient cpu와 pod triggered scale-up을 확인할 수 있다.

 

Events:
  Type     Reason            Age   From                Message
  ----     ------            ----  ----                -------
  Waring  FailedScheduling  15s   default-scheduler   0/2 nodes are available: 2 Insufficient cpu.
  Normal   TriggeredScaleUp  9s    cluster-autoscaler  pod triggered scale-up: [{eks-myeks-ng1-8ac09a28-288f-6ab0-5ff3-f759aa3af27a 2->3 (max: 4)}]

시간이 좀 더 지나면 node가 오토 스케일링되어 개수가 증가하고,

$ kubectl get nodes
NAME                                                STATUS   ROLES    AGE     VERSION
ip-192-168-100-17.ap-northeast-2.compute.internal   Ready    <none>   13m     v1.22.6-eks-7d68063
ip-192-168-135-92.ap-northeast-2.compute.internal   Ready    <none>   6h33m   v1.22.6-eks-7d68063
ip-192-168-185-60.ap-northeast-2.compute.internal   Ready    <none>   27m     v1.22.6-eks-7d68063

파드가 모두 배치되어 Running 상태가 된 것을 확인할 수 있다.

$ kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
myweb-deploy-5c4cbfd766-2php6   1/1     Running   0          2m44s
myweb-deploy-5c4cbfd766-2xhzz   1/1     Running   0          2m44s
myweb-deploy-5c4cbfd766-2zx99   1/1     Running   0          2m44s
myweb-deploy-5c4cbfd766-77zsk   1/1     Running   0          2m44s
myweb-deploy-5c4cbfd766-9b7np   1/1     Running   0          2m44s
myweb-deploy-5c4cbfd766-fg92v   1/1     Running   0          2m50s
myweb-deploy-5c4cbfd766-rv66k   1/1     Running   0          2m44s
myweb-deploy-5c4cbfd766-rwxnw   1/1     Running   0          2m44s
myweb-deploy-5c4cbfd766-wmxm8   1/1     Running   0          2m50s
myweb-deploy-5c4cbfd766-xmrvp   1/1     Running   0          2m44s



✔️ CloudWatch Container Insight

EKS에서 Conatiner Insight 기능을 사용하면 Prometheus, EFK를 구성하지 않더라도

기본적인 모니터링과 로깅이 가능하다.

 

Container-Insights-setup-EKS-quickstart에 따라 진행해보자. 본 실습에서는 Fluent Bit를 사용한다.

shell을 사용 중이라면 바로 다음 명령을 실행하면 되고,

글쓴이는 windows에서 실습 중이라, bash를 실행하기 위해 Git Bash를 사용했다.

👉 Git Bash 설치하기

 

ClusterName=myeks-custom
RegionName=ap-northeast-2
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
curl https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluent-bit-quickstart.yaml | sed 's/{{cluster_name}}/'${ClusterName}'/;s/{{region_name}}/'${RegionName}'/;s/{{http_server_toggle}}/"'${FluentBitHttpServer}'"/;s/{{http_server_port}}/"'${FluentBitHttpPort}'"/;s/{{read_from_head}}/"'${FluentBitReadFromHead}'"/;s/{{read_from_tail}}/"'${FluentBitReadFromTail}'"/' | kubectl apply -f - 

amazon-cloudwatch 네임스페이스에 cloudwatch-agent와 fluent-bit를 확인할 수 있다.

fluent bit가 로그를 수집하고, cloudwatch로 전송시킨다.

 

$ kubectl get po -n amazon-cloudwatch
NAME                     READY   STATUS    RESTARTS   AGE
cloudwatch-agent-kgjwq   1/1     Running   0          63s
cloudwatch-agent-r68pk   1/1     Running   0          63s
fluent-bit-ht594         1/1     Running   0          63s
fluent-bit-rwsjb         1/1     Running   0          63s

 

AWS CloudWatch를 콘솔로 접속해보면 다음과 같이 로그 그룹들을 확인할 수 있다.

  • /aws/eks/myeks-custom/cluster : ControlPlane의 로그
  • /aws/containerinsights/myeks-custom/application : 애플리케이션의 로그
  • /aws/containerinsights/myeks-custom/host : 호스트의 로그
  • /aws/containerinsights/myeks-custom/performance : 성능 데이터 수집 로그

로그들은 만기가 없고, 계속 쌓이기 때문에 잘 관리해주어야 한다.

[인사이트] - [Container Insights]를 클릭하면 다음과 같은 정보들을 확인할 수 있다.

Prometheus를 사용하지 않더라도 CPU/Memory 리소스량 등을 확인할 수 있는 것이다.

다음과 같이 컨테이너 맵도 확인할 수 있으며,

Performance monitoring도 가능하다.

 

실습이 끝나고 cluster와 로그를 삭제하는 것을 잊지 말자.

eksctl delete cluster -f .\myeks.yaml --force --disable-nodegroup-eviction

 

Prometheus 및 EFK를 구성하는 내용은 아래의 포스팅에서 확인할 수 있다.

  • k8s Logging : EFK 개요 및 설치
  • k8s monitoring : Helm으로 Prometheus, Grafana 설치하기




Reference

더보기
  • https://swalloow.github.io/eks-autoscale/
  • AutoScaling - Amazon EKS

 

 

728x90
저작자표시 비영리 (새창열림)
    'DevOps/Kubernetes' 카테고리의 다른 글
    • [Kubernetes] Kubernetes Patterns : Singleton Pattern
    • [Kubernetes] k8s HA(고가용성) 클러스터 구축하기 : stacked etcd
    • [Kubernetes] k8s Monitoring : Metrics-Server
    • [Kubernetes] AWS EKS : EBS CSI(Container Storage Interface) Driver 설치하기
    nayoungs
    nayoungs
    안되면 될 때까지

    티스토리툴바