나의 공부기록

[Kubernetes] 17. CI/CD : Git-Action 본문

CS/Kubernetes

[Kubernetes] 17. CI/CD : Git-Action

나의 개발자 2025. 5. 8. 17:50

사전 설정 - Cluster(pri-cluster) & LB Controller

더보기

환경변수 등록

export PRI_SUBNET1_ID=subnet-0b0
export PRI_SUBNET2_ID=subnet-09a
export CLUSTER_NAME=pri-cluster
export ACCOUNT_ID=<AWS 계정 ID>
export VPC_ID=vpc-035

 

Cluster 생성

eksctl create cluster --vpc-private-subnets $PRI_SUBNET1_ID,$PRI_SUBNET2_ID --name pri-cluster --region ap-northeast-2 --version 1.32 --nodegroup-name pricng --node-type t3.small --nodes 5 --nodes-min 3 --nodes-max 7 --node-private-networking

 

LB Controller 설치

# AWS 계정 정보 확인
aws sts get-caller-identity

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

# IRSA & AWS SA 생성
eksctl create iamserviceaccount   --cluster=$CLUSTER_NAME   --namespace=kube-system   --name=aws-load-balancer-controller   --role-name AmazonEKSLoadBalancerControllerRole   --attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy   --override-existing-serviceaccounts   --approve

# SA 생성 확인
kubectl get sa -n kube-system | grep -i load

# LB Controller 설치
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=$CLUSTER_NAME \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set image.repository=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-load-balancer-controller \
--set region=ap-northeast-2 \
--set vpcId=$VPC_ID

 

로컬 환경에서 App 띄우기

더보기

1. 내 Github에 fork

 

GitHub - oolralra/svelte-fast

Contribute to oolralra/svelte-fast development by creating an account on GitHub.

github.com

  • fork 결과 확인

 

2. Git Clone

git clone https://github.com/BoHyun-Choi-0320/svelte-fast.git

cd svelte-fast/
  • 코드 분석
    • frontend : svelte 앱의 front
    • 나머지는 backend 관련 파일

 

svelte 앱을 로컬에 띄우기 위해 RDS 생성

3. 서브넷 그룹 생성

  • Public Subnet으로 구성된 서브넷 그룹 생성
  • 추후 RDS 생성 시, 서브넷 그룹으로 선택

 

4. RDS 생성

 

5.  RDS 접속 확인

  • RDS가 정상적으로 접속이 가능한지 확인
apt install mysql-client-8.0

# RDS 접속 확인
mysql -u user -ptest1234 -h <RDS 주소>

 

 

Backend

6. Backend - Dockerfile

vi Dockerfile 

#FROM public.ecr.aws/docker/library/python:3.9-slim
FROM python:3.9-slim

COPY . /app
WORKDIR /app

RUN pip install -r requirements.txt

RUN chmod +x entrypoint.sh
#
ENV DB_URL=mysql+pymysql://<사용자>:<비밀번호>@<RDS 주소>/db
ENTRYPOINT ["/app/entrypoint.sh"]

 

7. Backend - Docker 이미지 빌드 & Container 생성

docker build -t backend:1 .

docker run -dp 8000:8000 --name back backend:1

docker  ps
# [ 결과 ]
CONTAINER ID   IMAGE       COMMAND                CREATED         STATUS         PORTS                                         NAMES
126dfe1a76e2   backend:1   "/app/entrypoint.sh"   6 seconds ago   Up 5 seconds   0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp   back

 

8. 컨테이너 작동 확인

 

Frontend

9. Frontend - Dockerfile

cd frontend/

vi Dockerfile 

FROM public.ecr.aws/docker/library/node:20.15.1-slim
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
CMD ["npm","run","dev","--","--host=0.0.0.0"]

 

10. Front - Back 주소 수정

  • .env : Backend 파일 명시
vi .env 

VITE_SERVER_URL=http://211.183.3.99:8000
# 백엔드의 주소

 

11. Front - Docker 이미지 빌드

docker build -t frontend:1 .

# 80번 포트 사용중이면 중지 ➡️ docker run
ss -tnlp

docker run -dp 80:5173 --name front frontend:1

docker ps

# [ 결과 ]
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                                         NAMES
e168773317e1   frontend:1   "docker-entrypoint.s…"   3 seconds ago    Up 2 seconds    0.0.0.0:80->5173/tcp, [::]:80->5173/tcp       front
126dfe1a76e2   backend:1    "/app/entrypoint.sh"     24 minutes ago   Up 24 minutes   0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp   back

 

