AEWS STUDY 7주차 - Amazon EKS Automation

Hanryang·2023년 6월 11일
0

AEWS 스터디

목록 보기
7/7
post-thumbnail

가시다님께서 진행하신 AEWS라는 스터디를 진행하면서 작성하는 글입니다.

AEWS= AWS EKS Workshop Study

AEWS 스터디는 4월 23일 ~ 6월 4일동안7번 진행될 예정입니다.

PKOS 스터디에서 정말 좋은 경험을 했어서 다시 이렇게 참가하게 되었습니다.

가시다님께서 진행하시는 스터디에 관심있으신 분들은 Cloudnet@Blog에 들어가시면 자세한 정보를 확인하실 수 있습니다.

AWS Controller for Kubernetes (ACK)


Kubernetes용 AWS 컨트롤러(ACK)를 사용 하면 Kubernetes에서 직접 AWS 서비스 리소스를 정의하고 사용할 수 있습니다. ACK를 사용하면 클러스터 외부에서 리소스를 정의하거나 클러스터 내에서 데이터베이스 또는 메시지 대기열과 같은 지원 기능을 제공하는 서비스를 실행할 필요 없이 Kubernetes 애플리케이션을 위한 AWS 관리형 서비스를 활용할 수 있습니다.

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

ACK S3 Controlle 실습


ACK S3 Controller를 한번 실습해보겠습니다.

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

# helm 차트 다운로드
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-controlle

그리고 IRSA를 생성하고 적용하겠습니다.

# Kubernetes 서비스 계정에 바인딩된 AWS IAM 역할 생성 및 적용
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

# 확인 
eksctl get iamserviceaccount --cluster $CLUSTER_NAME

# ACK 서비스 컨트롤러 배포를 다시 시작합니다.
**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**

IRSA 적용을 완료하였으므로 이제 S3 버킷을 생성, 업데이트, 삭제를 진행해보겠습니다.

  • 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
  • S3 버킷 생성 및 확인
    # S3 버킷 생성
    aws s3 ls
    **kubectl create -f bucket.yaml**
    bucket.s3.services.k8s.aws/my-ack-s3-bucket-758651871205 created
    
    # S3 버킷 확인
    aws s3 ls
    **kubectl get buckets**
    kubectl describe bucket/$BUCKET_NAME | head -6
  • 버킷 업데이트
    # 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 delete -f bucket.yaml**
    
    # 확인
    kubectl get bucket/$BUCKET_NAME
    aws s3 ls | grep $BUCKET_NAME

ACK S3 Controoler 실습을 완료했으므로 삭제를 진행하겠습니다.

# 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

ACK EC2-Controller 실습


ACK EC2 Controller를 한번 실습해보겠습니다.

  • 설치

    # 서비스명 변수 지정 및 helm 차트 다운로드
    **export SERVICE=ec2**
    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 EC2-Controller 설치
    export ACK_SYSTEM_NAMESPACE=ack-system
    export AWS_REGION=ap-northeast-2
    helm install -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller --set aws.region="$AWS_REGION" ~/$SERVICE-chart
    
    # 설치 확인
    helm list --namespace $ACK_SYSTEM_NAMESPACE
    kubectl -n $ACK_SYSTEM_NAMESPACE get pods -l "app.kubernetes.io/instance=ack-$SERVICE-controller"
    **kubectl get crd | grep $SERVICE**

  • IRSA 설정

    # Kubernetes 서비스 계정에 바인딩된 AWS IAM 역할 생성 및 적용
    eksctl create **iamserviceaccount** \
      --name **ack-**$SERVICE**-controller** \
      --namespace $ACK_SYSTEM_NAMESPACE \
      --cluster $CLUSTER_NAME \
      --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`**AmazonEC2FullAccess**`].Arn' --output text) \
      --**override-existing-serviceaccounts** --approve
    
    # 확인
    eksctl get iamserviceaccount --cluster $CLUSTER_NAME

    #  ACK 서비스 컨트롤러 배포를 다시 시작합니다.
    **kubectl -n $**ACK_SYSTEM_NAMESPACE **rollout restart deploy ack-$**SERVICE**-controller-$**SERVICE**-chart**
    
    # IRSA 적용으로 Env, Volume 추가 확인
    kubectl describe pod -n $ACK_SYSTEM_NAMESPACE -l k8s-app=$SERVICE-chart

