시나리오
쿠버네티스에서 배포한 애플리케이션 코드가 수정되었거나, 보안 취약점을 수정하기 위해 패치를 했다고 가정해보자. 이 경우에는 버전 업데이트를 위해서 새 파드가 생성되어야 한다. 즉, 새로운 이미지를 빌드하고, 이를 쿠버네티스 클러스터 상에 배포하여 사용자가 업데이트 된 버전에 접근 가능하도록 만들어 주어야 한다.
롤링(rolling) 업데이트
위와 같은 상황에서 쿠버네티스의 롤링 업데이트 기능(순차적 업데이트라고 이해하면 된다)을 사용하면 서비스 다운타임없이 업데이트를 해 줄 수 있다. 롤링 업데이트 메커니즘은 배포가 새 버전으로 업데이트될 시 새 ReplicaSet을 만들고, 이전 ReplicaSet의 레플리카가 감소하면서 새 ReplicaSet의 레플리카 수가 천천히 증가하는 것이다. 아래 그림에서 볼 수 있듯이 롤링 업데이트는 업데이트가 진행되는 동안 이전 버전(blue)과 최신 버전(green)이 함께 존재하며, 모든 레플리카가 최신 버전으로 생성되면 업데이트가 끝난다.
롤링 업데이트 트리거하기
배포를 업데이트하려면 다음 명령어를 실행할 수 있다.
kubectl edit deployment [deployment_name]
위의 명령어를 실행하면 해당 deployment의 yaml 파일을 vi 편집기로 열게 된다(기본 설정이 vi이므로, 따로 설정을 바꾸지 않는다면 항상 vi 에디터로 편집하게 된다). 변경하고 싶은 사항이 있다면 a
를 눌러 insert mode(입력 모드)로 들어가고, 자유롭게 편집한 다음 ESC
를 눌러 다시 명령 모드(command mode)로 돌아오면 된다. 파일 편집이 다 끝나면 :wq
를 입력해 변경 사항을 저장하고 종료하면 된다. 이렇게 파일 편집 후 저장만 해주면 자동으로 업데이트된 배포가 클러스터에 저장되고, Kubernetes에서 롤링 업데이트가 시작된다!
롤링 업데이트 일시중지하기/재개하기
가끔 실행 중인 출시에 문제가 발생해 업데이트를 중지하고 싶은 상황이 생길 수 있다. 이런 상황에서는 다음 명령어를 사용하여 업데이트를 일시중지했다가 다시 재개할 수 있다.
kubectl rollout pause [deployment_name]
# 현재 상태 확인
kubectl rollout status [deployment_name]
kubectl rollout resume [deployment_name]
물론, 업데이트 중에 pause
를 통해 일시중지한다면 일부 pod는 최신 버전이고 일부 pod는 예전 버전으로 혼합되어 있는 상황이 유지된다. 따라서 문제가 없음이 밝혀지면 빠르게 resume
하고, 문제가 있음이 명확하다면 업데이트를 롤백하여 모든 사용자가 문제가 없는 이전 버전만 사용하도록 만들어야 한다.
롤링 업데이트 롤백하기
새 버전에 반드시 고쳐야 할 버그가 있어 업데이트를 롤백하고 버그를 고친 후 수정된 버전을 다시 출시해야 한다면, rollout 명령어를 사용하여 이전 버전으로 롤백할 수 있다.
kubectl rollout undo [deployment_name]
# 롤백 히스토리 확인
kubectl rollout history [deployment_name]
Blue/Green 업데이트
롤링 업데이트는 최소한의 오버헤드와 다운타임으로 애플리케이션을 배포할 수 있기 때문에 가장 좋은 업데이트 방식이다. 그러나 가끔 어떤 상황에서는 새로운 버전의 배포를 실제 환경에서 테스트하고 싶을 때가 있다. 이럴 때는 레플리카를 순차적으로 교체해나가는 롤링 업데이트가 아니라, Blue/Green 업데이트를 사용한다.
Blue/Green 업데이트는 구버전과 동일한 환경에 신버전의 배포를 전부 구축한 후,로드 밸런서를 수정하여 신버전을 한꺼번에 가리키게 하는 방식이다. Kubernetes에서는 이전 버전용 배포(blue)와 신 버전용 배포(green)를 만들어 업데이트할 수 있다. 먼저 신 버전의 배포를 모두 구축하고, 배포가 가동 및 실행되면 서비스를 업데이트하여 로드 밸런서가 이 버전을 사용하도록 전환하는 방식이다.
먼저 green 배포용 yaml 파일을 생성한다. 이전 버전의 배포 yaml 파일과 내용이 같지만, 사용하는 이미지의 경로와 labels
의 version
만 바꿔주면 된다.
# Blue 배포의 yaml 파일에서 이미지 경로가 수정된 Green 배포용 test-green.yaml 파일 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-green
spec:
template:
metadata:
labels:
version: 2.0.0
spec:
containers:
- name: app
image: deployment/app:2.0.0
...
이제 green 배포를 만든 후, 서비스가 새로운 버전을 가리키도록 업데이트하면 된다.
# 새로운 배포 생성
kubectl create -f test-green.yaml
# 서비스 업데이트
kubectl apply -f test-green.yaml
Blue/Green 업데이트 롤백
물론 이 업데이트를 사용하는 경우에도 롤백을 진행하고 싶을 수 있다. 이 경우에는 업데이트와 정반대 일을 해주면 된다. 즉, 로드 밸런서가 blue 배포를 다시 가리키도록 만들면 된다.
# 이전 버전으로 롤백
kubectl apply -f test-blue.yaml
물론 이전 버전 배포를 이미 삭제한 후라면 롤백할 수 없다.
Blue/Green 업데이트의 단점
Blue/Green 업데이트를 진행할 경우, 신버전을 완전히 새로운 환경에서 구축해 놓아야 하기 때문에 일시적이라도 시스템 자원이 반드시 두 배로 필요하다. 또한, 위에서 언급했듯이 이전 버전 배포를 삭제한 후에는(결과적으로는 당연히 삭제하게 된다. 그냥 놔두면 필요없는 이전 버전을 계속 운영하면서 시스템 자원을 낭비하게 되니까!) 롤백이 불가능하므로, 새로운 배포에 대한 테스트가 반드시 진행되어야 한다.
카나리아(Canary) 업데이트
위에서 롤링 업데이트를 사용하면 최소한의 오버헤드를 통해 업데이트가 진행된다고 말했다. 이는 쉽게 말하자면 최대한 빠르게 업데이트가 진행된다는 뜻이다. 즉, 문제가 있는 신버전이 순식간에 모든 사용자에게 노출될 만한 위험성을 가지고 있다. 한편으로 Blue/Green 업데이트는 시스템 자원을 두 배로 사용해야 한다는 단점을 가지고 있다.
이런 상황에서 우리는 일부 사용자에게만 신버전을 테스트해 본 후, 그 다음에 모든 사용자에게 업데이트를 진행하고 싶을 수도 있다. 이때 사용할 수 있는 방식이 카나리아 업데이트이다. 카나리아 업데이트는 과거 광부들이 카나리아 새를 광산에 두고, 카나리아가 유독가스를 감지하여 죽게 되면 대피했던 것에서 유래한 말이다. 이 업데이트는 구버전을 사용하고 있는 실제 유저 트레픽의 일부를 신버전으로 유입하여 배포를 테스트하는 것으로, 작은 규모의 사용자에게만 변경 사항을 릴리스하여 새로운 업데이트와 관련된 위험을 줄일 수 있다. 가끔 인스타그램이나 트위터에서 일부 사용자에게만 새로운 기능이 보이거나 기능이 변경되었다는 이야기를 들을 수 있는데, 이는 카나리아 업데이트를 통해 실제 유저에게 신 기능을 테스트 중이기 때문이다(버그가 아니다!).
먼저 카나리아 업데이트 용 새로운 배포 파일을 만든다. track: canary
를 통해 카나리아 업데이트를 만들어 줄 수 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-canary
spec:
template:
metadata:
labels:
track: canary
version: 2.0.0
...
그 후 kubectl create -f [yaml_filename]
을 통해 카나리아 배포를 만들면 된다.
카나리아 업데이트의 문제점
카나리아 업데이트는 다음과 같은 문제가 생길 수 있다. 만약 UI/UX가 변경되어 100명의 유저가 사용하는 서비스에서 20명을 대상으로 카나리아 업데이트를 진행하고 싶다고 하자. 가장 일반적인 방식 중 하나는 로드 밸런서를 통해서 서비스의 엔드포인트를 유저들에게 노출하는 것이다. 그런데 로드 밸런서는 서버의 과부하가 일어나지 않는 가장 최적화된 방식으로 트레픽을 분산한다. 즉, 한 명의 유저가 서비스를 사용할 때 로드 밸런서에 의해 자동으로 여러 서버에 접속될 수 있다.
그런데 이때 어떤 유저가 웹페이지를 새로고침했을 때 로드 밸런싱이 일어나 카나리아 업데이트가 있는 서버에서 기존 서버로 바뀌었다고 가정해보자. 그럼 갑자기 신버전 UI/UX에서 구버전으로 변경되게 된다. 서비스를 사용하기 불편할 뿐만 아니라, UI/UX에서 사용자 반응성이나 이용 시간 등 일련의 과정을 거쳐야 하는 테스트를 진행하기 힘들 수 있다.
이럴 때는 스티키 세션을 사용하여 사용자가 한번 특정한 서버에 접속되어 있으면 그 서버에만 계속 접속되도록 만들 수 있다. 스티키 세션에 대한 글:
'👷♂️DevOps > Kubernetes' 카테고리의 다른 글
[Kubernetes] 카나리아 배포와 Session Affinity(스티키 세션, 세션 선호도) (0) | 2023.05.17 |
---|