[aews] EKS Automation

xgro·2023년 6월 5일
0

AEWS

목록 보기
7/7

Gasida-서종호님과 악분일상-최성욱Jerry-이정훈님의 노고에 다시한번 🙇 감사드립니다.

📌 Review

7주차의 주제는 EKS Automation 입니다.

ACK를 통해 AWS의 리소스를 yaml을 이용하여 쿠버네티스에서 컨트롤할 수 있는 서비스를 실습해보았습니다. 하지만, 아직은 Drift(선언 후 수동으로 리소스가 변경되었을때) 상태에 대해서 정확하게 추종하지는 못해서 아직까지는 도입에는 쉽지 않을것 같습니다.

EKS 스터디를 하며, Nodeless와 ALB-controller 등 실습했었던 서비스를 종합적으로 적용하여 ArgoCD를 배포하는 과정을 정리하였습니다.

7주간의 짧은 시간이었지만 PKOS 때보다도 더 쿠버네티스 운영에 익숙해진 것 같습니다.



🎤 Speech

7주차는 임연욱님, 배효성님의 경험 및 기술 공유를 발표하셨습니다.

임연욱님은 EKS Reliability 내용을 상세하게 전달해 주셨습니다. 특히 Multi-region(DR) 예방하는 아키텍처는 당장 도입해도 좋을 정도로 적은 비용으로 재해를 방지할 수 있는 솔루션이었던것 같습니다.

배효성님은 ISMS/ISMS-P 인증심사에 대해서 상세하게 알려주셨습니다. 심사를 직접 실시하는 직무를 수행하며 일반적으로 각각의 업체에서 놓치기 쉬운 부분을 짚어주셔서 추후 ISMS 인증 심사시 큰 도움이 될 것 같습니다.

두분께 다시한번 감사드립니다



📌 Summary

  • ACK를 이용하여 AWS의 리소스를 쿠버네티스 yaml을 이용하여 관리할 수 있습니다.

  • EKS에서 ArgoCD를 배포하여 GitOps를 실습해봅니다.

  • Nodeless Concept과 ALB-controller 등 스터디에서 실습한 내용을 바탕으로 운영 환경을 구성할 수 있습니다.



📌 Study

👉 Step 00. 실습 환경 배포

Amazon EKS 윈클릭 배포 가이드를 참조하여 실습에 필요한 인프라 구성요소를 간편하게 배포할 수 있습니다.


👉 Step 01. AWS Controller for Kubernetes (ACK)

  • ACK : aws 서비스 리소스를 k8s 에서 직접 정의하고 용 할 수 있음
    • 예시) 사용자는 kubectl (쿠버네티스 api) 를 사용하여 AWS S3 버킷을 생성 할 수 있다

    • 예시) 쿠버네티스 api 는 ack-s3-controller 에 요청을 전달하고, ack-s3-controller(IRSA)이 AWS S3 API 를 통해 버킷을 생성하게 됩니다

출처 - https://aws-controllers-k8s.github.io/community/docs/community/how-it-works/

ACK 가 지원하는 AWS 서비스 : (‘23.5.29일) 현재 17개 서비스는 GA General Availability (정식 출시) 되었고, 10개Preview (평가판) 상태입니다 - 링크

  • Maintenance Phases 관리 단계 : PREVIEW (테스트 단계, 상용 서비스 비권장) , GENERAL AVAILABILITY (상용 서비스 권장), DEPRECATED, NOT SUPPORTED
  • GA 서비스 : ApiGatewayV2, CloudTrail, DynamoDB, EC2, ECR, EKS, IAM, KMS, Lambda, MemoryDB, RDS, S3, SageMaker…
  • Preview 서비스 : ACM, ElastiCache, EventBridge, MQ, Route 53, SNS, SQS…

Permissions : k8s api 와 aws api 의 2개의 RBAC 시스템 확인, 각 서비스 컨트롤러 파드는 AWS 서비스 권한 필요 ← IRSA role for ACK Service Controller


출처 - https://aws-controllers-k8s.github.io/community/docs/user-docs/authorization/

서비스 별 ACK Controller 설치(w/Helm) 과 IAM Permissions 설정은 서비스 이름만 변수(예. SERVICE=s3 혹은 SERVICE=rds) 에 지정해서 CMD 복사/붙여넣기 하자

S3

  • ACK S3 Controller 설치 with Helm
# 서비스명 변수 지정
export SERVICE=s3

# helm 차트 다운로드
#aws ecr-public get-login-password --region us-east-1 | helm registry login --username AWS --password-stdin public.ecr.aws
export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/$SERVICE-controller/releases/latest | grep '"tag_name":' | cut -d'"' -f4 | cut -c 2-)
helm pull oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart --version=$RELEASE_VERSION
tar xzvf $SERVICE-chart-$RELEASE_VERSION.tgz