12. App 결과 확인

  • 목록에 값이 없으면, [질문 등록하기]를 통해 등록 ➡️ 목록이 등록되면 정상⭕/ 목록이 안뜨면 비정상❌

 

ECR을 사용하여 EKS 배포

더보기

1. ECR 레포지토리 생성

aws ecr create-repository --repository-name cdcd-frontend --region ap-northeast-2

aws ecr create-repository --repository-name cdcd-backend --region ap-northeast-2

aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.ap-northeast-2.amazonaws.com

export ECR=$ACCOUNT_ID.dkr.ecr.ap-northeast-2.amazonaws.com

 

Backend

2. Backend - Docker 이미지 빌드 & PUSH

docker build -t backend:1 .
docker tag backend:1 $ECR/cdcd-backend:1
docker push $ECR/cdcd-backend:1

 

3. Backend - SVC & Deployment 정의

apiVersion: v1
kind: Service
metadata:
  name: svc-back
spec:
  type: ClusterIP
  selector:
    app: backend
  ports:
  - port: 8000
    targetPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: back-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      name: backend-pod
      labels:
        app: backend
    spec:
      containers:
      - name: backend-con
        image: $ECR/cdcd-backend:1

 

4. Backend - SVC & Deployment 생성

kubectl apply -f backend.yml

 

Frontend

5. Frontend - Backend 주소 수정

vi .env 

VITE_SERVER_URL=http://svc-back
# 백엔드의 주소

 

6. Frontend - 이미지 빌드 & PUSH

docker build -t frontend:3 .
docker tag frontend:3 $ECR/cdcd-frontend:3
docker push $ECR/cdcd-frontend:3

 

7. Frontend - SVC, Deployment 정의

apiVersion: v1
kind: Service
metadata:
  name: svc-front
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
spec:
  type: LoadBalancer
  selector:
    app: frontend
  ports:
  - port: 80
    targetPort: 5173
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: front-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      name: frontend-pod
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend-con
        image: $ECR/cdcd-frontend:3

 

8. Frontend - SVC, Deployment 생성

kubectl apply -f frontend.yml

 

9. 결과 확인

  • 웹 브라우저에서 Backend의 SVC를 찾아가지 못함

 

✅ 웹 브라우저에서 Backend의 SVC를 찾지 못하는 이유

 

해결 방법

1️⃣front를 띄운 nodejs앱에서 Reverse Proxy 코드 추가

2️⃣ npm build를 통해 정적 파일을 생성 후, nginx를 통해 Reverse Proxy 생성

 

앱 업데이트(CI 관점)

1. 프로그래밍 언어로 짜인 코드 수정
2. 새로 앱 빌드
3. 새로 컨테이너 이미지 빌드( = 이미지의 Tag 변경 )
4. 이미지의 Tag가 변경이 됐다는 사실을 manifest 파일에 명시
5. argoCD가 인지해서 자동으로 반영(apply)

 

Github-Action을 통한 CI/CD

더보기

1. 경로 이동

ls
# [ 결과 ]
alembic.ini  domain         frontend    models.py         test
database.py  eks            main.py     README.md
Dockerfile   entrypoint.sh  migrations  requirements.txt

pwd
# [ 결과 ]
/root/mani/svelte-fast

 

2. frontend 앱을 최상위 경로로 복사

cp -r frontend/ ~/frontend

 

3. Git initializing - Githube 레포지토리화

  • 경로에 " .git "이 없어야 함 ➡️ github 레포지토리화 하기 위함
root@aws-cli:~/frontend# git init
Initialized empty Git repository in /root/frontend/.git/

 

4. 원격 레포지토리 설정

  • 원격 레포지토리를 만들지는 않았지만 앞으로 만들 예정
git remote add origin https://github.com/<Github 계정 ID>/src

# remote 결과 확인
git remote -v
--- 결과---
origin	https://github.com/BoHyun-Choi-0320/src (fetch)
origin	https://github.com/BoHyun-Choi-0320/src (push)

 

5. 깃허브에 레포지토리 생성

 

6.  github 설정

# 모든 변경사항 추가
git add .

# Github 정보 등록
git config --global user.email "320fleur@gmail.com"
git config --global user.name "BoHyun-Choi-0320"

# git commit
git commit -m "first"

