이번 게시글은 개인사정으로 인해 금주 중 전면 재개편될 예정입니다. 게시글의 개선은 아래와 같이 이루어질 예정입니다.
이 내용은 CloudNet@ 에서 진행하는 쿠버네티스 실무 실습 스터디에 대한 연재글입니다.
스터디에서 사용하는 교재는 24단계 실습으로 정복하는 쿠버네티스 입니다.
본 3주차에는 교재의 제 3부 내용을 살펴보고 있습니다. 전체 컨텍스트를 이해하시려면 교재를 참고하시기를 추천드립니다.
쿠버네티스를 클라우드 환경에서 사용하고자 하는 것 자체가 이미 하기 사항들에 대한 기본적인 이해와 준비사항을 요합니다.
이번 연재글에서는 개념에 대한 상세한 추가설명은 가급적 없이 작성하려 합니다. 다만 제가 공부하며 기본적으로 알아야겠다 싶은 연재글에 대해 대신 소개드립니다.
주의! 비용이 많이 발생할 수 있으니, 빠르게 실습 후 종료하시기를 권장드립니다.
t3.medium
c5d.large
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
운영 프로세스를 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 서비스로 메시지를 주고받음으로써 아래 작업들을 자동으로 지시합니다.
쉽게말해, 무엇을 하라 는 모든 것들이 텍스트로 적혀있다는 뜻입니다.
terraform apply
를 수행하면 되겠지요.한마디로, VCS에 담긴 코드만이 맞는 말을 하고있다 라는 뜻입니다. 앞서 말씀드린 선언형 모델로 작성된 코드를 통해 자원을 임대받고(테라폼 등), 그 자원에 어떤 것들을 작업할지 쓰여진 대로 일한 후(앤서블 등), 그 위에 쿠버네티스 클러스터를 구축하지요.
애플리케이션을 컨테이너화 하여 관리하기 위해 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"
helm uninstall -n harbor harbor
kubectl delete pvc --all -n harbor
kubectl delete ns 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
되면 자동으로 스캔한다 라는 기능을 체크하고 작업합시다.
이미지 푸시 후 스캔이 완료되었는지 살펴봅시다.
# 모니터링
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 계정 암호)
설치 후 사용자 생성 및 신규 프로젝트를 생성해봅시다.
드디어 GitOps 시스템을 구축해봅시다. 먼저 CD가 뭔지 다시 한 번 살펴봅시다.
# 모니터링
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"
helm uninstall -n argocd argocd
kubectl delete ns argocd
# 최신버전 설치
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 구축에 대해 살펴보았습니다.
이번 장에서는 아래 내용을 반드시 기억하셨으면 좋겠습니다.
이것으로 제 3장을 마칩니다. 긴 글 읽어주셔서 감사합니다.