VPC,Subnet 생성 및 삭제를 진행해보겠습니다.

  • VPC 생성 및 확인
    # VPC 생성
    cat <<EOF > vpc.yaml
    apiVersion: **ec2.services.k8s.aws/v1alpha1**
    kind: **VPC**
    metadata:
      name: **vpc-tutorial-test**
    spec:
      cidrBlocks: 
      - **10.0.0.0/16**
      enableDNSSupport: true
      enableDNSHostnames: true
    EOF
     
    **kubectl apply -f vpc.yaml**
    
    # VPC 생성 확인
    kubectl get vpcs
    kubectl describe vpcs
    **aws ec2 describe-vpcs --query 'Vpcs[*].{VPCId:VpcId, CidrBlock:CidrBlock}' --output text**
  • 서브넷 생성 및 확인
    # 서브넷 생성
    VPCID=$(kubectl get vpcs vpc-tutorial-test -o jsonpath={.status.vpcID})
    
    cat <<EOF > subnet.yaml
    apiVersion: **ec2**.services.k8s.aws/v1alpha1
    kind: **Subnet**
    metadata:
      name: **subnet-tutorial-test**
    spec:
      cidrBlock: **10.0.0.0/20**
      vpcID: $VPCID
    EOF
    **kubectl apply -f subnet.yaml**
    
    # 서브넷 생성 확인
    kubectl get subnets
    kubectl describe subnets
    **aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --query 'Subnets[*].{SubnetId:SubnetId, CidrBlock:CidrBlock}' --output text**
    
  • 리소스 삭제
    # 리소스 삭제
    kubectl delete -f subnet.yaml && kubectl delete -f vpc.yaml

이번에는 VPC 워크플로우 생성 실습을 해보겠습니다.

단일 YAML 매니페스트를 사용하여 연결된 여러 리소스로 구성된 네트워크 토폴로지를 생성할 수 있습니다.

  • VPC 1개
  • 인스턴스 1개
  • 인터넷 게이트웨이 1개
  • NAT 게이트웨이 1개
  • 탄력적 IP 1개
  • 2개의 경로 테이블
  • 서브넷 2개(퍼블릭 1개, 프라이빗 1개)
  • 보안 그룹 1개

우선 vpc-workflow.yaml파일을 생성하고 적해보겠습니다. → 링크

cat <<EOF > vpc-workflow.yaml
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **VPC**
metadata:
  name: **tutorial-vpc**
spec:
  cidrBlocks: 
  - **10.0.0.0/16**
  enableDNSSupport: true
  enableDNSHostnames: true
  tags:
    - key: name
      value: vpc-tutorial
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **InternetGateway**
metadata:
  name: **tutorial-igw**
spec:
  **vpcRef**:
    from:
      name: **tutorial-vpc**
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **NATGateway**
metadata:
  name: **tutorial-natgateway1**
spec:
  **subnetRef**:
    from:
      name: tutorial-public-subnet1
  **allocationRef**:
    from:
      name: tutorial-eip1
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **ElasticIPAddress**
metadata:
  name: **tutorial-eip1**
spec:
  tags:
    - key: name
      value: eip-tutorial
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **RouteTable**
metadata:
  name: **tutorial-public-route-table**
spec:
  **vpcRef**:
    from:
      name: tutorial-vpc
  **routes**:
  - destinationCIDRBlock: 0.0.0.0/0
    **gatewayRef**:
      from:
        name: tutorial-igw
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **RouteTable**
metadata:
  name: **tutorial-private-route-table-az1**
spec:
  **vpcRef**:
    from:
      name: tutorial-vpc
  routes:
  - destinationCIDRBlock: 0.0.0.0/0
    **natGatewayRef**:
      from:
        name: tutorial-natgateway1
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **Subnet**
metadata:
  name: tutorial-**public**-subnet1
