EKS 클러스터를 배포하는 방식 중 하나로 AWS콘솔, CloudFormation, CDK, eksctl, Terraform 등의 대안이 존재한다.
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
AWS Cloud9 추가 셋팅하기
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# -s: 결과 화면 출력 X
# -X: 태그 없이 요청을 보내면 GET 요청이 들어가고 그 외의 Post등은 지정할 수 있는데 PUT는 존재하지 않는다.
# -H: header
아무 설정 값을 주지 않고 eksctl create cluster를 실행하면 default parameter로 클러스터가 배포되지만, 몇 가지 값을 커스텀하게 주기 위해 구성 파일을 작성한다. 이는 오브젝트들의 바라는 상태를 쉽게 파악하고 관리할 수 있는 이점을 가져다준다. 링크를 참고하자.
cat << EOF > eks-demo-cluster.yaml
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: eks-demo # 생성할 EKS 클러스터명
region: ${AWS_REGION} # 클러스터를 생성할 리전
version: "1.27"
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에 대한 권한 추가
cloudWatch:
clusterLogging:
enableTypes: ["*"]
iam:
withOIDC: true
EOF
eksctl create cluster -f eks-demo-cluster.yaml
콘솔 크레덴셜 더하기
위의 클러스터는 cloud9의 IAM credentials를 통해 생성했기 때문에 해당 클러스터 정보를 확인하기 위해서는 실제 콘솔에 접근할 IAM entity의 AWS Console credentials을 클러스터에 추가하는 작업이 필요하다.
Instance(default): 클러스터 내의 노드를 ALB의 대상으로 등록, ALB 트래픽은 NodePort로 라우팅 된 다음 파드로 프록시
IP: 파드를 ALB의 대상으로 등록, ALB 트래픽은 파드로 직접 라우팅, 해당 모드 사용을 위해선 Ingress.yaml파일을 수정해야 한다.
AWS Load Balancer를 배포하기 전 controller가 워커 노드 위에서 동작하기 때문에 IAM permissions를 통해 AWS ALB/NLB 리소스에 접근할 수 있도록 IAM permissions는 ServiceAccount를 위한 IAM roles를 설치하거나 워커 노드의 IAM roles에 직접 붙일 수 있다.
로드밸런서 컨트롤러 배포 전 클러스터에 대한 IAM OIDC identity provider를 생성해야 한다. 쿠버네티스가 직접 관리하는 사용자 계정인 service Account에 IAM role을 사용하기 위해 생성된 클러스터에 IAM OIDC provider가 존재해야 한다.
eksctl utils associate-iam-oidc-provider \
--region ${AWS_REGION} \
--cluster eks-demo \
--approve
# IAM Open ID Connect provider is already associated with cluster "eks-demo" in "ap-northeast-2"
AWS Load Balancer Controller에 부여할 IAM Policy를 생성하는 작업
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml
# 우선 인증서 구성을 웹훅에 삽입할 수 있게 cert-manager를 설치
curl -Lo v2_5_4_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.5.4/v2_5_4_full.yaml
# Load balancer controller yaml 파일을 다운로드
sed -i.bak -e '596,604d' ./v2_5_4_full.yaml
# 매니페스트 파일의 ServiceAccount 섹션을 제거하는데 이 과정이 없다면 이전 단계에서 작업한 service account의 필수 annotation이 덮어씌워진다.
sed -i.bak -e 's|your-cluster-name|eks-demo|' ./v2_5_4_full.yaml
# Deployment 섹션의 my-cluster를 현재 eks실습에 사용되는 클러스터 이름으로 변경
kubectl apply -f v2_5_4_full.yaml
# AWS Load Balancer Controller 파일을 배포
curl -Lo v2_5_4_ingclass.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.5.4/v2_5_4_ingclass.yaml
# IngressClass 및 IngressClassParams 매니페스트를 다운로드하고 클러스터에 매니페스트를 적용
kubectl apply -f v2_5_4_ingclass.yaml
# 해당 명령어로 관련 로그를 확인 가능
ALBPOD=$(kubectl get pod -n kube-system | egrep -o "aws-load-balancer[a-zA-Z0-9-]+")
kubectl describe pod -n kube-system ${ALBPOD}
# 해당 명령어로 자세한 속성 값을 파악할 수 있다.
속성 값
Name: aws-load-balancer-controller-85f7c7f8c4-j7g9w Namespace: kube-system Priority: 2000000000 Priority Class Name: system-cluster-critical Service Account: aws-load-balancer-controller Node: ip-10-0-166-71.ap-northeast-2.compute.internal/10.0.166.71 Start Time: Sun, 21 Apr 2024 08:05:25 +0000 Labels: app.kubernetes.io/component=controller app.kubernetes.io/name=aws-load-balancer-controller pod-template-hash=85f7c7f8c4 Annotations: Status: Running IP: 10.0.173.1 IPs: IP: 10.0.173.1 Controlled By: ReplicaSet/aws-load-balancer-controller-85f7c7f8c4 Containers: controller: Container ID: containerd://536d81b3b7a0360a0f8ba25108755e91931270590abb5886cde222216789666b Image: public.ecr.aws/eks/aws-load-balancer-controller:v2.5.4 Image ID: public.ecr.aws/eks/aws-load-balancer-controller@sha256:764a2a43208b2d221883570eeb72647c7facc1988e1ef7ef388442272d8a980d Port: 9443/TCP Host Port: 0/TCP Args: --cluster-name=eks-demo --ingress-class=alb State: Running Started: Sun, 21 Apr 2024 08:05:29 +0000 Ready: True Restart Count: 0 Limits: cpu: 200m memory: 500Mi Requests: cpu: 100m memory: 200Mi Liveness: http-get http://:61779/healthz delay=30s timeout=10s period=10s #success=1 #failure=2 Environment: AWS_STS_REGIONAL_ENDPOINTS: regional AWS_DEFAULT_REGION: ap-northeast-2 AWS_REGION: ap-northeast-2 AWS_ROLE_ARN: arn:aws:iam::566620743708:role/eksctl-eks-demo-addon-iamserviceaccount-kube--Role1-IWCN8BROTASH AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token Mounts: /tmp/k8s-webhook-server/serving-certs from cert (ro) /var/run/secrets/eks.amazonaws.com/serviceaccount from aws-iam-token (ro) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-vczsc (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: aws-iam-token: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 86400 cert: Type: Secret (a volume populated by a Secret) SecretName: aws-load-balancer-webhook-tls Optional: false kube-api-access-vczsc: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: DownwardAPI: true QoS Class: Burstable Node-Selectors: Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 10m default-scheduler Successfully assigned kube-system/aws-load-balancer-controller-85f7c7f8c4-j7g9w to ip-10-0-166-71.ap-northeast-2.compute.internal Warning FailedMount 10m kubelet MountVolume.SetUp failed for volume "cert" : secret "aws-load-balancer-webhook-tls" not found Normal Pulling 10m kubelet Pulling image "public.ecr.aws/eks/aws-load-balancer-controller:v2.5.4" Normal Pulled 10m kubelet Successfully pulled image "public.ecr.aws/eks/aws-load-balancer-controller:v2.5.4" in 3.377368838s (3.377390734s including waiting) Normal Created 10m kubelet Created container controller Normal Started 10m kubelet Started container controller
서비스 배포하기
웹 서비스를 구성하는 백, 프론트를 EKS에 배포할 것인데 각 서비스 배포 순서는 아래와 같다.
소스 코드 다운로드
Amazon ECR에 각 서비스에 대한 리포지토리 생성
Dockerfile을 포함한 소스 코드 위치에서 컨테이너 이미지 빌드 후, 리포지토리에 푸시
각 서비스에 대한 Deployment, Service, Ingress 매니페스트 파일 생성 및 배포
사용자의 접근 순서
순서대로 deployment -> service -> ingress yaml 파일을 작성해준다.
Amazon CloudWatch Container Insight: 컨테이너형 애플리케이션 및 마이크로 서비스에 대한 모니터링, 트러블 슈팅 및 알람을 위한 완전 관리형 관측 서비스로 cloudwatch콘솔에서 자동화된 대시보드를 통해 container metrics, Prometeus metrics, application logs와 performance log evenets를 탐색, 분석, 시각화할 수 있다.
ECS, EKS, ECS Fargate, EC2위에 구동되는 k8s클러스터에서 사용 가능하다.
우선 매니페스트 파일을 관리하기 위한 폴더를 만들어주고
cd ~/environment
mkdir -p manifests/cloudwatch-insight && cd manifests/cloudwatch-insight
kubectl create ns amazon-cloudwatch
# amazon-cloudwatch라는 네임스페이스를 생성한다.
ClusterName=eks-demo
RegionName=$AWS_REGION
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
# 설정 값들을 명명해주고
wget 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
# yaml파일을 등록
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: eks.amazonaws.com/compute-type
operator: NotIn
values:
- fargate
# spec 밑에 위의 내용을 추가
kubectl apply -f cwagent-fluent-bit-quickstart.yaml
# 파일을 디플로이
이렇게 해주면 cloudwatch 콘솔에서 Container Insights를 통해 리소스 리스트들을 확인할 수 있다.
Autoscaling Pod & Cluster
쿠버네티스는 두 가지의 오토스케일링 기능이 있다.
HPA(Horizontal Pod AutoScaler)
Cluster Autoscaler HPA는 CPU 사용량 또는 사용자 저으이 메트릭을 관찰해 파드 개수를 자동으로 스케일링하지만 파드가 올라가는 EKS 클러스터 자체 자원이 모자라게 되는 경우 Cluster Autoscaler를 고려해야 한다.
HPA를 사용해 파드 스케일링 적용하기
쿠버네티스 metric server를 생성한다. Metrics Server는 쿠버네티스 클러스터 전체의 리소스 가용 데이터를 집계한다. 각 워커노드에 설치된 kubelet을 통해 워커 노드나 컨테이너의 CPU및 메모리 사용량 같은 메트릭을 수집한다.
해당 명령어로 이전에 생성한 파드를 삭제하면 워커 노드가 스케일인 되는 것을 확인할 수 있다.
kubectl delete deployment autoscaler-demo
CI/CD for EKS cluster
EKS 클러스터, Kubernetes를 위한 CI/CD
빠르고 쉽고 자동화가 가능한 툴
이 목표에 따라 application 소스와 k8s manifests의 변경사항이 발생할 때마다 자동으로 Github Action을 통해 빌드/통합하고, 통합된 배포 대상을 ArgoCD를 통해 k8s 클러스터에 배호하는 gitops 파이프라인을 만드는 과정으로 k8s manifests를 통합/패키징 하는 도구로 Kustomize를 사용하고 kubernetes manifest 정적 분석을 위해 Checkov와 Trivy를 함께 사용해 클러스터의 보안을 향상시킬 수 있다.
EKS 클러스터, kubernetes를 위한 CI/CD with HELM / CDK
CodeCommit에 위치한 application 소스와 Helm Chart의 변경 사항이 발생될 때마다 자동으로 CodeBuild를 통해 빌드/통합(Continous Integeration)하고, 통합된 배포 대상을 ArgoCD를 통해 k8s 클러스터에 배포하는 일종의 gitops 파이프라인을 만드는 과정을 할 것이고 k8s manifests를 통합/패키징 하는 도구로 Helm을 사용하고 컨테이너 이미지 및 kubernetes manifest 정적 분석을 위해 Checkov와 Trivy를 함꼐 사용한다.