# helm chart 확인
tree ~/$SERVICE-chart

# ACK S3 Controller 설치
export ACK_SYSTEM_NAMESPACE=ack-system
export AWS_REGION=ap-northeast-2
helm install --create-namespace -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller --set aws.region="$AWS_REGION" ~/$SERVICE-chart

# 설치 확인
helm list --namespace $ACK_SYSTEM_NAMESPACE
kubectl -n ack-system get pods
kubectl get crd | grep $SERVICE
buckets.s3.services.k8s.aws                  2022-04-24T13:24:00Z

kubectl get all -n ack-system
kubectl describe sa -n ack-system ack-s3-controller

  • IRSA 설정 : 권장 정책 AmazonS3FullAccess - 링크
# Create an iamserviceaccount - AWS IAM role bound to a Kubernetes service account
eksctl create iamserviceaccount \
  --name ack-$SERVICE-controller \
  --namespace ack-system \
  --cluster $CLUSTER_NAME \
  --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3FullAccess`].Arn' --output text) \
  --override-existing-serviceaccounts --approve

# 확인 >> 웹 관리 콘솔에서 CloudFormation Stack >> IAM Role 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME

# Inspecting the newly created Kubernetes Service Account, we can see the role we want it to assume in our pod.
kubectl get sa -n ack-system
kubectl describe sa ack-$SERVICE-controller -n ack-system

# Restart ACK service controller deployment using the following commands.
kubectl -n ack-system rollout restart deploy ack-$SERVICE-controller-$SERVICE-chart

# IRSA 적용으로 Env, Volume 추가 확인
kubectl describe pod -n ack-system -l k8s-app=$SERVICE-chart
...
  • S3 버킷 생성, 업데이트, 삭제
# [터미널1] 모니터링
watch -d aws s3 ls

# S3 버킷 생성을 위한 설정 파일 생성
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
export BUCKET_NAME=my-ack-s3-bucket-$AWS_ACCOUNT_ID

read -r -d '' BUCKET_MANIFEST <<EOF
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
  name: $BUCKET_NAME
spec:
  name: $BUCKET_NAME
EOF

echo "${BUCKET_MANIFEST}" > bucket.yaml
cat bucket.yaml | yh

# S3 버킷 생성
aws s3 ls
kubectl create -f bucket.yaml
bucket.s3.services.k8s.aws/my-ack-s3-bucket-<my account id> created

# S3 버킷 확인
aws s3 ls
kubectl get buckets
kubectl describe bucket/$BUCKET_NAME | head -6
Name:         my-ack-s3-bucket-<my account id>
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  s3.services.k8s.aws/v1alpha1
Kind:         Bucket

aws s3 ls | grep $BUCKET_NAME
2022-04-24 18:02:07 my-ack-s3-bucket-<my account id>

# S3 버킷 업데이트 : 태그 정보 입력
read -r -d '' BUCKET_MANIFEST <<EOF
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
  name: $BUCKET_NAME
spec:
  name: $BUCKET_NAME
  tagging:
    tagSet:
    - key: myTagKey
      value: myTagValue
EOF

echo "${BUCKET_MANIFEST}" > bucket.yaml

# S3 버킷 설정 업데이트 실행 : 필요 주석 자동 업뎃 내용이니 무시해도됨!
kubectl apply -f bucket.yaml

# S3 버킷 업데이트 확인 
kubectl describe bucket/$BUCKET_NAME | grep Spec: -A5
Spec:
  Name:  my-ack-s3-bucket-<my account id>
  Tagging:
    Tag Set:
      Key:    myTagKey
      Value:  myTagValue

# S3 버킷 삭제
kubectl delete -f bucket.yaml

# verify the bucket no longer exists
kubectl get bucket/$BUCKET_NAME
aws s3 ls | grep $BUCKET_NAME
  • ACK S3 Controller 삭제 - 링크
# helm uninstall
export SERVICE=s3
helm uninstall -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller

# ACK S3 Controller 관련 crd 삭제
kubectl delete -f ~/$SERVICE-chart/crds

# IRSA 삭제
eksctl delete iamserviceaccount --cluster myeks --name ack-$SERVICE-controller --namespace ack-system

# namespace 삭제 >> ACK 모든 실습 후 삭제
kubectl delete namespace $ACK_K8S_NAMESPACE



✅ ArgoCD

이전 글들과 연계되는 내용입니다.
1. [eks]Nodeless Concept
2. [pkos] 쿠버네티스 스터디 - 4주차 [Step 03. ArgoCD]

ArgoCD란?

Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.

Application definitions, configurations, and environments should be declarative and version controlled. Application deployment and lifecycle management should be automated, auditable, and easy to understand.

ArgoCD는 원하는 애플리케이션 상태를 정의하기 위한 소스로 Git 리포지토리를 사용하는 GitOps 패턴을 따릅니다.

EKS 환경에서 ArgoCD를 배포하고 사용합니다.

달성하고자 하는 목표는 다음과 같습니다.

  • ArgoCD 파드 Fargate에 배포

  • ALB-Controller를 이용하여 ALB(Ingress) 생성


📕 ArgoCD 설치

👉 Step 01. Helm 설치

# 설치
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd --set server.service.type=NodePort --namespace argocd --version 5.19.14

CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
MyDomain=xgro.be
ALB_NAME=$CLUSTER-ingress-alb
ALB_GROUP_NAME=aews

echo $CERT_ARN $MyDomain $ALB_NAME $ALB_GROUP_NAME 

👉 Step 02. gRPC 및 https 라우팅을 위한 svc, ingress 생성

주의
spec.alb.ingress.kubernetes.io/backend-protocol-version: HTTP2 설정시 에러 발생

gRPC 대신, HTTP2를 사용하여 argogrpc 서비스를 생성하면 타겟그룹이 unhealthy가 됩니다.

ArgoCD는 CLI를 통한 통신에는 gRPC를 사용하고, UI는 https를 사용합니다.

요청에 따라 트래픽을 전달하기 위해서, gRPC 전용 서비스와 ALB 생성을 위한 Ingress를 각각 생성합니다.

cat <<EOT | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol-version: GRPC #This tells AWS to send traffic from the ALB using HTTP2. Can use GRPC as well if you want to leverage GRPC specific features
  labels:
    app: argogrpc
  name: argogrpc
  namespace: argocd
spec:
  ports:
  - name: "443"
    port: 443
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-server
  sessionAffinity: None
  type: NodePort
EOT
cat <<EOT | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol: HTTPS
    # Use this annotation (which must match a service name) to route traffic to HTTP2 backends.
    alb.ingress.kubernetes.io/conditions.argogrpc: |
      [{"field":"http-header","httpHeaderConfig":{"httpHeaderName": "Content-Type", "values":["application/grpc"]}}]
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
    alb.ingress.kubernetes.io/load-balancer-name: $ALB_NAME
    alb.ingress.kubernetes.io/group.name: $ALB_GROUP_NAME
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
  name: argocd
  namespace: argocd
spec:
  ingressClassName: alb
  rules:
  - host: argocd.$MyDomain
    http:
      paths:
      - path: /
        backend:
          service:
            name: argogrpc
            port:
              number: 443
        pathType: Prefix
      - path: /
        backend:
          service:
            name: argocd-server
            port:
              number: 443
        pathType: Prefix
  tls:
  - hosts:
    - argocd.$MyDomain
EOT

위의 서비스와 인그레스를 각각 배포하면, 아래와 같이 로드밸런서가 생성되며 타겟그룹이 Healthy 상태로 정상 작동하는것을 확인할 수 있습니다.

👉 Step 03. admin 계정의 암호 확인 및 로그인
정상적으로 배포가 완료되었다면, 아래 커맨드를 이용해서 Argocd의 초기 admin 비밀번호를 확인할 수 있습니다.

# admin 계정의 암호 확인
ARGOPW=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)
echo $ARGOPW
mf8bOtNEq7iHMqq1
# 웹 접속 로그인 (아이디: admin) ALB의 DNS 주소로 접속 https
echo -e "Argocd Web URL = https://argocd.$MyDomain"

📘 서비스 배포하기

실습에는 Github Repo를 사용하였습니다.

실습 진행을 위한 준비사항으로 아래 순서에 따라 진행합니다.

👉 Step 01. Private Repository를 생성

👉 Step 02. nginx.yaml 업로드
nginx를 배포해서 ArgoCD의 기능을 확인합니다.

cat << EOT > nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
      provision: karpenter
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: nginx
EOT

👉 Step 03. 토큰 발급
Settings / Developer Settings에서 Repo 접근을 위한 Token을 발급합니다.

👉 Step 04. 리소스 등록
ArgoCD CLI 또는 UI를 이용하여 nginx 레포를 등록합니다.
참조 - 악분의 ArgoCD 공부기록


📗 결과

앞서 Karpenter를 미리 배포하였으므로, ArgoCD에 의해 등록된 리소스(nginx)는 Karpenter에 의해 생성되는 노드에서 배포되는것을 확인할 수 있습니다.



📌 Reference

profile
안녕하세요! DevOps 엔지니어 이재찬입니다. 블로그에 대한 피드백은 언제나 환영합니다! 기술, 개발, 운영에 관한 다양한 주제로 함께 나누며, 더 나은 협업과 효율적인 개발 환경을 만드는 과정에 대해 인사이트를 나누고 싶습니다. 함께 여행하는 기분으로, 즐겁게 읽어주시면 감사하겠습니다! 🚀

0개의 댓글