[CloudNet@] 쿠버네티스 실무 실습 스터디 3주차 - GitOps 시스템

s3ich4n·2023년 3월 24일
0
post-thumbnail

DISCLAIMER

이번 게시글은 개인사정으로 인해 금주 중 전면 재개편될 예정입니다. 게시글의 개선은 아래와 같이 이루어질 예정입니다.

  • DDD를 통한 파이썬 웹 애플리케이션 설계 및 구현 연재글 배포
  • 1을 쿠버네티스 클러스터에서 GitOps 플로우를 통해 배포하는 게시글을 3주차 내용과 함께 보강
  • PLG 스택을 사용한 상기 클러스터 모니터링 내용 업데이트 (본문내용 업데이트 포함)

들어가며

이 내용은 CloudNet@ 에서 진행하는 쿠버네티스 실무 실습 스터디에 대한 연재글입니다.

스터디에서 사용하는 교재는 24단계 실습으로 정복하는 쿠버네티스 입니다.

본 3주차에는 교재의 제 3부 내용을 살펴보고 있습니다. 전체 컨텍스트를 이해하시려면 교재를 참고하시기를 추천드립니다.

Prerequisites

쿠버네티스를 클라우드 환경에서 사용하고자 하는 것 자체가 이미 하기 사항들에 대한 기본적인 이해와 준비사항을 요합니다.

이번 연재글에서는 개념에 대한 상세한 추가설명은 가급적 없이 작성하려 합니다. 다만 제가 공부하며 기본적으로 알아야겠다 싶은 연재글에 대해 대신 소개드립니다.

들어가며

사전 준비사항 (1)

  1. AWS Free Tier 계정(비용문제로 인해 필요합니다!)
  2. IAM User 생성 후 권한 부여
    1. 학습을 위해 자신의 작업환경 IP에서만 접근할 수 있도록 하고, 관리자 권한을 주는 식으로 해결해도 좋습니다.
  3. Route 53 퍼블릭 호스팅 영역
    1. 혹은 도메인 구매사이트에서 도메인 구매 후, Route 53 설정 지정하기

사전 준비사항 (2)

주의! 비용이 많이 발생할 수 있으니, 빠르게 실습 후 종료하시기를 권장드립니다.

  1. 마스터노드 t3.medium
  2. 워커노드 c5d.large
  3. kOps 커맨드를 수행할 인스턴스 t3.small

아래 커맨드를 통해 배포하여 주십시오.

설치과정

# 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-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32  MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName='gasida.link' S3StateStore='gasida-k8s-s3' 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

설치 후 점검

아래 커맨드를 수행하여 배포가 잘 되었는지 확인하여 주십시오.

# default NS 진입
kubectl ns default

# 도커 설치 : 이미 되어 있음
amazon-linux-extras install docker -y
systemctl start docker && systemctl enable docker

# 설치된 패키지 확인 : 도커 엔진 확인
yum list installed

# 도커 정보 확인 : client - server, Docker Root Dir, Registry
docker info

# bridge 통한 트래픽을 iptables로 통제 설정
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
sysctl -p
docker info

# 도커 정보 확인 : Docker Engine - Community
docker version

# 도커 서비스 상태 확인
systemctl status docker

# 모든 서비스의 상태 표시 - 링크
systemctl list-units --type=service

# 도커 루트 디렉터리 확인
tree -L 3 /var/lib/docker

GitOps에 대해

운영 프로세스를 Git을 통한 개발 프로세스에 합쳐서 DevOps를 꾸려가는 방식을 의미합니다. Ansible, Terraform, Kubernetes 순으로 배우고 익히면서 왜 이런 접근이 이루어졌는지를 이해하는 것이 좋습니다.

GitOps의 발전 과정
출처: https://blogs.vmware.com/cloud/2021/02/24/gitops-cloud-operating-model/

서버 세팅을 위해 반복되는 작업을 쉘 스크립트로 수행하는 것은 금방 한계를 맞이합니다. 이런 환경 설정을 자동으로 하는 방안이 소개되고, 이후 환경 자체를 자동으로 구상하는 방안 까지 등장하더니 현재는 Git 같은 VCS에 이런 코드들이 올라오자마자 모두 자동으로 해주는 시기가 왔습니다(!). 이것이 GitOps라는 개념이 태동하기까지의 과정입니다.

그렇다면 GitOps의 전체 플로우는 어떻게 될까요? 아래 내용으로 도식을 그려보았습니다.

GitOps의 핵심은 선언형 모델로 작성된 모든 코드들 이 VCS 하에 관리되고(SSOT, 후술), VCS 코드로 관리되는 시점에 CI/CD 서비스로 메시지를 주고받음으로써 아래 작업들을 자동으로 지시합니다.

  • 서비스 구성에 필요한 애플리케이션을 컨테이너화 후 별도 저장소로 관리할 수 있습니다.
  • 각종 서버 자원, 세팅 및 클러스터 배포를 지시할 수 있습니다.

선언형 모델

쉽게말해, 무엇을 하라 는 모든 것들이 텍스트로 적혀있다는 뜻입니다.

  • Ansible에서는 ansible-playbook으로 읽을 수 있는 설정들을 의미합니다. 해당 서버에서 무엇을 하라 하고 지시하는 YAML 파일이지요.
  • Terraform에서는 HCL로 표현되는 일련의 인프라 설정을 의미할 것입니다. 만약 AWS에 배포한다면, 프로바이더를 AWS로 지정하고 어떤식의 인프라를 꾸릴 것인지 작성 후 terraform apply를 수행하면 되겠지요.
  • 이번에 배우는 쿠버네티스에서는 쿠버네티스 클러스터를 꾸리기 위한 컨테이너, 시스템, 스토리지 등을 YAML 파일로 표현할 수 있습니다. 이를 헬름으로 띄우거나 개별 매니페스트를 띄우는 방식을 의미합니다.

