Kubernetes

[Kubernetes] Gitea와 ArgoCD를 통한 CD 파이프라인 구축

테런 2024. 6. 5. 15:14
Overview

 

Prerequisite
  • [Kubernetes] ArgoCD 설치하기 (링크)
  • [Git] Docker를 통한 Gitea 구축하기(GitLab과 차이) (링크)
  • [Gitea] Gitea를 통한 CI 파이프라인 구축 (with Docker Hub) (링크)
  • [Gitea] Gitea를 통한 CI 파이프라인 구축 (with Nexus) (링크)
  • [Helm] Helm 설치하기 (링크)

 

Helm Chart 생성
// demo 애플리케이션 진입
$ cd demo

// Helm Chart 생성 시 권한 에러 방지
$ chmod go-r ~/.kube/config

// 애플리케이션 Root 경로에서 생성
// Helm Chart 생성
$ helm create helm

// Helm Chart에서 Template 파일들은 모두 제거 
$ cd helm/templates && rm -rf *

// deployment yaml
$ vi deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.name }}-deploy
  namespace: {{ .Values.namespace }}
  labels:
    app: {{ .Values.name }}
spec:
  replicas: 3
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: {{ .Values.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.name }}
    spec:
      containers:
        - name: {{ .Values.name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
          - name: http
            containerPort: 8080

// ingress yaml
$ vi ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Values.name }}-ingress
  namespace: {{ .Values.namespace }}
spec:
  ingressClassName: nginx
  rules:
  - host: "gitea.{{ .Values.ip }}.sslip.io"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: {{ .Values.name }}-svc
            port:
              number: 8080

// service yaml
$ vi service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.name }}-svc
  namespace: {{ .Values.namespace }}
spec:
  selector:
    app: {{ .Values.name }}
  ports:
  - protocol: TCP
    name: http
    port: 8080
    targetPort: http

 

Gitea CI (Docker Hub)
$ cd ../../.gitea/workflows

// CI 파이프라인 구축
$ vi gitea-ci.yaml
name: Build And Test
run-name: ${{ gitea.actor }} is runs ci pipeline
on:
  push:
    branches:
      - master
      
jobs:
  Gitea-Docker-Build-Push:
    runs-on: ubuntu-22.04
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ account }}/demo:${{ gitea.run_number }}
      - name: Update values.yaml
        run: |
          cd helm
          cat <<EOF > "values.yaml"
          name: gitea
          namespace: gitea
          ip: ${{ Kubernetes Master Node Public IP }}
          
          image:
            repository: ${{ account }}/demo
            pullPolicy: Always
            tag: ${{ gitea.run_number }}
            
          nameOverride: "gitea"
          fullnameOverride: "gitea"
          EOF
          git config --global user.name 'gitea'
          git config --global user.email 'gitea@github.com'          
          git add values.yaml
          git commit -m "Update values.yaml"
          git push
          
// sed로 값 대체 또는 직접 수정
$ sed -i 's/${{ account }}/{계정명}/g' gitea-ci.yaml
$ sed -i 's/${{ Kubernetes Master Node Public IP }}/{Kubernetes Master Node Public IP}/g' gitea-ci.yaml

// Git에 Push
$ git push

// Docker Hub에 이미지 확인

 

Gitea CI (Nexus)
$ cd ../../.gitea/workflows

// CI 파이프라인 구축
$ vi gitea-ci.yaml
name: Build And Test
run-name: ${{ gitea.actor }} is runs ci pipeline
on:
  push:
    branches:
      - master

jobs:
  Gitea-Docker-Build-Push:
    runs-on: ubuntu-22.04
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Login to Nexus
        run: |
          docker login nexus-docker.${{ Nexus Public IP }}.sslip.io \
          -u ${{ secrets.USERID }} \
          -p ${{ secrets.PASSWORD }}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64
          push: true
          tags: nexus-docker.${{ Nexus Public IP }}.sslip.io/demo:1.0.${{ gitea.run_number }}
      - name: Update values.yaml
        run: |
          cd helm
          cat <<EOF > "values.yaml"
          name: gitea
          namespace: gitea
          ip: ${{ Kubernetes Master Node Public IP }}
          
          image:
            repository: nexus-docker.${{ Nexus Public IP }}.sslip.io/demo
            pullPolicy: Always
            tag: 1.0.${{ gitea.run_number }}
            
          nameOverride: "gitea"
          fullnameOverride: "gitea"
          EOF
          git config --global user.name 'gitea'
          git config --global user.email 'gitea@github.com'          
          git add values.yaml
          git commit -m "Update values.yaml"
          git push
          
// sed로 값 대체 또는 직접 수정
$ sed -i 's/${{ Nexus Public IP }}/{Nexus Public IP}/g' gitea-ci.yaml
$ sed -i 's/${{ Kubernetes Master Node Public IP }}/{Kubernetes Master Node Public IP}/g' gitea-ci.yaml

// Git에 Push
$ git push

// Nexus에 이미지 확인

 

ArgoCD

ArgoCD 접속 > Settings
Repositories > Connect Repo 클릭
Git 정보 입력
Status 확인
CD 생성
오른쪽 상단 EDIT AS YAML 클릭
Yaml의 기본값

// CD Yaml 변경
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: gitea
spec:
  project: default
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: gitea # 배포할 Namespace
  source:
    path: helm
    repoURL: '{Git 주소}'
    targetRevision: master # 브랜치
    helm:
      valueFiles:
        - values.yaml  # Helm Chart의 Default 값
  syncPolicy:
    automated: # 자동 동기화
      prune: true
      selfHeal: true
    syncOptions:
    - Validate=false
    - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

Git에서 정보를 얻어와서 Kubernetes 클러스터에 배포
정상 배포 확인

 

+ 추가)
RKE2를 이용해서 Kubernetes Cluster를 구축했고, Private Image Registry (Nexus)를 이용하고자 하면 필수적으로 수정해야할 사항이 있습니다. (링크)
// Nexus가 설치된 서버
$ sudo su -

// SSL CA 키 확인
$ cat /etc/letsencrypt/live/nexus-docker.{Public IP}.sslip.io/cert.pem
// 모든 Kubernetes Node에서 아래 진행 후 Node 재실행
$ sudo su -
$ vi /usr/local/share/ca-certificates/cert.pem
Nexus 서버의 CA 키 입력

$ vi /etc/rancher/rke2/registries.yaml
mirrors:
  nexus-docker.{Public IP}.sslip.io:
    endpoint:
      - "https://nexus-docker.{Public IP}.sslip.io:443"
configs:
  "nexus-docker.{Public IP}.sslip.io:443":
    auth:
      username: {Nexus 계정}
      password: {Nexus 비밀번호}
    tls:
      ca_file: /usr/local/share/ca-certificates/cert.pem