# git branch 정의
git branch -M main

# git push
git push origin main
-- 결과 --
Username for 'https://github.com': ghp_GV8
Password for 'https://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@github.com': <enter>

 

7.ECR 생성 & 로그인

# 환경 변수 등록

export ACCOUNT_ID=<AWS Account ID>
export VPC_ID=<VPC ID>
export REGION=ap-northeast-2
export ECR=$ACCOUNT_ID.dkr.ecr.ap-northeast-2.amazonaws.com
export FRONT=$ECR/cdcd-frontend

# ECR 로그인
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.ap-northeast-2.amazonaws.com

-- 결과 --
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

 

8. 배포할 Deployment 정의

root@aws-cli:~# pwd
/root
root@aws-cli:~# mkdir deploy
root@aws-cli:~# cd deploy
root@aws-cli:~/deploy# vi frontend.yml

apiVersion: v1
kind: Service
metadata:
  name: svc-front
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
  type: LoadBalancer
  selector:
    app: front
  ports:
  - port: 80
    targetPort: 5173
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dep-front
spec:
  replicas: 1
  selector:
    matchLabels:
      app: front
  template:
    metadata:
      name: pod-front
      labels:
        app: front
    spec:
      containers:
      - name: con-front
        image: <ACCOUNT ID>.dkr.ecr.ap-northeast-2.amazonaws.com/cdcd-frontend:1

 

9. Deployment 생성

kubectl apply -f frontend.yml

 

 10. 

root@aws-cli:~/frontend# docker build -t $FRONT:1 .
root@aws-cli:~/frontend# docker push $FRONT:1

 

 

11. 생성된 Pod 삭제 후, SVC로 접속

  • Deployment의 replicas로 인해, Pod 다시 생성됨
kubectl get pod
kubectl delete pod dep-front-5ccd78b668-zkh9m

root@aws-cli:~/frontend# kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                                         PORT(S)        AGE
kubernetes   ClusterIP      172.20.0.1      <none>                                                                              443/TCP        8m48s
svc-front    LoadBalancer   172.20.131.50   k8s-default-svcfront-7aea6c5afc-ee829bf50ab58dc9.elb.ap-northeast-2.amazonaws.com   80:32586/TCP   113s

 

  • SVC 접속 화면

 

Github-Action



나중에 ArgoCD가 모니터링할 레포지토리

 

12. Github Action을 통해 CI 할 스크립트 정의 - main.yml

  • 위 과정을 Github-Action을 통해 정의할 예정 
  • main 브랜치에 push가 됐을 때, 트리거가 될 것 ➡️ 예외할 디렉토리나 파일도 존재
name: fast CI/CD


on: # on 언제 action을 동작시킬지
  push: # push가 됐을때 동작시키겠다.
    branches: [main] # 대상 브랜치.
    paths-ignore: # push 이벤트가 발생해도 무시할 파일.
    - '.gitignore'
    - '.dockerignore'

jobs:
  ci:
    runs-on: ubuntu-latest  #깃액션이 동작하는 환경
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1 #가장 최근 commit의 히스토리만 가져옴.

 

13. ECR PUSH 하기 위한 계정 등록

➡️ ECR에 접근할 수 있는 최소한의 권한만 가지고 있는 계정을 생성해서 등록하는 게 Best🌟

