一、Service简介
1.服务发现与负载均衡资源(Service & Ingress)
这类资源决定了如何访问运行中的应用。
-
Service(服务) :为一组 Pod 提供固定的访问入口和负载均衡。它主要有四种类型:
ClusterIP(集群内部访问)、NodePort(节点端口映射,通过节点 IP+端口访问)、LoadBalancer(对接云厂商负载均衡器)和Headless(用于 StatefulSet 的稳定 DNS)。 -
Ingress(入口) :管理集群外部访问集群内服务的七层(HTTP/HTTPS)路由 。例如,根据域名
api.example.com路由到api-service,根据路径/web路由到web-service。
2.理解标签与service中的endpoint
建立一个service
bash
[root@k8s-master ~]# mkdir service/
[root@k8s-master ~]# cd service/
[root@k8s-master service]# kubectl create service clusterip --tcp 80:80 testservice --dry-run=client -o yaml >> testservice.yaml
[root@k8s-master service]# vim testservice.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: testservice
name: testservice
spec:
ports:
- name: webport
port: 80
protocol: TCP
targetPort: 80
selector:
app: webserver
type: ClusterIP
[root@k8s-master service]# kubectl apply -f testservice.yml
service/testservice created
[root@k8s-master service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
testservice ClusterIP 10.100.99.225 <none> 80/TCP 4s
[root@k8s-master service]# kubectl describe svc testservice

建立pod并测试pod是否可以被testservice暴漏
bash
[root@k8s-master service]# kubectl run webserver --image myapp:v1 --dry-run=client -o yaml > webserver.yml
[root@k8s-master service]# vim webserver.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: webserver
name: webserver
spec:
containers:
- image: myapp:v1
name: webserver
[root@k8s-master service]# kubectl get pods -o wide;kubectl describe service testservice

由于标签没有匹配上,所以此时并没有被暴露
更改标签然后观察
bash
[root@k8s-master service]# kubectl label pods webserver app=webserver
pod/webserver labeled
[root@k8s-master service]# kubectl describe service testservice
[root@k8s-master service]# curl 10.100.99.225
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

3.利用service暴漏控制器
监控
bash
[root@k8s-master service]# watch -n 1 "kubectl describe svc webservice ; kubectl get deploy --show-labels;kubectl get pods -o wide --show-labels "
生成控制器和service的组合yam
bash
[root@k8s-master service]# kubectl create service clusterip --tcp 80:80 webservice --dry-run=client -o yaml >> webservice.yaml
[root@k8s-master service]# kubectl create deployment webcluster --image myapp:v1 --dry-run=client -o yaml >>webservice.yaml
[root@k8s-master service]# vim webservice.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: webservice
name: webservice
spec:
port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: myapp:v1
name: myapp
生成控制器和service
bash
[root@k8s-master service]# kubectl apply -f webservice.yaml
#测试
[root@k8s-master service]# curl 10.100.140.222
[root@k8s-master service]# curl 10.100.140.222/hostname.html
[root@k8s-master service]# curl 10.100.140.222/hostname.html

二、service的ipvs模式
-
Service 是由 kube-proxy 组件,加上 iptables 来共同实现的
-
kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源
-
IPVS模式的service,可以使K8s集群支持更多量级的Pod
注意:切换ipvs模式后,kube-proxy会在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配所有service IP
1.在所有节点中安装ipvsadm工具
bash
[root@k8s-master service]# for name in 100 10 20 200
> do
> ssh -l root 172.25.254.$name "dnf install ipvsadm -y"
> done
2.配置集群中的kube-proxy
重启pod,在pod运行时配置文件中采用默认配置,当改变配置文件后已经运行的pod状态不会变化,所以要重启pod
bash
[root@k8s-master service]# kubectl -n kube-system edit cm kube-proxy
59 mode: "ipvs"
[root@k8s-master service]# kubectl -n kube-system get pods
kube-proxy-n7zrb 1/1 Running 1 (28h ago) 8d
kube-proxy-pq7qn 1/1 Running 0 8d
kube-proxy-r6zc7 1/1 Running 1 (28h ago) 8d
[root@k8s-master service]# kubectl -n kube-system get pods |awk '/proxy/{system("kubectl -n kube-system delete pods "$1)}'
pod "kube-proxy-n7zrb" deleted from kube-system namespace
pod "kube-proxy-pq7qn" deleted from kube-system namespace
pod "kube-proxy-r6zc7" deleted from kube-system namespace

3.效果
bash
[root@k8s-master service]# ipvsadm -Ln

三、Service的类型
| 微服务类型 | 作用描述 |
|---|---|
| ClusterIP | 默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问 |
| NodePort | 将Service通过指定的Node上的端口暴露给外部,访问任意一个NodeIP:nodePort都将路由到ClusterIP |
| LoadBalancer | 在NodePort的基础上,借助cloud provider创建一个外部的负载均衡器,并将请求转发到 NodeIP:NodePort,此模式只能在云服务器上使用 |
| ExternalName | 将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定 |
1.ClusterIP
yaml文件内容
bash
[root@k8s-master service]# vim webservice.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: webservice
name: webservice
spec:
ports:
- name: webport
port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: myapp:v1
name: myapp
[root@k8s-master service]# kubectl apply -f webservice.yaml

集群内部解析
注意:集群内部通常使用service的解析名称进行通信地址的指定,因为资源的ip会变但是名字不会
bash
[root@k8s-master service]# kubectl -n kube-system get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
calico-typha ClusterIP 10.97.97.73 <none> 5473/TCP 28h
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 13d
[root@k8s-master service]# dig webservice.default.svc.cluster.local @10.96.0.10

clusterIP的headless模式
当设定此模式,那么service不会被分配一个ip而是直接把endpoints上的ip直接通过dns裸漏
bash
[root@k8s-master service]# vim webservice.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: webservice
name: webservice
spec:
ports:
- name: webport
port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: ClusterIP
clusterIP: None ##加上这条
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: myapp:v1
name: myapp
[root@k8s-master service]# kubectl apply -f webservice.yaml

bash
#查看解析
[root@k8s-master service]# dig webservice.default.svc.cluster.local @10.96.0.10

2.nodePort模式
nodePort的yaml文件内容
bash
[root@k8s-master service]# vim webservice.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: webservice
name: webservice
spec:
ports:
- name: webport
port: 80
protocol: TCP
targetPort: 80
nodePort: 30001 #指定端口,如不写可以从30000~32767之间随机分
selector:
app: webcluster
type: NodePort #NodePort模式
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: myapp:v1
name: myapp
[root@k8s-master service]# kubectl apply -f webservice.yaml
查看策略与访问测试
bash
[root@k8s-master service]# ipvsadm -Ln
TCP 172.25.254.100:30001 rr
-> 10.224.36.78:80 Masq 1 0 0
-> 10.224.169.157:80 Masq 1 0 0
TCP 10.244.0.0:30001 rr
-> 10.224.36.78:80 Masq 1 0 0
-> 10.224.169.157:80 Masq 1 0 0
[root@k8s-master service]# curl 172.25.254.100:30001
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]# curl 172.25.254.100:30001/hostname.html
webcluster-77c87d9946-tg8qr
[root@k8s-master service]# curl 172.25.254.100:30001/hostname.html
webcluster-77c87d9946-kjc9n


