[온프레미스-K8S] Argo-CD를 사용한 GitOps 구축

반영환·2024년 5월 9일
0

k8s

목록 보기
11/14
post-thumbnail

Argo-CD를 이용한 GitOps 시스템 구축

GitOps & SSOT

프로그램 소스, Kubernetes 리소스 그리고 심지어 인프라까지 코드로 구현될 수 있다. 여러 환경에 흩어져 있는 코드들을 Git을 사용해 한 곳에 보관하고, 현재 운영중인 상태 (Ops) 와 동일하게 맞추는 것이 깃옵스의 의미이다.

운영 중의 서비스는 반드시 하나의 버전만을 바라보아야 하며, 이를 단일 진실 원칙 ( SSTO ) 라고 한다.

깃옵스에서 Git Repository가 시스템의 구성과 상태에 대한 단일 진실 원천의 역할을 한다.

현재의 운영 상태를 개별 사용자가 임의로 명령어로 변경하거나, 커밋하지 않은 코드로 바꾸는 것을 허용하지 않고 오직 Git Repository의 내용을 운영 환경에 반영하는 것을 목표로 한다.

깃옵스로 시스템의 일관성이 유지돼 모든 시스템과 사용자들이 동일한 코드를 참조해 정보의 불일치를 줄일 수 있다는 점이 내가 생각하는 가장 큰 장점이다.

Argo-CD

깃옵스 환경에서 Continuous Deployment 에 사용되는 도구가 Argo-CD 이다.

ArgoCD는 지정된 Git Repository와 Kubernetes Cluster를 지속적으로 모니터링한다.
Auto Sync. 옵션이 켜져있다면 자동으로 동기화를 시켜준다.

또한 대시보드도 제공하기에 애플리케이션의 실시간 상태, Health Check를 GUI로 확인할 수 있어 운영에 편리함을 주어 많은 현업에서 사용한다고 한다.

설치

YAML

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Helm

helm repo add argo https://argoproj.github.io/argo-helm
helm pull argo/argo-cd --version v5.14.1
tar xvfz argo-cd-5.14.1.tgz
mv argo-cd argo-cd-v5.14.1
rm -rf argo-cd-5.14.1.tgz
cd argo-cd-v5.14.1
mkdir ci && cp values.yaml ci/hwany-values.yaml

원격의 ArgoCD의 헬름 리포지토리를 등록 helm repo add 하고 로컬에 헬름 차트를 다운 helm pull 받는다.
이 후 기본 헬름 Value 파일을 각 환경에 맞게 수정하기 위하여 기존 Values.yaml 파일을 복사하여 임의의 이름 hwany-values.yaml 으로 변경한다.

설정

Argo-CD가 바라볼 저장소를 지정해주어야하는데 방법은 GUI와 YML파일, 총 두 가지가 있다.
깃옵스 철학에 맞게 해당 설정 또한 코드로 남기는 것을 추천한다.

Values.yaml

복사했던 values 파일 ( hwany-values.yaml ) 의 아래 부분을 변경해준다. 나는 argo의 설정파일을 관리하기 위해 private repository를 만들었지만 terraform으로도 관리할 수 있을 것 같다.

# -- Repository credentials to be used as Templates for other repos
  ## Creates a secret for each key/value specified below to create repository credentials
  credentialTemplates:
    [template name]:
      url: [github url]
      username: [user name]
      password: [token]

  # -- Annotations to be added to `configs.credentialTemplates` Secret
  # 안쓰면 주석처리 해줘야 함
  # credentialTemplatesAnnotations: {}

  # -- Repositories list to be used by applications
  ## Creates a secret for each key/value specified below to create repositories
  ## Note: the last example in the list would use a repository credential template, configured under "configs.repositoryCredentials".
  repositories:
    [repository name]:
      url: [github url]
      type: git
      credentialsTemplate: [template name]

배포

Argo-CD가 변경 사항을 확인 할 K8S 클러스터에 Argo-CD를 배포한다.

helm install argocd argo/argo-cd -n argocd --create-namespace -f ci/hwany-values.yaml

접속

배포한 Argo-CD의 대시보드에 접근하려면 서비스를 외부에 노출시켜야한다.
클러스터 외부에서 내부의 파드에 접근할 때에는 주로 Ingress Resource를 사용하지만, 현재 온프레미스-K8S 클러스터를 사용하고 있고, EC2에서 운용중이기에 ELB Auto Provisioning이 되지 않아 ( 정책상 문제 ) Ingress Resource를 사용할 수 없다.

자주 접속하지 않고 단발성으로 접근할 때 사용할 수 있는 Port-Forwarding이나, 서비스를 노드포트 타입으로 변경해 도메인을 할당해 접속하는 방법이 있다.

Port-Forwarding

kubectl port-forward svc/argocd-server <외부#>:443

SVC -> NodePort Type

기본적으로 svc 자원은 ClusterIP 타입이다. 클러스터 내부에서만 서비스에 접근가능한 것이 기본 값으로 설정돼있다.

따라서 외부 접속을 허용하기 위해 NodePort로 서비스를 노출시키고 포트 맵핑을 해 외부에서 접근 가능하도록 하면 된다.

