데이터 플레인: 워커 노드로 구성되어 있어 컨테이너화된 애플리케이션의 구성 요소인 파드를 호스트
Kubernetes Objects(pod, service, deployment): 바라는 상태를 담은 레코드로 오브젝트를 생성하면 쿠버네티스의 컨트롤 플레인에서 오브젝트의 현재 상태와 바라는 상태를 일치시키기 위해 끊임없이 관리한다.
Amazon EKS
EKS: Kubernetes를 쉽게 실행할 수 있는 관리형 서비스로 EKS 사용시 컨트롤 플레인, 노드를 직접 설치, 운영, 유지할 필요가 없다.
애플리케이션에 대한 확장성 및 보안을 제공하는 서비스를 제공한다.
컨테이너 이미지 저장소인 Amazon ECR(Elastic Container Registry)
로드 분산을 위한 AWS ELB(Elastic Load Balancing)
인증을 위한 AWS IAM
격리된 Amazon VPC
실습 환경 구축
Administrator 사용자 분리
Cloud9 구성
AWS Cloud9으로 IDE 구성
IAM Role 생성
IDE(AWS Cloud9 인스턴스)에 IAM Role 부여
IDE에서 IAM 설정 업데이트
Kubectl 설치
그 외의 툴 설치
eksctl 설치
AWS Cloud9 추가 셋팅
Administrator 사용자 분리
Root User가 아닌 Administrator 계정을 생성해 해당 계정으로 로그인 한 후 작업을 진행한다.
Cloud9
브라우저만으로 코드를 작성, 실행 및 디버깅할 수 있는 클라우드 기반 IDE
Cloud9은 IAM credentials을 동적으로 관리한다. 이는 EKS IAM authentication과 호환되지 않기 때문에 비활성화하고 Cloud9에 IAM Role을 붙인다.
Cloud9 접속 -> Settings -> AWS SETTINGS -> Credentials off
IAM credentials, EKS IAM Authentication의 차이점
IAM Credentials (IAM 자격 증명):
IAM (Identity and Access Management) 은 AWS에서 사용자, 그룹 및 역할을 관리하는 서비스
IAM credentials는 AWS 리소스에 액세스할 때 필요한 액세스 키와 비밀 키로 구성
이러한 자격 증명은 정적으로 관리되며, 사용자가 직접 생성하거나 관리
예를 들어, AWS CLI, SDK 또는 다른 AWS 서비스에 액세스할 때 사용
AWS Cloud9은 일반적으로 이러한 IAM credentials를 동적으로 관리
EKS IAM Authentication (EKS IAM 인증):
Amazon EKS (Elastic Kubernetes Service) 는 Kubernetes 클러스터를 관리하기 위한 관리형 서비스
EKS IAM authentication은 Kubernetes 클러스터에 액세스할 때 사용되는 인증 방법
EKS 클러스터에 액세스하려면 Kubernetes kubeconfig 파일을 구성해야 한다 이 kubeconfig 파일은 aws-iam-authenticator 플러그인을 사용하여 생성된다
aws-iam-authenticator는 IAM credentials 대신 AWS IAM 역할을 사용하여 EKS 클러스터에 액세스한다
차이점:
IAM credentials는 AWS 리소스에 액세스할 때 사용되는 정적인 자격 증명
EKS IAM authentication은 Kubernetes 클러스터에 액세스할 때 사용되는 동적인 인증 방법
EKS IAM authentication은 aws-iam-authenticator 플러그인을 통해 IAM 역할을 활용하여 작동
kubectl 설치
kubectl: 쿠버네티스 클러스터에 명령을 내리는 CLI로 쿠버네티스는 오브젝트 관리를 위해 쿠버네티스 API를 사용하는데 kubectl CLI를 사용하면 해당 명령어가 쿠버네티스 API를 호출해 관련 동작을 수행한다.
eksctl 설치
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
export AWS_REGION=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r '.region')
# | 앞부분: 윗부분에서 가져온 토큰으로 region 검색
# 뒷부분: json 형식에서 region을 추출, 여기에서 나오는 정보는 다음과 같다.
# {
# "accountId" : "",
# "architecture" : "",
# "availabilityZone" : "",
# "billingProducts" : ,
# "devpayProductCodes" : ,
# "marketplaceProductCodes" : ,
# "imageId" : "",
# "instanceId" : "",
# "instanceType" : "",
# "kernelId" : ,
# "pendingTime" : "",
# "privateIp" : "",
# "ramdiskId" : ,
# "region" : "",
# "version" : ""
# }
echo "export AWS_REGION=${AWS_REGION}" | tee -a ~/.bash_profile
# tee: 결과값을 출력하면서 동시에 저장하는 명령어, echo는 출력은 되지 않는다.
aws configure set default.region ${AWS_REGION}
# 실습 진행되고 있는 리전을 기본 값으로 설정
aws configure get default.region
# 설정한 리전 값을 확인
export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
echo "export ACCOUNT_ID=${ACCOUNT_ID}" | tee -a ~/.bash_profile
wget https://gist.githubusercontent.com/joozero/b48ee68e2174a4f1ead93aaf2b582090/raw/2dda79390a10328df66e5f6162846017c682bef5/resize.sh
# 웹에서 파일 다운로드를 도와주는 유틸리티로 HTTP, HTTPS, FTP프로토콜을 이용해 웹서버에서 파일을 다운로드
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를 함꼐 사용한다.
추가로 해당 ip는 인스턴스 메타데이터를 검색하기 위한 것으로 를 확인하면 된다.
아무 설정 값을 주지 않고 eksctl create cluster를 실행하면 default parameter로 클러스터가 배포되지만, 몇 가지 값을 커스텀하게 주기 위해 구성 파일을 작성한다. 이는 오브젝트들의 바라는 상태를 쉽게 파악하고 관리할 수 있는 이점을 가져다준다. 를 참고하자.