IT/Container&k8s

[k8s] GitOps(Image registy, Source repository, Continuous Delivery)

Hayley Shim 2023. 10. 29. 00:40

안녕하세요. CloudNet@ K8S Study를 진행하며 해당 내용을 이해하고 공유하기 위해 작성한 글입니다. DevOps 이정훈님의 도서 ‘24단계 실습으로 정복하는 쿠버네티스’ 의 내용을 바탕으로 스터디를 하며 어떻게 k8s에 적용할지 고민하며 정리해봤습니다.

사전 환경

# YAML 파일 다운로드
$ curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/kops-oneclick-f1.yaml

# CloudFormation 스택 배포 : 노드 인스턴스 타입 변경 - MasterNodeInstanceType=t3.medium WorkerNodeInstanceType=c5d.large
$ aws cloudformation deploy --template-file kops-oneclick-f1.yaml --stack-name mykops --parameter-overrides KeyName=kp-hayley3 SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32  MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName='wellbeconnected.com' S3StateStore='hayley-bucket-test' MasterNodeInstanceType=c5a.2xlarge WorkerNodeInstanceType=c5a.2xlarge --region ap-northeast-2

# CloudFormation 스택 배포 완료 후 kOps EC2 IP 출력
$ aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text

# 13분 후 작업 SSH 접속
$ ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text)

# EC2 instance profiles 에 IAM Policy 추가(attach) : 처음 입력 시 적용이 잘 안될 경우 다시 한번 더 입력 하자! - IAM Role에서 새로고침 먼저 확인!
$ aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME
$ aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME

# 메트릭 서버 확인 : 메트릭은 15초 간격으로 cAdvisor를 통하여 가져옴
$ kubectl top node
NAME                  CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
i-080ab199b531ce380   122m         1%     2150Mi          13%
i-0e3efb68d03b515b3   36m          0%     1027Mi          6%
i-0e5f09676399bd1c5   31m          0%     933Mi           5%

하버(Harbor)를 이용하여 로컬 컨테이너 이미지 저장소 구축

  • Harbor : 오픈 소스 레지스트리(an open source registry that secures artifacts with policies and role-based access control, ensures images are scanned and free from vulnerabilities, and signs images as trusted)
  • Helm 설치
  • HTTPS 접속을 위해 전에 미리 AWS Certificate Manager(ACM)로 인증서를 생성해둡니다.
# 사용 리전의 인증서 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"
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:903575331688:certificate/0da88cd5-dff6-43fd-81e0-ee1c76903d8b

# 하버 설치
$ 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줄, ACM 통해 생성
expose.ingress.hosts.core=harbor.<각자자신의도메인>    # 36줄
expose.ingress.hosts.notary=notary.<각자자신의도메인>  # 37줄
expose.ingress.hosts.core=harbor.wellbeconnected.com
expose.ingress.hosts.notary=notary.wellbeconnected.com
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.wellbeconnectked.com          
----------------------

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

# 설치
$ helm install harbor harbor/harbor -f ~/harbor/values.yaml --namespace harbor --version 1.11.0
NAME: harbor
LAST DEPLOYED: Sun Mar 19 22:01:02 2023
NAMESPACE: harbor
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at https://harbor.wellbeconnected.com
For more details, please visit https://github.com/goharbor/harbor

NAME                                        READY   STATUS    RESTARTS      AGE
pod/harbor-chartmuseum-76dd448b4c-phnv2     1/1     Running   0             65s
pod/harbor-core-798878894f-fwg9v            1/1     Running   0             65s
pod/harbor-database-0                       1/1     Running   0             65s
pod/harbor-jobservice-5d64b8c7f4-wkd5w      0/1     Running   2 (33s ago)   65s
pod/harbor-notary-server-6f5f5d467-t5zgx    1/1     Running   0             65s
pod/harbor-notary-signer-74c797586b-qn6lb   1/1     Running   0             65s
pod/harbor-portal-d74b69db4-j7dhp           1/1     Running   0             65s
pod/harbor-redis-0                          1/1     Running   0             65s
pod/harbor-registry-c676c7ddc-66pp5         2/2     Running   0             65s
pod/harbor-trivy-0                          1/1     Running   0             65s