kubectl edit svc argocd-server -n argocd

이후 AWS에서 인바운드 30401 포트를 IPv4, IPv6 모두 열어준다.

접속

초기 ID : admin
초기 비밀번호 :

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

위 명령어를 통해 확인할 수 있다.

Fail로 뜨더라도 안심하자. 빈 Repository기 때문에 초기에는 Fail이 뜬다.

서비스 배포 with Kustomize

Kustomize 를 사용해 Deployment를 관리할 것이다.
Kustomize는 Helm과 마찬가지로 Kubernetes 자원을 관리해주는 패키지이다.

Argo-CD는 특정 yaml 파일의 변경을 확인할 뿐, push event등을 감지할 수는 없다. 따라서 Argo-CD가 바라볼 레포지토리에 Kustomize를 사용해 K8S 리소스를 관리할 것이다.

Kustomize Repository 구성


base 폴더에 기본적인 K8S Resource yaml 파일을 작성한다.
overlay/dev 폴더에 argo-cd가 바라볼 kustomization.yml 을 작성해 놓는다.

base/kustomization.yml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - contract-service.yml

overlay/dev/contract....yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: contract-service-deployment
spec:
  replicas: 2

이 yml 파일은 우리가 실제 배포 환경에서 이루어지기 원하는 deployment의 특성을 정의한다.

이런 기능을 kustomize가 지원하기 때문에 환경에 따라 다른 옵션을 적용해 배포할 수 있다.
overlay/dev/kustomiazation.yml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
  - name: contract-service-image
    newName: <ECR-Repo-URL>
    newTag: <TAG-NAME>
resources:
  - ../../base
patchesStrategicMerge:
  - contract-service-deployment-replica.yml

images.name 부분은 deployment에 선언된 name과 이름이 같아야 한다.

Github Action 구성 (Source)

Kustomize 레포지토리는 민감 정보가 많이 포함돼있기 때문에 프라이빗으로 만들어서 관리해야한다.

따라서 일반적으로 Source Code 레포지토리와 분리돼야 하는데 이를 위해 Github Action의 dispatch 이벤트를 사용해 간접적으로 파일을 업데이트 할 수 있다.

- name: Set timestamp
        id: vars
        run: echo "TIMESTAMP=$(date +%s)" >> $GITHUB_ENV

      - name: Build & Push to ECR
        run: |
          docker build -t contract-service .
          IMAGE_TAG="${{ secrets.AWS_ACCOUNT_NUM }}.dkr.ecr.ap-northeast-2.amazonaws.com/yhp-capstone-repository:contract-service-${TIMESTAMP}"
          docker tag contract-service $IMAGE_TAG
          docker push $IMAGE_TAG
        env:
          TIMESTAMP: ${{ env.TIMESTAMP }}

      - name: Trigger Kustomize Repository Workflow
        run: |
          JSON_PAYLOAD=$(jq -n \
            --arg image_tag "contract-service-${TIMESTAMP}" \
            --arg target_kusto "contract-kustomize" \
            '{event_type: "update-image-tag", client_payload: {image_tag: $image_tag, target_kusto: $target_kusto}}')
          curl -X POST -u "<organization or user name>:${{ secrets.G_TOKEN }}" \
          -H "Accept: application/vnd.github.v3+json" \
          https://api.github.com/repos/<organization or user name>/<Repository Name without .git>/dispatches \
          -d "$JSON_PAYLOAD"
        env:
          TIMESTAMP: ${{ env.TIMESTAMP }}

위 부분을 workflow 파일에 추가해준다.

Github Action 구성 (Kustomize)

name: Update Image Tag CI
on:
  repository_dispatch:
    types: [update-image-tag]
jobs:
  update-kustomization:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
        with:
          repository: <organization or user name>/<Repository Name without .git>
          token: ${{ secrets.G_TOKEN }} # Personal Access Token

      - name: Update kustomization file
        run: |
          echo ${{ github.event.client_payload.image_tag }}
          sed -i "s/newTag: .*/newTag: ${{ github.event.client_payload.image_tag }}/g" ./${{ github.event.client_payload.target_kusto }}/overlay/dev/kustomization.yml

      - name: Commit changes
        run: |
          git config --global user.name 'username'
          git config --global user.email 'username@gmail.com'
          git add .
          git commit -m "Update image tag to ${{ github.event.client_payload.image_tag }}"
          git push

이벤트를 캡쳐한 Kustomize가 action workflow 를 통해 소스 코드를 업데이트한다. 이 과정에서 client_payload의 내용을 받아서 소스 코드 내용을 업데이트하게 된다.

Argo-CD


이 부분에서 argo-cd가 참조할 kustomization.yml 파일의 경로를 적어주면 된다.

이 부분에서 namespace를 설정해주면 된다.

주의!! 새로운 네임스페이스에 배포시 ecr-secret이 생성됐는지 확인하자. 아니면 ErrImagePullBackOff 에러가 발생해 당황할 수 있다...

profile
최고의 오늘을 꿈꾸는 개발자

0개의 댓글