0.2. Jenkins : The open source automation server, support building deploying and automating any project - DockerHub , Github , Docs
CI(지속적 제공)/CD(지속적 배포) 워크플로 예제 : Continuous Integration Server + Continuous Development, Build, Test, Deploy - Link
최신 코드 가져오기 : 개발을 위해 중앙 코드 리포지터리에서 로컬 시스템으로 애플리케이션의 최신 코드를 가져옴
단위 테스트 구현과 실행 : 코드 작성 전 단위 테스트 케이스를 먼저 작성
코드 개발 : 실패한 테스트 케이스를 성공으로 바꾸면서 코드 개발
단위 테스트 케이스 재실행 : 단위 테스트 케이스 실행 시 통과(성공!)
코드 푸시와 병합 : 개발 소스 코드를 중앙 리포지터리로 푸시하고, 코드 병합
코드 병합 후 컴파일 : 변경 함수 코드가 병함되면 전체 애플리케이션이 컴파일된다
병합된 코드에서 테스트 실행 : 개별 테스트뿐만 아니라 전체 통합 테스트를 실행하여 문제 없는지 확인
아티팩트 배포 : 애플리케이션을 빌드하고, 애플리케이션 서버의 프로덕션 환경에 배포
배포 애플리케이션의 E-E 테스트 실행 : 셀레늄 Selenium과 같은 User Interface 자동화 도구를 통해 애플리케이션의 전체 워크플로가 정상 동작하는지 확인하는 종단간 End-to-End 테스트를 실행.
소프트웨어 개발 프로세스의 다양한 단계를 자동화하는 도구로서 중앙 소스 코드 리포지터리에서 최신 코드 가져오기, 소스 코드 컴파일, 단위 테스트 실행, 산출물을 다양한 유형으로 패키징, 산출물을 여러 종류의 환경으로 배포하기 등의 기능을 제공.
젠킨스는 아파치 톰캣처럼 서블릿 컨테이너 내부에서 실행되는 서버 시스템이다. 자바로 작성됐고, 소프트웨어 개발과 관련된 다양한 도구를 지원.
젠킨스는 DSLDomain Specific Language (jenkins file)로 E-E 빌드 수명 주기 단계를 구축한다.
젠킨스는 파이프라인이라고 부르는 스크립트를 작성할 수 있는데, 이를 사용해서 각 빌드 단계마다 젠킨스가 수행할 태스트 및 하위 태스크의 순서를 정의.
다양한 Plugins 연동
0.3. Jenkins 컨테이너에서 호스트에 도커 데몬 사용 설정 (Docker-out-of-Docker) : macOS 사용자
Copy
# Jenkins 컨테이너 내부에 도커 실행 파일 설치
docker compose exec --privileged -u root jenkins bash
-----------------------------------------------------
id
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update && apt install docker-ce-cli curl tree jq yq -y
docker info
docker ps
which docker
# Jenkins 컨테이너 내부에서 root가 아닌 jenkins 유저도 docker를 실행할 수 있도록 권한을 부여
groupadd -g 2000 -f docker # macOS(Container)
chgrp docker /var/run/docker.sock
ls -l /var/run/docker.sock
usermod -aG docker jenkins
cat /etc/group | grep docker
exit
--------------------------------------------
# jenkins item 실행 시 docker 명령 실행 권한 에러 발생 : Jenkins 컨테이너 재기동으로 위 설정 내용을 Jenkins app 에도 적용 필요
docker compose restart jenkins
# jenkins user로 docker 명령 실행 확인
docker compose exec jenkins id
docker compose exec jenkins docker info
docker compose exec jenkins docker ps
‣
mac 재부팅 시에 jenkins 컨테이너에서 docker 실행 실패 시 : 소켓 파일에 docker 그룹을 다시 지정
0.4. Gogs : Gogs is a painless self-hosted Git service
초기 설정 웹 접속
초기 설정
→ Gogs 설치하기 클릭 ⇒ 관리자 계정으로 로그인 후 접속
[Token 생성] 로그인 후 → Your Settings → Applications : Generate New Token 클릭 - Token Name(devops) ⇒ Generate Token 클릭 : 메모해두기!
New Repository 1 : 개발팀용
New Repository 2 : 데브옵스팀용
0.5. Gogs 실습을 위한 저장소 설정 : 호스트에서 직접 git 작업 , Windows 경우 WSL2 혹은 호스트에서 작업 둘 다 가능
Copy
# (옵션) GIT 인증 정보 초기화
git credential-cache exit
#
git config --list --show-origin
#
TOKEN=<각자 Gogs Token>
TOKEN=de6665398b85d560c06b790830bd9a2533cfd26a
MyIP=<각자 자신의 PC IP> # Windows (WSL2) 사용자는 자신의 WSL2 Ubuntu eth0 IP 입력 할 것!
MyIP=192.168.254.127
git clone <각자 Gogs dev-app repo 주소>
git clone http://devops:$TOKEN@$MyIP:3000/devops/dev-app.git
Cloning into 'dev-app'...
...
#
cd dev-app
#
git --no-pager config --local --list
git config --local user.name "devops"
git config --local user.email "a@a.com"
git config --local init.defaultBranch main
git config --local credential.helper store
git --no-pager config --local --list
cat .git/config
#
git --no-pager branch
git remote -v
# server.py 파일 작성
cat > server.py <<EOF
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
from datetime import datetime
import socket
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
match self.path:
case '/':
now = datetime.now()
hostname = socket.gethostname()
response_string = now.strftime("The time is %-I:%M:%S %p, VERSION 0.0.1\n")
response_string += f"Server hostname: {hostname}\n"
self.respond_with(200, response_string)
case '/healthz':
self.respond_with(200, "Healthy")
case _:
self.respond_with(404, "Not Found")
def respond_with(self, status_code: int, content: str) -> None:
self.send_response(status_code)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(bytes(content, "utf-8"))
def startServer():
try:
server = ThreadingHTTPServer(('', 80), RequestHandler)
print("Listening on " + ":".join(map(str, server.server_address)))
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
if __name__== "__main__":
startServer()
EOF
# (참고) python 실행 확인
python3 server.py
curl localhost
curl localhost/healthz
CTRL+C 실행 종료
# Dockerfile 생성
cat > Dockerfile <<EOF
FROM python:3.12
ENV PYTHONUNBUFFERED 1
COPY . /app
WORKDIR /app
CMD python3 server.py
EOF
# VERSION 파일 생성
echo "0.0.1" > VERSION
#
tree
git status
git add .
git commit -m "Add dev-app"
git push -u origin main
...
1.6. k8s Deploying an application with Jenkins(pipeline-ci)
Deploying to Kubernetes
원하는 상태 설정 시 k8s 는 충족을 위해 노력함 : Kubernetes uses declarative configuration, where you declare the state you want (like “I want 3 copies of my container running in the cluster”) in a configuration file. Then, submit that config to the cluster, and Kubernetes will strive to meet the requirements you specified.
Copy
# 디플로이먼트 오브젝트 배포 : 리플리카(파드 2개), 컨테이너 이미지 >> 아래 도커 계정 부분만 변경해서 배포해보자
DHUSER=<도커 허브 계정명>
DHUSER=gylee815
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: timeserver
spec:
replicas: 2
selector:
matchLabels:
pod: timeserver-pod
template:
metadata:
labels:
pod: timeserver-pod
spec:
containers:
- name: timeserver-container
image: docker.io/$DHUSER/dev-app:0.0.1
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 30
httpGet:
path: /healthz
port: 80
scheme: HTTP
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
EOF
watch -d kubectl get deploy,rs,pod -o wide
# 배포 상태 확인 : kube-ops-view 웹 확인
kubectl get events -w --sort-by '.lastTimestamp'
kubectl get deploy,pod -o wide
kubectl describe pod
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 52s default-scheduler Successfully assigned default/timeserver-7fb496bcd4-wxrrf to myk8s-worker2
Normal BackOff 23s (x2 over 49s) kubelet Back-off pulling image "docker.io/gylee815/dev-app:0.0.1"
Warning Failed 23s (x2 over 49s) kubelet Error: ImagePullBackOff
Normal Pulling 10s (x3 over 51s) kubelet Pulling image "docker.io/gylee815/dev-app:0.0.1"
Warning Failed 9s (x3 over 50s) kubelet Failed to pull image "docker.io/gylee815/dev-app:0.0.1": failed to pull and unpack image "docker.io/gylee815/dev-app:0.0.1": failed to resolve reference "docker.io/gylee815/dev-app:0.0.1": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
Warning Failed 9s (x3 over 50s) kubelet Error: ErrImagePull
Check the spelling of your image and verify that the image is in your repository.
Copy
# k8s secret : 도커 자격증명 설정
kubectl get secret -A # 생성 시 타입 지정
DHUSER=<도커 허브 계정>
DHPASS=<도커 허브 암호 혹은 토큰>
echo $DHUSER $DHPASS
DHUSER=gasida
DHPASS=dckr_pat_KWx-0N27iEd1lk8aNvRz8pDrQlI
echo $DHUSER $DHPASS
kubectl create secret docker-registry dockerhub-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=$DHUSER \
--docker-password=$DHPASS
# 확인
kubectl get secret
kubectl describe secret
kubectl get secrets -o yaml | kubectl neat # base64 인코딩 확인
SECRET=eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJnYXNpZGEiLCJwYXNzd29yZCI6ImRja3JfcGF0X0tXeC0wTjI3aUVkMWxrOGFOdlJ6OHBEclFsSSIsImF1dGgiOiJaMkZ6YVdSaE9tUmphM0pmY0dGMFgwdFhlQzB3VGpJM2FVVmtNV3hyT0dGT2RsSjZPSEJFY2xGc1NRPT0ifX19
echo "$SECRET" | base64 -d ; echo
{"auths":{"https://index.docker.io/v1/":{"username":"gylee815","password":"SOME_TOKEN","auth":"AUTH_INFO"}}}
# 디플로이먼트 오브젝트 업데이트 : 시크릿 적용 >> 아래 도커 계정 부분만 변경해서 배포해보자
cat <
PODIP1=10.244.1.4
kubectl exec -it curl-pod -- curl $PODIP1
The time is 5:57:14 AM, VERSION 0.0.1
Server hostname: timeserver-6777ff7cd-4s4fn
kubectl exec -it curl-pod -- curl $PODIP1/healthz
# 로그 확인
kubectl logs deploy/timeserver
kubectl logs deploy/timeserver -f
kubectl stern deploy/timeserver
kubectl stern -l pod=timeserver-pod
파드 1개 삭제 후 동작 확인 → 접속 확인
Copy
#
POD1NAME=<파드 1개 이름>
POD1NAME=timeserver-7954b8f6df-l25wx
kubectl get pod -owide
kubectl delete pod $POD1NAME && kubectl get pod -w
# 셀프 힐링 , 파드 IP 변경 -> 고정 진입점(고정 IP/도메인네임) 필요 => Service
kubectl get deploy,rs,pod -owide
Publishing your Service
Each Pod is given its own cluster-local (internal) IP address, which can be used for communication between Pods within the cluster.
It’s possible to expose Pods directly on the internet as well as on the node’s IP (with the field hostPort), but unless you’re writing a real-time game server, that’s rarely what you’ll do.
Typically, and especially when Deployment is used, you will aggregate your Pods into a Service, which provides a single access point with an internal (and optionally external) IP, and load balance requests across your pods.
디플로이먼트에 파드 1개가 있다하더라도 서비스를 통해 안정적인 주소를 제공
In addition to load balancing, Services keep track of which Pods are running and capable of receiving traffic. For example, while you may have specified three replicas in your Deployment, that doesn’t mean that three replicas will be available at all times.
노드 업그레이드 등 이벤트 발생 시 정상 동작 파드로만 라우팅 처리 : There might only be two if a node is being upgraded, or there could be more than three while you’re rolling out a new version of your Deployment. The Service will only route traffic to running Pods (in the next chapter, we’ll cover some key information you need to provide to make that works smoothly).
Services are used internally within the cluster to enable communication between multiple applications (a so-called microservice architecture) and offer convenient features, such as service discovery, for this purpose.
Each Pod and Service in Kubernetes has its own internal cluster IP, so you don’t need to worry about port conflicts between Pods.
Notice also that this Service has a section named selector, like our Deployment had.
The Service doesn’t reference the Deployment and actually has no knowledge of the Deployment.
Instead, it references the set of Pods that have the given label (which, in this case, will be the Pods created by our Deployment).
Unlike in the Deployment object, the selector section has no matchLabels subsection.
They are, however, equivalent. Deployment is just using a newer, more expressive syntax in Kubernetes.
The selectors in the Deployment and in the Service are achieving the same result: specifying the set of Pods that the object is referencing.
Updating your application**
샘플 앱 server.py 코드 변경 → 젠킨스(지금 빌드 실행) : 새 0.0.2 버전 태그로 컨테이너 이미지 빌드 → 컨테이너 저장소 Push ⇒ k8s deployment 업데이트 배포
태그는 버전 정보 사용을 권장 : You can make this tag anything you like, but it’s a good convention to use version numbers.
The READY column shows how many Pods are servingtraffic and how many we requested.
In this case, all three are ready. The UP-TO-DATE column, however, indicates that only one of these Pods is the current version.
This is because, rather than replacing all the Pods at once, causing some downtime to the application, by default, Pods are updated with a so-called rolling update strategy—that is, one or several at a time.
1.7. Gogs Webhooks 설정 : Jenkins Job Trigger
gogs 에 /data/gogs/conf/app.ini 파일 수정 후 컨테이너 재기동 - issue
gogs 에 Webhooks 설정 : Jenkins job Trigger - Setting → Webhooks → Gogs 클릭
(TS) gogs 에 Webhooks 동작이 잘 되지 않을 경우 /data/gogs/conf/app.ini 파일 내에 아래 항목 확인 해볼것.
kubectl apply -f rollout.yaml
kubectl get po
NAME READY STATUS RESTARTS AGE
curl-pod 1/1 Running 0 8h
rollout-bluegreen-5ffd47b8d4-4gs8c 1/1 Running 0 14m
rollout-bluegreen-5ffd47b8d4-qc57m 1/1 Running 0 14m
kubectl get rs
NAME DESIRED CURRENT READY AGE
rollout-bluegreen-5ffd47b8d4 2 2 2 14m
kubectl get ep
NAME ENDPOINTS AGE
kubernetes 172.19.0.3:6443 7h5m
rollout-bluegreen-active 10.244.1.41:8080,10.244.2.38:8080 14m
rollout-bluegreen-preview 10.244.1.41:8080,10.244.2.38:8080 14m
이제 blue/green 배포를 위한 준비가 완료되었으면, 아래와 같이 rollout-bluegreen rollout resource의 container.image를 green으로 변경한다.
새롭게 green version의 rs가 생성되었고, preview service가 green version의 rs를 바라보고게 되고 endpoints도 green version의 pod ip인것을 볼 수 있다.
argo-rollout web을 확인해보면 아래와 같이 blue version은 아직 stable 상태로있고, 새롭게 생성된 green version이 preview로 추가된것을 볼 수 있다.
아래에서 보는 것 처럼 active service에 접근하면 blue version의 web이 보이고, preview serivce에 접근하면 green version의 web이 보이고 있다.
ingress와 연동한다면 사용자에게 노출할 ingress는 active service에 연결해두고, 내부에서 배포전에 확인 할 용도로 사용할 ingress에는 preview service를 연결해두어 내부적으로 검증을 하면 되겠다.
이제 preview service의 green version app이 모두 검증이 끝났다고 가정을 하면, 사용자에게도 green version의 app이 노출되게 해야 한다.
argo-rollout web상에서 promote를 통해서 active service도 green version을 바라보도록 할 수 있다.
이제 green version app의 rs가 stable/ active 상태인것을 볼 수 있다.
아래에서 볼 수 있듯이 active와 preview service모두 같은 endpoint 를 갖고 있다. 즉, 두 service 모두 green version app의 rs를 바라보고있다.
이렇게 하여 최종적으로 검증이 완료된 green verion의 app이 사용자에게 노출되게 된다.
Copy
kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7h28m <none>
rollout-bluegreen-active NodePort 10.96.223.222 <none> 80:30000/TCP 38m app=rollout-bluegreen,rollouts-pod-template-hash=75695867f
rollout-bluegreen-preview NodePort 10.96.36.245 <none> 80:30001/TCP 38m app=rollout-bluegreen,rollouts-pod-template-hash=75695867f
kubectl get ep
NAME ENDPOINTS AGE
kubernetes 172.19.0.3:6443 7h28m
rollout-bluegreen-active 10.244.1.42:8080,10.244.2.39:8080 38m
rollout-bluegreen-preview 10.244.1.42:8080,10.244.2.39:8080 38m
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curl-pod 1/1 Running 0 8h 10.244.1.5 myk8s-worker <none> <none>
rollout-bluegreen-5ffd47b8d4-4gs8c 1/1 Running 0 38m 10.244.1.41 myk8s-worker <none> <none>
rollout-bluegreen-5ffd47b8d4-qc57m 1/1 Running 0 38m 10.244.2.38 myk8s-worker2 <none> <none>
rollout-bluegreen-75695867f-4w6cs 1/1 Running 0 24m 10.244.2.39 myk8s-worker2 <none> <none>
rollout-bluegreen-75695867f-q52hj 1/1 Running 0 24m 10.244.1.42 myk8s-worker <none> <none>
kubectl get rs
NAME DESIRED CURRENT READY AGE
rollout-bluegreen-5ffd47b8d4 2 2 2 38m
rollout-bluegreen-75695867f 2 2 2 24m
7.2.2. Canary
Argo Rollouts 설치
# 네임스페이스 생성 및 파라미터 파일 작성
cd cicd-labs
kubectl create ns argo-rollouts
cat <<EOT > argorollouts-values.yaml
dashboard:
enabled: true
service:
type: NodePort
nodePort: 30003
EOT
# 설치: 2.35.1
helm install argo-rollouts argo/argo-rollouts --version 2.39.2 -f argorollouts-values.yaml --namespace argo-rollouts
# 확인
kubectl get all -n argo-rollouts
kubectl get crds
# Argo rollouts 대시보드 접속 주소 확인
echo "http://127.0.0.1:30003"
open "http://127.0.0.1:30003"
Deploying a Rollout
먼저, 롤아웃 리소스와 해당 롤아웃을 타겟으로 하는 Kubernetes 서비스를 배포합니다.
이 가이드의 예제 롤아웃은 카나리아 업데이트 전략을 사용하여 트래픽의 20%를 카나리아로 보내고, 이어서 수동 프로모션을 실시하며, 마지막으로 업그레이드의 나머지 기간 동안 점진적으로 자동 트래픽이 증가합니다.
# 다음 명령을 실행하여 초기 롤아웃 및 서비스를 배포합니다:
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/rollout.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/service.yaml
# 확인
kubectl get rollout --watch
kubectl get rollout
kubectl describe rollout
kubectl get pod -l app=rollouts-demo
kubectl get svc,ep rollouts-demo
kubectl get rollouts rollouts-demo -o json | grep rollouts-demo
...
"image": "argoproj/rollouts-demo:blue"
...
default 네임스페이스 선택 → rollout-demo 클릭
모든 롤아웃의 초기 생성물은 업그레이드가 발생하지 않았기 때문에 즉시 복제본을 100%로 확장합니다(카나리 업그레이드 단계, 분석 등 생략).
Argo 롤아웃 쿠벡틀 플러그인을 사용하면 롤아웃 및 관련 리소스(ReplicaSets, Pods, AnalysisRuns)를 시각화할 수 있으며, 발생하는 실시간 상태 변경 사항을 표시할 수 있습니다. 롤아웃이 배포되는 동안 롤아웃을 확인하려면 플러그인에서 get rollout --watch 명령을 실행하세요:
Updating a Rollout
다음은 업데이트를 수행할 시간입니다. 배포와 마찬가지로 Pod 템플릿 필드(spec.template)를 변경하면 새로운 버전(즉, ReplicaSet)이 배포됩니다.
롤아웃 업데이트에는 롤아웃 사양을 수정하고 일반적으로 컨테이너 이미지 필드를 새 버전으로 변경한 다음 새로운 매니페스트에 대해 kubectl 적용을 실행하는 작업이 포함됩니다.
편의상 롤아웃 플러그인은 실시간 롤아웃 객체에 대해 다음 단계를 수행하는 설정 이미지 명령을 제공합니다. 다음 명령을 실행하여 롤아웃 데모 롤아웃을 컨테이너의 "yellow" 버전으로 업데이트합니다:
# Run the following command to update the rollouts-demo Rollout with the "yellow" version of the container:
KUBE_EDITOR="nano" kubectl edit rollouts rollouts-demo
..
- image: argoproj/rollouts-demo:yellow
...
#
kubectl get rollout --watch
# 파드 label 정보 확인
watch -d kubectl get pod -l app=rollouts-demo -owide --show-labels
롤아웃 업데이트 중에 컨트롤러는 롤아웃의 업데이트 전략에 정의된 단계를 진행합니다.
예제 롤아웃은 카나리아의 트래픽 가중치를 20%로 설정하고, 롤아웃을 일시 중지/촉진하기 위한 사용자 조치가 취해질 때까지 롤아웃을 무기한 일시 중지합니다. 이미지를 업데이트한 후 일시 중지 상태에 도달할 때까지 롤아웃을 확인하세요.
데모 롤아웃이 두 번째 단계에 도달하면 플러그인을 통해 롤아웃이 일시 중지된 상태이며, 이제 5개의 복제본 중 1개가 포드 템플릿의 새 버전을 실행하고 있고, 5개의 복제본 중 4개가 이전 버전을 실행하고 있음을 알 수 있습니다. 이는 set Weight: 20로 정의된 20%에 해당합니다.
Promoting a Rollout
이제 롤아웃이 일시 중지된 상태입니다. 롤아웃이 지속 시간 없이 일시 중지 단계에 도달하면 재개/추진될 때까지 무기한 일시 중지된 상태로 유지됩니다. 롤아웃을 다음 단계로 수동으로 승격하려면 플러그인의 promote 명령을 실행합니다:
# 아래 입력 혹은 UI에서 Promote Yes 클릭
kubectl argo rollouts promote rollouts-demo
# 정보 확인
kubectl get rollouts rollouts-demo -o json | grep rollouts-demo
watch -d kubectl get pod -l app=rollouts-demo -owide --show-labels
프로모션 후 롤아웃은 나머지 단계를 실행합니다. 예제의 남은 롤아웃 단계는 완전히 자동화되어 있으므로 롤아웃은 새 버전으로 완전히 전환될 때까지 단계를 완료합니다. 모든 단계가 완료될 때까지 롤아웃을 확인하세요
모든 단계가 성공적으로 완료되면 새로운 ReplicaSet은 "Healthy" ReplicaSet으로 표시됩니다. 업데이트 중에 실패한 카나리아 분석을 통해 자동으로 또는 사용자가 수동으로 롤아웃을 중단하면 롤아웃은 다시 "Healthy" 버전으로 돌아갑니다.
Rollback
만약 Blue/Green 혹은 Canary 배포가 완료되고, 현재 new version의 application에 문제가 발생하였을때 rollback 기능을 통해서 기존 old version으로 원복 할 수 있다.
Rollback 역시 기존과 마찬가지로(기존에 blue → yellow로 변경시 Canary update 진행) Canary방식으로 점진적 배포가 이루어진다.
요약
이 기본 예제의 롤아웃은 트래픽을 라우팅하기 위해 입력 컨트롤러나 서비스 메시 제공자를 사용하지 않았습니다. 대신, 일반적인 Kubernetes 서비스 네트워킹(즉, kube-proxy)을 사용하여 새로운 복제본 수와 이전 복제본 수의 가장 가까운 비율을 기준으로 대략적인 카나리아 가중치를 달성했습니다. 그 결과, 이 롤아웃은 새로운 버전을 실행하기 위해 5개의 포드 중 1개를 확장함으로써 최소 카나리아 가중치를 20%까지만 달성할 수 있다는 한계가 있었습니다. 훨씬 더 세밀한 카나리아를 달성하기 위해서는 입력 컨트롤러나 서비스 메시가 필요합니다.
트래픽 라우팅 가이드 중 하나를 따라가면 Argo Rollouts가 네트워킹 제공업체를 어떻게 활용하여 보다 발전된 트래픽 형성을 달성할 수 있는지 확인할 수 있습니다.