NAME                                                    STATUS   VOLUME
                            CAPACITY   ACCESS MODES   STORAGECLASS    AGE
persistentvolumeclaim/data-harbor-redis-0               Bound    pvc-492702a5-25
ca-4dd7-9246-26dc0c83cee0   1Gi        RWO            kops-csi-1-21   65s
persistentvolumeclaim/data-harbor-trivy-0               Bound    pvc-30f16079-db
48-4320-8d2c-054165cd0091   5Gi        RWO            kops-csi-1-21   65s
persistentvolumeclaim/database-data-harbor-database-0   Bound    pvc-bdf181c0-fe
40-4d34-a539-92200e4827c3   1Gi        RWO            kops-csi-1-21   65s
persistentvolumeclaim/harbor-chartmuseum                Bound    pvc-52e1b2aa-37
88-4085-9d43-49eae2c6842c   5Gi        RWO            kops-csi-1-21   65s


# 확인
# 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
PV NAME                                   PVC NAME             NAMESPACE  NODE NAME            POD NAME                            VOLUME MOUNT NAME  SIZE   USED  AVAILABLE  %USED  IUSED  IFREE   %IUSED
 pvc-762eaba4-d20f-4cfa-9346-a1078d9c5644  data-harbor-redis-0  harbor     i-007760f4d46d6fdd1  harbor-redis-0                      data               973Mi  24Ki  957Mi      0.00   11     65525   0.02
 pvc-3056926f-fdd0-463a-bdf5-faf0a7d69ead  harbor-chartmuseum   harbor     i-007760f4d46d6fdd1  harbor-chartmuseum-dfb7458d5-z4vgp  chartmuseum-data   4Gi    24Ki  4Gi        0.00   11     327669  0.00
 pvc-4f882ea3-7f11-4f0e-928c-de52efb0dc76  data-harbor-trivy-0  harbor     i-007760f4d46d6fdd1  harbor-trivy-0                      data               4Gi    24Ki  4Gi        0.00   11     327669  0.00


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

 PV NAME                                   PVC NAME             NAMESPACE  NODE NAME            POD NAME                             VOLUME MOUNT NAME  SIZE  USED  AVAILABLE  %USED  IUSED  IFREE   %IUSED
 pvc-c13c22ac-a737-41b1-998c-2d749529aca2  harbor-chartmuseum   harbor     i-067d4c7af8303cfcf  harbor-chartmuseum-5cf6688695-gnjb9  chartmuseum-data   4Gi   24Ki  4Gi        0.00   11     327669  0.00
 pvc-2ce7fd75-f131-477a-97d3-3e361df8dbbb  data-harbor-trivy-0  harbor     i-067d4c7af8303cfcf  harbor-trivy-0                       data               4Gi   24Ki  4Gi        0.00   11     327669  0.00

**주의할 점***

  • 아래와 같이 생성된 ALB에서 Listeners 규칙에 HTTPS:443 규칙이 잘 적용되었는지 확인해줍니다.

SSL Certificate 내에 생성한 ACM이 적용되었는지 확인해줍니다.

시간이 좀 지난 후 연결해준 도메인에 접속해봅니다. alb 에 대상 타겟(파드)로 헬스체크가 성공(완료)가 되어야 되서 조금 시간이 걸립니다.

생성해 준 인증서가 적용된 것을 확인합니다.

하버 웹 접속 및 로컬 이미지 업로드

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

# 태그 설정
$ docker tag busybox harbor.$KOPS_CLUSTER_NAME/pkos/busybox:0.1
$ docker image ls
REPOSITORY                                TAG       IMAGE ID       CREATED       SIZE
busybox                                   latest    7cfbbec8963d   2 days ago    4.86MB
harbor.wellbeconnected.com/pkos/busybox   0.1       7cfbbec8963d   2 days ago    4.86MB
nginx                                     latest    904b8cb13b93   2 weeks ago   142MB

