카카오클라우드 미니 프로젝트 2(쿠버네티스 CI CD 구축하기/ Github Action, argo)
1. 프로젝트 flow
- 코드 빌드 및 컨테이너화: 코드가 업데이트되면 파이프라인 작업을 실행 시킵니다.
- 이미지 업로드: 파이프라인 도구를 사용하여 소스 코드를 컨테이너화된 애플리케이션으로 변환합니다. 생성된 컨테이너 이미지는 카카오클라우드 Container Registry에 푸시됩니다.
- 매니페스트 업데이트: 업로드된 컨테이너 이미지에 대한 정보가 배포 매니페스트를 관리하는 깃 저장소에 업데이트됩니다. 이 단계는 새 이미지 세부 정보를 배포 구성에 통합합니다.
- 코드 업데이트 감지: ArgoCD는 배포 매니페스트를 포함하는 깃 저장소의 변경 사항을 모니터링합니다.
- ArgoCD를 이용한 배포 자동화: 업데이트가 감지되면 ArgoCD가 이러한 변경 사항을 인프라에 자동으로 적용하여 수동 개입 없이 최신 애플리케이션 버전이 배포되도록 합니다.
https://docs.kakaocloud.com/tutorial/dev-tools/gitops-pipeline#step-5-build-argocd
카카오클라우드 쿠버네티스 환경에서 GitOps 구축 | 카카오클라우드
카카오클라우드 쿠버네티스 환경에서 간단한 GitOps 환경을 구축합니다. 파이프라인 도구를 이용하여 코드를 빌드하고 컨테이너라이징하여 카카오클라우드 Container Registry에 업로드합니다. 업로
docs.kakaocloud.com
2. K8SE 클러스터 생성
1. 아래 링크를 참조하여 클러스터를 생성한다.
쿠버네티스 버전 : 1.29 / CNI : Calico / 노드풀 : 3개
2. 네임스페이스 생성
kubectl create namespace {네임스페이스명}
3. Container Registry 인증 Secret 추가
# Container Registry 인증 시크릿 생성
kubectl create namespace kakaocloud-library
kubectl create -n kakaocloud-library secret docker-registry kc-tutorial-cr \
--docker-server=${클라우드 프로젝트 이름}.kr-central-2.kcr.dev \
--docker-username=${액세스 키 ID} \
--docker-password=${보안 액세스 키} \
--docker-email=${사용자 이메일}
- namespace {네임스페이스명}
3. 파일스토리지 생성 및 NFS Client Provisioner 설정
1. 파일 스토리지 생성
https://docs.kakaocloud.com/service/container-pack/k8se/how-to-guides/k8se-nfs
2. Helm으로 NFS Client Provisioner 배포
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
3. NFS Client Provisioner 설치
helm install --kubeconfig=$KUBE_CONFIG nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=[File Storage IP] --set nfs.path=[File Storage Mount Path]
4. StorageClass 확인
kubectl --kubeconfig=$KUBE_CONFIG get sc
5. PersistentVolumeClaim 생성 및 자동 프로비저닝 테스트
PVC 생성 예제 파일
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
6. File Storage 할당하기
kubectl --kubeconfig=$KUBE_CONFIG get pvc // PVC 확인
kubectl --kubeconfig=$KUBE_CONFIG get pv // PV 확인
4. Container Registry 생성
Container Registry를 이용하여 쿠버네티스에 배포할 컨테이너 이미지를 보관하여 활용할 수 있습니다.
카카오클라우드 콘솔> Container Registry 메뉴에서 Repository(이하 CR Repository)를 생성할 수 있습니다. 아래 정보를 확인하여 CR Repository를 생성합니다.
구분 | Repository 설정값 |
공개 여부 | 비공개 |
리포지토리 이름 | tutorial |
태그 덮어쓰기 | 가능 |
이미지 스캔 | 자동 |
5. 예제 프로젝트 복제
1. 아래 표를 참고하여, 사용자 GitHub 환경에 Repository(이하 Git Repository)를 생성합니다.
정보 | 값 |
이름 | kakaocloud-library |
공개 | Public |
2. 터미널을 실행하여 예제 프로젝트를 복제합니다.
git clone -b kakaocloud-library https://github.com/kakaoenterprise/kakaocloud-tutorials
3. 복제한 프로젝트 폴더로 작업 디렉터리를 이동합니다.
cd kakaocloud-tutorials
4. 복제한 예제 프로젝트의 원격 저장소 정보를 이전 생성한 Git Repository로 업데이트합니다.
git remote remove origin
git remote add origin https://github.com/${GIT_USERNAME}/kakaocloud-library
git branch -M main
git push -u origin main
5. 예제 프로젝트 내용을 사용자의 Git Repository 환경으로 업로드합니다. 해당 작업을 위해 사용자 Git 환경에 대한 인증이 필요합니다.
git push
7. 배포를 위한 Manifest 리포지토리 생성
아래 표를 참고하여, 사용자 GitHub 환경에 리포지토리를 생성합니다.
정보 | 값 |
이름 | deploy-manifests |
공개 | Private |
8. services.yaml 파일을 아래 데이터로 작성하여 추가합니다.
네임스페이스 kakaocloud-library와 LoadBalancer 유형의 서비스를 생성합니다.
apiVersion: v1
kind: Namespace
metadata:
name: kakaocloud-library
---
apiVersion: v1
kind: Service
metadata:
name: client
namespace: kakaocloud-library
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: client
---
apiVersion: v1
kind: Service
metadata:
name: server
namespace: kakaocloud-library
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
selector:
app: server
9. 프론트엔드 애플리케이션 배포를 위한 deployment 파일을 작성합니다.
./deployment-client.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: client
namespace: kakaocloud-library
spec:
replicas: 2
revisionHistoryLimit: 3
selector:
matchLabels:
app: client
template:
metadata:
labels:
app: client
spec:
containers:
- image: {프로젝트명}.kr-central-2.kcr.dev/{Container Registry 레포지토리명}/kakaocloud-library-client:latest
name: kakaocloud-library-client
ports:
- containerPort: 80
env:
- name: SERVER_ENDPOINT
value: "http://server.kakaocloud-library.svc.cluster.local:8080"
imagePullSecrets:
- name: kc-cr-secret
10 . 백엔드 애플리케이션 배포를 위한 deployment 파일을 작성합니다.
./deployment-server.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: server
namespace: kakaocloud-library
spec:
replicas: 2
revisionHistoryLimit: 3
selector:
matchLabels:
app: server
template:
metadata:
labels:
app: server
spec:
containers:
- image: {프로젝트명}.kr-central-2.kcr.dev/{Container Registry 레포지토리명}/kakaocloud-library-client:latest
name: kakaocloud-library-server
ports:
- containerPort: 8080
env:
- name: PROFILE
value: "local"
- name: SERVER_PORT
value: "8080"
imagePullSecrets:
- name: kc-cr-secret
6. 파이프라인 도구 구축 및 설정
1. GitHub-Actions 실행에 사용할 Secret 정보를 작성합니다. 복제한 kakaocloud library 리포지터리 페이지로 이동합니다. Repo 관리 페이지 > Settings 탭으로 이동합니다.
2. Security > Secrets and variables > Actions 메뉴로 이동합니다. 해당 메뉴에서 actions에서 사용할 환경 변수와 Secret 정보를 관리할 수 있습니다. 아래 표를 확인하여 새로운 Repository secrets 정보를 추가합니다.
Name | Secret |
PROJECT_NAME | 카카오클라우드 콘솔의 프로젝트 이름 |
ACCESS_KEY | 액세스 키 |
ACCESS_SECRET_KEY | 사용자 보안 액세스 키 |
REPOSITORY_NAME | 컨테이너 리포지토리 이름 |
USERNAME | GitHub 유저 이름 |
GitHub 유저 이메일 | |
PAT | GitHub의 Personal Access Token |
3. 사용자 Git 환경 kakaocloud-library이름의 Git Repository에 GitHub-Actions 설정 파일을 작성합니다. Repo 루트 경로에서 .github/workflows/action-client.yaml 파일을 생성하고 아래 내용을 복사해 붙여 넣습니다.
.github/workflows/action-client.yaml
name: KakaoCloud-tutorial-client
run-name: kakaoCloud tutorial client workflow
on:
push:
paths:
- 'client/**'
jobs:
build-and-push-image:
runs-on: ubuntu-latest
steps:
- name: Set up Qemu
uses: docker/setup-qemu-action@v2
- name: Login KakaoCloud
uses: docker/login-action@v2
with:
registry: ${{ secrets.PROJECT_NAME }}.kr-central-2.kcr.dev
username: ${{ secrets.ACCESS_KEY }}
password: ${{ secrets.ACCESS_SECRET_KEY }}
- uses: actions/checkout@v3
- name: Build and Push
uses: docker/build-push-action@v4
with:
file: ./client/deploy/Dockerfile
context: ./client
push: true
tags: ${{ secrets.PROJECT_NAME }}.kr-central-2.kcr.dev/${{ secrets.REPOSITORY_NAME }}/kakaocloud-library-client:${{ github.sha }}
update-deployment-file:
runs-on: ubuntu-latest
needs: build-and-push-image
steps:
- name: Checkout deploy-manifests repository
uses: actions/checkout@v3
with:
repository: ${{ secrets.USERNAME }}/deploy-manifests
token: ${{ secrets.PAT }}
- name: Install yq
run: sudo snap install yq
- name: Update image in deployment file
run: |
yq e '.spec.template.spec.containers[0].image = "${{ secrets.PROJECT_NAME }}.kr-central-2.kcr.dev/${{ secrets.REPOSITORY_NAME }}/kakaocloud-library-client:${{ github.sha }}"' ./deployment-client.yaml -i
- name: Commit and Push changes
run: |
git config --global user.email "${{ secrets.EMAIL }}"
git config --global user.name "${{ secrets.USERNAME }}"
git add .
git commit -m "Update deployment-client.yaml"
git remote set-url origin https://${{ secrets.PAT }}@github.com/${{ secrets.USERNAME }}/deploy-manifests
git push --set-upstream origin HEAD
4. 사용자 Git 환경 kakaocloud-library 이름의 Git Repository에 GitHub-Actions 설정 파일을 작성합니다. .github/workflows/action-server.yaml 파일을 생성하고 아래 내용을 복사해 붙여 넣습니다. 아래 내용은 다음과 같습니다.
.github/workflows/action-server.yaml
name: KakaoCloud-tutorial-server
run-name: kakaoCloud tutorial server workflow
on:
push:
paths:
- 'server/**'
jobs:
build-and-push-image:
runs-on: ubuntu-latest
steps:
- name: Set up Qemu
uses: docker/setup-qemu-action@v2
- name: Login KakaoCloud
uses: docker/login-action@v2
with:
registry: ${{ secrets.PROJECT_NAME }}.kr-central-2.kcr.dev
username: ${{ secrets.ACCESS_KEY }}
password: ${{ secrets.ACCESS_SECRET_KEY }}
- uses: actions/checkout@v3
- name: Build and Push
uses: docker/build-push-action@v4
with:
file: ./server/deploy/Dockerfile
context: ./server
push: true
tags: ${{ secrets.PROJECT_NAME }}.kr-central-2.kcr.dev/${{ secrets.REPOSITORY_NAME }}/kakaocloud-library-server:${{ github.sha }}
update-deployment-file:
runs-on: ubuntu-latest
needs: build-and-push-image
steps:
- name: Checkout deploy-manifests repository
uses: actions/checkout@v3
with:
repository: ${{ secrets.USERNAME }}/deploy-manifests
token: ${{ secrets.PAT }}
- name: Install yq
run: sudo snap install yq
- name: Update image in deployment file
run: |
yq e '.spec.template.spec.containers[0].image = "${{ secrets.PROJECT_NAME }}.kr-central-2.kcr.dev/${{ secrets.REPOSITORY_NAME }}/kakaocloud-library-server:${{ github.sha }}"' ./deployment-server.yaml -i
- name: Commit and Push changes
run: |
git config --global user.email "${{ secrets.EMAIL }}"
git config --global user.name "${{ secrets.USERNAME }}"
git add .
git commit -m "Update deployment-server.yaml"
git remote set-url origin https://${{ secrets.PAT }}@github.com/${{ secrets.USERNAME }}/deploy-manifests
git push --set-upstream origin HEAD
Repo에 Push 이벤트를 발생시키고 결과를 확인합니다. 결과 확인까지 시간이 소요될 수 있습니다.
- (이벤트를 발생하는 예시) 결과 확인을 위해 ./server 와 ./client 디렉터리 내에 README.md 파일을 생성하고 Repo에 반영합니다.
빌드 결과 확인
- 카카오클라우드 콘솔> Container Registry 메뉴에서 이미지가 업로드되었는지 확인합니다.
- 콘솔에서 추가된 컨테이너 이미지 및 태그 정보를 확인합니다.
7. ArgoCD 구축
1. 쿠버네티스 클러스터에 ArgoCD를 설치합니다.
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/release-2.8/manifests/install.yaml
2. GitHub 리포지토리 주소와 GitHub 인증 정보를 작성하여 ArgoCD 프로젝트를 배포합니다.
apiVersion: v1
kind: Secret
metadata:
name: private-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
url: https://github.com/${GITHUB_USERNAME}/deploy-manifests
username: ${GITHUB_USERNAME}
password: ${GITHUB_PAT}
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kakaocloud-library
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/${GITHUB_USERNAME}/deploy-manifests
targetRevision: HEAD
path: ./
destination:
server: https://kubernetes.default.svc
namespace: kakaocloud-library
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
8. 배포 결과 확인
1. ArgoCD는 웹 관리 페이지를 통해 배포된 워크로드를 확인할 수 있습니다. 관리 페이지 접속을 위해 포트 포워딩을 진행합니다. 사용자 로컬호스트 8080 포트 인바운드를 ArgoCD 관리 페이지에 접속하는 포트로 포워딩합니다.
kubectl port-forward svc/argocd-server -n argocd 8080:443&
2. 브라우저에서 로컬호스트 8080 포트로 접속합니다.
open http://localhost:8080
3. 인증을 위해 ID와 비밀번호가 필요합니다. 아래 명령어를 입력하여 기본 관리자 계정의 비밀번호를 확인합니다.
- 관리자 ID: admin
- 관리자 패스워드: (출력 결과)
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
4. ArgoCD 웹 페이지를 통해 배포된 워크로드를 확인합니다.
5. 카카오클라우드 콘솔에서 Load Balancer 서비스에 접속합니다. 생성된 로드 밸런서에 퍼블릭 IP를 부여하고 생성된 퍼블릭 IP로 접속하여 배포된 서비스를 확인합니다.
9. Prometheus & Grafana 설치 가이드
1. Helm 리포지토리 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
2. 네임스페이스 생성
kubectl create namespace monitoring
3. Prometheus 설치 (with cross-namespace config)
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false \
--set 'prometheus.prometheusSpec.serviceMonitorNamespaceSelector.matchNames[0]={확인할 네임스페이스명}'
serviceMonitorNamespaceSelector 설정으로 다른 네임스페이스에 있는 ServiceMonitor를 감지할 수 있게 허용
4. Grafana 웹 대시보드 접속
kubectl port-forward -n monitoring svc/prometheus-grafana 3000:80
- 접속 주소: http://localhost:3000
- 초기 계정:
- ID: admin
- PW: kubectl get secret -n monitoring prometheus-grafana -o jsonpath="{.data.admin-password}" | base64 -d
5. kakaocloud-library 네임스페이스에서 모니터링할 리소스에 ServiceMonitor 생성
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: client-monitor
namespace: kakaocloud-library
labels:
release: prometheus
spec:
selector:
matchLabels:
app: client
endpoints:
- port: http
interval: 15s
6. RBAC 권한 추가 (옵션 - 대부분 Helm 설치 시 자동 설정되지만 문제 있을 경우 수동 설정)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-monitoring-access
rules:
- apiGroups: ["", "monitoring.coreos.com"]
resources: ["services", "endpoints", "pods", "servicemonitors"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-monitoring-access
roleRef:
kind: ClusterRole
name: prometheus-monitoring-access
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: prometheus-kube-prometheus-prometheus
namespace: monitoring