[AWES 3기] 9주차 스터디 내용 정리

ajufresh·2일 전
0

해당 워크샵은 Amazon EKS Upgrades: Strategies and Best Practices
를 기반으로 진행하는 AWES 스터디에서 진행한 내용입니다.

K8S Upgrade

1년에 3개의 마이너 버전 출시 → 최근 3개 버전 release branches(패치) 지원하기 때문에 업데이트가 필요함

[가상의 온프레미스 환경 K8S 에서 업그레이드 계획 짜기]

환경 구성

  • ControlPlane * 3EA (with LB)
  • DataPlane * 3EA (with LB)

  • Ubuntu 22.04 (kernel 5.15)
  • Containerd 1.7.z
  • K8S Version 1.28.2 - kubeadm, kubelet
  • CNI : Cilium 1.4.z
  • CSI : OpenEBS 3.y.z
  • 애플리케이션 및 요구사항 확인 : 현황 조사 후 작성…
    => 목표 버전이 k8s 1.32 일 때 ...

1. 버전 호환성 검토
1. K8S(kubelet, apiserver..) 1.32 요구 커널 버전 확인 : 예) user namespace 사용 시 커널 6.5 이상 필요 - Docs
2. containerd 버전 조사 : 예) user namespace 에 대한 CRI 지원 시 containerd v2.0 및 runc v1.2 이상 필요 - Docs
3. CNI(Cilium) 요구 커널 버전 확인 : 예) BPF-based host routing 기능 필요 시 커널 5.10 이상 필요 - Docs
- CNI 이 지원하는 K8S 버전 확인 - Docs
4. CSI
5. 애플리케이션 요구사항 검토

2. 업그레이드 방법 결정

  • in-place: 기존의 클러스터 상에서 버전을 올리는 것
  • blue-green: 온프레미스 클러스터 set을 하나 더 만들어서 앞단의 LB에서 바꿔주는 것

3. 결정된 방법으로 업그레이드 계획 수립

4. 사전 준비
1. (옵션) 각 작업 별 상세 명령 실행 및 스크립트 작성, 작업 중단 실패 시 롤백 명령/스크립트 작성
2. 모니터링 설정
3. (1) ETCD 백업
4. (2) CNI(cilium) 업그레이드

5. CP(Control Plane) 노드 순차 업그레이드

  • 노드 1대씩 작업 진행 1.28 → 1.29
    • (3) Ubuntu OS(kernel) 업그레이드 → 재부팅
    • (4) containerd 업그레이드 → containerd 서비스 재시작
    • (5) kubeadm 업그레이드 → kubelet/kubectl 업그레이드 설치 → kubelet 재시작
  • 노드 1대씩 작업 진행 1.29 → 1.30
    • (5) kubeadm 업그레이드 → kubelet/kubectl 업그레이드 설치 → kubelet 재시작
  • 작업 완료 후 CP 노드 상태 확인

6. DP(Data Plane) 노드 순차 업그레이드 : 1.28 → 1.29 → 1.30

  • 노드 1대씩 작업 진행 1.28 → 1.29
    • (6) 작업 노드 drain 설정 후 파드 Evicted 확인, 서비스 중단 여부 모니터링 확인
    • (7) Ubuntu OS(kernel) 업그레이드 → 재부팅
    • (8) containerd 업그레이드 → containerd 서비스 재시작
    • (9) kubeadm 업그레이드 → kubelet 업그레이드 설치 → kubelet 재시작
  • 노드 1대씩 작업 진행 1.29 → 1.30
    • (9) kubeadm 업그레이드 → kubelet 업그레이드 설치 → kubelet 재시작
  • 작업 완료 후 DP 노드 상태 확인 ⇒ (10) 작업 노드 uncordon 설정 후 다시 상태 확인

7. K8S 관련 전체적인 동작 1차 점검

  • 애플리케이션이 정상적으로 동작하는지 확인

8. CP 노드 순차 업그레이드 : 1.30 → 1.31 → 1.32

  • 노드 1대씩 작업 진행 x 버전별 반복
    • kubeadm 업그레이드 → kubelet/kubectl 업그레이드 설치 → kubelet 재시작
  • 작업 완료 후 CP 노드 상태 확인

