이 글은 아주 짧습니다 :)
실습 스크립트 및 코드는 이곳에 있습니다.
현재 블루 그린의 경우 무중단 배포가 되지 않습니다!
편의상 쿠버네티스를 k8s 혹은 쿠버라고 표시하겠습니다 :)
눈물 젖은 젠킨스와의 추억
젠킨스에 셸 스크립트 작성하며 눈물 흘리며 지새웠던 지난 밤들의 추억...
쿠버를 사용하면 그 고통의 추억들을 보상받을 수 있다
아래는 내가 작성했던 젠킨스의 파이프라인이다
스케줄링 기능이 본 WAS 2대 중 한 대로 잡혀있는 구조라서 저렇게 다소 복잡하게 짜여진 것도 한 몫을 한다
일반적인 WAS 구조를 가정해서 조금 더 간소화하면 아래와 같다
하지만 쿠버네티스의 경우 아래와 같이 한 단계만이 존재한다
정확히는 yml파일에 배포할 container image를 넣고 아래와 같은 명령어를 기술하면 된다 (!!!)
kubectl apply -f deply-was.yml
많은 내용은 없으나 아래와 같이 간단하게 3가지 배포의 경우에 대한 설정 파일을 소개하고자 한다
롤링 배포
아래와 같이 롤링 배포가 있는데,
파란색이 기존에 운영되던 서비스고, 초록색이 배포할 서비스이다
저렇게 새로운 버전을 배포 후 기존 서비스를 내리는 방식이 롤링 배포이다
- script -
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-was
spec:
selector:
matchLabels:
pod-type: was
replicas: 1
strategy:
type: RollingUpdate
template:
metadata:
labels:
pod-type: was
spec:
containers:
- name: container
image: progress0407/app-ver1
resources:
requests:
memory: 20Mi
limits:
memory: 300Mi
그러나 단순히 위처럼 구성 후 배포하면 아래와 같이 요청이 끊기는 구간이 생긴다
이유는 새로운 버전을 배포 후에 pod가 Running으로 표시되더라도
스프링 부트 앱이 실제로 트래픽을 받을 준비는 되지 않았기 때문이다
그래서 언제 트래픽을 받을 준비가 되었는지를 체크한 후 이후에 신규 배포된 pod로 트래픽을 옮길 수 있도록 해야 한다
쿠버에선 이것을 readiness probe가 담당한다
즉 아래 그림처럼 되어야 한다
아래는 바뀐 script이다
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-was
spec:
selector:
matchLabels:
pod-type: was
replicas: 1
strategy:
type: RollingUpdate
template:
metadata:
labels:
pod-type: was
spec:
containers:
- name: container
image: progress0407/app-ver1
resources:
requests:
memory: 20Mi
limits:
memory: 300Mi
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
scheme: HTTP
initialDelaySeconds: 2
periodSeconds: 2
successThreshold: 2
timeoutSeconds: 60
하단의 readinessProbe 영역을 추가했다
액츄에이터 헬스 체크를 60초 동안 2초 간격으로 확인하는데,
첫 2초를 건너 뛰고 2회 성공하면 성공으로 간주하여 트래픽 연결을 한다
(정확히는 서비스의 셀렉터와 pod의 라벨과 연결을 시켜준다)
그러면 이제 아래처럼 안정적으로 무중단 배포가 된다
Blue Green 배포
Blue Green의 경우 무중단 배포가 되지 않아요 ! ㅠ
(애당초 kubectl만으로 블루그린을 만들지 않음!! )
일반적인 상황에서, argo cd를 사용합니다!
아래 그림처럼 파란 Pod군이 기존 배포된 Blue군이고
초록색이 Green군이다
Green군을 배포 할 때 Blue군을 유지하고 완료되면 종료시키는 방식이다
k8s에서 공식적으로 블루그린을 지원하지 않아서 어느 정도 직접 구현을 해야 한다
아래는 내가 구현한 블루 그린 스크립트이다
- script -
#!/bin/bash
k="minikube kubectl -- "
# deploy green
$k apply -f deploy-was-green.yml
# wait while deploying green
while true; do
status=$($k get pods | grep deploy-was-green | awk '{print $3}')
if [[ $status == "Running" ]]; then
echo "Blue is Running!"
break;
fi;
sleep 1;
done;
# delete blue traffic
$k delete svc svc-nodeport-blue
# allow green traffic
$k apply -f svc-nodeport-green.yml
# now, close blue traffic
$k delete deploy deploy-was-blue
# display blue's status
curl $(minikube ip):30000/actuator/health
echo ""
curl $(minikube ip):30000/version
다만 이 경우 레드니스 프로브 체크 로직을 넣기가 쉽지 않았는데,
덕분에 중단 배포가 된다... ㅎㅎ
카나리 배포
쿠버의 Ingress weight 기능을 사용하면 카나리 배포를 할 수 있다
아래 스크립트를 확인해보자
- script -
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-v2
namespace: ns-deploy
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
ingressClassName: nginx
rules:
- host: www.app.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc-v1
port:
number: 8080
App version 1
apiVersion: v1
kind: Pod
metadata:
name: pod-v1
labels:
app: v1
namespace: ns-deploy
spec:
containers:
- name: container
image: progress0407/app-ver1
---
apiVersion: v1
kind: Service
metadata:
name: svc-v1
namespace: ns-deploy
spec:
selector:
app: v1
ports:
- port: 8080
App version 2
apiVersion: v1
kind: Pod
metadata:
name: pod-v2
labels:
app: v2
namespace: ns-deploy
spec:
containers:
- name: container
image: progress0407/app-ver2
---
apiVersion: v1
kind: Service
metadata:
name: svc-v2
namespace: ns-deploy
spec:
selector:
app: v2
ports:
- port: 8080
새 버전의 pod와 service를 배포한 후
canary-weight 속성을 통해서 이전 버전과 새 버전의 서비스의 트래픽을 분배할 수 있다
예를 들어 canary-weight가 10일 경우 새로운 버전의 트래픽은 전체 트래픽의 10%만 유입이 된다
그리고 ingress의 카나리 기능에 오해한게 있었다.
자동으로 weight값이 올라가지 않는다.
즉, ingress의 기능만으로 온전히 카나리 배포가 되지 않는다
그래서 나의 경우 아래처럼 shell로 한 번 더 카나리 배포를 구현했다
format_weight_json_str() {
local ratio=$1
echo "{\"metadata\":{\"annotations\":{\"nginx.ingress.kubernetes.io/canary-weight\":\"$ratio\"}}}"
}
ratio_list=(10 25 50 100)
for ratio in "${ratio_list[@]}"
do
echo "current deploy's ratio is $ratio"
$k patch ingress canary-deploy -p "$(format_weight_json_str $ratio)"
sleep 5
done
10, 25, 50, 100의 비율로 신규 버전으로 배포되는 형태이다
그러면 아래처럼 로그가 찍힌다
'Infra, DevOps > Kubernetes, Docker' 카테고리의 다른 글
[k8s] 쿠버로 백엔드 환경 구축하기 (0) | 2024.02.19 |
---|---|
[배포 기록] 도커 역사 및 빠른 재정리 (feat. 삽질 ..) (0) | 2024.01.20 |
따끈따끈 쿠버네티스 기초 개념 요약 (0) | 2024.01.17 |
윈도우에서 쿠버네티스 긴급 사용 후기 (2) | 2024.01.16 |
순전히 GPT의 도움으로 Docker기반 MySQL 셋업하기 (0) | 2023.07.08 |
hi hello... World >< 가장 아름다운 하나의 해답이 존재한다
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!