端口破限
默认端口范围30000~32767
bash
[root@k8s-master service]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
42 - --service-node-port-range=30000-50000
[root@k8s-master service]# kubectl -n kube-system delete pods all
[root@k8s-master service]# vim webservice.yaml
nodePort: 44444
[root@k8s-master service]# kubectl apply -f webservice.yaml

3.loadbalancer
loadbalancer的yaml文件内容
bash
[root@k8s-master service]# cp webservice.yaml loadbalancer.yml
[root@k8s-master service]# vim loadbalancer.yml
apiVersion: v1
kind: Service
metadata:
labels:
app: webservice
name: webservice
spec:
ports:
- name: webport
port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: LoadBalancer #指定LoadBalancer模式
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: myapp:v1
name: myapp
[root@k8s-master service]# kubectl apply -f loadbalancer.yml
[root@k8s-master metaLLB]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
webservice LoadBalancer 10.102.221.3 <none> 80:43957/TCP 3m59s
构建metalLB
bash
[root@k8s-master service]# tar zxf metallb-v0.16.1.tar.gz
[root@k8s-master service]# cd metaLLB/
[root@k8s-master metaLLB]# ls
1-metallb-native.yaml 2-metallb-confmap.yml metallb-v0.16.1.tar
#镜像推入harbor仓库
[root@k8s-master metaLLB]# docker load -i metallb-v0.16.1.tar
[root@k8s-master metaLLB]# docker tag quay.io/metallb/controller:v0.16.1 reg.timinglee.org/metallb/controller:v0.16.1
[root@k8s-master metaLLB]# docker tag quay.io/metallb/speaker:v0.16.1 reg.timinglee.org/metallb/speaker:v0.16.1
[root@k8s-master metaLLB]# docker push reg.timinglee.org/metallb/controller:v0.16.1
[root@k8s-master metaLLB]# docker push reg.timinglee.org/metallb/speaker:v0.16.1
#更新proxy
[root@k8s-master mateLLB]# kubectl edit configmap -n kube-system kube-proxy
59 mode: "ipvs"
60 ipvs:
61 strictARP: true
[root@k8s-master metaLLB]# kubectl -n kube-system get pods |awk '/proxy/{system("kubectl -n kube-system delete pods "$1)}'
#修改配置文件的镜像位置
[root@k8s-master metaLLB]# vim 1-metallb-native.yaml
[root@k8s-master metaLLB]# grep image: 1-metallb-native.yaml
1-metallb-native.yaml: image: metallb/controller:v0.16.1
1-metallb-native.yaml: image: metallb/speaker:v0.16.1
#设定获取ip范围
[root@k8s-master metaLLB]# vim 2-metallb-confmap.yml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 172.25.254.50-172.25.254.99
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
验证
bash
[root@k8s-master metaLLB]# kubectl apply -f 1-metallb-native.yaml
#等待1的配置加载完成
[root@k8s-master metaLLB]# kubectl apply -f 2-metallb-confmap.yml
[root@k8s-master metaLLB]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
webservice LoadBalancer 10.102.221.3 172.25.254.50 80:43957/TCP 26m