9. DP 노드 순차 업그레이드 : 1.30 → 1.31 → 1.32

  • 노드 버전별로 반복
    • 작업 노드 drain 설정 후 파드 Evicted 확인, 서비스 중단 여부 모니터링 확인
    • kubeadm 업그레이드 → kubelet 업그레이드 설치 → kubelet 재시작
  • 작업 완료 후 DP 노드 상태 확인 ⇒ 작업 노드 uncordon 설정 후 다시 상태 확인

10. K8S 관련 전체적인 동작 2차 점검

  • 애플리케이션이 정상적으로 동작하는지 확인

Amazon EKS Upgrades: Strategies and Best Practices

미리 제공받은 워크샵 환경에 접속하면 EKS가 미리 준비되어 있는 것을 확인할 수 있다.

whoami
pwd

# s3 버킷 확인
aws s3 ls

# 환경변수(테라폼 포함) 및 단축키 alias 등 확인
cat ~/.bashrc


# eks 플랫폼 버전 **eks.44**
aws eks describe-cluster --name $EKS_CLUSTER_NAME | jq

1.25 버전을 사용하고 있는 것을 확인할 수 있다.

eksctl get nodegroup --cluster $CLUSTER_NAME

kubectl get node --label-columns=eks.amazonaws.com/capacityType,node.kubernetes.io/lifecycle,karpenter.sh/capacity-type,eks.amazonaws.com/compute-type

kubectl get nodes -owide

argocd도 load balancer로 미리 설정되어 있다. (url은 Loadbalancer에서 확인 가능)

kubectl describe cm -n kube-system aws-auth

[Cluster insights]

현재 사용하고 있는 버전에서 deprecated 되는 API가 있으면 미리 알려준다.

[kube-ops-view 설치]

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm repo update
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --namespace kube-system

#
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-type: external
  labels:
    app.kubernetes.io/instance: kube-ops-view
    app.kubernetes.io/name: kube-ops-view
  name: kube-ops-view-nlb
  namespace: kube-system
spec:
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/instance: kube-ops-view
    app.kubernetes.io/name: kube-ops-view
EOF


# kube-ops-view 접속 URL 확인 (1.5, 1.3 배율)
kubectl get svc -n kube-system kube-ops-view-nlb -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | awk '{ print "KUBE-OPS-VIEW URL = http://"$1"/#scale=1.5"}'
kubectl get svc -n kube-system kube-ops-view-nlb -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | awk '{ print "KUBE-OPS-VIEW URL = http://"$1"/#scale=1.3"}'

[krew 설치]

# 설치
(
  set -x; cd "$(mktemp -d)" &&
  OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
  ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
  KREW="krew-${OS}_${ARCH}" &&
  curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
  tar zxvf "${KREW}.tar.gz" &&
  ./"${KREW}" install krew
)

# PATH
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
vi ~/.bashrc
-----------
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
-----------

# 플러그인 설치
kubectl krew install ctx ns df-pv get-all neat stern oomd whoami rbac-tool rolesum
kubectl krew list

#
kubectl df-pv

#
kubectl whoami --all

[실습 환경 배포한 테라폼 파일 확인]

aws s3 ls
aws s3 ls s3://workshop-stack-tfstatebackendbucketf0fc9a9d-kas98meuhol5

# backend_override.tf 수정
terraform { 
  backend "s3" {
    bucket = "workshop-stack-tfstatebackendbucketf0fc9a9d-kas98meuhol5"
    region = "us-west-2"
    key    = "terraform.tfstate"
  }
}

# 확인
terraform state list
terraform output

샘플 애플리케이션: 고객이 카탈로그를 탐색하고 장바구니에 항목을 추가하며 결제 프로세스를 통해 주문을 완료할 수 있는 간단한 웹 스토어 애플리케이션

#
cd ~/environment
git clone codecommit::${REGION}://eks-gitops-repo

#
sudo yum install tree -y
tree eks-gitops-repo/ -L 2

ArgoCD의 App of Apps 패턴으로 구성되어 있다.


# Login to ArgoCD Console using credentials from following commands:
export ARGOCD_SERVER=$(kubectl get svc argo-cd-argocd-server -n argocd -o json | jq --raw-output '.status.loadBalancer.ingress[0].hostname')
echo "ArgoCD URL: http://${ARGOCD_SERVER}"
ArgoCD URL: http://k8s-argocd-argocdar-01634fea43-3cdeb4d8a7e05ff9.elb.us-west-2.amazonaws.com