# 로그인 - 방안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
The push refers to repository [harbor.wellbeconnected.com/pkos/busybox]
baacf561cfff: Pushed
0.1: digest: sha256:acaddd9ed544f7baf3373064064a51250b14cfe3ec604d65765a53da5958e5f5 size: 528
이미지 업로드 후

컨테이너 이미지 저장소 주소를 로컬 하버로 변경

# 파드 배포
$ 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
deployment.apps/busybox created

# 확인 : 정상적으로 harbor 에서 이미지 다운로드되어 파드가 동작!
$ kubectl get pod

$ kubectl describe pod | grep Events: -A7

이미지 보안 스캔 기능 사용 — Trivy 이미지 스캐닝 도구

자동으로 보안 스캔 설정

  • Projects — Configuration — Vulnerability scanning — Save
# 태그 설정
$ docker tag nginx harbor.$KOPS_CLUSTER_NAME/pkos/nginx:0.1
$ docker image ls

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

아래와 같이 자동으로 스캔 수행됩니다.

깃랩(GitLab)를 이용하여 로컬 깃(Git) 소스 저장소 구축

깃랩(GitLab)은 무료 오픈소스로 사용 가능한 소스 코드 원격 저장소입니다.

# 모니터링
$ 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.wellbeconnected.com                  80      61s
gitlab-minio                alb     minio.wellbeconnected.com                80      61s
gitlab-registry             alb     registry.wellbeconnected.com             80      61s
gitlab-webservice-default   alb     gitlab.wellbeconnected.com               80      61s


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

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

***주의 ***

  • 마찬가지로 alb에 Listeners에 HTTPSS:443 규칙이 잘 생성되었는지 확인합니다.
  • alb 에 대상 타겟(파드)로 헬스체크가 성공(완료)가 되어야 되서 조금 시간이 걸립니다.

Gitlab ALB Rule에서 Listener 규칙에 4개의 Ingress가 1개의 ALB를 사용하는 것을 확인합니다. 이는 아래와 같이 AND 조건으로 Rule 매치를 하기 때문에 가능합니다.

트래픽이 많지않다면 아래와 같이 1개의 alb로 관리해줘도 무방합니다.

로그인 : root / 생성된 pw
  • 접속 후 별도의 사용자 생성 : Admins → Users(admin 권한 부여)
  • Impersonation Tokens : Name(test), Scopes(모두 Check) → Create ⇒ 토큰 값 확인 glpat-s2SkyxGA2S-MG7ezygsJ
  • Users : 유저 선택 후 암호 입력, admin 권한 체크 ⇒ root 계정 로그아웃 ⇒ User 계정 로그인 ⇒ 암호 변경
비밀번호 변경

신규 프로젝트 생성

  • Project Name, URL, Visibility Level(Internal), Readme 파일 생성 체크

생성한 깃랩 프로젝트에 k8s에서 사용하는 YAML 파일 업로드

#
$ mkdir ~/gitlab-test && cd ~/gitlab-test

# git 계정 초기화 : 토큰 및 로그인 실패 시 매번 실행
$ git config --system --unset credential.helper
$ git config --global --unset credential.helper

# git 계정 정보 확인 및 global 계정 정보 입력
$ git config --list
$ git config --global user.name "<각자 자신의 Gialba 계정>"
$ git config --global user.email "<각자 자신의 Gialba 계정의 이메일>"
$ git config --global user.name "hayley17"
$ git config --global user.email "yhshim17@gmail.com"

# git clone
$ git clone https://gitlab.$KOPS_CLUSTER_NAME/<각자 자신의 Gitlab 계정>/test-dev.git
$ git clone https://gitlab.$KOPS_CLUSTER_NAME/hayley17/test-dev.git
Cloning into 'test-dev'...
Username for 'https://wellbeconnected': hayley17
Password for 'https://yhshim17@gmail.com': <토큰 입력>

# 이동
$ ls -al test-stg && cd test-stg && pwd