➡️ 절대 Administrator 권한 부여 ❌

  • 사용자 생성
  • 액세스 키 생성
  •  마우스 휠 + Click > secrets and variables > actions

 

  • IAM 사용자 ACCESS KEY & SECRET ACCESS KEY 등록

 

  • 결과 - Repository secrets 3개 등록  

 

  • AWS Configure와 비슷 - 위에서 구성한 Secrets에 저장이 되어있음
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

 

  • ECR에 로그인하기 위한 액션 추가
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

 

  • 환경변수 선언
    • GITHUB_ENV라는 파일에 저장해놨다고 생각해도 좋음 ➡️ 나중에 env으로 호출가능
  • ${{ github.run_number }} = 깃허브액션에서 제공하는 액션넘버🌟
    ➡️ 매니패스트의 이미지 태그가 latest로 변경이 되지 않으면 ArgoCD가 변경된 것을 인지하지 못하기 때문에, 환경변수로 수정
      - name: Set Variables
        id: set-var
        run: |
          echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV
          echo "ECR_REPOSITORY=frontend" >> $GITHUB_ENV #본인 ecr레포에 맞게 수정
          echo "IMAGE_TAG=${{ github.run_number }}" >> $GITHUB_ENV
          echo "GIT_EMAIL=320fleur@gmail.com" >> $GITHUB_ENV
          echo "GIT_NAME=BoHyun-Choi-0320" >> $GITHUB_ENV

 

  • 이미지 빌드
    • run : | ➡️ 밑에 여러 줄의 명령어가 있지만 한 줄로 사용한다는 의미
      - name: Docker Image Build
        id: build-image
        run: |
          docker build -t ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }} .

 

  •  ECR 이미지 PUSH
      - name: Docker image Push
        id: push-image
        run: |
          docker push ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}

 

  • manifest file 수정
    • 깃허브 소스 레포 = BoHyun-Choi-0320
    • 깃허브  매니페스트 레포 = BoHyun-Choi-0320/dep
  • 변경이 된다는 것만 인지
    • BoHyun-Choi-0320/dep에 있는 매니페스트를 Clone한 후, sed로 이미지 태그 변경 후,  push
  • 매니페스트 레포로 변경
      - name: Checkout Deployment Repository
        uses: actions/checkout@v4
        with:
          repository: BoHyun-Choi-0320/dep #본인에 맞게 수정
          ref: main  # branch
          token: ${{ secrets.GH_TOKEN }}

 

  • 리눅스 환경에서는 구분자를 's/<변경 전>/<변경 후>/g'로 사용했지만, 컨테이너 레지스트리와 레포를 구분하는 용도로 /가 사용되기 때문에, 구분자를 @로 했음 : sed -i s@<변경 전>@<변경 후>@g

 

      - name: k8s manifest update
        run: |
          sed -i "s@ \
          image: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:.*@ \
          image: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}@g" deploy.yml

 

  • git push
      - name: Commit and Push
        run: |
          git config user.email ${{ env.GIT_EMAIL }}
          git config user.name ${{ env.GIT_NAME }}
          git add deploy.yml
          git commit -m "Update image tag"
          git push origin main

 

 

  • 최종 main.yml파일
name: fast CI/CD


on: # on 언제 action을 동작시킬지
  push: # push가 됐을때 동작시키겠다.
    branches: [main] # 대상 브랜치.
    paths-ignore: # push 이벤트가 발생해도 무시할 파일.
    - '.gitignore'
    - '.dockerignore'

jobs:
  ci:
    runs-on: ubuntu-latest  #깃액션이 동작하는 환경
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1 #가장 최근 commit의 히스토리만 가져옴.
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2
      
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
      
      - name: Set Variables
        id: set-var
        run: |
          echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV
          echo "ECR_REPOSITORY=frontend" >> $GITHUB_ENV #본인 ecr레포에 맞게 수정
          echo "IMAGE_TAG=${{ github.run_number }}" >> $GITHUB_ENV
          echo "GIT_EMAIL=320fleur@gmail.com" >> $GITHUB_ENV
          echo "GIT_NAME=BoHyun-Choi-0320" >> $GITHUB_ENV
      
      - name: Docker Image Build
        id: build-image
        run: |
          docker build -t ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }} .
      
      - name: Docker image Push
        id: push-image
        run: |
          docker push ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}

      - name: Checkout Deployment Repository
        uses: actions/checkout@v4
        with:
          repository: BoHyun-Choi-0320/dep #본인에 맞게 수정
          ref: main  # branch
          token: ${{ secrets.GH_TOKEN }}

      - name: k8s manifest update
        run: |
          sed -i "s@ \
          image: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:.*@ \
          image: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}@g" deploy.yml

      - name: Commit and Push
        run: |
          git config user.email ${{ env.GIT_EMAIL }}
          git config user.name ${{ env.GIT_NAME }}
          git add deploy.yml
          git commit -m "Update image tag"
          git push origin main

 

14. 진행 현황

 

15. 성공 화면

 

16. 소스 레포지토리 - 변경 확인

 

 

ArgoCD를 설치 후, dep 레포지토리를 등록 ➡ 소스레포에 변경사항 발생 ➡ App이 업데이트되는지 확인

17. ArgoCD 설치

 

18. 소스 레포지토리 변경사항 발생시키기

 

19. Github Action 빌드

 

20. ArgoCD에서 재배포 확인

  • Github Action 성공

 

21. 소스 레포지토리 변경 확인