創建一個測試用namespace
apiVersion: v1
kind: Namespace
metadata:
name: test-ingress
[root@192 test-ingress]# kubectl apply -f create-namespace.yaml
namespace/test-ingress created
[root@192 test-ingress]#
[root@192 test-ingress]#
[root@192 test-ingress]# kubectl get namespace
NAME STATUS AGE
default Active 3d17h
istio-system Active 3d17h
kube-node-lease Active 3d17h
kube-public Active 3d17h
kube-system Active 3d17h
kubernetes-dashboard Active 3d17h
test-ingress Active 10s
安裝nginx-ingress
參考官方文檔:
//kubernetes.github.io/ingress-nginx/deploy/#minikube不同環境有不同的安裝方式,這里以minikube環境為例
The ingress controller can be installed through minikube's addons system:
minikube addons enable ingress
檢查安裝成功
##查看ingress的訪問入口,注意ingress是默認安裝到ingress-nginx命名空間的
[root@192 test-ingress]# kubectl get services -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.99.151.210 <none> 80:31359/TCP,443:32466/TCP 17m
ingress-nginx-controller-admission ClusterIP 10.108.13.155 <none> 443/TCP 17m
##可以看出是以nodeport方式暴露這個nginx的,我們可以看下我們的node地址
[root@192 test-ingress]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
minikube Ready control-plane 3d18h v1.28.3 192.168.49.2 <none> Ubuntu 22.04.4 LTS 5.14.0-503.el9.x86_64 docker://26.1.1
#測試下80端口,能訪問說明成功
[root@192 test-ingress]# curl //192.168.49.2:80
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
創建app-v1(Deployment)、svc-v1(Service)、ingress-v1(Ingress)
[root@192 test-ingress]# kubectl apply -f create-v1-all.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: app-v1
name: app-v1
namespace: test-ingress
spec:
replicas: 1
selector:
matchLabels:
app: app-v1
template:
metadata:
labels:
app: app-v1
spec:
containers:
- image: nginx:alpine
name: app-v1
# 此處修改nginx主頁顯示為 this is app-v1
command: ["/bin/sh","-c","echo 'this is app-v1'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]
---
apiVersion: v1
kind: Service
metadata:
name: svc-v1
namespace: test-ingress
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: app-v1
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-v1
namespace: test-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: "www.test.com"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
# 指定服務的名稱和端口
name: svc-v1
port:
number: 80
注意注解 kubernetes.io/ingress.class: "nginx"需要進行填入,表示使用nginx-ingress
驗證訪問ingress->app-v1
[root@192 test-ingress]# kubectl get ingress -n test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-v1 <none> www.test.com 192.168.49.2 80 30m
[root@192 test-ingress]# kubectl get ingress -n test-ingress -o yaml
apiVersion: v1
items:
- apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.k8s.io/v1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-v1","namespace":"test-ingress"},"spec":{"rules":[{"host":"www.test.com","http":{"paths":[{"backend":{"service":{"name":"svc-v1","port":{"number":80}}},"path":"/","pathType":"Prefix"}]}}]}}
kubernetes.io/ingress.class: nginx
creationTimestamp: "2024-09-09T02:22:37Z"
generation: 1
name: ingress-v1
namespace: test-ingress
resourceVersion: "92470"
uid: 8129d9c3-8615-45cd-838b-cfd49725a282
spec:
rules:
- host: www.test.com
http:
paths:
- backend:
service:
name: svc-v1
port:
number: 80
path: /
pathType: Prefix
status:
loadBalancer:
ingress:
- ip: 192.168.49.2
kind: List
metadata:
resourceVersion: ""
[root@192 test-ingress]# curl -H "Host:www.test.com" //192.168.49.2/
this is app-v1
[root@192 test-ingress]#
創建app-v2、svc-v2、ingress-v2
[root@192 test-ingress]# kubectl apply -f create-v2-all.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: app-v2
name: app-v2
namespace: test-ingress
spec:
replicas: 1
selector:
matchLabels:
app: app-v2
template:
metadata:
labels:
app: app-v2
spec:
containers:
- image: nginx:alpine
name: app-v2
# 此處修改nginx主頁顯示為 this is app-v2
command: ["/bin/sh","-c","echo 'this is app-v2'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]
---
apiVersion: v1
kind: Service
metadata:
name: svc-v2
namespace: test-ingress
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: app-v2
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-v2
namespace: test-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
rules:
- host: "www.test.com"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: svc-v2
port:
number: 80
nginx.ingress.kubernetes.io/canary: "true" #啟動金絲雀
nginx.ingress.kubernetes.io/canary-weight: "10" #百分之10流量
驗證訪問流量
[root@192 test-ingress]# kubectl get ingress -n test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-v1 <none> www.test.com 192.168.49.2 80 47m
ingress-v2 <none> www.test.com 192.168.49.2 80 52s
[root@192 test-ingress]# for i in $(seq 1 20);do curl -H "Host: www.test.com" //192.168.49.2;done
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v2
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v2
this is app-v1
this is app-v1
this is app-v1
##可以看出流量有大概10%的到了v2版本
驗證不符合預期-回滾操作
刪掉v2對應的ingress,再訪問流量就回到原來的v1了
[root@192 test-ingress]# kubectl delete -f create-v2-all.yaml
deployment.apps "app-v2" deleted
service "svc-v2" deleted
ingress.networking.k8s.io "ingress-v2" deleted
[root@192 test-ingress]#
[root@192 test-ingress]#
[root@192 test-ingress]# for i in $(seq 1 20);do curl -H "Host: www.test.com" //192.168.49.2;done
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
this is app-v1
驗證符合預期-慢慢放大v2版本流量
這里就不演示逐步加到app-v2的pod數量,以應對更多的流量
[root@192 test-ingress]# kubectl apply -f v2-ingress100.yaml
ingress.networking.k8s.io/ingress-v2 configured
[root@192 test-ingress]#
[root@192 test-ingress]#
[root@192 test-ingress]# for i in $(seq 1 20);do curl -H "Host: www.test.com" //192.168.49.2;done
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
this is app-v2
我們可以調整v2-ingress100.yaml 這個文件的流量比例,慢慢放大v2版本的流量
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-v2
namespace: test-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "100"
spec:
rules:
- host: "www.test.com"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: svc-v2
port:
number: 80
通常金絲雀規則驗證完,我們會刪掉金絲雀規則,直接讓原非金絲雀流量也轉到v2版本里去
我們可以創建一個新的ingress-v2-release規則,將所有流量轉到svc-v2里去,例如如下。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-v2-release
namespace: test-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: "www.test.com"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
# 指定服務的名稱和端口
name: svc-v2
port:
number: 80
然后再刪除ingress-v1和ingress-v2,以及svc-v1和app-v1,只保留svc-v2和app-v2
根據Header做金絲雀
[root@192 test-ingress]# kubectl apply -f v2-ingress-header-forward.yaml
ingress.networking.k8s.io/ingress-v2 configured
[root@192 test-ingress]# kubectl get ingress -n test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-v1 <none> www.test.com 192.168.49.2 80 69m
ingress-v2 <none> www.test.com 192.168.49.2 80 8m37s
[root@192 test-ingress]# curl -H "Host: www.test.com" //192.168.49.2
this is app-v1
[root@192 test-ingress]# curl -H "Host: www.test.com" -H "version: v2" //192.168.49.2
this is app-v2
以下yaml文件指定了根據header來做金絲雀
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "version"
nginx.ingress.kubernetes.io/canary-by-header-value: "v2"
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-v2
namespace: test-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "version"
nginx.ingress.kubernetes.io/canary-by-header-value: "v2"
spec:
rules:
- host: "www.test.com"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: svc-v2
port:
number: 80