# 파일 생성 및 깃 업로드(push) : 웹에서 확인
$ echo "gitlab test memo" >> test.txt
$ git add . && git commit -m "initial commit - add test.txt"
$ git push
cloning into 'test-dev'...
Username for 'https://gitlab.wellbeconnected.com': hayley17
Password for 'https://hayley17@gitlab.wellbeconnected.com':
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

# 이동
$ ls -al test-stg && cd test-stg && pwd

# 파일 생성 및 깃 업로드(push) : 웹에서 확인
$ echo "gitlab test memo" >> test.txt
$ git add . && git commit -m "initial commit - add test.txt"
[main 6969df2] initial commit - all test.txt
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt
$ git push
Username for 'https://gitlab.wellbeconnected.com': hayley17
Password for 'https://hayley17@gitlab.wellbeconnected.com':
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 302 bytes | 302.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://gitlab.wellbeconnected.com/hayley17/test-dev.git
   d256a36..6969df2  main -> main
test.txt 파일 업로드 확인

ArgoCD를 활용한 깃옵스(GitOps) 시스템 구축

ArgoCD를 활용하여 깃옵스(GitOps) 시스템을 구축해봅니다.

  • 지속적인 배포(Continuous Delivery, CD)란 개발자가 소스코드를 변경해서 깃 저장소에 푸시하면 해당 변경 사항이 고객이 사용하는 실제 운영환경의 시스템까지 자동으로 반영하는 것입니다.

설치

# 모니터링
$ kubectl create ns argocd
namespace/argocd created
$ 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-22T15:02:27Z
applicationsets.argoproj.io           2023-03-22T15:02:27Z
appprojects.argoproj.io               2023-03-22T15:02:27Z

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

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

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

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
argocd: v2.6.6+6d4de2e
FATA[0000] Argo CD server address unspecified

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

# argocd 서버 로그인
$ argocd login argocd.$KOPS_CLUSTER_NAME --username admin --password $ARGOPW
WARNING: server certificate had error: x509: certificate is valid for localhost, argocd-server, argocd-server.argocd, argocd-server.argocd.svc, argocd-server.argocd.svc.cluster.local, not argocd.wellbeconnected.com. Proceed insecurely (y/n)? y
'admin:login' logged in successfully
Context 'argocd.wellbeconnected.com' updated

# 기 설치한 깃랩의 프로젝트 URL 을 argocd 깃 리포지토리(argocd repo)로 등록. 깃랩은 프로젝트 단위로 소스 코드를 보관.
$ argocd repo add https://gitlab.$KOPS_CLUSTER_NAME/<깃랩 계정명>/test-dev.git --username <깃랩 계정명> --password <깃랩 계정 암호>
$ argocd repo add https://gitlab.$KOPS_CLUSTER_NAME/hayley17/test-dev.git --username hayley17 --password Test1234
Repository 'https://gitlab.wellbeconnected.com/hayley17/test-dev.git' added
 
# 등록 확인 : 기본적으로 아르고시디가 설치된 쿠버네티스 클러스터는 타깃 클러스터로 등록됨
$ argocd repo list
TYPE  NAME  REPO                                                      INSECURE  OCI    LFS    CREDS  STATUS      MESSAGE  PROJECT
git         https://gitlab.wellbeconnected.com/hayley17/test-dev.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 배포 확인

ArgoCD를 이용하여 RabbitMQ 헬름 애플리케이션 배포

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

# 깃 원격 오리진 주소 확인
$ git config -l | grep remote.origin.url
remote.origin.url=https://gitlab.wellbeconnected.com/hayley17/test-dev.git

# RabbitMQ 헬름 차트 설치
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
$ 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
rabbitmq 폴더가 업로드된 걸 확인할 수 있음

아래와 같이 argocd CRD 를 확인합니다.

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

# 수정
$ cd ~/
$ curl -s -O https://raw.githubusercontent.com/wikibook/kubepractice/main/ch15/rabbitmq-helm-argo-application.yml
$ vim rabbitmq-helm-argo-application.yml #repoURL 변경해주기!!!
--------------------------------------
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.wellbeconnected.com/hayley17/test-dev.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"
Argocd Web URL = https://argocd.wellbeconnected.com

