반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- gitea
- operator
- kubernetes operator
- gitops
- Kubeflow
- Kopf
- tekton
- mlops
- 카오스 엔지니어링
- MLflow
- CANARY
- Continuous Deployment
- Argo
- CI/CD
- Kubernetes
- Model Serving
- knative
- 오퍼레이터
- opentelemetry
- nginx ingress
- blue/green
- opensearch
- Litmus
- keda
- seldon core
- serving
- argo rollout
- Pulumi
- argocd
- Kubernetes 인증
Archives
- Today
- Total
Kubernetes 이야기
Nginx Ingress를 통해 Canary 배포 설정 본문
반응형
Canary 배포는 새 버전이 모든 사용자에게 릴리스되기 전에 초기 테스트로 일부 사용자에게 점진적으로 롤아웃하는 방법이다.
자세한 내용은 다음을 참고한다.
Nginx에서는 Canary 배포를 위한 다양한 Annotation 을 지원한다. Nginx Ingress Controller 에서 제공하는 Canary 배포 annotation 은 다음과 같다.
- nginx.ingress.kubernetes.io/canary : canary 활성화 여부, "true" or "false"
- nginx.ingress.kubernetes.io/canary-by-header : Canary Ingress에 지정된 서비스로 요청을 라우팅하도록 Ingress에 알리는 데 사용할 헤더
- nginx.ingress.kubernetes.io/canary-by-header-value : Ingress에 요청을 Canary Ingress에 지정된 서비스로 라우팅하도록 알리기 위해 일치시킬 헤더 값
- nginx.ingress.kubernetes.io/canary-by-header-pattern : CIngress에 요청을 Canary Ingress에 지정된 서비스로 라우팅하도록 알리는 데 사용할 정규식
- nginx.ingress.kubernetes.io/canary-by-cookie : Ingress에 요청을 Canary Ingress에 지정된 서비스로 라우팅하도록 알리는 데 사용할 쿠키 값. 쿠키 값이 always로 설정되면 canary로 라우팅된다.
- nginx.ingress.kubernetes.io/canary-weight : Canary Ingress에 지정된 서비스로 라우팅되어야 하는 임의 요청의 백분율
- nginx.ingress.kubernetes.io/canary-weight-total : 트래픽의 총 중량. 지정하지 않으면 기본값은 100
카나리아 규칙의 우선 순위는 다음과 같다.
canary-by-header -> canary-by-cookie -> canary-weight
다음과 같은 앱을 배포해 보자.
apiVersion: apps/v1
kind: Deployment
metadata:
name: production
labels:
app: production
spec:
replicas: 1
selector:
matchLabels:
app: production
template:
metadata:
labels:
app: production
spec:
containers:
- name: production
image: mirrorgooglecontainers/echoserver:1.10
ports:
- containerPort: 8080
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
---
apiVersion: v1
kind: Service
metadata:
name: production
labels:
app: production
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: production
이제 Ingress에 다음과 같이 설정한다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: production
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: test.10.10.0.110.nip.io
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: production
port:
number: 80
서비스를 한 번 호출해 보자.
배포 사용 예
다음과 같이 새로 만들 앱 (name : canary)을 배포해 보자.
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary
labels:
app: canary
spec:
replicas: 1
selector:
matchLabels:
app: canary
template:
metadata:
labels:
app: canary
spec:
containers:
- name: canary
image: mirrorgooglecontainers/echoserver:1.10
ports:
- containerPort: 8080
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
---
apiVersion: v1
kind: Service
metadata:
name: canary
labels:
app: canary
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: canary
현재 배포된 앱은 다음과 같다.
# k get svc,pod -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/canary ClusterIP 10.100.51.112 <none> 80/TCP 26s
service/production ClusterIP 10.97.182.169 <none> 80/TCP 15m
NAME READY STATUS RESTARTS AGE
pod/canary-58dc8b498f-bbrss 1/1 Running 0 26s
pod/production-846769889f-g2dck 1/1 Running 0 15m
Header 기반 설정
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "x-region"
nginx.ingress.kubernetes.io/canary-by-header-value: "ap-seoul"
spec:
rules:
- host: test.10.10.0.110.nip.io
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: canary
port:
number: 80
header값을 canary 의 haeder값으로 설정하여 호출해 보자. ( hostname이 canary-xx 로 호출되는 것을 볼 수 있다. )
# curl -H "Host: test.10.10.0.110.nip.io" -H "x-region: ap-seoul" http://test.10.10.0.110.nip.io
Hostname: canary-58dc8b498f-bbrss
Pod Information:
node name: node2
pod name: canary-58dc8b498f-bbrss
pod namespace: test
pod IP: 192.168.104.17
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=192.168.166.129
method=GET
real path=/
query=
request_version=1.1
request_scheme=http
request_uri=http://test.10.10.0.110.nip.io:8080/
Request Headers:
accept=*/*
host=test.10.10.0.110.nip.io
user-agent=curl/7.29.0
x-forwarded-for=10.10.0.110
x-forwarded-host=test.10.10.0.110.nip.io
x-forwarded-port=80
x-forwarded-proto=http
x-forwarded-scheme=http
x-real-ip=10.10.0.110
x-region=ap-seoul
x-request-id=8deb3ad9419a786ebf7148db99b513c4
x-scheme=http
Request Body:
-no body in request-
header 값이 틀린 경우는 기존 production 이 호출된다.
# curl -H "Host: test.10.10.0.110.nip.io" -H "x-region: ap-busan" http://test.10.10.0.110.nip.io
Hostname: production-846769889f-g2dck
Pod Information:
node name: node1
pod name: production-846769889f-g2dck
pod namespace: test
pod IP: 192.168.166.136
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=10.140.0.112
method=GET
real path=/
query=
request_version=1.1
request_scheme=http
request_uri=http://test.10.10.0.110.nip.io:8080/
Request Headers:
accept=*/*
host=test.10.10.0.110.nip.io
user-agent=curl/7.29.0
x-forwarded-for=10.10.0.110
x-forwarded-host=test.10.10.0.110.nip.io
x-forwarded-port=80
x-forwarded-proto=http
x-forwarded-scheme=http
x-real-ip=10.10.0.110
x-region=ap-busan
x-request-id=b7de598c0fc2ed55111e2fdb96b837e6
x-scheme=http
Request Body:
-no body in request-
Cookie 기반 정책
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "canary-session"
spec:
rules:
- host: test.10.10.0.110.nip.io
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: canary
port:
number: 80
Cookie값을 "canary-session" 값으로 설정하여 호출해 보자.
# curl -H "Host: test.10.10.0.110.nip.io" --cookie "canary-session=always" http://test.10.10.0.110.nip.io
Hostname: canary-58dc8b498f-bbrss
Pod Information:
node name: node2
pod name: canary-58dc8b498f-bbrss
pod namespace: test
pod IP: 192.168.104.17
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=192.168.166.129
method=GET
real path=/
query=
request_version=1.1
request_scheme=http
request_uri=http://test.10.10.0.110.nip.io:8080/
Request Headers:
accept=*/*
cookie=canary-session=always
host=test.10.10.0.110.nip.io
user-agent=curl/7.29.0
x-forwarded-for=10.10.0.110
x-forwarded-host=test.10.10.0.110.nip.io
x-forwarded-port=80
x-forwarded-proto=http
x-forwarded-scheme=http
x-real-ip=10.10.0.110
x-request-id=8fdff585937ec03b60688f3ca5fc9f21
x-scheme=http
Request Body:
-no body in request-
가중치(weight) 기반 정책
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
rules:
- host: test.10.10.0.110.nip.io
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: canary
port:
number: 80
다음과 같이 호출해 보자.
# for i in {1..10}; do curl -ss -H "Host: test.10.10.0.110.nip.io" http://test.10.10.0.110.nip.io; done | grep Hostname
Hostname: production-846769889f-g2dck
Hostname: production-846769889f-g2dck
Hostname: production-846769889f-g2dck
Hostname: production-846769889f-g2dck
Hostname: production-846769889f-g2dck
Hostname: canary-58dc8b498f-bbrss
Hostname: canary-58dc8b498f-bbrss
Hostname: production-846769889f-g2dck
Hostname: production-846769889f-g2dck
Hostname: production-846769889f-g2dck
가중치를 100%로 하게되면 Blue/Green 배포와 유사한 형태가 된다.
반응형
'Kubernetes > devops' 카테고리의 다른 글
Jenkins와 Keycloak을 이용한 OIDC 연동 (0) | 2022.09.10 |
---|---|
jenkins 를 활용하여 Kubernetes에 이미지 배포 및 모니터링 (0) | 2022.09.08 |
Keptn (활용) (0) | 2022.08.04 |
Ketpn (설치) (0) | 2022.07.28 |
argo CD Image Updater (0) | 2022.05.20 |
Comments