반응형
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 |
Tags
- Pulumi
- opensearch
- 카오스 엔지니어링
- nginx ingress
- Kubernetes 인증
- knative
- Argo
- keda
- MLflow
- Kopf
- kubernetes operator
- gitops
- tekton
- CI/CD
- serving
- mlops
- Kubernetes
- xdp
- CANARY
- eBPF
- blue/green
- opentelemetry
- Kubeflow
- Model Serving
- 오퍼레이터
- seldon core
- Continuous Deployment
- argocd
- operator
- Litmus
Archives
- Today
- Total
Kubernetes 이야기
Nginx Ingress를 통해 Canary 배포 설정 본문
반응형
Canary 배포는 새 버전이 모든 사용자에게 릴리스되기 전에 초기 테스트로 일부 사용자에게 점진적으로 롤아웃하는 방법이다.
자세한 내용은 다음을 참고한다.
Kubernetes의 다양한 배포방식 (3) Canary 배포
Canary 배포 Canary 라는 용어는 옛날 탄광에서 나오는 유독 가스에 죽거나 다치는 일을 피하고자 광부들이 유독 가스에 민감한 카나리아를 데리고 갱도로 내려간 일에서 나온 용어로 다가온 위험
kmaster.tistory.com
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 (1) | 2022.05.20 |
Comments