모놀리틱에서 MSA 기반으로 개선했지만 부하 분산을 위해 서버를 2개 이상 띄워야할 때 이를 처리하는 방법에 대해 고민해보았다. 직접 서버에 접속해 컨테이너를 관리할 수 없었기 때문에 컨테이너를 편리하게 관리하면서 설정을 통해 자동으로 장애에 대응하고 무중단 업데이트도 진행하는 컨테이너 오케스트레이션을 사용해보기로 했다.
Docker Swarm 등 다른 도구가 있었지만 쿠버네티스를 선택하게 된 이유는 오픈 소스 커뮤니티가 굉장히 잘 되어 있다. 또한 AWS의 EKS, GCP의 GKE 등 쿠버네티스를 전문적으로 지원하는 플랫폼이 있다보니 접근성 또한 뛰어나서 선택하게 되었다.

쿠버네티스는 크게 클러스터 내부 핵심 기능을 담당하는 Control Plane과 실제 작업을 담당하는 Node Component로 나뉜다. 위와 같이 구성되어 각자의 작업을 수행한다. 모두 각자의 기능이 있지만 여기서 대표적으로 API Server와 Kubelet, k-proxy를 설명드리자면 다음과 같다. 전체 설명 주소
DaemonSet의 형태로 배포되어 있다.쿠버네티스에 대해 전무했었기 때문에 우선 인프런의 최일선님의 강의를 들었던 게 도움이 많이 됐다. 강의가 비싸서 다른 저렴한 강의를 들어도 괜찮을 것 같다.
데브옵스(DevOps)를 위한 쿠버네티스 마스터
나는 이번에 구글에서 지원하는 GKE를 사용했다. 처음에는 모두 직접 해보기 위해 VMware를 3개를 생성하고 클러스터를 구성했는데 클라우드 플랫폼으로 로드밸런싱을 위한 IP를 할당받기 위해서는 GKE나 EKS를 사용하는 것이 훨씬 생산성이 좋아서 GKE를 사용하게 됐다. GKE에는 Autopilot과 Standard 방식 두 가지가 있는데 공부를 할 목적이기 때문에 클러스터를 직접 설정해야 하는 Standard 를 선택하면 된다.

쿠버네티스에서는 kubectl 이라는 명령어를 많이 쓴다. 이는 클러스터에 필요한 쿠버네티스를 다루기 위한 명령행 도구이다. Nodes, Pod, StorageClass ,,, 등등 클러스터를 이루는 대부분의 것들을 kubectl 명령어를 통해 관리할 수 있다.

하나의 서비스를 제대로 배포하고 관리하기 위해서는 무수히 많은 Resource를 작성하고 적용해야 한다. 예를 들자면 Gateway 를 배포하기 위해서 작성해야하는 것은 Deployment, Service, Secret, ConfigMap, HPA 등 각각의 yaml파일을 만들어서 적용시키기엔 부담이 된다.
이때 helm chart를 사용하면 편리하게 배포할 수 있다. 쿠버네티스 설계도와 같은 느낌으로 템플릿을 만들어서 한번에 배포할 수 있는 장점이 있다. 자세한 코드는 Github에 있습니다.
클러스터를 관리하다보면 현재 노드의 자원이 얼마나 사용되고 있고 트래픽은 얼마나 되는지, API 호출은 얼마나 되는지 확인해야할 필요가 있다. 이때 Grafana와 Prometheus를 통해서 확인할 수 있다. 또한 특정 로그 발생시 Email이나 Slack 등으로 알람을 보낼 수 있는 기능까지 이용할 수 있어서 유용하게 쓸 수 있다. 자세한 배포 코드는 Github에 있습니다.


우리 프로젝트의 배포 아키텍처이다. 젠킨스를 통해서 Dockerhub에 이미지를 Push 함과 동시에 helm chart에 버전 업데이트를 진행한다. 그러면 Argo에 등록된 Helm Chart 저장소에서 yaml resource를 읽게 되고 코드에 맞춰 쿠버네티스에 배포가 진행된다.
배포 전략에는 크게 3가지가 존재한다. 롤링 업데이트, 블루/그린 업데이트, 카나리 등이 있는데 난 그중에서 롤링 업데이트를 선택했다. 쿠버네티스에서 기본적으로 제공하기도 하고 yaml 을 통해 maxSurge, maxUnavailable 값을 세부적으로 조절할 수 있었다. 배포 전략 세부 설명
...
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
...
위와 같이 maxSurge(최대로 새로 추가되는 수), maxUnavailable(최대 이용 불가능 수)을 적절하게 수정하고 배포하면 적용된다.

모두 적용하고 나면 이렇게 내가 생성한 github helm chart 저장소 상태를 감지해서 변경이 일어나면 배포가 진행된다.

cadqe13@cloudshell:~ (refactor-allback)$ k get all -n gateway-ns
NAME READY STATUS RESTARTS AGE
pod/gateway-deployment-7f96f6db87-4wdhn 1/1 Running 0 12d
pod/gateway-deployment-7f96f6db87-gqz75 1/1 Running 0 12d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/gateway-service ClusterIP 10.96.3.110 <none> 8080/TCP 31d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/gateway-deployment 2/2 2 2 31d
NAME DESIRED CURRENT READY AGE
replicaset.apps/gateway-deployment-6d786757cc 0 0 0 19d
replicaset.apps/gateway-deployment-7f4d7d9646 0 0 0 12d
replicaset.apps/gateway-deployment-7f96f6db87 2 2 2 12d
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/gateway-hpa Deployment/gateway-deployment <unknown>/50% 2 4 2 15d