写在前面:如有问题,以你为准,
目前24年应届生,各位大佬轻喷,部分资料与图片来自网络
内容较长,页面右上角目录方便跳转
ingress 介绍 架构
原理
- 我们已经知道,Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点:
- NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显。
- LoadBalancer的缺点是每个Service都需要一个LB,浪费,麻烦,并且需要kubernetes之外的设备的支持。
ingress可以解决的问题
1)动态配置服务
如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要而外的操作。
2)减少不必要的端口暴露
配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式。
- 基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求,实现多个service的反向代理和负载均衡,工作机制大致如下图所示:
实际上,Ingress相当于一个七层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解为Ingress里面建立了诸多映射规则,Ingress Controller通过监听这些配置规则并转化为Nginx的反向代理配置,然后对外提供服务。
Ingress: K8s中的一个抽象资源,给管理员提供一个暴露应用的入口定义方法
Ingress Controller: 根据Ingress生成具体的路由规则,并对Pod负载均衡器
-
- Ingress:kubernetes中的一个对象,作用是定义请求如何转发到Service的规则。将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可,每一个ingress就是一个nginx方向代理规则
- Ingress Controller:具体实现反向代理及负载均衡的程序,对Ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现的方式有很多,比如Nginx,Contour,Haproxy等。将新加入的Ingress转化成Nginx的配置文件并使之生效
- Ingress(以Nginx)的工作原理如下:
- 用户编写Ingress规则,说明那个域名对应kubernetes集群中的那个Service。
- Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx的反向代理配置。
- Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新。
- 到此为止,其实真正在工作的就是一个Nginx,来实现反向代理,内部配置了用户定义的请求规则。(当然也可以是一个haproxy Controller)
下面图中ingress service 就是ingress资源对象,通过yaml部署,规则动态更新
架构图
流量路径
浏览器(ip:port) --> ServiceNodeport (ingress controller) --> ingress controller pod --> service( web) --> deployment pod (web)
[root@master kube-bench]# kubectl get svc,pod -n ingress-nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/ingress-nginx-controller NodePort 10.111.123.202 <none> 80:32172/TCP,443:31755/TCP 256dservice/ingress-nginx-controller-admission ClusterIP 10.106.250.140 <none> 443/TCP 256dNAME READY STATUS RESTARTS AGEpod/ingress-nginx-controller-cf4967654-f9v7j 1/1 Running 0 45h
应用场景
灰度发布/金丝雀(详解在后面)
业务域拆分
证书 CA
性能调优
部署 Ingress Controller(nginx ingress)
基于nginx服务的ingress controller根据不同的开发公司,又分为
k8s社区的ingres-nginx和nginx公司的nginx-ingress
k8s社区提供的ingress,github地址如下:https://github.com/kubernetes/ingress-nginx
官网:https://kubernetes.github.io/ingress-nginx/deploy/
nginx社区提供的ingress,github地址如下:https://github.com/nginxinc/kubernetes-ingress
Ingress-NGINX version | Alpine Version | ||
v1.6.4 | 3.17.0 | ||
v1.5.1 | 3.16.2 | ||
v1.4.0 | 3.16.2 | ||
v1.3.1 | 3.16.2 | ||
v1.3.0 | 3.16.0 | ||
v1.2.1 | 3.14.6 |
部署教程:kubernetes 部署 Ingress Controller(nginx ingress)-CSDN博客
登入 ingress controller 查看nginx配置
原理
https://www.bilibili.com/video/BV1r64y1m72f/?spm_id_from=333.337.search-card.all.click&vd_source=d649e016cd28e49d35879f17f8ba6892
多进程管理,ingress-nginx-controller 是在pod 里面,但是外部还有一个ingress-nginx-controller进程来通过kubernetes api 管理这些pod,并对这些pod写入ingress 配置
reload 流程
部署 Service和Dployment
apiVersion: apps/v1kind: Deploymentmetadata:name: nginx-deploymentnamespace: studyspec:replicas: 3selector:matchLabels:app: nginx-podtemplate:metadata:labels:app: nginx-podspec:containers:- name: nginximage: nginx:1.17.1ports:- containerPort: 80---apiVersion: apps/v1kind: Deploymentmetadata:name: tomcat-deploymentnamespace: studyspec:replicas: 3selector:matchLabels:app: tomcat-podtemplate:metadata:labels:app: tomcat-podspec:containers:- name: tomcatimage: tomcat:8.0.52ports:- containerPort: 8080---apiVersion: v1kind: Servicemetadata:name: nginx-servicenamespace: studyspec:selector:app: nginx-podclusterIP: Nonetype: ClusterIPports:- port: 80targetPort: 80---apiVersion: v1kind: Servicemetadata:name: tomcat-servicenamespace: studyspec:selector:app: tomcat-podclusterIP: Nonetype: ClusterIPports:- port: 8080targetPort: 8080
[root@master k8s]# kubectl apply -f ms.yamldeployment.apps/nginx-deployment createddeployment.apps/tomcat-deployment createdservice/nginx-service createdservice/tomcat-service created[root@master k8s]# kubectl get deploy,svc -n studyNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/nginx-deployment 3/3 3 3 69sdeployment.apps/tomcat-deployment 3/3 3 3 69sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/nginx-service ClusterIP None <none> 80/TCP 69sservice/tomcat-service ClusterIP None <none> 8080/TCP 69s
ingress yaml 详解
[root@master k8s]# kubectl get ingressclasses.networking.k8s.ioNAME CONTROLLER PARAMETERS AGEnginx k8s.io/ingress-nginx <none> 32m
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: ingress-httpnamespace: studyspec:ingressClassName: nginx # (1.20开始使用)
# defaultBackend: 处理不匹配的请求的后端,如果没有指定任何规则# 则必须指定默认后端如果没有设置默认后端处理请求不匹配任何规则将由入口控制器决定# service:# name: nginx-service# port:# number: 80# tls: # 指定https 密钥证书# - hosts: # 指定使用该密钥的规则# - nginx.xudaxian.com# - tomcat.xudaxian.com# secretName: tls-secret # 指定秘钥rules: # 规则指定请求匹配规则,每一个规则都是<[]Object>- host: www.snj.com #指定匹配域名,默认端口为80,443http:paths:- path: / # 这里的路径指的host访问的路径,不同路径可以绑定不同的servicepathType: Prefix # 匹配规则,Prefix 前缀匹配 it.nginx.com/* 都可以匹配到backend: # 后端的serviceservice:name: nginx-service # 绑定 serviceport:number: 80 # 指定service 端口- host: tomcat.snj.comhttp:paths:- path: /pathType: Prefixbackend:service:name: tomcat-serviceport:number: 8080
Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由 / 分隔符分隔的路径中的标签列表。 如果每个 p 都是请求路径 p 的元素前缀,则请求与路径 p 匹配。
Exact:精确匹配 URL 路径,且区分大小写。
ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 或 Exact 类型作相同处理。
[root@master k8s]# kubectl get ing -n studyNAME CLASS HOSTS ADDRESS PORTS AGEingress-http <none> nginx.snj.com,tomcat.snj.com 80 12m[root@master k8s]# kubectl get ingress -n study -o wideNAME CLASS HOSTS ADDRESS PORTS AGEingress-http nginx nginx.snj.com,tomcat.snj.com 80 28s[root@master k8s]# kubectl describe ingress -n studyName: ingress-httpLabels: <none>Namespace: studyAddress: Ingress Class: nginxDefault backend: <default>Rules:Host Path Backends---- ---- --------nginx.snj.com / nginx-service:80 (10.244.104.28:80,10.244.166.153:80,10.244.166.155:80)tomcat.snj.com / tomcat-service:80 (10.244.104.29:8080,10.244.104.34:8080,10.244.166.154:8080)Annotations: <none>Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 33s nginx-ingress-controller Scheduled for sync# 有上面这个Normal 则绑定成功
测试(http实现)
[root@master k8s]# kubectl describe svc -n ingress-nginx ingress-nginx-controllerName: ingress-nginx-controllerNamespace: ingress-nginxLabels: app.kubernetes.io/component=controllerapp.kubernetes.io/instance=ingress-nginxapp.kubernetes.io/name=ingress-nginxapp.kubernetes.io/part-of=ingress-nginxapp.kubernetes.io/version=1.6.4Annotations: <none>Selector: app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginxType: NodePortIP Family Policy: SingleStackIP Families: IPv4IP: 10.111.123.202IPs: 10.111.123.202Port: http 80/TCPTargetPort: http/TCPNodePort: http 32172/TCPEndpoints: 192.168.100.51:80 # 外部访问ingress的IP地址Port: https 443/TCPTargetPort: https/TCPNodePort: https 31755/TCPEndpoints: 192.168.100.51:443 # 外部访问ingress的IP地址Session Affinity: NoneExternal Traffic Policy: LocalEvents: <none>
出现的问题:集群内部都能也可以从自己的地址访问到ingress,hosts对应写自身地址
因为搭建ingress-nginx的service的时候,会向ipvs写入规则(访问ip为自身地址)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port Forward Weight ActiveConn InActConnTCP 192.168.100.53:31755 rr-> 192.168.100.51:443 Masq 1 0 0 TCP 192.168.100.53:32172 rr-> 192.168.100.51:80 Masq 1 0 0
但是外部不能通过master物理地址访问到ingress,外部要通过ingress pod 部署到的node的物理地址来访问
192.168.100.51 nginx.snj.com192.168.100.51 tomcat.snj.com
[root@master k8s]# kubectl get svc -n ingress-nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEingress-nginx-controller NodePort 10.102.42.91 <none> 80:32310/TCP,443:30777/TCP 4m29singress-nginx-controller-admission ClusterIP 10.96.129.195 <none> 443/TCP 4m29s# http端口为 32310 https端口为 30777
https 实现(ingress 证书)
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=xudaxian.com"[root@master k8s]# ls | grep tlstls.crttls.key
[root@master k8s]# kubectl create secret tls tls-secret --key tls.key --cert tls.crtsecret/tls-secret created
[root@master k8s]# kubectl get pod,svc,deploy -n studyNAME READY STATUS RESTARTS AGEpod/nginx-deployment-6bb9d9f778-6dnhh 1/1 Running 0 86mpod/nginx-deployment-6bb9d9f778-nfzk4 1/1 Running 0 86mpod/nginx-deployment-6bb9d9f778-rl7nr 1/1 Running 0 86mpod/tomcat-deployment-84748d94d5-dgmvh 1/1 Running 0 86mpod/tomcat-deployment-84748d94d5-nczhr 1/1 Running 0 86mpod/tomcat-deployment-84748d94d5-qbp59 1/1 Running 0 86mNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/nginx-service ClusterIP None <none> 80/TCP 86mservice/tomcat-service ClusterIP None <none> 8080/TCP 86mNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/nginx-deployment 3/3 3 3 86mdeployment.apps/tomcat-deployment 3/3 3 3 86m
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: ingress-httpnamespace: studyspec:ingressClassName: nginx # (1.20开始使用)tls: # 指定https 密钥证书- hosts: # 指定使用该密钥的规则- nginx.xudaxian.com- tomcat.xudaxian.comsecretName: tls-secret # 指定秘钥 rules: # 规则指定请求匹配规则,每一个规则都是<[]Object>- host: nginx.snj.com #指定匹配域名,默认端口为80,443http:paths:- path: / # 这里的路径指的host访问的路径,不同路径可以绑定不同的servicepathType: Prefixbackend: #后端的serviceservice:name: nginx-service # 绑定 serviceport:number: 80 # 指定service 端口- host: tomcat.snj.comhttp:paths:- path: /pathType: Prefixbackend:service:name: tomcat-serviceport:number: 8080
[root@master k8s]# kubectl apply -f ingress.yamlingress.networking.k8s.io/ingress-http created[root@master k8s]# kubectl get ing -n studyNAME CLASS HOSTS ADDRESS PORTS AGEingress-http nginx www.snj.com,tomcat.snj.com 80, 443 8s[root@master k8s]# kubectl describe ing -n studyName: ingress-httpLabels: <none>Namespace: studyAddress: Ingress Class: nginxDefault backend: <default>TLS:tls-secret terminates nginx.xudaxian.com,tomcat.xudaxian.comRules:Host Path Backends---- ---- --------www.snj.com / nginx-service:80 (10.244.104.38:80,10.244.166.165:80,10.244.166.166:80)tomcat.snj.com / tomcat-service:8080 (10.244.104.39:8080,10.244.104.40:8080,10.244.166.167:8080)Annotations: <none>Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 38s nginx-ingress-controller Scheduled for sync[root@master k8s]# kubectl get svc -n ingress-nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEingress-nginx-controller NodePort 10.111.123.202 <none> 80:32172/TCP,443:31755/TCP 92mingress-nginx-controller-admission ClusterIP 10.106.250.140 <none> 443/TCP 92m
# 访问端口 443:31755/TCPcurl -k https://nginx.snj.com:31755
单域名多路径
访问时跳转指定地址
不使用域名,使用ip
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: ingress-v1namespace: studyspec:ingressClassName: "nginx"rules:- http:paths:- path: /pathType: Prefixbackend:service:name: v1-serviceport:number: 80
[root@master canary]# curl 10.111.123.202v1-pod
限流操作
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: rate-ingressnamespace: defaultannotations: # https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limitingkubernetes.io/ingress.class: "nginx"nginx.ingress.kubernetes.io/backend-protocol: "HTTP" nginx.ingress.kubernetes.io/limit-rps: "1" # 限流spec:rules:- host: nginx.xudaxian.comhttp:paths:- path: /pathType: Prefixbackend:service:name: nginx-svcport:number: 80
基于 Cookie 的会话保持技术
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: rate-ingressnamespace: defaultannotations: # https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limitingkubernetes.io/ingress.class: "nginx"nginx.ingress.kubernetes.io/backend-protocol: "HTTP" nginx.ingress.kubernetes.io/affinity: "cookie"spec:rules:- host: nginx.xudaxian.comhttp:paths:- path: /pathType: Prefixbackend:service:name: nginx-svcport:number: 80
其他示例
出现问题
IngressClass
kubectl logs -n ingress-nginx ingress-nginx-controller-cf4967654-fkwcl# 进行排错# 比如出现一下错误# W0102 12:51:07.374785 7 controller.go:278] ignoring ingress nginx-ingress in study based on annotation : ingress does not contain a valid IngressClass# 说明没有配置 ingress classI0102 13:53:52.597216 7 main.go:100] "successfully validated configuration, accepting" ingress="study/nginx-ingress"I0102 13:53:52.604268 7 store.go:433] "Found valid IngressClass" ingress="study/nginx-ingress" ingressclass="nginx"I0102 13:53:52.614011 7 event.go:285] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"study", Name:"nginx-ingress", UID:"0f72d9c8-4b9c-4dee-afec-e5a7d213323e", APIVersion:"networking.k8s.io/v1", ResourceVersion:"8126946", FieldPath:""}): type: 'Normal' reason: 'Sync' Scheduled for syncI0102 13:53:53.128640 7 controller.go:188] "Configuration changes detected, backend reload required"I0102 13:53:53.246681 7 controller.go:205] "Backend successfully reloaded"I0102 13:53:53.254908 7 event.go:285] Event(v1.ObjectReference{Kind:"Pod", Namespace:"ingress-nginx", Name:"ingress-nginx-controller-cf4967654-fkwcl", UID:"a50e3220-3928-4fac-bdd6-b5fe5409be00", APIVersion:"v1", ResourceVersion:"8047653", FieldPath:""}): type: 'Normal' reason: 'RELOAD' NGINX reload triggered due to a change in configurationI0102 13:54:14.813365 7 status.go:300] "updating Ingress status" namespace="study" ingress="nginx-ingress" currentValue=[] newValue=[{IP:10.111.123.202 Hostname: Ports:[]}]I0102 13:54:14.817935 7 event.go:285] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"study", Name:"nginx-ingress", UID:"0f72d9c8-4b9c-4dee-afec-e5a7d213323e", APIVersion:"networking.k8s.io/v1", ResourceVersion:"8126996", FieldPath:""}): type: 'Normal' reason: 'Sync' Scheduled for sync
[root@master k8s]# kubectl get ingress -n studyNAME CLASS HOSTS ADDRESS PORTS AGEnginx-ingress nginx * 10.111.123.202 80 65s
master 访问问题
因为master没有ingress-nginx-controller控制器
外部不能通过master物理地址访问到ingress,外部要通过ingress pod 部署到的node的物理地址来访问
灰度发布/蓝绿发布/金丝雀发布
概述
以前使用 Kubernetes 的 Service 配合 Deployment 进行金丝雀的部署,原理如下所示:
- 但是,也是有缺点的,就是不能自定义灰度逻辑,如:指定用户进行灰度(新功能只让 VIP 先体验一个月,一个月之后再将新功能解锁,让所有用户都体验到)。
- Ingress 金丝雀发布的原理如下所示:
canary - 监绿和灰度发布而社区版本
service - 蓝绿和灰度发布云端版本(阿里云)
基于Request Headerf的流量切分,适用于灰度发布及AB测试
基于Cookie的流量切分,适用于灰度发布及AB测试
环境:已经部署了一个old nginx的ingress以及后端的deployment service资源
现在部署完了new nginx 的deployment service资源,要部署一个实现蓝绿发布的ingress(同一个host 域名)
环境部署
deployment service
部署 v1 deployment service 和 v2 deployment service
apiVersion: v1kind: Namespacemetadata:name: study---apiVersion: apps/v1kind: Deploymentmetadata:name: v1-deploymentlabels:app: v1-deploymentnamespace: studyspec:replicas: 2selector:matchLabels:app: v1-podtemplate:metadata:name: nginxlabels:app: v1-podspec:initContainers:- name: busyboximage: busybox:1.30imagePullPolicy: IfNotPresentcommand: ["/bin/sh","-c","echo v2-pod > /app/index.html;"]volumeMounts:- mountPath: /appname: appcontainers:- name: nginximage: nginx:1.17.1imagePullPolicy: IfNotPresentports:- containerPort: 80resources:requests:cpu: 100mmemory: 100Milimits:cpu: 250mmemory: 500MivolumeMounts:- name: appmountPath: /usr/share/nginx/html volumes:- name: appemptyDir: {} restartPolicy: Always---apiVersion: v1kind: Servicemetadata:name: v1-servicenamespace: studyspec:selector:app: v1-podtype: ClusterIPports:- name: nginxprotocol: TCPport: 80targetPort: 80---apiVersion: apps/v1kind: Deploymentmetadata:name: v2-deploymentlabels:app: v2-deploymentnamespace: studyspec:replicas: 3selector:matchLabels:app: v2-podtemplate:metadata:name: v2-podlabels:app: v2-podspec:initContainers:- name: busyboximage: busybox:1.30imagePullPolicy: IfNotPresentcommand: ["/bin/sh","-c","echo v2-pod > /app/index.html;"]volumeMounts:- mountPath: /appname: appcontainers:- name: nginximage: nginx:1.17.2imagePullPolicy: IfNotPresentports:- containerPort: 80resources:requests:cpu: 100mmemory: 100Milimits:cpu: 250mmemory: 500MivolumeMounts:- name: appmountPath: /usr/share/nginx/htmlvolumes:- name: appemptyDir: {}restartPolicy: Always---apiVersion: v1kind: Servicemetadata:name: v2-servicenamespace: studyspec:selector:app: v2-podtype: ClusterIPports:- name: nginxprotocol: TCPport: 80targetPort: 80
v1-ingress
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: ingress-v1namespace: defaultspec:ingressClassName: "nginx"rules:- host: nginx.xudaxian.comhttp:paths:- path: /pathType: Prefixbackend:service:name: v1-serviceport:number: 80
检查
[root@master canary]# kubectl get deploy,svc,pod,ing -n studyNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/v1-deployment 2/2 2 2 9m1sdeployment.apps/v2-deployment 3/3 3 3 9m1sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/v1-service ClusterIP 10.100.50.208 <none> 80/TCP 9m1sservice/v2-service ClusterIP 10.107.230.80 <none> 80/TCP 9m1sNAME READY STATUS RESTARTS AGEpod/v1-deployment-7c455c58d8-6njc2 1/1 Running 0 9m1spod/v1-deployment-7c455c58d8-ngkq2 1/1 Running 0 9m1spod/v2-deployment-bc9fc6679-6lgjf 1/1 Running 0 9m1spod/v2-deployment-bc9fc6679-n8b49 1/1 Running 0 9m1spod/v2-deployment-bc9fc6679-p86ln 1/1 Running 0 9m1sNAME CLASS HOSTS ADDRESS PORTS AGEingress.networking.k8s.io/ingress-v1 nginx nginx.snj.com 10.111.123.202 80 83s
[root@ip-15 ~]# curl nginx.snj.comv1-pod
v2-ingress
基于 Header 的流量切分
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: v2-ingress-canary-headernamespace: studyannotations:nginx.ingress.kubernetes.io/canary: "true" # 开启金丝雀nginx.ingress.kubernetes.io/canary-by-header: "Region" # 基于请求头# 如果 请求头 Region = always ,就路由到金丝雀版本;如果 Region = never ,就永远不会路由到金丝雀版本。# canary-by-header-value 默认 是always和 nervernginx.ingress.kubernetes.io/canary-by-header-value: "sz" # 自定义值# 如果 请求头 Region = sz ,就路由到金丝雀版本;如果 Region != sz ,就永远不会路由到金丝雀版本。# nginx.ingress.kubernetes.io/canary-by-header-pattern: "sh|sz"# 如果 请求头 Region = sh 或 Region = sz ,就路由到金丝雀版本;如果 Region != sz 并且 Region != sz ,就永远不会路由到金丝雀版本。spec:ingressClassName: "nginx"rules:- host: nginx.snj.comhttp:paths:- path: /pathType: Prefixbackend:service:name: v2-serviceport:number: 80
[root@ip-15 ~]# curl nginx.snj.comv1-pod[root@ip-15 ~]# curl -H "Region: sz" nginx.snj.comv2-pod
# 此时进行测试,如负载等测试,如果没问题即可直接根据下面的完全上线新版本
基于 Cookie 的流量切分
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: ingress-canary-cookienamespace: studyannotations:nginx.ingress.kubernetes.io/canary: "true" # 开启金丝雀nginx.ingress.kubernetes.io/canary-by-cookie: "vip"# 如果 cookie 是 vip = always ,就会路由到到金丝雀版本# 如果 cookie 是 vip = never ,就永远不会路由到金丝雀的版本。spec:ingressClassName: "nginx"rules:- host: nginx.snj.comhttp:paths:- path: /pathType: Prefixbackend:service:name: v2-serviceport:number: 80
[root@ip-15 ~]# curl nginx.snj.comv1-pod[root@ip-15 ~]# curl --cookie "vip=always" nginx.snj.comv2-pod# 此时进行测试,如负载等测试,如果没问题即可直接根据下面的完全上线新版本
基于服务权重的流量切分
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: ingress-canary-weightnamespace: studyannotations:nginx.ingress.kubernetes.io/canary: "true" # 开启金丝雀nginx.ingress.kubernetes.io/canary-weight: "10" # 基于服务权重spec:ingressClassName: "nginx"rules:- host: nginx.snj.comhttp:paths:- path: /pathType: Prefixbackend:service:name: v2-serviceport:number: 80
[root@master canary]# kubectl get deploy,svc,pod,ing -n studyNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/v1-deployment 2/2 2 2 28mdeployment.apps/v2-deployment 3/3 3 3 28mNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/v1-service ClusterIP 10.107.153.174 <none> 80/TCP 28mservice/v2-service ClusterIP 10.97.36.128 <none> 80/TCP 28mNAME READY STATUS RESTARTS AGEpod/v1-deployment-7c455c58d8-68k9r 1/1 Running 0 28mpod/v1-deployment-7c455c58d8-kdmgl 1/1 Running 0 28mpod/v2-deployment-568ff74948-cs6dr 1/1 Running 0 28mpod/v2-deployment-568ff74948-ptsdx 1/1 Running 0 28mpod/v2-deployment-568ff74948-rpql8 1/1 Running 0 28mNAME CLASS HOSTS ADDRESS PORTS AGEingress.networking.k8s.io/ingress-canary-weight nginx nginx.snj.com 10.111.123.202 80 30singress.networking.k8s.io/ingress-v1 nginx nginx.snj.com 10.111.123.202 80 27m[root@ip-15 ~]# for i in {1..10}; do curl nginx.snj.com; done;v1-podv1-podv1-podv1-podv1-podv2-podv1-podv1-podv1-podv1-pod
完全上线新版本
改ingress的后端service
[root@master canary]# kubectl edit ingress -n study ingress-v1ingress.networking.k8s.io/ingress-v1 edited- backend:service:name: v2-serviceport:number: 80
改service标签选择器
直接就老版本的service的标签选择器指向新版本的deploy的标签
首先在网络中使用的http协议进行传输,http协议是一个明文传输协议
此时为了安全,我们就需要使用https加密传输协议,但是需要对 ingress 进行证书配置