Loading [MathJax]/jax/output/HTML-CSS/jax.js
  • pric라는 이름으로 EKS 클러스터 생성
eksctl create cluster --vpc-private-subnets subnet-033d8f789eee8880d,subnet-0ca72dc02ff537a25 --name pric --region ap-northeast-2 --version 1.32 --nodegroup-name mycng --node-type t3.small --nodes 1 --nodes-min 1 --nodes-max 3 --node-private-networking

EBS(Block storage) - 하드웨어(디스크)

단일 인스턴스에 attach해야함. 파일 시스템이 구성이 안되어있다.

(attach된)특정노드에 존재하는 pod만 접근 가능

EFS(File) - NFS

다수의 인스턴스에서 접근 가능

여러 노드에 존재하는 다수의 pod들이 접근 가능

EKS 환경에서 동적 프로비저닝할때 이걸 써야 한다.


EKS 환경에서 동적 프로비저닝

CSI(Container Storage Interface) - 다이나믹 프로비저닝을 위한 애드온

ALB 생성을 위해 LB Controller를 설치했던 것과 유사하다.

export CLUSTER_NAME=pric
export ACCOUNT_ID=651109015678
export VPC_ID=vpc-0a4d6d7b49d1ecafc
export REGION=ap-northeast-2
export ROLE_NAME=AmazonEKS_EFS_CSI_DriverRole

  • OIDC 활성화
eksctl utils associate-iam-oidc-provider --cluster $CLUSTER_NAME --approve

# 정책은 이미 aws에 구성된 관리형 정책 사용

eksctl create iamserviceaccount \
    --name efs-csi-controller-sa \
    --namespace kube-system \
    --cluster $CLUSTER_NAME \
    --role-name $ROLE_NAME \
    --role-only \
    --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
    --approve

# IRSA = ROLE_NAME = AmazonEKS_EFS_CSI_DriverRole 생성

# IAM SA = efs-csi-controller-sa 생성

# 정책은 이미 존재하는 관리형 정책 = AmazonEFSCSIDriverPolicy


 

생성이 안된다면 CloudFormation에 남아있는 기존 스택을 지워주고 다시 생성

  • IAM에서 Role 잘 생성됐는지 확인

  • 정책 편집
TRUST_POLICY=(awsiamgetrolerolenameROLE_NAME --output json --query 'Role.AssumeRolePolicyDocument' |     sed -e 's/efs-csi-controller-sa/efs-csi-*/' -e 's/StringEquals/StringLike/')

  • 애드온 설치
eksctl create addon --cluster CLUSTERNAMEnameawsefscsidriverversionlatest serviceaccountrolearnarn:aws:iam::ACCOUNT_ID:role/$ROLE_NAME --force

# 설치 성공

  • pv가 생성될 EFS를 구성

# 생성 성공

vi sc.yml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: <자신의 EFS ID>
  directoryPerms: "700"
kubectl apply -f sc.yml

# 스토리지클래스의 이름 = efs-sc = 나중에 pvc에서 명시

  • 테스트할 pvc
vi pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim-1
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Mi
kubectl apply -f pvc.yml

혹시 위에서 수정한 부분을 다시 원상복구 후, pvc를 지웠다가 다시 생성하면

# 정상적으로 pv가 생성

# pod에서 불러올 시크릿 생성. rds의 인증정보

# 내가 생성한 시크릿


시크릿 CSI 드라이버 설치

  • OIDC 활성화
eksctl utils associate-iam-oidc-provider --cluster $CLUSTER_NAME --approve
  • IAM SA생성
eksctl create iamserviceaccount --name secret-sa --region=REGIONclusterCLUSTER_NAME --attach-policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite --approve --override-existing-serviceaccounts

# secret-sa 라는 이름의 IAM SA가 잘 생성됨


노드 용량 늘리기

root@aws-cli:~# eksctl scale nodegroup --cluster pric --name mycng --nodes 3
  • 헬름으로 시크릿 CSI 드라이버를 설치
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
  • kube-system에 릴리스 생성
