본문 바로가기
Tech/Kubernetes

[PKOS_2기] 3주차 GitOps

by 구름_쟁이 2023. 3. 25.

본 시리즈는 가시다님의 PKOS(Production Kubernetes Online Study) 2기 진행 내용입니다.

스터디에 사용된 서적은 이정훈님의 24단계 실습으로 정복하는 쿠버네티스 입니다.

도서 링크 : http://www.yes24.com/Product/Goods/115187666

 

 

GitOps란?
애플리케이션의 배포와 운영에 관련된 모든 요소를 코드화하여 깃(Git)에서 관리(Ops)하는 것이다.
기본 개념은 코드를 이용하여 인프라를 프로비저닝 하고 관리하는 IaC(Infrastructure as Code)에서 나온 것으로 깃옵스는 이를 인프라에서 전체 애플리케이션 범위로 확장했다.
쉽게 말하자면 현재의 쿠버네티스 상태를 Git으로 관리하는 문화.

 

 

목차

1. Harbor를 이용한 로컬 컨테이너 이미지 저장소 구축

2. 깃랩(Gitlab)을 이용하여 로컬 깃(Git) 소스 저장소 구축

3. ArgoCD를 활용한 GitOps 시스템 구축

 

오늘은 3주차 강의를 토대로 Container Image 저장소를 구축하고, Git 소스 저장소를 구축하며, 쿠버네티스의 애플리케이션 배포 환경을 자동화하는 GitOps 시스템을 구축할 예정이다.

 

복잡해보이지만, 차근차근 각각의 용도와 동작 로직을 이해한다면 쿠버네티스의 GitOps 시스템을 구축하거나 이를 운영하는 데에 많은 도움이 될 것이다.

 

 

 


1. Harbor를 이용한 로컬 컨테이너 이미지 저장소 구축

 

 

배포 특이사항

- kops 인스턴스 t3.small & 노드 c5a.2xlarge

 

 

헬름 차트로 하버 설치

# 사용 리전의 인증서 ARN 확인
aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo "alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN"

# 하버 설치
helm repo add harbor https://helm.goharbor.io
helm fetch harbor/harbor --untar --version 1.11.0
vim ~/harbor/values.yaml
----------------------
expose.tls.certSource=none                        # 19줄
expose.ingress.hosts.core=harbor.<각자자신의도메인>    # 36줄
expose.ingress.hosts.notary=notary.<각자자신의도메인>  # 37줄
expose.ingress.hosts.core=harbor.gasida.link
expose.ingress.hosts.notary=notary.gasida.link
expose.ingress.controller=alb                      # 44줄
expose.ingress.className=alb                       # 47줄~
expose.ingress.annotations=alb.ingress.kubernetes.io/scheme: internet-facing
expose.ingress.annotations=alb.ingress.kubernetes.io/target-type: ip
expose.ingress.annotations=alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
expose.ingress.annotations=alb.ingress.kubernetes.io/certificate-arn: ${CERT_ARN}   # 각자 자신의 값으로 수정입력
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/certificate-arn: ${CERT_ARN}   # 각자 자신의 값으로 수정입력
externalURL=https://harbor.<각자자신의도메인>          # 131줄
externalURL=https://harbor.gasida.link             
----------------------

# 모니터링
kubectl create ns harbor
watch kubectl get pod,pvc,ingress -n harbor

# 설치
helm install harbor harbor/harbor -f ~/harbor/values.yaml --namespace harbor --version 1.11.0

# 확인
# registry : 컨테이너 이미지를 저장
# chartmuseum : 하버를 컨테이너 이미지뿐 아니라, 헬름 차트 리포지토리로도 사용
# notary : 서명이 완료된 컨테이너 이미지만 운영 환경에 사용하도록 설정. 서명이 완료된 이미지는 별도로 구분
# trivy : 컨테이너 이미지의 보안 취약점을 스캔, 스캔 기능은 별도 솔루션에서 제공하여 관리자는 보안 스캔용 도구를 선택 가능
helm list -n harbor
kubectl get-all -n harbor
kubectl get pod,pvc,ingress,deploy,sts -n harbor
kubectl get ingress -n harbor harbor-ingress -o json | jq
kubectl krew install df-pv && kubectl df-pv

