![[워밍업클럽: 쿠버네티스] #11. 배포 전에 알아줘야 할 것들](https://cdn.inflearn.com/public/files/blogs/8ebca590-5997-41df-b5cd-89d05f2e7ce6/인프런 워밍업 클럽 4기.jpg)
[워밍업클럽: 쿠버네티스] #11. 배포 전에 알아줘야 할 것들
CI/CD 배포 환경을 만들 때, 몇가지 고려할 요소들을 생각한 후에 환경 구성방법을 선정해주는 것이 좋다.
배포 환경 안에서 담당부분이 나누어 지는 경우.
운영 정책 상 한 배포 구성에서 개발 과 운영 파트를 분리하는 경우
배포한 툴 제품 선정 시 보안 및 유지보수에 따라 선택하는 경우 로 하나씩 요소들을 살펴보겠다.
배포 환경 안에서 담당부분이 나누어 지는 경우
CI/CD 환경에서 소스코드를 빌드하고, 컨테이너에 담아 배포하는 과정을 분리해서 담당하는 경우와,
파이프라인을 구축해 과정 전체를 한번에 배포까지 하는 경우로 구분할 수 있다.
파이프라인을 구축해 자동화하는 것이 효과적으로 보일 수 있지만, 프로젝트 규모가 커지면서 관리해야하는 담당이 정해져 있는 경우엔 과정 하나하나를 분리해 업무를 분장하는 것이 효율적이다.
각 상황에 맞추어서 소스 빌드는 개발자가 담당하고, 컨테이너를 빌드하고 배포하는 역할은 Devops 엔지니어가 담당하는 것과 같이 유동적으로 선정을 할 줄 아는 것이 좋다.
운영 정책 상 한 배포 구성에서 개발 과 운영 파트를 분리하는 경우
젠킨스 빌드 환경 안에서 배포를 하는 경우도 가능하지만, ArgoCD를 통해 배포를 구성하는 경우도 가능하다.
즉, 빌드 파트와 배포 파트를 분리하는 것이며, 이때 배포 환경과 인프라 환경을 구축할 때
1:N 관계로 한 배포 구성에서 개발과 운영 인프라를 구성하는 방법과
1:1 관계로 인프라 환경마다 배포 환경을 구성하는 경우 (개발, 운영 인프라 분리) 로 구분할 수 있다.
각 인프라마다 배포 환경을 구성하는 경우(1:1) , 이중 관리가 필요해지지만 서로의 환경에 영향을 주는 것이 없어 한 인프라에 장애가 발생해도 다른 인프라에 영향도가 없다.
반면 배포 환경 하나로 여러 인프라를 구성하는 경우(1:N), 관리의 부담은 줄어들지만 개발 인프라에서 장애가 발생하는 경우 운영 인프라에서도 장애를 받아 배포를 못하게 되는 등 영향을 받게된다.
이렇게 어떤 구성을 하는 지에 따라 각각의 장단점이 존재하므로, 운영 정책에 따라 관리 편의성을 중시할 지 / 장애 영향도를 중시할 지 적절히 선택을 해야한다.
배포 툴 제품 선정 요소
CI/CD 제품은 온라인용으로 GitHub Actions, CI tool로는 TravisCI, circleCI, 오프라인용으로 Jenkins, JenkinsX, Tenton, CD tool로 argoCD, Sprinaker 등이 있다.
온라인용을 선택할 시 따로 CI/CD 서버를 별도 구성할 필요가 없다는 장점이 있으며,
오프라인용은 인터넷에 App의 데이터를 올리면 안되는 경우 선택을 한다. 금융권이나 의료기관 등 시스템에서 다루는 데이터가 중요한 경우 인터넷 영역으로 올리지 않으며, 오프라인 툴을 선택을 하는 것이다.
또한 컨테이너 빌드 시 도커를 쓰지 않고 다른 툴들을 사용하기도 한다. 도커는 기능이 많아 제품이 무겁다는 것과(자원 차지 많음), Daemon을 항상 유지해야하는 단점이 있다(리눅스 OS 백그라운드에 항상 실행되어야한다).
반대 개념인 Daemon리스트 앱, kubectl은 별도로 실행유지를 하지 않고 명령어만 사용할 때 실행을 하는 구조이다.
그래서 도커로 컨테이너를 여러개 띄운 상태에서 데몬이 죽으면 컨테이너가 모두 다운된다는 단점이 존재한다.
그치만 CI/CD 환경에서 도커는 컨테이너 빌드용으로 사용되고, 인프라 환경에서 쿠버네티스를 통해 컨테이너를 띄우기 때문에 치명적인 단점이 되지는 않는다. 그래도 자원을 잘 활용하려는 상황에선 다른 툴을 사용하는 것이 좋고,
대표적인 컨테이너 빌드 툴로 builah가 있다. 도커허브에서 podman으로 jdk 이미지를 받고, 컨테이너 빌드 후 skopeo로 이미지를 허브에 업로드 해주는 과정은 도커와 유사하지만, 자원사용량이 낮다는 장점이 있다.
배포전략
배포 전략으로 Recreate, RollingUpdate, Blue/Green, Canary 가 있다.
Recreate
새로운 파드를 배포를 하게 되면, 기존의 파드들은 운영을 멈추고, 새로운 파드를 생성해 운영하는 방식이다.
새로운 파드가 동작하기 전까지 기존 서비스가 운영하지 못하는 Downtime이 존재한다.RollingUpdate
새로운 파드를 배포할 때, 기존 파드를 얼마나 줄이고, 새로운 파드를 얼마나 늘릴지 정해서
단계적으로 파드를 교체해나가는 방식이다. 서비스는 중단되지 않고 계속해서 운영된다는 특징이 있다.
Recreate와 RollingUpdate 방식은 Deployment를 업데이트하면 자동으로 배포되는 방식이고,
배포되는 동안 중지하거나, 기존 버전으로 롤백이 가능하다.
또한 각 파드에 대한 트래픽을 조정하는 것은 불가능하며, 파드 개수만큼 트래픽이 1/n 분배되는 방식이다.Blue/Green
기존 버전 v1의 Deployment를 업데이트하는 것이 아닌, 새로운 버전으로 v2 Deployment를 생성하면, 관련된 파드들이 추가로 생성이 된다. 이후 Service에서 기존 v1에서 v2로 selector를 변경해 새로운 파드에 트래픽이 들어오도록 변경해주면, 기존의 v1 Deployment를 삭제해주는 방식이 Blue/Green이다.
이 방식은 수동으로 배포를 해주는 방식이라 도중에 문제를 발견하면 바로 롤백이 가능하다는 장점과, 배포 과정을 Script로 작성을 하게 되면 자동 배포도 가능해진다는 장점을 가진다.
하지만 새로운 버전 v2로 전환한 직후 트래픽이 과도하게 들어올 경우 문제가 발생할 수 있다.
앱이 처음 기동을 하면 memory, DB를 최적화하는 과정이 필요해 CPU 사용량이 늘어나게 되고, 해당 과정동안 트래픽이 많아지게 되면 파드가 죽어버리는 경우가 생길 수 있다. -> 사전에 부하 테스트를 통해 배포가 가능한 지 미리 확인하는 과정이 필요하다.
또한 운영 DB에서만 테스트가 가능한 유즈케이스의 경우 Blue/Green 배포 방식이 최적의 케이스가 된다.Canary
Blue/Green 방식에서 각 서비스에 Ingress 리소스를 추가해 서비스마다 들어오는 트래픽 양을 조절할 수 있는 방식이다.
Nginx 같은 Ingress Controller로 각 서비스의 Ingress마다 트래픽 수치를 조정할 수 있다는 장점을 가진다.
Canary 방식은 특정 헤더 값에 한해서 다른 서비스에 트래픽 유입을 조정할 수 있다. SourcePort, User, Language 등 원하는 값을 설정해 특정 트래픽으로 다른 서비스에 유입시키는 방식의 유즈케이스에서 유용하다.
사실 Recreate 방식을 제외하면 모두 무중단배포라는 특징을 가진다. 하지만 무중단배포가 무조건 좋은것은 아니며,
상황에 맞게 배포방식을 선택하는 것이 좋다. DB schema를 변경해야하는 경우 서버를 내리고 DB 작업을 마친 후에 다시 서버를 운영하는 것이 맞는 방식이다.
파이프라인 단계별로 구축하는 방법
배포 방식으로 여러 방식을 사용하는 걸 앞서 요소 별로 살펴보았는데, 처음부터 파이프라인을 만들고, 배포 툴을 사용해서 CI/CD 환경을 구축하는 것보다, 최대한 간단한 방식으로 먼저 배포 구성을 해보고, 점차 방식을 바꿔가면서 툴을 추가하는 것이 안정적으로 구성하는 방법이다.
Jenkins 기본 구성 -> 실습했던 방식처럼 Jenkins 환경 세팅 후, 소스코드 빌드, 컨테이너 빌드, 배포 방식을 구분해서 실행하는 방식이다.
Jenkins Pipeline 구성
jenkins Pipeline은 배포때 사용한 yaml파일, DockerFile처럼 JenkinsFile이라는 스크립트를 기반으로 파이프라인을 관리할 수 있다. 처음부터 Script를 구성하기 보단, Jenkins Dashboard에서 제공하는 UI로 먼저 만들어보고, 해당 구성에 맞게 샘플 코드를 알려주니 이후 Script 코드를 짜는 방식으로 나아가는 게 좋다.Kustomize, Helm 배포 툴 사용
인프라 환경 별로 배포를 하려면 기존에는 각 환경마다 yaml파일을 복사해 값을 수정하는 방식을 사용했다면,
배포 툴에선 Package를 통해 각 환경마다 다르게 줘야 할 변수들을 지정해 한 yaml 파일에 동적으로 값을 주는 방식을 사용할 수있다. 덕분에 yaml 여러개를 구성해 관리하지 않고, 하나의 yaml로 관리가 가능해졌다.ArgoCD로 빌드와 배포 분리
Jenkins 환경에서 배포를 하는 것이 아닌, 새로운 배포 환경을 구성해 ArgoCD 환경에서 Helm 같은 배포 툴을 사용하는 방식이다. ArgoCD는 기존 yaml 파일 같은 스크립트 파일을 원격 저장소에 저장을 하면, 인프라 환경에 존재하는 파일과 비교를 하며 원격 저장소에서 값이 바뀌면 인프라에도 반영하거나, 인프라에서 수정되면 저장소 상에도 반영을 해주는 동기화를 제공한다. 또한 대시보드를 통해 k8s와 Resource 간의 관계도를 표현해주는 기능도 있어 유용하게 사용할 수 있다.
댓글을 작성해보세요.