# 배포
$ kubectl apply -f rabbitmq-helm-argo-application.yml
application.argoproj.io/rabbitmq-helm created

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

Git 저장소의 내용과 ArgoCD 환경에 배포된 내용의 sync를 맞춰줍니다.

# 모니터링
$ watch kubectl get pod,pvc -n rabbitmq

# 배포 확인
$ kubectl get all,svc,cm -n rabbitmq
NAME                  READY   STATUS    RESTARTS   AGE
pod/rabbitmq-helm-0   1/1     Running   0          109s

NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                 AGE
service/rabbitmq-helm            ClusterIP   100.71.188.255   <none>        5672/TCP,4369/TCP,25672/TCP,15672/TCP   109s
service/rabbitmq-helm-headless   ClusterIP   None             <none>        4369/TCP,5672/TCP,25672/TCP,15672/TCP   109s

NAME                             READY   AGE
statefulset.apps/rabbitmq-helm   1/1     109s

NAME                         DATA   AGE
configmap/kube-root-ca.crt   1      111s

Gitops 실습: 클러스터 설정 내역 변경과 Git 저장소 자동 반영

  • GitOps 설정을 검증합니다. GitOps는 Git 저장소의 상태가 항상 실제 운영되는 k8s와 일치해서 항상 동기화되는 상태를 의미합니다. GitOps기능 검증을 위해 1) 임의로 클러스터의 설정을 변경하고 2) Git 소스를 변경하는 테스트를 실행합니다.

아파치 웹 서버와 서비스를 ArgoCD를 이용해 배포합니다.

미리 httpd 네임스페이스를 생성해줍니다.

# 아파치 웹서버를 배포합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
  namespace: httpd
  labels:
    app: httpd  #service가 바라보는 label이 아님. 주의.
spec:
  replicas: 3
  selector:
    matchLabels:
      app: httpd  
  template:
    metadata:
      labels:
        app: httpd  # Service가 바라보는 label 지정 
    spec:
      containers:
      - name: httpd
        image: httpd

위 아파치 웹서버를 외부에 노출하기 위해 NodePort Type의 서비스를 생성합니다.

apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
  namespace: httpd
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30180
  selector:
    app: httpd
  type: NodePort

깃랩을 배포한 폴더로 이동하여 해당 파일을 로컬 깃랩 리포지토리에 업로드합니다.

$ cd ~/gitlab-test/test-dev/
$ ls
httpd-deploy.yaml  httpd-svc.yaml  rabbitmq  README.md  test.txt

# 파일을 업로드합니다.
$ git add . && git commit -m "add httpd minifest"
[main 062b32b] add httpd minifest
 2 files changed, 35 insertions(+)
 create mode 100644 httpd-deploy.yaml
 create mode 100644 httpd-svc.yaml

$ git push

해당 파일을 ArgoCD의 Application CRD를 이용해 실제 쿠버네티스 클러스터와 동기화합니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: httpd
  namespace: argocd  
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: httpd
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: https://gitlab.wellbeconnected.com/hayley17/test-dev.git
    path: 03.httpd # 아파치 웹서버에 대한 YAML파일이 저장된 사설 깃랩 저장소의 디렉터리 위치를 저장
    targetRevision: HEAD
    directory:
      recurse: true # 아파치 웹서버의 경우 헬름 차트가 아닌 일반 디플로이먼트 및 서비스 YAML파일이므로 ArgoCD에 directory로 지정합니다. recurse옵션은 하위 디렉터리까지 배포한다는 의미
  syncPolicy:
    syncOptions:
    - CreateNamespace=true
    automated:
      prune: true # 깃에서 오브젝트를 삭제하면 클러스터에서도 함께 삭제함
$ k apply -f httpd-directory-argo-application.yaml 
application.argoproj.io/httpd created

$ k get applications -n argocd
NAME            SYNC STATUS   HEALTH STATUS
httpd           Synced        Healthy