# 웹 접속 주소 확인 및 접속
echo -e "harbor URL = https://harbor.$KOPS_CLUSTER_NAME"
echo -e "notary URL = https://notary.$KOPS_CLUSTER_NAME"

서비스 확인

이 화면에서 로그인이 안된다면?

더보기

정답은.

HTTPS로 접속해야 한다.

 

 

ALB 확인

 

Project 생성 및 테스트 이미지 업로드

# 컨테이너 이미지 가져오기
docker pull nginx && docker pull busybox && docker images

# 태그 설정
docker tag busybox harbor.$KOPS_CLUSTER_NAME/pkos/busybox:0.1
docker image ls

# 로그인 - 방안2
echo 'Harbor12345' > harborpw.txt
cat harborpw.txt | docker login harbor.$KOPS_CLUSTER_NAME -u admin --password-stdin
cat /root/.docker/config.json | jq

# 이미지 업로드
docker push harbor.$KOPS_CLUSTER_NAME/pkos/busybox:0.1

 

저자님의 busybox:0.1 사용하는 YAML 파일을 받아 나의 이미지 저장소(harbor.netcloudy.im/pkos)로 변경하여 배포 테스트

# 파드 배포
curl -s -O https://raw.githubusercontent.com/junghoon2/kube-books/main/ch13/busybox-deploy.yml
sed -i "s|harbor.myweb.io/erp|harbor.$KOPS_CLUSTER_NAME/pkos|g" busybox-deploy.yml
kubectl apply -f busybox-deploy.yml

 

Harbor Scan

- Harbor 에 적재된 컨테이너 이미지에 대한 취약점 점검을 수행

 

 

만약 이미지가 push될 때마다 자동으로 취약점 점검을 하고싶다면?

Project - Configuration 에서 Automatically scan images on push 를 체크해주자

 

이후 nginx를 harbor에 push 하는 경우 자동으로 scan 을 수행한다.

앞서 pull받은 nginx 이미지를 harbor 저장소에 push
자동으로 Scanning

 

 

 

 

결론

여태 사용해본 Container Image Registry는 도커 허브와 ACR(Azure Container Registry), ECR(Elastic Container Registry) 정도였고 클라우드 종속적이지 않고 자체 구축하여 사용하는 저장소는 처음 써보게 되었다. (사실 익히 들어서 알고는 있었는데 실제로 구축/운영 해본 것은 처음이였다.)

 

이미지를 Private하게 운영하거나 규모가 커질 때에 대한 시스템적 유연함 등이 굉장히 매력적이다.

 

자체적으로 Helm Chart 를 만들어 운영한다면 멀티 태넌트 환경에서 각각의 Harbor가 필요하거나 일관성이 필요한 경우에도 적절하게 구축 및 운영이 가능할 것이라 생각된다.

 


2. 깃랩(Gitlab)을 이용하여 로컬 깃(Git) 소스 저장소 구축

 

헬름 차트로 깃랩 설치 후 웹 로그인

# 모니터링
kubectl create ns gitlab
watch kubectl get pod,pvc,ingress -n gitlab

# 설치
echo $CERT_ARN
helm repo add gitlab https://charts.gitlab.io/
helm repo update
helm fetch gitlab/gitlab --untar --version 6.8.1
vim ~/gitlab/values.yaml
----------------------
global:
  hosts:
    domain: <각자자신의도메인>             # 52줄
    https: true

  ingress:                             # 66줄~
    configureCertmanager: false
    provider: aws
    class: alb
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
      alb.ingress.kubernetes.io/certificate-arn: ${CERT_ARN}   # 각자 자신의 값으로 수정입력
      alb.ingress.kubernetes.io/success-codes: 200-399
      alb.ingress.kubernetes.io/group.name: "gitlab"
    tls:                               # 79줄
      enabled: false
----------------------
helm install gitlab gitlab/gitlab -f ~/gitlab/values.yaml --set certmanager.install=false --set nginx-ingress.enabled=false --set prometheus.install=false --set gitlab-runner.install=false --namespace gitlab --version 6.8.4