export ARGOCD_USER="admin"
export ARGOCD_PWD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)
echo "Username: ${ARGOCD_USER}"
echo "Password: ${ARGOCD_PWD}"
Username: admin
Password: ~

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-type: external
  labels:
    app.kubernetes.io/instance: ui
    app.kubernetes.io/name: ui
  name: ui-nlb
  namespace: ui
spec:
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/instance: ui
    app.kubernetes.io/name: ui
EOF


kubectl get svc -n ui ui-nlb -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | awk '{ print "UI URL = http://"$1""}'

[Choosing an Upgrade Strategy : 업그레이드 전략 선택 (In-Place vs Blue-Green)]

  • in-place 업그레이드 전략 : 기존 EKS 클러스터를 최신 Kubernetes 버전으로 업그레이드
  1. EKS Control Plan을 대상 Kubernetes 버전으로 업그레이드합니다.
  2. 새로운 Kubernetes 버전과 일치하도록 작업자 노드 AMI를 업데이트합니다.
  3. 애플리케이션 가동 중지 시간을 최소화하기 위해 작업자 노드를 한 번에 하나씩 또는 소규모로 비우고 교체합니다.
  4. 새 버전과의 호환성을 보장하기 위해 모든 Kubernetes 매니페스트, 애드온 및 구성을 업데이트합니다.
  5. 철저한 테스트와 검증을 수행하여 애플리케이션과 서비스가 예상대로 작동하는지 확인합니다.

장점
1. VPC, 서브넷, 보안 그룹 등 기존 클러스터 리소스와 구성을 유지합니다.
2. 동일한 클러스터 API 엔드포인트를 유지하므로 외부 통합 및 도구를 업데이트할 필요성이 최소화됩니다.
3. 업그레이드 프로세스 중에 여러 클러스터를 관리하는 것에 비해 인프라 오버헤드가 덜 필요합니다.
4. 클러스터 간에 상태 저장 애플리케이션과 지속형 데이터를 마이그레이션할 필요성을 최소화합니다.

단점

  1. 업그레이드 과정에서 가동 중지 시간을 최소화하려면 신중한 계획과 조정이 필요합니다.
  2. 여러 Kubernetes 버전을 건너뛸 경우 연속적인 업그레이드가 여러 번 필요할 수 있으며, 업그레이드 프로세스가 길어질 수 있습니다.
  3. 업그레이드 중에 문제가 발생하면 롤백이 더 어렵고 시간이 많이 걸릴 수 있습니다. Control Plane이 업그레이드되면 롤백할 수 없습니다.
  4. 호환성을 보장하기 위해 모든 구성 요소와 종속성에 대한 철저한 테스트와 검증이 필요합니다.
  • Blue-Green 업그레이드 전략 : 새 EKS 클러스터(addon, apps)를 만들고 트래픽을 이전 클러스터에서 새 클러스터로 점진적으로 전환


출처: https://jafreitas90.medium.com/aws-deployment-strategies-ebc910420bf2

  1. 원하는 Kubernetes 버전 및 구성으로 새 EKS 클러스터(green)를 만듭니다.
  2. 새 클러스터에 애플리케이션, 애드온 및 구성을 배포합니다.
  3. 새 클러스터가 예상대로 작동하는지 확인하기 위해 철저한 테스트와 검증을 수행합니다.
  4. DNS 업데이트, 로드 밸런서 구성 또는 서비스 메시와 같은 기술을 사용하여 점진적으로 이전 클러스터(blue)에서 새 클러스터(green)로 트래픽을 전환합니다.
  5. 새 클러스터를 면밀히 모니터링하여 트래픽을 처리하고 예상대로 성능이 발휘되는지 확인하세요.
  6. 모든 트래픽이 새 클러스터로 전환되면 이전 클러스터를 해제합니다.

장점

  1. 새로운 클러스터를 프로덕션 트래픽으로 전환하기 전에 철저히 테스트할 수 있으므로, 보다 통제되고 안전한 업그레이드 프로세스가 가능합니다.
  2. 단일 업그레이드에서 여러 Kubernetes 버전을 건너뛸 수 있으므로 전체 업그레이드 시간과 노력이 줄어듭니다.
  3. 문제가 발생할 경우 트래픽을 이전 클러스터로 다시 전환하여 빠르고 쉬운 롤백 메커니즘을 제공합니다.
  4. 새 클러스터가 완전히 검증될 때까지 이전 클러스터가 계속 트래픽을 제공하므로 업그레이드 프로세스 동안 가동 중지 시간이 최소화됩니다.