$ k get pod,svc -n httpd
NAME                         READY   STATUS    RESTARTS   AGE
pod/httpd-676d9bc46d-9m5gc   1/1     Running   0          18m
pod/httpd-676d9bc46d-ddmtz   1/1     Running   0          18m
pod/httpd-676d9bc46d-dzpmp   1/1     Running   0          18m

NAME                TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/httpd-svc   NodePort   100.66.157.138   <none>        80:30180/TCP   18m

깃 저장소에서 소스를 변경하지 않고 클러스터에서 1)임의로 리소스를 변경하고 2) 오브젝트를 삭제해서 ArgoCD의 GitOps동작을 확인합니다.

$ k ns httpd
Context "wellbeconnected.com" modified.
Active namespace is "httpd".

$ k get deployments.apps httpd -o yaml > httpd.yaml
spec:
      containers:
        image: httpd:alpine

$ k replace -f httpd.yaml --force
deployment.apps "httpd" deleted
deployment.apps/httpd replaced

$ k get deployments.apps -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
httpd   3/3     3            3           24s   httpd        httpd:alpine   app=httpd

위와 같이 깃 저장소의 소스 이미지 버전(httpd)과 현재 클러스터의 실행 상태의 이미지 버전(httpd:alpine)이 서로 다릅니다. 이때 ArgoCD의 동작은 어떤지 보겠습니다.

$ k get applications -n argocd
NAME            SYNC STATUS   HEALTH STATUS
httpd           OutOfSync     Healthy

ArgoCD의 application CRD를 확인하면 기존과 다르게 비동기화(OutOfSync) 상태입니다. 깃 소스와 실행 중인 디플로이먼트의 이미지 버전이 다르기 때문입니다.

httpd — APP DIFF에서 이전버전과 현재 버전의 차이를 알 수 있습니다.

다음과 같이 오브젝트를 삭제하면 ArgoCD는 그 차이를 감지해서 경고 메시지를 나타냅니다.

$ k get svc
NAME        TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
httpd-svc   NodePort   100.66.157.138   <none>        80:30180/TCP   32m

$ k delete svc httpd-svc
service "httpd-svc" deleted

관리자 페이지에서 아래와 같이 서비스 오브젝트 상태가 Missing 으로 변경되었습니다. 임의로 클러스터의 상태를 변경하면 ArgoCD의 argocd-application-controller 파드가 웹훅 방식으로 감지해서 자동으로 쿠버네티스 리소스의 변경 사항을 관리자 화면에 나타냅니다.

다시 SYNC를 맞추면 ArgoCD 가 자동으로 깃 저장소의 YAML파일 기준으로 쿠버네티스 오브젝트를 동기화합니다.

자원 삭제

  • Helm Chart 삭제
# argocd 삭제
kubectl delete application.argoproj.io -n argocd rabbitmq-helm  # 미 삭제되어 있을 경우 삭제
helm uninstall -n argocd argocd
kubectl delete ns argocd

# gitlab 삭제
helm uninstall -n gitlab gitlab
kubectl delete pvc --all -n gitlab
kubectl delete ns gitlab

# harbor 삭제
helm uninstall -n harbor harbor
kubectl delete pvc --all -n harbor
kubectl delete ns harbor
  • glpat-s2SkyxGA2S-MG7ezygsJ
  • kOps 클러스터 삭제 & AWS CloudFormation 스택 삭제
$ kops delete cluster --yes && aws cloudformation delete-stack --stack-name mykops

 

blog migration project

written in 2023.3.23

https://medium.com/techblog-hayleyshim/k8s-gitops-bd967be07de1

 

 

'IT > Container&k8s' 카테고리의 다른 글

[k8s] Security  (0) 2023.10.29
[k8s] Monitoring(Prometheus, Grafana, Loki)  (0) 2023.10.29
[k8s] Storage  (0) 2023.10.29
[k8s] Network  (0) 2023.10.29
[k8s] Kube DNS & External DNS  (0) 2023.10.29