# 확인 - SubCharts
# gitlab-gitaly : 웹서비스 혹은 ssh 방식으로 진행되는 깃 제목, 브랜치, 태그 등의 깃 요청 등에 대한 작업을 담당
# gitlab-gitlab-shell : https 가 아닌 ssh 방식으로 깃 명령어 실행 시 해당 요청을 처리
# gitlab-kas : gitlab agent server
# gitlab-postgresql : 유저, 권한, 이슈 등 깃랩의 메타 데이터 정보가 저장
# gitlab-redis-master : 깃랩 작업 정보는 레디스 캐시 서버를 이용하여 처리
# gitlab-sidekiq-all-in-1-v2 : 레디스와 연동하여 작업 큐 처리 용도로 사용
# gitlab-webservice-default : 깃랩 웹 서비스를 처리
helm list -n gitlab
kubectl get pod,pvc,ingress,deploy,sts -n gitlab
kubectl df-pv -n gitlab
kubectl get-all -n gitlab

# 4개의 Ingress 가 1개의 ALB를 공유해서 사용 : ALB의 Rule 확인해볼것!
# alb.ingress.kubernetes.io/group.name: "gitlab"
kubectl get ingress -n gitlab
NAME                        CLASS   HOSTS                  ADDRESS                                                             PORTS   AGE
gitlab-kas                  alb     kas.gasida.link        k8s-gitlab-3fbf5c8cab-1066962252.ap-northeast-2.elb.amazonaws.com   80      93s
gitlab-minio                alb     minio.gasida.link      k8s-gitlab-3fbf5c8cab-1066962252.ap-northeast-2.elb.amazonaws.com   80      93s
gitlab-registry             alb     registry.gasida.link   k8s-gitlab-3fbf5c8cab-1066962252.ap-northeast-2.elb.amazonaws.com   80      93s
gitlab-webservice-default   alb     gitlab.gasida.link     k8s-gitlab-3fbf5c8cab-1066962252.ap-northeast-2.elb.amazonaws.com   80      93s

# 웹 root 계정 암호 확인
kubectl get secrets -n gitlab gitlab-gitlab-initial-root-password --template={{.data.password}} | base64 -d ;echo
<결과 확인>

# 웹 접속 주소 확인 및 접속
echo -e "gitlab URL = https://gitlab.$KOPS_CLUSTER_NAME"

# 웹 접속 https://gitlab.<각자 자신의 도메인> (root / 웹 root 계정 암호)

ALB 확인

하나의 ALB안에 조건을 AND로 묶어서 여러 서브도메인을 사용할 수 있다.

 

Gitlab 서비스 확인

계정만드는 부분은 생략

 

위에 net이라는 계정으로 들어가 test-stg 라는 이름의 신규 프로젝트 생성

 

 

git config 설정

git source clone

clone 결과 확인

 

생성된 계정으로 Git 소스 commit

 

Git 소스 push

 

Git 소스 push 결과

 

과제

도전 : 책 p250페이지 깃랩에 추가 계정 생성 후 테스트

test01이라는 user 생성 후 test-stg Project에 test01 유저를 Invite

테스트를 위해 Worker node에 접속하여 git configuration

test-stg git 소스 clone 및 확인

(소스 수정)

README.md 파일 내 상단에 아래 내용 입력

add comment from test01 user

 

git 소스 push (Error)

이 에러는 무엇인고...

 

문제해결

더보기

2FA를 enabled로 걸어놓았기 때문에 Personal Access Token을 사용해서 로그인해야 함.

 

문제 해결 후 git 소스 push

 

다시 net 계정으로 돌아와 README.md 에 Text 추가 작업 후 push

파일이 git 저장소의 것과 다르니 git pull이나 이런것들을 해보라는 힌트.

git pull 에 rebase 옵션값을 이용하여 해결.

 

도전 결과

add comment from test01 user : test01 유저 작성 및 push

나는 일하는 구름 : net 유저 작성 및 push

 

결론

좀더 깊은 이해를 원한다면 git-flow를 검색...(저도 더 공부가 필요한듯)

 


3. ArgoCD를 활용한 GitOps 시스템 구축

 

대망의 ArgoCD... Start!!

 

헬름 차트로 설치 후 웹 로그인

# 모니터링
kubectl create ns argocd
watch kubectl get pod,pvc,svc -n argocd

# 설치
cd
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd --set server.service.type=LoadBalancer --namespace argocd --version 5.19.14