spec:
  availabilityZone: **ap-northeast-2a**
  cidrBlock: **10.0.0.0/20**
  mapPublicIPOnLaunch: true
  **vpcRef**:
    from:
      name: tutorial-vpc
  **routeTableRefs**:
  - from:
      name: tutorial-public-route-table
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **Subnet**
metadata:
  name: tutorial-**private**-subnet1
spec:
  availabilityZone: **ap-northeast-2a**
  cidrBlock: **10.0.128.0/20**
  **vpcRef**:
    from:
      name: tutorial-vpc
  **routeTableRefs**:
  - from:
      name: tutorial-private-route-table-az1
---
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **SecurityGroup**
metadata:
  name: tutorial-security-group
spec:
  description: "ack security group"
  name: tutorial-sg
  vpcRef:
     from:
       name: tutorial-vpc
  ingressRules:
    - ipProtocol: tcp
      fromPort: 22
      toPort: 22
      ipRanges:
        - cidrIP: "0.0.0.0/0"
          description: "ingress"
EOF

# 적용
**kubectl apply -f vpc-workflow.yaml**

그리고 vpc 환경이 생성이 되었는지 확인해보겠습니다.

# VPC 환경 생성 확인
kubectl describe vpcs
kubectl describe internetgateways
kubectl describe routetables
kubectl describe natgateways
kubectl describe elasticipaddresses
kubectl describe securitygroups

이제 퍼블릿 서브넷에 인스턴스를 생성해보겠습니다.

# public 서브넷 ID 확인
PUBSUB1=$(kubectl get subnets **tutorial-public-subnet1** -o jsonpath={.status.subnetID})
echo $PUBSUB1

# 보안그룹 ID 확인
TSG=$(kubectl get securitygroups **tutorial-security-group** -o jsonpath={.status.id})
echo $TSG