SSOT(Single source of truth)?

한마디로, VCS에 담긴 코드만이 맞는 말을 하고있다 라는 뜻입니다. 앞서 말씀드린 선언형 모델로 작성된 코드를 통해 자원을 임대받고(테라폼 등), 그 자원에 어떤 것들을 작업할지 쓰여진 대로 일한 후(앤서블 등), 그 위에 쿠버네티스 클러스터를 구축하지요.

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

애플리케이션을 컨테이너화 하여 관리하기 위해 Harbor를 통한 로컬 컨테이너 이미지 저장소를 구축해보겠습니다.

설치 전

  • 컨테이너 이미지 저장소는 아래 스펙을 준수해야 합니다
    • 2CPU, 4GiBMem, Disk 40GiB

헬름 차트를 통한 Harbor 설치

헬름 차트를 이용하여 Harbor를 설치해봅시다.

# 사용 리전의 인증서 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"
  • 참고사항: Harbor 삭제 시
    helm uninstall -n harbor harbor
    kubectl delete pvc --all -n harbor
    kubectl delete ns harbor

배포된 Harbor 웹을 사용해봅시다

먼저 Harbor 웹페이지에 로그인 해봅시다.

로컬 이미지 배포를 배포하려면 어떻게 해야할까요? 개발 과정이라면 프로그래머가 CI 를 거치고 모두 pass하는 순간 이미지를 푸시하면 될 것입니다.

이 예시에서는 kops-ec2 인스턴스에서 이미지를 하나 push 해봅시다.

# 컨테이너 이미지 가져오기
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

(추가사항) Trivy 를 이용한 도커 이미지 스캔

Trivy를 설치해서 써봅시다. 네이버 클라우드의 Private Docker container에서 제공하던 기능이 떠오르는군요!

설정에서 push되면 자동으로 스캔한다 라는 기능을 체크하고 작업합시다.

이미지 푸시 후 스캔이 완료되었는지 살펴봅시다.

GitLab 구축을 통한 로컬 VCS 구축

헬름 차트를 통한 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.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
hhBvAjXoANx8kVIVpcwdgvc6A0kFDIIQFxikRDJfwVPBXn0dxmNBgc7zssSBskTj

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

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

설치 후 사용자 생성 및 신규 프로젝트를 생성해봅시다.

ArgoCD를 활용한 GitOps 시스템 로컬 구축

드디어 GitOps 시스템을 구축해봅시다. 먼저 CD가 뭔지 다시 한 번 살펴봅시다.

  • 지속적인 배포란(Continuous Delivery, CD) 개발자가 소스코드를 변경해서 깃 저장소에 푸시하면 해당 변경 사항이 고객이 사용하는 실제 운영환경의 시스템까지 자동으로 반영하는 것을 의미합니다.
    • 개발자의 코드가 원격 저장소에 업로드됐을 때 아르고시디가 자동으로 해당 코드를 클러스터 운영환경에 배포합니다.
    • 아르고시티로 배포한 헬름 애플리케이션의 리소스 목록, 각 리소스 간 관계 및 에러 유무를 UI로 보여줍니다.

헬름 차트를 통한 ArgoCD 설치

# 모니터링
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-19T11:39:26Z
applicationsets.argoproj.io           2023-03-19T11:39:26Z
appprojects.argoproj.io               2023-03-19T11: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
mf8bOtNEq7iHMqq1

# 웹 접속 로그인 (admin) CLB의 DNS 주소로 접속
echo -e "Argocd Web URL = https://argocd.$KOPS_CLUSTER_NAME"
  • 참고사항: ArgoCD 삭제 시
    helm uninstall -n argocd argocd
    kubectl delete ns argocd

ArgoCD에 VCS, k8s 정보 등록하기

# 최신버전 설치
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 gasida --password P@ssw0rd

# 등록 확인 : 기본적으로 아르고시디가 설치된 쿠버네티스 클러스터는 타깃 클러스터로 등록됨
argocd repo list
TYPE  NAME  REPO                                            INSECURE  OCI    LFS    CREDS  STATUS      MESSAGE  PROJECT
git         https://gitlab.gasida.link/gasida/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 삭제
kubectl delete application -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

kOps 클러스터 삭제 및 AWS CloudFormation 스택 삭제

실습 마무리를 수행합니다.

kops delete cluster --yes && aws cloudformation delete-stack --stack-name mykops

마무리

제 3장에서는 Harbor, GitLab 및 ArgoCD를 활용한 GitOps 구축에 대해 살펴보았습니다.

이번 장에서는 아래 내용을 반드시 기억하셨으면 좋겠습니다.

  1. GitOps라는 개념이 어떻게 이루어질 수 있게 되었는지를 살펴보았습니다.
  2. GitOps를 구성하는 기본적 요소들을 직접 구축해보았습니다.
    1. Harbor로 로컬 컨테이너 저장소 구축 및 활용을 수행해보았습니다.
    2. GitLab으로 로컬 Git 서버 구축 및 SSOT로서 활용을 직접 겪어보았습니다.
    3. ArgoCD를 통해, GitOps 시스템을 구축하고 배포과정까지 이해하였습니다.

이것으로 제 3장을 마칩니다. 긴 글 읽어주셔서 감사합니다.

profile
백엔드 프로그래머

0개의 댓글