# 확인
# argocd-application-controller : 실행 중인 k8s 애플리케이션의 설정과 깃 저장소의 소스 파일에 선언된 상태를 서로 비교하는 컨트롤러. 상태와 다르면 ‘OutOfSync’ 에러를 출력.
# argocd-dex-server : 외부 사용자의 LDAP 인증에 Dex 서버를 사용할 수 있음
# argocd-repo-server : 원격 깃 저장소의 소스 코드를 아르고시디 내부 캐시 서버에 저장합니다. 디렉토리 경로, 소스, 헬름 차트 등이 저장.
helm list -n argocd
kubectl get pod,pvc,svc,deploy,sts -n argocd
kubectl get-all -n argocd

kubectl get crd | grep argoproj
applications.argoproj.io              2023-03-25T11:39:26Z
applicationsets.argoproj.io           2023-03-25T11:39:26Z
appprojects.argoproj.io               2023-03-25T11:39:26Z

# CLB에 ExternanDNS 로 도메인 연결
kubectl annotate service -n argocd argocd-server "external-dns.alpha.kubernetes.io/hostname=argocd.$KOPS_CLUSTER_NAME"

# admin 계정의 암호 확인
ARGOPW=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)
echo $ARGOPW
<결과 확인>

# 웹 접속 로그인 (admin) CLB의 DNS 주소로 접속
echo -e "Argocd Web URL = https://argocd.$KOPS_CLUSTER_NAME"

 

 

 

아르고시디로 애플리케이션 배포에 사용할 깃 저장소와 쿠버네티스 클러스터 정보를 등록을 위해, argocd CLI 도구 설치 - 링크 악분일상

# 최신버전 설치
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
chmod +x /usr/local/bin/argocd

# 버전 확인
argocd version --short

# Help
# argocd app : 쿠버네티스 애플리케이션 동기화 상태 확인
# argocd context : 복수의 쿠버네티스 클러스터 등록 및 선택
# argocd login : 아르고시디 서버에 로그인 
# argocd repo : 원격 깃 저장소를 등록하고 현황 파악
argocd

# argocd 서버 로그인
argocd login argocd.$KOPS_CLUSTER_NAME --username admin --password $ARGOPW

# 기 설치한 깃랩의 프로젝트 URL 을 argocd 깃 리포지토리(argocd repo)로 등록. 깃랩은 프로젝트 단위로 소스 코드를 보관.
argocd repo add https://gitlab.$KOPS_CLUSTER_NAME/<깃랩 계정명>/test-stg.git --username <깃랩 계정명> --password <깃랩 계정 암호>
argocd repo add https://gitlab.$KOPS_CLUSTER_NAME/gasida/test-stg.git --username net --password P@ssw0rd
 
# 등록 확인 : 기본적으로 아르고시디가 설치된 쿠버네티스 클러스터는 타깃 클러스터로 등록됨
argocd repo list
TYPE  NAME  REPO                                            INSECURE  OCI    LFS    CREDS  STATUS      MESSAGE  PROJECT
git         https://gitlab.netcloudy.im/net/test-stg.git  false     false  false  true   Successful

# 기본적으로 아르고시디가 설치된 쿠버네티스 클러스터는 타깃 클러스터로 등록됨
argocd cluster list
SERVER                          NAME        VERSION  STATUS   MESSAGE                                                  PROJECT
https://kubernetes.default.svc  in-cluster           Unknown  Cluster has no applications and is not being monitored.

 

ArgoCD를 이용하여 RabbitMQ 헬름 애플리케이션 배포하기 : RabbitMQ Helm 깃랩 업로드

# test-stg 깃 디렉터리에서 아래 실행
cd ~/gitlab-test/test-stg

# 깃 원격 오리진 주소 확인
git config -l | grep remote.origin.url

# RabbitMQ 헬름 차트 설치
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm fetch bitnami/rabbitmq --untar --version 11.10.3
cd rabbitmq/
cp values.yaml my-values.yaml

# 헬름 차트를 깃랩 저장소에 업로드
git add . && git commit -m "add rabbitmq helm"
git push

# argocd CRD 확인
kubectl get crd | grep argo
applications.argoproj.io                              2022-03-25T15:46:16Z   # 배포 앱 현재 실행 상태와 깃 저장소의 의도한 상태를 계속 비교
appprojects.argoproj.io                               2022-03-25T15:46:16Z   # 프로젝트 단위 구분
argocdextensions.argoproj.io                          2022-03-25T15:46:16Z