단점

  1. 두 개의 클러스터를 동시에 유지 관리해야 하므로 업그레이드 프로세스에 추가적인 인프라 리소스와 비용이 필요합니다.
  2. 클러스터 간 트래픽 이동에 대한 보다 복잡한 조정 및 관리가 필요합니다.
  3. CI/CD 파이프라인, 모니터링 시스템, 액세스 제어 등의 외부 통합을 업데이트하여 새 클러스터를 가리키도록 해야 합니다.
  4. 클러스터 간 데이터 마이그레이션이나 동기화가 필요한 상태 저장 애플리케이션의 경우 어려울 수 있습니다.

[In-place Cluster Upgrade : 1.25 → 1.26]

호환성 검토 했다고 가정하고 진행

1. Control Plane Upgrade

# 
cd ~/environment/terraform
terraform state list

# 현재 버전 확인 : 파일로 저장해두기
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c > 1.25.txt
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
      6 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni:v1.19.3-eksbuild.1
      6 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-network-policy-agent:v1.2.0-eksbuild.1
      8 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/aws-ebs-csi-driver:v1.41.0
      2 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/coredns:v1.8.7-eksbuild.10
      2 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/csi-attacher:v4.8.1-eks-1-32-7
      6 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/csi-node-driver-registrar:v2.13.0-eks-1-32-7
      2 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/csi-provisioner:v5.2.0-eks-1-32-7
      2 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/csi-resizer:v1.13.2-eks-1-32-7
      2 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/csi-snapshotter:v8.2.1-eks-1-32-7
      6 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/kube-proxy:v1.25.16-minimal-eksbuild.8
      8 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/livenessprobe:v2.14.0-eks-1-32-7
      8 amazon/aws-efs-csi-driver:v1.7.6
      1 amazon/dynamodb-local:1.13.1
      1 ghcr.io/dexidp/dex:v2.38.0
      1 hjacobs/kube-ops-view:20.4.0
      1 public.ecr.aws/aws-containers/retail-store-sample-assets:0.4.0
      1 public.ecr.aws/aws-containers/retail-store-sample-cart:0.7.0
      1 public.ecr.aws/aws-containers/retail-store-sample-catalog:0.4.0
      1 public.ecr.aws/aws-containers/retail-store-sample-checkout:0.4.0
      1 public.ecr.aws/aws-containers/retail-store-sample-orders:0.4.0
      1 public.ecr.aws/aws-containers/retail-store-sample-ui:0.4.0
      1 public.ecr.aws/bitnami/rabbitmq:3.11.1-debian-11-r0
      2 public.ecr.aws/docker/library/mysql:8.0
      1 public.ecr.aws/docker/library/redis:6.0-alpine
      1 public.ecr.aws/docker/library/redis:7.0.15-alpine
      2 public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner:v3.6.3-eks-1-29-2
      8 public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe:v2.11.0-eks-1-29-2
      6 public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar:v2.9.3-eks-1-29-2
      2 public.ecr.aws/eks/aws-load-balancer-controller:v2.7.1
      2 public.ecr.aws/karpenter/controller:0.37.0@sha256:157f478f5db1fe999f5e2d27badcc742bf51cc470508b3cebe78224d0947674f
      5 quay.io/argoproj/argocd:v2.10.0
      1 registry.k8s.io/metrics-server/metrics-server:v0.7.0


