Github Actions로 사내 프로젝트 CI/CD 구축하기(2)
Productivity/CI/CD
· 2025-03-19

들어가며
지난 게시글에서는 Github Actions를 통하여 빌드 자동화하는 방법을 정리하였다. 현재 연구소에서는 설치형 솔루션을 Azure 클라우드 환경에서 Kubernetes로 관리하고 있으며 배포 자동화에 대해 정해진 프로세스가 없는 상황이다. 따라서, 이미지가 빌드되었다면, 클러스터 워크로드에 직접 접근하여 이미지 태그명을 업데이트하고 kubectl
로 edit
또는 apply -f
로 배포하고 있다. 이 과정을 자동화시켜보자.
배포하기 위한 고려 사항
배포하기 앞서 무엇이 필요한지 생각해보자. Github Action은 워크플로우로서 개발자가 원하는 특정 작업을 수행하도록 yaml
에 명시해주고 git push
로 업로드해주면 되었다. 필요한 프로퍼티들은 문서를 따라 살펴볼 수 있었고 그 과정에서 필요한 환경 변수 또는 시크릿 값들은 웹 상에서 추가해주고 변수로 받아서 워크플로우 잡에서 직접 선언하여 쓸 수 있었다.
배포를 위한 구현은 크게 어려워보이진 않는다. 먼저, 사용자가 입력할 값들을 지정해주자. 필요한 정보들을 잡이 받아서 쓸 수 있도록 해주고, 웹 상에서 Credential을 넣어주면 끝날 것만 같다. 구체적으로 어떤게 필요할까?
- Azure Login을 위한 Credentials
- Cluster, Resource Group Name
- Target Namespace, Deployment Name
Custom Inputs
먼저, 클러스터 이름과 리소스 그룹, 네임스페이스 등은 시크릿으로 관리될 필요가 없으니, 사용자가 직접 드롭 다운에서 선택 또는 입력하도록 세팅해보자.
1name: CI/CD Pipeline # 이제 CD가 추가되었으니 'Manually Build and Push Docker Image'에서 바꿔주자 2on: 3 workflow_dispatch: 4 inputs: 5 TARGET_NAME: 6 type: choice 7 description: "Container Registry Target Repo Name (e.g. front-dev, front-stg)" 8 required: true 9 options: 10 - front-dev 11 - front-stag 12 - front-prod 13 14 CUSTOM_TAG: 15 type: string 16 description: "Optional: Custom image tag (overrides secrets.VERSION if provided)" 17 required: true 18 19 RESOURCE_GROUP: 20 type: choice 21 description: "Select AKS Resource Group" 22 required: true 23 options: 24 - dev-aks 25 - stg-aks 26 - prod-aks 27 28 AKS_CLUSTER: 29 type: choice 30 description: "Select AKS cluster for deployment" 31 required: true 32 options: 33 - dev-cluster 34 - stg-cluster 35 - prod-cluster 36 37 NAMESPACE: 38 type: choice 39 description: "Select Kubernetes namespace" 40 required: true 41 options: 42 - default 43 - custom-system
추가해주고 git push
해주면 다음과 같이 기본 세팅이 완료된다. 깔끔하지 않은가?
Setting for CD
Azure Login
Azure Credential 시크릿을 추가해주고 로그인을 해준다.
1jobs: 2 build-and-push: 3 # ... 기존 CI 작업 유지... 4 5 deploy-to-aks: 6 needs: build-and-push # CI 작업이 완료된 후 실행 7 runs-on: ubuntu-latest 8 9 steps: 10 - name: Checkout code 11 uses: actions/checkout@v4 12 13 - name: Azure login 14 uses: azure/login@v1 15 with: 16 creds: ${{ secrets.AZURE_CREDENTIALS }} 17 18 - name: Set AKS context 19 uses: azure/aks-set-context@v3 20 with: 21 # input으로 받은 리소스 그룹명, 클러스터 이름 준비 22 resource-group: ${{ inputs.RESOURCE_GROUP }} 23 cluster-name: ${{ inputs.AKS_CLUSTER }}
Resource Yaml Setting
배포에 필요한 리소스(디플로이먼트, 서비스) yaml들은 프로젝트 내부 /manifest
경로에서 관리해줄 것이다. 이 매니페스트 파일들은 일종의 템플릿처럼 쓸 수 있으며, Github Actions 실행시 실제 값들로 치환된다.
1# k8s/deployment.yaml 2apiVersion: apps/v1 3kind: Deployment 4metadata: 5 name: ${TARGET_NAME}-deployment 6spec: 7 replicas: 3 8 selector: 9 matchLabels: 10 app: ${TARGET_NAME} 11 template: 12 metadata: 13 labels: 14 app: ${TARGET_NAME} 15 spec: 16 containers: 17 - name: ${TARGET_NAME} 18 image: ${SKUBER_PLUS_REGISTRY}/${TARGET_NAME}:${TAG} 19 ports: 20 - containerPort: 80 21 resources: 22 requests: 23 cpu: '100m' 24 memory: '128Mi' 25 limits: 26 cpu: '200m' 27 memory: '256Mi' 28 29# k8s/service.yaml 30apiVersion: v1 31kind: Service 32metadata: 33 name: ${TARGET_NAME}-service 34spec: 35 type: ClusterIP 36 ports: 37 - port: 80 38 targetPort: 80 39 protocol: TCP 40 selector: 41 app: ${TARGET_NAME}
최종 배포
마지막으로 실제 AKS에 배포하는 단계로, 먼저 sed
명령어를 사용하여 매니페스트 파일의 변수들을 실제 값으로 치환시키자. 이후 azure/k8s-deploy@v4
액션은 실제 K8s 클러스터 배포시킨다.
1# deployment.yaml과 service.yaml의 변수들을 실제 값으로 치환 2- name: Update Kubernetes manifests 3 run: | 4 # deployment.yaml의 변수들을 실제 값으로 치환 5 sed -i 's/${TARGET_NAME}/${{ inputs.TARGET_NAME }}/g' k8s/deployment.yaml k8s/service.yaml 6 sed -i 's/${SKUBER_PLUS_REGISTRY}/${{ env.SKUBER_PLUS_REGISTRY }}/g' k8s/deployment.yaml 7 sed -i 's/${TAG}/${{ inputs.CUSTOM_TAG }}/g' k8s/deployment.yaml 8 9- name: Deploy to AKS 10 uses: azure/k8s-deploy@v4 11 with: 12 namespace: ${{ inputs.NAMESPACE }} 13 manifests: | 14 k8s/deployment.yaml 15 k8s/service.yaml 16 images: | 17 ${{ env.SKUBER_PLUS_REGISTRY }}/${{ inputs.TARGET_NAME }}:${{ inputs.CUSTOM_TAG }} 18 19- name: Generate Deployment Summary 20 if: always() 21 run: | 22 echo "### Deployment Summary" >> $GITHUB_STEP_SUMMARY 23 echo "- **Cluster:** ${{ inputs.AKS_CLUSTER }}" >> $GITHUB_STEP_SUMMARY 24 echo "- **Namespace:** ${{ inputs.NAMESPACE }}" >> $GITHUB_STEP_SUMMARY 25 echo "- **Application:** ${{ inputs.TARGET_NAME }}" >> $GITHUB_STEP_SUMMARY 26 echo "- **Version:** ${{ inputs.CUSTOM_TAG }}" >> $GITHUB_STEP_SUMMARY
배포가 완료되면 Generate Deployment Summary
스텝에서 배포 결과를 요약하여 보여주도록 했다. 이 요약은 GitHub Actions의 실행 결과 페이지에서 확인할 수 있는 특별한 섹션(GITHUB_STEP_SUMMARY
)에 기록되며, 이를 통해 어떤 클러스터의 어떤 네임스페이스에 어떤 버전이 배포되었는지 히스토리처럼 남도록 하였다.
개선점
사실 이미 편리한건 사실이다. 이미지 빌드 자동화부터 배포 자동화까지.. 그리고 분명 더 꼼꼼하게 검증하고자 하는 것들을 더 넣으면 보안과 관리 측면에서도 기능이 향상될테다. 개선사항으론 아래 항목들을 생각해보고 적용해보려고 한다.
-
리소스 그룹명과 클러스터 이름에 대한 Validation Step으로 예외케이스 핸들링
-
Kubernetes 매니페스트 파일들을 프로젝트 디렉토리 내부에서 관리하는 것이 뭔가 신경쓰인다. 당장은 2~3가지 이상의 리소스 관리가 없기에 니즈가 없어보이지만, 금방이라도 피부로 와닿을 개선점 같기만 하다. 더 나은 방법이 있다면 이 쪽에 기입해둘 예정이다. → GitOps 전용 리포지토리 리서치해볼 것.