helm install -n kube-system csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver

Helm 릴리스 이름(csi-secrets-store)이 이미 존재하기 때문에 에러 발생

root@aws-cli:~/efs# helm upgrade -n kube-system csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver


ASCP(AWS Secrets and Configuration Provider) 설치

aws의 시크릿을 eks의 시크릿처럼 쓸 수 있게 만들어줌

  • ASCP를 위한 헬름 레포 추가
helm repo add aws-secrets-manager https://aws.github.io/secrets-store-csi-driver-provider-aws
  • ASCP 릴리스 생성
helm install -n kube-system secrets-provider-aws aws-secrets-manager/secrets-store-csi-driver-provider-aws

SecretProviderClass 생성

vi spc.yml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: aws-secrets
spec:
  provider: aws
  parameters:
    objects: |
        - objectName: "<내 시크릿의 ARN>"

# metadata.name: aws-secrets 이거는 나중에 파드 정의시 SecretProviderClass를 명시할때 쓰이는 이름

테스트용 deployment 생성

vi dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fast-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fast
  template:
    metadata:
      name: fast-pod
      labels:
        app: fast
    spec:
      serviceAccountName: secret-sa 
      containers:
      - name: fast-con
        image: oolralra/ipnginx
        volumeMounts:
        - name: secrets-store-inline
          mountPath: "/mnt/secrets-store"  # 비밀 정보가 마운트될 경로
          readOnly: true
      volumes:
      - name: secrets-store-inline
        csi:
          driver: secrets-store.csi.k8s.io
          readOnly: true
          volumeAttributes:
            secretProviderClass: "aws-secrets"  # 참조하는 SecretProviderClass의 이름

# 적절하게 파싱을 해서 코드에 넣어주자!


root@aws-cli:~/exam# helm uninstall -n kube-system secrets-provider-aws
root@aws-cli:~/exam# helm uninstall -n kube-system csi-secrets-store
eksctl delete addon --cluster $CLUSTER_NAME --name  aws-efs-csi-driver

ArgoCD(Continuous Deployment)

k8s환경에서 CD를 하기위한 툴, CNCF에서 강추하는 CD툴

ArgoCD 설치

  • 네임스페이스 생성 
kubectl create ns argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
root@aws-cli:~/exam# kubectl get pod -n argocd
root@aws-cli:~/exam# kubectl get svc -n argocd

# 서비스 타입 변경이 필요

patch or edit

  • LoadBalancer로 타입변경
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
  • 주소 확인
kubectl get svc -n argocd | grep -i argocd-server

  • 안되면 노드 용량 확인
kubectl describe svc -n argocd argocd-server
eksctl scale nodegroup --cluster <클러스터이름> --name <노드그룹이름> --nodes <변경할노드수> --nodes-max <변경할최대노드수>

  • 초기 패스워드 조회
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo

# 초기 암호 입력 후 비번 업데이트


  • 기존 svc 및 deployment 삭제
root@aws-cli:~/exam# kubectl delete svc --all
root@aws-cli:~/exam# kubectl delete deploy --all
  • 내가 배포할 매니페스트
vi argo-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: svc-ip
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
kubectl apply -f argo-svc.yml 

배포할 deployment

  • github의 레포에 둘 예정

  • deployment 파일 생성

dep/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx-pod
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-con
        image: oolralra/ipnginx

# argoCD가 모니터링할 레포의 파일

ArgoCD에서 위 레포를 모니터링하도록 설정

  •  내 레포 주소 확인 후 설정하고 connect

# 레포 등록

  • 레포를 등록 후 앱을 띄우기 위해 설정하고 create

# 배포할 네임스페이스

# rev(=revision number는 1)

# rs의 레플리카수는 1

 

# 현재 replicas: 1 인데  이걸 바꿔보자.