# IDE-Server 혹은 자신의 PC에서 반복 접속 해두자!
export UI_WEB=$(kubectl get svc -n ui ui-nlb -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'/actuator/health/liveness)
curl -s $UI_WEB ; echo
{"status":"UP"}

# 반복 접속 1
UI_WEB=k8s-ui-uinlb-d75345d621-e2b7d1ff5cf09378.elb.us-west-2.amazonaws.com/actuator/health/liveness
while true; do curl -s $UI_WEB ; date; sleep 1; echo; done

# 반복 접속 2 : aws cli 자격증명 설정 필요
aws eks describe-cluster --name $EKS_CLUSTER_NAME | egrep 'version|endpoint"|issuer|platformVersion'
        "version": "1.25",
        "endpoint": "https://A77BDC5EEBAE5EC887F1747B6AE965B3.gr7.us-west-2.eks.amazonaws.com",
                "issuer": "https://oidc.eks.us-west-2.amazonaws.com/id/A77BDC5EEBAE5EC887F1747B6AE965B3"
        "platformVersion": "eks.44",

# 반복 접속 2
while true; do curl -s $UI_WEB; date; aws eks describe-cluster --name eksworkshop-eksctl | egrep 'version|endpoint"|issuer|platformVersion'; echo ; sleep 2; echo; done

terraform에서 version을 1.26으로 바꾼다.

# 기본 정보
aws eks describe-cluster --name $EKS_CLUSTER_NAME | egrep 'version|endpoint"|issuer|platformVersion'
     
        
# 클러스터 버전을 변경하면 테라폼 계획에 표시된 것처럼, 관리 노드 그룹에 대한 특정 버전이나 AMI가 테라폼 파일에 정의되지 않은 경우,
# eks 클러스터 제어 평면과 관리 노드 그룹 및 애드온과 같은 관련 리소스를 업데이트하게 됩니다. 
# 이 계획을 적용하여 제어 평면 버전을 업데이트해 보겠습니다.
terraform apply -auto-approve 

# eks control plane 1.26 업글 확인
aws eks describe-cluster --name $EKS_CLUSTER_NAME | jq

...

서비스 중단 없이 잘 업그레이드 된 것을 확인할 수 있다.

2. Upgrading EKS Addons

현재 사용하고 있는 addons

eks_addons = {
    coredns = {
      addon_version = "v1.8.7-eksbuild.10"
    }
    kube-proxy = {
      addon_version = "v1.25.16-eksbuild.8"
    }
    vpc-cni = {
      most_recent = true
    }
    aws-ebs-csi-driver = {
      service_account_role_arn = module.ebs_csi_driver_irsa.iam_role_arn
    }
  }

추천하는 버전으로 업데이트하고 다시 apply 한다.

apply 이후에 플러그인 버전도 잘 바뀐 것을 확인할 수 있다.

3. Upgrading DataPlane (관리형 노드그룹)

blue는 아직 사용하지 않는거라 1.25 버전으로 고정한다.

ami id를 수정한다.

    custom = {
      instance_types = ["t3.medium"]
      min_size     = 1
      max_size     = 2
      desired_size = 1
      update_config = {
        max_unavailable_percentage = 35
      }
      ami_id = try(var.ami_id)
      enable_bootstrap_user_data = true 
    }

관리형 노드 그룹도 추가한다.

terraform apply -auto-approve

custom node group은 specific한 ami를 사용한다. 이제 variable.tf 에서 변수 mng_cluster_version을 "1.25"에서 "1.26"으로 변경하고 ami id도 바꾼 뒤 테라폼을 apply 한다.

variable "mng_cluster_version" {
  description = "EKS cluster mng version."
  type        = string
  default     = "1.26"
}


variable "ami_id" {
  description = "EKS AMI ID for node groups"
  type        = string
  default     = "ami-086414611b43bb691"
}


Node group 버전이 올라간 것을 확인할 수 있다.

custom은 제거 후 다시 apply 한다.

[Blue-Green Cluster Upgrades]
** 이후에 진행되는 내용은 워크샵 종료 되어 노션으로만 공부한 내용을 정리해두었습니다

Blue-Green EKS 클러스터 업그레이드는 다음 단계들로 구성된다.

  • 최신 또는 원하는 K8 버전의 새 EKS 클러스터 출시
  • 필요에 따라 호환되는 Kubernetes 애드온 및 사용자 지정 컨트롤러 배포
  • 워크로드를 새 클러스터에 배포합니다(필요에 따라 API 사용 중단에 업데이트 적용)
  • 파란색 클러스터에서 녹색 클러스터로 트래픽 라우팅

상태 비저장 애플리케이션은 클러스터에 영구 데이터를 보관할 필요가 없으므로 업그레이드 중에 새 녹색 클러스터에 배포하고 트래픽을 라우팅하기만 하면 된다.

입력 리소스에 대한 다음 주석을 활용하여 Amazon Route 53에서 DNS 레코드 가중치를 설정할 수 있다.

external-dns.alpha.kubernetes.io/set-identifier: {{ .Values.spec.clusterName }}
external-dns.alpha.kubernetes.io/aws-weight: '{{ .Values.spec.ingress.route53_weight }}'
profile
공블로그

0개의 댓글

관련 채용 정보