Kubernetes原生支持重建、滚动更新两种部署策略。通过修改Service的label,切换流量转发可以实现蓝绿部署、金丝雀部署。

部署前的准备

1、需要有一个k8s集群。没有可查看此博客 https://blog.csdn.net/u010606397/article/details/89817958

2、安装ingress控制器。下载mandatory.yaml、service-nodeport.yaml文件可能会被墙,请走代理。

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/mandatory.yaml
kubectl apply -f mandatory.yaml
kubectl get pod -n ingress-nginx

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/provider/baremetal/service-nodeport.yaml

vim service-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
      # 修改此处,绑定裸机端口为30080
      nodePort: 30080
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
      # 修改此处,绑定裸机端口30443
      nodePort: 30443
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

kubectl apply -f service-nodeport.yaml
kubectl get svc -n ingress-nginx

3、ingress的host不支持使用ip,修改集群master节点的/etc/hosts,将127.0.0.1映射给k8s01.com,使用其他域名也可以,不是非得用k8s01.com

vim /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 k8s01.com

重建部署策略

重建部署策略是先把旧的pod全部停掉,然后新建pod。由于部署期间出现服务中断,这种部署策略很少用。

新建yaml文件,写好Deployment、Service、Ingress配置。注意:master的hosts配置了127.0.0.1映射到k8s01.com,所以ingress的host值是k8s01.com。

vim 08-recreate.yaml

# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  strategy:
    # 使用重建部署策略
    type: Recreate
  selector:
    matchLabels:
      app: myapp
  replicas: 2
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: containers-myapp
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: 256Mi
            cpu: 500m
          limits:
            memory: 512Mi
            cpu: 1000m
        lifecycle:
          preStop:
            exec:
              command:
                - /bin/bash
                - '-c'
                - sleep 10            
        readinessProbe:
          httpGet:
            path: /index.html
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 1            
        livenessProbe:
          httpGet:
            path: /index.html
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 1

---
#Service
apiVersion: v1
kind: Service
metadata:
  name: service-myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  type: ClusterIP

---
# Ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-my
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    # host不支持IP,必须是域名
  - host: k8s01.com
    http:
      paths:
      - path: /
        backend:
          serviceName: service-myapp
          servicePort: 80

08-recreate.yaml有几个注意点

  strategy:
    # 使用重建部署策略
    type: Recreate

  rules:
    # host不支持IP,必须是域名。注意master节点的hosts配置了127.0.0.1映射到k8s01.com
  - host: k8s01.com

部署

kubectl apply -f 08-recreate.yaml

新开一个master节点的终端,执行如下命令,循环请求服务。

while true; do curl http://k8s01.com:30080/index.html; sleep 0.1; done

开始升级服务,将ikubernetes/myapp升级到v2版本,查看服务是否会间断。

vim 08-recreate.yaml

        image: ikubernetes/myapp:v2

升级v2版本

kubectl apply -f 08-recreate.yaml

使用重建部署策略服务会间断。

滚动更新部署

滚动更新部署策略使用新的实例逐步更新旧实例。要实现零间断更新,必须配置就绪探针readinessProbe、存活探针livenessProbe,结束容器前要休眠一小段时间。

使用08-recreate.yaml复制出08-rollingUpdate.yaml

mv 08-recreate.yaml 08-rollingUpdate.yaml

修改08-rollingUpdate.yaml的部署策略为滚动更新,并将image: ikubernetes/myapp版本改为1,只需要修改以下的红色部分即可:

spec:
  strategy:
    # 使用滚动更新策略
    type: RollingUpdate
    rollingUpdate:
      # 更新期间超过期望的Pod数量为1
      maxSurge: 1
      # 更新期间不可用pod数量为0,即更新期间所有pod都可用
      maxUnavailable: 0

  selector:
    matchLabels:
      app: myapp

image: ikubernetes/myapp:v1

使用滚动更新部署

kubectl apply -f 08-rollingUpdate.yaml

滚动更新的过程如下图