# 말하고자하는 포인트는, 결국 github 레포의 매니페스트를 수정하면, 그걸 모니터링하고 있는 argoCD가 자동으로(Continuous) 그 수정된 사항을 반영(apply) 시켜준다.

  • 2로 변경후 apply

 

# 물론 자동으로 반영을 해주긴 하지만 10분정도까지 걸릴 수 있기 때문에, sync를 눌러주면 즉시 반영

 

어플리케이션이 업데이트 됐다고 가정을 해보자!

앱 업데이트 (CD 관점)

  1. 프로그래밍 언어로 짜여진 코드를 수정
  2. 새로 앱 빌드
  3. 새로 컨테이너 이미지 빌드(이미지의 태그가 변경이 됐다는 뜻)
  4. 그렇다면 이미지의 태그가 변경됐다는 사실을 어디에 명시? → 메니페스트 파일에 명시
  5. argoCD거 아룰 인지해서 자동으로 apply 해준다.

oolralra/ipnginx:latest 가 배포가 되어있는 상태 = 이미 만들어져있는 구버전의 앱

oolralra/ipnginx:2 → 새로 업데이트된 앱 (hnginx) = 호스트네임을 호출하는 앱

# :latest → :2로 수정

# rs는 껍데기만 남아있다. 

# 새로생성된 파드는 당연히 oolralra/ipnginx:2 라는 이미지로 구성되어있다. 즉 앱이 업데이트가 됐다는 뜻이다.

하지만 이게 앱이 잘못 업데이트가 됐다고 가정해보자.
# curl을 찍으면 호스트네임을 반환

하지만 이게 앱이 잘못 업데이트가 됐다고 가정해보자. → 롤백 필요

# 기존이미지로 돌아간 상태
# 다시 ipnginx로 돌아온걸 확인가능
# 롤백 전후


argoCD의 장점

  1. 설치가 쉬움
  2. CD 구성도 쉬움
  3. 편리하게 버전업데이트 및 롤백도 가능
  4. 시각화

실습)

ECR이나 도커허브를 통해 앱을 업데이트 해보세요.

leeseohoo/web-argo:1 은

nginx를 기반으로 'CD is difficult' 라는 내용을 배포

leeseohoo/web-argo:2 는

nginx를 기반으로 'CD is easy' 라는 내용을 배포하는 이미지 일때

github/leeseohoo/web-argo 라는 레포에 매니페스트를 등록해두고 매니페스트의 이미지를 web-argo:1 에서 web-argo:2로 변경했을때 10분정도 대기후 자동으로 앱이 변경되는지 확인해보세요.

  • index 파일
root@aws-cli:~/web-argo# vi ./v1/index.html
root@aws-cli:~/web-argo# vi ./v2/index.html
<!DOCTYPE html>
<html>
<body>
    <h1>CD is difficult</h1>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
    <h1>CD is easy</h1>
</body>
</html>

 

  • Dockerfile
root@aws-cli:~/web-argo# vi ./v1/Dockerfile
root@aws-cli:~/web-argo# vi ./v2/Dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
  • 빌드 및 푸시
# v1
cd v1
docker build -t leeseohoo/web-argo:1 .
docker push leeseohoo/web-argo:1

# v2
cd ../v2
docker build -t leeseohoo/web-argo:2 .
docker push leeseohoo/web-argo:2

  • 내가 배포할 매니페스트
vi argo-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: svc-ip
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
kubectl apply -f argo-svc.yml 
  • github deployment
argo-web/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx-pod
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-con
        image: leeseohoo/web-argo:1

# web-argo:1

  • github deployment 수정
image: leeseohoo/web-argo:2

# web-argo:2

  • 클러스터 삭제전에는 꼭 aws의 리소스를 생성하는 svc 같은거 지우기
kubectl delete svc --all
eksctl delete cluster pric
  • EIP, NATGW, RDS,EFS 제거
aws ec2 release-address --allocation-id eipalloc-06c26ae37751f6770