# Amazon Linux 2 최신 AMI ID 확인
AL2AMI=$(aws ec2 describe-images --owners **amazon** --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" --query 'Images[0].ImageId' --output text)
echo $AL2AMI

# 각자 자신의 SSH 키페어 이름 변수 지정
MYKEYPAIR=kopskeypair

**# 변수 확인 > 특히 서브넷 ID가 확인되었는지 꼭 확인하자!**
echo $PUBSUB1 , $TSG , $AL2AMI , $MYKEYPAIR

# public 서브넷에 인스턴스 생성
cat <<EOF > tutorial-bastion-host.yaml
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: **Instance**
metadata:
  name: **tutorial-bastion-host**
spec:
  imageID: $AL2AMI # AL2 AMI ID - ap-northeast-2
  instanceType: **t3.medium**
  subnetID: $PUBSUB1
  securityGroupIDs:
  - $TSG
  keyName: $MYKEYPAIR
  tags:
    - key: producer
      value: ack
EOF
**kubectl apply -f tutorial-bastion-host.yaml**

⇒ 해당 부분을 반복했지만 각 리소스들의 ID가 계속 생성이 되지 않는 오류가 발생하여 트러블 슈팅 진행 후 재시도해보겠습니다.

Flux


출저: 악분님 블로그

flux는 쿠버네티스를 위한 gitops 도구입니다.

flux는 git에 있는 쿠버네티스를 manifest를 읽고, 쿠버네티스에 manifest를 배포합니다.

  • flux는 쿠버네티스 operator패턴을 사용합니다. 사용자가 쿠버네티스에 배포할 내용을 flux CRD로 정의하면, flux controller가 CRD를 읽어 리소스를 쿠버네티스에 배포합니다.
  • 핵심 CRD는 소스(source)와 애플리케이션(application)입니다. 소스는 git, helm registry 등 manifest 주소를 설정합니다. 애플리케이션은 helm 또는 kustomize를 사용하여 manifest를 쿠버네티스에 배포합니다.

flux에 대해서 설치를 진행하면서 알아보도록하겠습니다.

Flux 실습


  • 토큰 발급

  • flux 설치

    # Flux CLI 설치
    **curl -s https://fluxcd.io/install.sh | sudo bash**
    . <(flux completion bash)
    
    # 버전 확인
    **flux --version**
    
    # 자신의 Github 토큰과 유저이름 변수 지정
    export GITHUB_TOKEN=<your-token>
    export GITHUB_USER=<your-username>
    
    # Bootstrap
    ## Creates a git repository **fleet-infra** on your GitHub account.
    ## Adds Flux component manifests to the repository.
    ## **Deploys** Flux Components to your Kubernetes Cluster.
    ## Configures Flux components to track the path /clusters/my-cluster/ in the repository.
    **flux bootstrap github \
      --owner=$GITHUB_USER \
      --repository=fleet-infra \
      --branch=main \
      --path=./clusters/my-cluster \
      --personal**
    
    # 설치 확인
    kubectl get pods -n flux-system
    kubectl get-all -n flux-system
    kubectl get crd | grep fluxc
    **kubectl get gitrepository -n flux-system**

  • Gitops 도구 설치

    • flux 대시보드 설치

      # gitops 도구 설치
      curl --silent --location "https://github.com/weaveworks/weave-gitops/releases/download/v0.24.0/gitops-$(uname)-$(uname -m).tar.gz" | tar xz -C /tmp
      sudo mv /tmp/gitops /usr/local/bin
      gitops version
      
      # flux 대시보드 설치
      PASSWORD="password"
      gitops create dashboard ww-gitops --password=$PASSWORD
      
      # 확인
      flux -n flux-system get helmrelease
      kubectl -n flux-system get pod,svc

    • ingress 설정

      CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
      echo $CERT_ARN
      
      # Ingress 설정
      cat <<EOT > gitops-ingress.yaml
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: gitops-ingress
        annotations:
          alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
          alb.ingress.kubernetes.io/group.name: **study**
          alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
          alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
          alb.ingress.kubernetes.io/scheme: internet-facing
          alb.ingress.kubernetes.io/ssl-redirect: "443"
          alb.ingress.kubernetes.io/success-codes: 200-399
          alb.ingress.kubernetes.io/target-type: ip
      spec:
        ingressClassName: alb
        rules:
        - host: gitops.$MyDomain
          http:
            paths:
            - backend:
                service:
                  name: ww-gitops-weave-gitops
                  port:
                    number: 9001
              path: /
              pathType: Prefix
      EOT
      kubectl apply -f gitops-ingress.yaml -n flux-system
      
      # 배포 확인
      kubectl get ingress -n flux-system
      
      # GitOps 접속 정보 확인 >> 웹 접속 후 정보 확인
      echo -e "GitOps Web https://gitops.$MyDomain"

  • flux hello world

    악분님의 github의 소스를 활용하여 flux 실습을 진행해보겠습니다.

    • github에 있는 nginx manifest를 쿠버네티스에 배포합니다.

      # 소스 생성 : 유형 - git, helm, oci, bucket
      # flux create source {소스 유형}
      # 악분(최성욱)님이 준비한 repo로 git 소스 생성
      GITURL="https://github.com/sungwook-practice/fluxcd-test.git"
      **flux create source git nginx-example1 --url=$GITURL --branch=main --interval=30s**
      
      # 소스 확인
      flux get sources git
      kubectl -n flux-system get gitrepositories

    • flux 애플리케이션 생성합니다.

      # flux 애플리케이션 생성 : nginx-example1
      flux create **kustomization** **nginx-example1** --target-namespace=default --interval=1m --source=nginx-example1 --path="**./nginx**" --health-check-timeout=2m
      
      # 확인
      kubectl get pod,svc nginx-example1
      kubectl get kustomizations -n flux-system
      flux get kustomizations

    • 에플리케이션 삭제

      # flux 애플리케이션 삭제 
      flux delete kustomization nginx-example1
      
      # 삭제 확인
      flux get kustomizations
      => 애플리케이션 생성 시 prune(default: false) 옵션을 활성화하지 않으면 파드와 서비스는 삭제되지 않음
      
      # 다시 flux 애플리케이션 생성 => --prune 옵션 true
      flux create kustomization nginx-example1 \
        --target-namespace=default \
        **--prune=true** \
        --interval=1m \
        --source=nginx-example1 \
        --path="./nginx" \
        --health-check-timeout=2m
      
      # 다시 삭제 진행
      **flux delete kustomization nginx-example1**

      # flux 소스 삭제
      flux delete source git nginx-example1
      
      # 소스 확인
      flux get sources git
profile
한량이 되고싶다..

0개의 댓글