Phased Release of Application Services through Kubernetes Ingress Controller

Release Scenarios

Scenario 1

Scenario 2

Annotation Description

1. nginx.ingress.kubernetes.io/service-match

nginx.ingress.kubernetes.io/service-match: | 
<service-name>: <match-rule>
# Parameter description:
# service-name: indicates the service name. Requests that conform to the rule specified by match-rule are routed to this service.
# match-rule: indicates the routing matching rule.
#
# Routing matching rule:
# 1. Supported matching types:
# - header: indicates matching based on the request header, which can be regular expression matching or exact expression matching.
# - cookie: indicates matching based on the cookie, which can be regular expression matching or exact expression matching.
# - query: indicates matching based on the query parameter, which can be regular expression matching or exact expression matching.
#
# 2. Matching modes:
# - Regular expression matching format: /{regular expression}/. // indicates matching based on a regular expression.
# - Exact expression matching format: "{exact expression}". "" indicates matching based on an exact expression.
# Requests whose foo in the request header contains ^bar$ (regular expression matching) are forwarded to the new-nginx service.
new-nginx: header("foo", /^bar$/)
# Requests whose foo in the request header equals bar (exact expression matching) are forwarded to the new-nginx service.
new-nginx: header("foo", "bar")
# Requests whose foo in the cookie contains ^sticky-.+$ (regular expression matching) are forwarded to the new-nginx service.
new-nginx: cookie("foo", /^sticky-.+$/)
# Requests whose foo in the query parameter equals bar (exact expression matching) are forwarded to the new-nginx service.
new-nginx: query("foo", "bar")

2. nginx.ingress.kubernetes.io/service-weight

nginx.ingress.kubernetes.io/service-weight: | 
<new-svc-name>:<new-svc-weight>, <old-svc-name>:<old-svc-weight>
Parameter description:
new-svc-name: indicates the name of the new-version service.
new-svc-weight: indicates the weight of the new-version service.
old-svc-name: indicates the name of the old-version service.
old-svc-weight: indicates the weight of the old-version service.
nginx.ingress.kubernetes.io/service-weight: | 
new-nginx: 20, old-nginx: 60

Version Updates

kubectl -n kube-system set image deploy/nginx-ingress-controller nginx-ingress-controller=registry.cn-hangzhou.aliyuncs.com/acs/aliyun-ingress-controller:0.12.0-5
kubectl -n kube-system set image ds/nginx-ingress-controller nginx-ingress-controller=registry.cn-hangzhou.aliyuncs.com/acs/aliyun-ingress-controller:0.12.0-5

Service Deployment

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: old-nginx
spec:
replicas: 2
selector:
matchLabels:
run: old-nginx
template:
metadata:
labels:
run: old-nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xianlu/old-nginx
imagePullPolicy: Always
name: old-nginx
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: old-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: old-nginx
sessionAffinity: None
type: NodePort
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gray-release
spec:
rules:
- host: www.example.com
http:
paths:
# Old-version service
- path: /
backend:
serviceName: old-nginx
servicePort: 80
kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
gray-release www.example.com 47.107.20.35 80 1m
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
old

Phased Release of the new-version Service

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: new-nginx
spec:
replicas: 1
selector:
matchLabels:
run: new-nginx
template:
metadata:
labels:
run: new-nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xianlu/new-nginx
imagePullPolicy: Always
name: new-nginx
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: new-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: new-nginx
sessionAffinity: None
type: NodePort

Scenario 1: Set a specific rule to allow clients that conform to this rule to access the new-nginx service.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gray-release
annotations:
# Requests whose foo in the request header contains bar (regular expression matching) are routed to the new-nginx service.
nginx.ingress.kubernetes.io/service-match: |
new-nginx: header("foo", /^bar$/)
spec:
rules:
- host: www.example.com
http:
paths:
# Old-version service
- path: /
backend:
serviceName: old-nginx
servicePort: 80
# New-version service
- path: /
backend:
serviceName: new-nginx
servicePort: 80
curl -H "Host: www.example.com"  http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" -H "foo: bar" http://47.107.20.35
new
curl -H "Host: www.example.com" -H "foo: bar" http://47.107.20.35
new
curl -H "Host: www.example.com" -H "foo: bar" http://47.107.20.35
new

Scenario 2: Set a specific rule to route a specified proportion of requests that conform to this rule to the new-nginx service.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gray-release
annotations:
# Requests whose foo in the request header contains bar (regular expression matching) are routed to the new-nginx service.
nginx.ingress.kubernetes.io/service-match: |
new-nginx: header("foo", /^bar$/)
# Only 50% of the requests that conform to the preceding matching rule are routed to the new-nginx service.
nginx.ingress.kubernetes.io/service-weight: |
new-nginx: 50, old-nginx: 50
spec:
rules:
- host: www.example.com
http:
paths:
# Old-version service
- path: /
backend:
serviceName: old-nginx
servicePort: 80
# New-version service
- path: /
backend:
serviceName: new-nginx
servicePort: 80
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" -H "foo: bar" http://47.107.20.35
new
curl -H "Host: www.example.com" -H "foo: bar" http://47.107.20.35
old
curl -H "Host: www.example.com" -H "foo: bar" http://47.107.20.35
old
curl -H "Host: www.example.com" -H "foo: bar" http://47.107.20.35
new

Scenario 3: Route a specified proportion of requests to the new-nginx service.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gray-release
annotations:
# Only 50% of traffic is routed to the new-nginx service.
nginx.ingress.kubernetes.io/service-weight: |
new-nginx: 50, old-nginx: 50
spec:
rules:
- host: www.example.com
http:
paths:
# Old-version service
- path: /
backend:
serviceName: old-nginx
servicePort: 80
# New-version service
- path: /
backend:
serviceName: new-nginx
servicePort: 80
curl -H "Host: www.example.com" http://47.107.20.35
new
curl -H "Host: www.example.com" http://47.107.20.35
new
curl -H "Host: www.example.com" http://47.107.20.35
new
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
old
curl -H "Host: www.example.com" http://47.107.20.35
new
curl -H "Host: www.example.com" http://47.107.20.35
old

Completion of the Phased Release

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gray-release
spec:
rules:
- host: www.example.com
http:
paths:
# New-version service
- path: /
backend:
serviceName: new-nginx
servicePort: 80
curl -H "Host: www.example.com" http://47.107.20.35
new
curl -H "Host: www.example.com" http://47.107.20.35
new
curl -H "Host: www.example.com" http://47.107.20.35
new

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store