1、myapp-7dff599968-smcgd 启动完成,处于Running状态,但是还未接收流量。READY为0/1表示pod启动完成但还没接收流量。

2、myapp-7dff599968-smcgd开始接收流量,READY为1/1;旧的myapp-697df9594f-gsl8d被中止,状态为Terminating,且不接收流量,READY为0/1。

3、旧的myapp-697df9594f-gsl8d被删除。

蓝绿部署

kubernetes实现蓝绿部署的步骤如下:

1、Deployment和Service的yaml分开写在两个文件中;Pod的标签多加一个键值对version: v1,Deployment的名称带上版本号,selector多加一个键值对version: v1;Service的selector也加一个键值对version: v1。

2、部署Deployment和Service。

3、修改Pod的标签为version: v2,镜像也改成v2版本,修改Deployment的名称,selector改为version: v2。

4、部署修改好的Deployment文件,等待v2版本的pod启动完毕,此时v1、v2版本同时在运行,但只有v1版本接收流量。

5、测试v2版本是否可用,若可用,则修改Service的selector为version: v2,将流量转给v2版本的服务。

6、若系统运行正常,删除v1版本;若系统运行不正常,修改Service的selector,将流量切换回v1。

实战

1、编写Deployment的配置文件08-blue-greed-deploy.yaml,与滚动更新部署的不同之处在于name、selector、labels做了修改,如下面红色字体所示。

# deploy
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
spec:
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: myapp
      version: v1

  replicas: 2
  template:
    metadata:
      labels:
        app: myapp
        version: v1

    spec:
      containers:
      - name: containers-myapp
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: 256Mi
            cpu: 500m
          limits:
            memory: 512Mi
            cpu: 1000m
        lifecycle:
          preStop:
            exec:
              command:
                - /bin/bash
                - '-c'
                - sleep 10            
        readinessProbe:
          httpGet:
            path: /index.html
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 1            
        livenessProbe:
          httpGet:
            path: /index.html
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 1

Service和Ingress的配置文件写在08-blue-greed-svc-ingress.yaml中,与滚动更新的不同之处是Service的selector多了版本标识,后面可通过修改版本号实现流量切换。

#service
apiVersion: v1
kind: Service
metadata:
  name: service-myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
    version: v1

  type: ClusterIP

---
# ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-my
  annotations:
    # 控制器使用nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    # host不支持IP,必须是域名
  - host: k8s01.com
    http:
      paths:
      - path: /
        backend:
          serviceName: service-myapp
          servicePort: 80

2、执行部署

kubectl apply -f 08-blue-greed-deploy.yaml

kubectl apply -f 08-blue-greed-svc-ingress.yaml

3、修改Deployment的配置文件为v2版本,如下面红色字体所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v2
省略部分配置
  selector:
    matchLabels:
      app: myapp
      version: v2
省略部分配置
      labels:
        app: myapp
        version: v2
    spec:
      省略部分配置
        image: ikubernetes/myapp:v2

4、部署v2版本的Deployment。注意:只部署Deployment即可,Service暂时不切换流量。

kubectl apply -f 08-blue-greed-deploy.yaml

myapp-v1、myapp-v2同时在运行,但只有myapp-v1接收流量。

5、测试myapp-v2是否正常,若正常,则修改Service的selector,将流量转给myapp-v2,如下面红色字体所示

  selector:
    app: myapp
    version: v2

重新部署service

kubectl apply -f 08-blue-greed-svc-ingress.yaml

6、若新版本服务正常,删除myapp-v1;若系统运行不正常,修改Service的selector,将流量切换回v1。

删除myapp-v1

kubectl delete deployment myapp-v1

使用蓝绿部署,服务不会中断。

金丝雀部署

在蓝绿部署的基础上稍加修改,就可以实现金丝雀部署。例如,删除service的selector的版本标识,让流量同时转到v1、v2版本。

#service
apiVersion: v1
kind: Service
metadata:
  name: service-myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
    # version: v2  selector 删除版本
  type: ClusterIP

两个版本都接收流量

如果要控制v1、v2版本的比例,修改deployment部署的节点数即可。

 

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