# 수정
cd ~/
curl -s -O https://raw.githubusercontent.com/wikibook/kubepractice/main/ch15/rabbitmq-helm-argo-application.yml
vim rabbitmq-helm-argo-application.yml
--------------------------------------
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: rabbitmq-helm
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: rabbitmq
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: https://gitlab.netcloudy.im/net/test-stg.git
    path: rabbitmq
    targetRevision: HEAD
    helm:
      valueFiles:
      - my-values.yaml
  syncPolicy:
    syncOptions:
    - CreateNamespace=true
--------------------------------------

# 모니터링 : argocd 웹 화면 보고 있기!
echo -e "Argocd Web URL = https://argocd.$KOPS_CLUSTER_NAME"

# 배포
kubectl apply -f rabbitmq-helm-argo-application.yml

# YAML 파일을 적용(apply)하여 아르고시디 ‘Application’ CRD를 생성
kubectl get applications.argoproj.io -n argocd
NAME            SYNC STATUS   HEALTH STATUS
rabbitmq-helm   OutOfSync     Missing

배포 결과 확인

 

Sync 실행

 

rabbitmq-helm의 replicas를 1->3으로 변경한다면?

rabbitmq-helm-1만 추가로 생성 중인 것 확인
마찬가지로 rabbitmq-helm-1만 추가로 생성 중인 것 확인

 

rabbitmq-helm을 1->3으로 늘려도 하나만 추가되는 이유는?
sts 즉 Statefulset의 경우 순서대로 배포가 진행되기 때문에 기본적으로 개수를 많이 늘려도 하나씩 추가 배포됨.
물론 이를 병렬처리하는 방법도 있지만 여기서는 넘어간다.

 

 

과제

도전 : ArgoCD 챕터인, 책 273페이지의 ‘Gitops 실습: 클러스터 설정 내역 변경과 깃 저장소 자동 반영’을 직접 스스로 실습해보세요

 

책 내용을 보고 진행

 

 

 

httpd deployment 수정

httpd -> httpd:alpine
Sync가 맞지 않게 되었다.

APP DIFF를 살펴보자

Sync가 맞지 않는 부분은 Alert으로 나타나며 작업자가 적절하게 조치하여 해결할 수 있다.

 

다음으로는 httpd의 service를 삭제해보자.

k delete svc httpd-svc

 

httpd의 상태가 Missing으로 변했다.
내부를 보면 svc가 없는 것을 확인할 수 있다.(물론이지 내가 지웠으니)

이 상태에서 Sync를 수행해보자

훌륭하게도 다시 돌아왔다
image 역시 기존 ArgoCD가 기억하고 있는 httpd 이미지를 사용했다.

 

이번에는 그럼 argoCD와 연동된 gitlab에서 배포했던 rabbitmq-helm의 설정값을 수정해서 쿠버네티스에도 잘 반영이 되는지 확인해보자.

간단하게 rabbitmq-helm의 서비스 타입을 ClusterIP에서 LoadBalancer로 변경.

 

rabbitmq-helm의 my-values.yaml
git push

 

APP DIFF를 확인해보자

 

지금 시점에서 서비스 타입 확인

rabbitmq-helm Sync 수행

 

Sync를 수행하며 우리가 연동해둔 gitlab의 rabbit-mq helm chart 내용(ClusterIP -> LoadBalancer)으로 쿠버네티스의 배포 환경을 구성하려고 한다.

 

결론

이로써 3주차 스터디 내용 복기가 끝났다. 사실 이것도 한번만 핥아 맛본 수준이므로 시간날 때마다 더 깊이깊이 T를 만들어나가야 겠다.

 

중간에 아르고시디를 괴롭힐 때는 굉장히 재미난 기분이였다.

이렇게도 괴롭혀보고 저렇게도 괴롭혀보면서 '이러면 어떻게 할건데!' 라고 저질러놓고 수습하는 모습을 보며 굉장히 요상스럽지만 재밌는 실습 형태로 인해 즐거움이 가득하다.

 

다음 4주차까지 또 화이팅!

 

댓글