4.extrnalname
bash
[root@k8s-master service]# kubectl create svc externalname externalname --external-name='www.timinglee.org' --dry-run=client -o yaml > externalname.yaml
[root@k8s-master service]# vim externalname.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: externalname
name: externalname
spec:
externalName: www.timinglee.org
selector:
app: externalname
type: ExternalName
[root@k8s-master service]# kubectl apply -f externalname.yaml
[root@k8s-master service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
externalname ExternalName <none> www.timinglee.org <none> 39s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d

四、ingress七层代理
1.ingress的部署
下载deploy文件
bash
[root@k8s-master service]# tar zxf ingress.1.15.1.tar.gz
[root@k8s-master service]# cd ingress-v1.15.1
[root@k8s-master ingress-v1.15.1]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/baremetal/deploy.yaml
准备ingress所需镜像
bash
[root@k8s-master ingress-v1.5.1]# docker load -i ingress-v1.15.1.tar
[root@k8s-master ingress-v1.5.1]# docker tag registry.k8s.io/ingress-nginx/controller:v1.15.1 reg.timinglee.org/ingress-nginx/controller:v1.15.1
[root@k8s-master ingress-v1.5.1]# docker push reg.timinglee.org/ingress-nginx/controller:v1.15.1
[root@k8s-master ~]# docker tag registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.9 reg.timinglee.org/ingress-nginx/kube-webhook-certgen:v1.6.9
[root@k8s-master ~]# docker push reg.timinglee.org/ingress-nginx/kube-webhook-certgen:v1.6.9
更改deploy.yaml
bash
[root@k8s-master ingress-v1.5.1]# vim deploy.yaml
444: image: ingress-nginx/controller:v1.15.1
547: image: ingress-nginx/kube-webhook-certgen:v1.6.9
603: image: ingress-nginx/kube-webhook-certgen:v1.6.9
365 type: LoadBalancer
[root@k8s-master ingress-v1.5.1]# kubectl apply -f deploy.yaml
[root@k8s-master ingress-v1.5.1]# kubectl get -n ingress-nginx svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.111.155.83 172.25.254.51 80:30805/TCP,443:32333/TCP 7d1h
ingress-nginx-controller-admission ClusterIP 10.101.96.196 <none> 443/TCP 7d1h

2.ingress功能的基本实现
pathtype:ImplementationSpecific(通配符匹配)| Exact(完全匹配)| Prefix(前缀匹配)
注意:ingress必须和输出的service资源处于同一namespace
建立ingress代理的微服务
bash
[root@k8s-master ingress-v1.5.1]# kubectl create deployment myappv1 --image myapp:v1 --replicas 2 --dry-run=client -o yaml > myappv1.yaml
[root@k8s-master ingress-v1.5.1]# kubectl create service clusterip servicev1 --tcp 80:80 --dry-run=client -o yaml >> myappv1.yaml
[root@k8s-master ingress-v1.5.1]# vim myappv1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myappv1
name: myappv1
spec:
replicas: 2
selector:
matchLabels:
app: myappv1
template:
metadata:
labels:
app: myappv1
spec:
containers:
- image: myapp:v1
name: myapp
---
apiVersion: v1
kind: Service
metadata:
labels:
app: servicev1
name: servicev1
spec:
ports:
- name: serviceportv1
port: 80
protocol: TCP
targetPort: 80
selector:
app: myappv1
type: ClusterIP
#同样方式建立myappv2
[root@k8s-master ingress-v1.5.1]# kubectl apply -f myappv1.yaml
[root@k8s-master ingress-v1.5.1]# kubectl apply -f myappv2.yaml


建立ingress
bash
[root@k8s-master ingress-v1.5.1]# kubectl create ingress ingress1 --class nginx --rule "*/=servicev1:80" --dry-run=client -o yaml > 1-ingress.yml
[root@k8s-master ingress-v1.5.1]# vim 1-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /v1
pathType: Prefix
- backend:
service:
name: servicev2
port:
number: 80
[root@k8s-master ingress-v1.5.1]# kubectl apply -f 1-ingress.yml
[root@k8s-master ingress-v1.5.1]# kubectl describe ingress ingress1

测试
bash
[root@k8s-master ingress-v1.5.1]# vim /etc/hosts
172.25.254.51 www.timinglee.org
[root@k8s-master ingress-v1.5.1]# curl www.timinglee.org/v1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ingress-v1.5.1]# curl www.timinglee.org/v2
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

3.基于域名的访问
bash
[root@k8s-master ingress-v1.5.1]# vim 2-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: 'myapp1.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /
pathType: Prefix
- host: 'myapp2.timinglee.org'
http:
paths:
- backend:
service:
name: servicev2
port:
number: 80
path: /
pathType: Prefix
[root@k8s-master ingress-v1.5.1]# kubectl apply -f 2-ingress.yml
测试
bash
[root@k8s-master ingress-v1.5.1]# vim /etc/hosts
172.25.254.51 www.timinglee.org myapp1.timinglee.org myapp2.timinglee.org
[root@k8s-master ingress-v1.5.1]# curl myapp1.timinglee.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ingress-v1.5.1]# curl myapp2.timinglee.org
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

4.基于动静分离的方式
bash
[root@k8s-master ingress-v1.5.1]# vim 3-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /index.html
spec:
ingressClassName: nginx
rules:
- host: www.timinglee.org
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /php
pathType: ImplementationSpecific
- backend:
service:
name: servicev2
port:
number: 80
path: /static
pathType: ImplementationSpecific

5.tls加密访问
bash
[root@k8s-master ingress-v1.5.1]# openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -subj "/CN=nginxsvc/O=nginxsvc" -out tls.crt
[root@k8s-master ingress-v1.5.1]# kubectl create secret tls web-tls-secret --key tls.key --cert tls.crt
[root@k8s-master ingress-v1.5.1]# vim 4-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
tls:
- hosts:
- www.timinglee.org
secretName: web-tls-secret
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /
pathType: Prefix

6.auth认证
生成认证文件并注入集群中
bash
[root@k8s-master ingress-v1.5.1]# dnf install httpd-tools -y
[root@k8s-master ingress-v1.5.1]# htpasswd -cm auth admin
#注入集群
[root@k8s-master ingress-v1.5.1]# kubectl create secret generic web-auth --from-file auth
在ingress中配置auth认证
bash
[root@k8s-master ingress-v1.5.1]# vim 5-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: web-auth
nginx.ingress.kubernetes.io/auth-realm: "Please input username and password"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /v1
pathType: Prefix

7.ingress中的网页重写
利用网页从写定义默认发布文
bash
[root@k8s-master ingress-v1.5.1]# vim 6-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /
pathType: Prefix
- backend:
service:
name: servicev2
port:
number: 80
path: /lee/(.*)
pathType: ImplementationSpecific
[root@k8s-master ingress-v1.5.1]# kubectl apply -f 6-ingress.yml

利用正侧表达式从定向网页
bash
[root@k8s-master ingress-v1.5.1]# vim 7-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /
pathType: Prefix
- backend:
service:
name: servicev2
port:
number: 80
path: /lee/(.*)
pathType: ImplementationSpecific

五、金丝雀发布(cannary)
金丝雀发布(Canary Release)也称为灰度发布,是一种软件发布策略。
主要目的是在将新版本的软件全面推广到生产环境之前,先在一小部分用户或服务器上进行测试和验证,以降低因新版本引入重大问题而对整个系统造成的影响。
是一种Pod的发布方式。金丝雀发布采取先添加、再删除的方式,保证Pod的总量不低于期望值。并且在更新部分Pod后,暂停更新,当确认新Pod版本运行正常后再进行其他版本的Pod的更新。
1.基于headr的灰度发布
bash
[root@k8s-master ingress-v1.5.1]# vim cannary-header.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /
pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress2
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "version"
nginx.ingress.kubernetes.io/canary-by-header-value: "2"
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev2
port:
number: 80
path: /
pathType: Prefix

2.基于权重的灰度发布
bash
[root@k8s-master ingress-v1.5.1]# vim cannary-weight.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress1
annotations:
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev1
port:
number: 80
path: /
pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress2
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "50"
nginx.ingress.kubernetes.io/canary-weight-total: "100"
spec:
ingressClassName: nginx
rules:
- host: 'www.timinglee.org'
http:
paths:
- backend:
service:
name: servicev2
port:
number: 80
path: /
pathType: Prefix
[root@k8s-master ingress-v1.5.1]# kubectl apply -f cannary-weight.yml
编写测试脚本
bash
[root@k8s-master ingress-v1.5.1]# vim check_cannary.sh
#!/bin/bash
v1=0
v2=0
for (( i=0; i<100; i++))
do
response=`curl -s www.timinglee.org |grep -c v1`
v1=`expr $v1 + $response`
v2=`expr $v2 + 1 - $response`
done
echo "v1:$v1, v2:$v2"
[root@k8s-master ingress-v1.5.1]# sh check_cannary.sh
v1:52, v2:48
