k8s学习--基于Ingress-nginx实现灰度发布系统

本文涉及的产品
.cn 域名,1个 12个月
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: k8s学习--基于Ingress-nginx实现灰度发布系统

@TOC


前言

首先在案例之前,先认识一下被业界广泛采用的服务发布有哪些,也是我们之后要实现的东西什么

发布策略

在现代软件开发和运维中,服务发布策略至关重要,以确保新版本能够顺利上线并最小化风险。以下是几种被业界广泛采用的服务发布策略:

  1. 蓝绿发布(Blue-Green Deployment)
    概念:
    蓝绿发布是一种减少停机时间和风险的部署策略。它通过维护两套几乎完全相同的生产环境——蓝色环境和绿色环境——来实现平滑的版本切换。
    流程:
    蓝色环境:当前活跃的生产环境,正在处理实际的用户流量。
    绿色环境:待更新的新版本被部署到绿色环境中。
    切换流量:一旦新版本在绿色环境中通过所有测试,流量从蓝色环境切换到绿色环境。
    回滚:如果新版本出现问题,可以迅速切换回蓝色环境。
    优点:
    无缝切换,最小化停机时间。
    容易回滚,风险较低。
    缺点:
    需要两套生产环境,成本较高。
    资源利用率可能不高。

  2. A/B 测试(A/B Testing)
    概念:
    A/B 测试是通过将用户流量分成两组或多组,分别体验不同版本的应用,从而比较其效果和性能差异的一种发布策略。
    流程:
    版本划分:创建版本A(现有版本)和版本B(新版本)。
    流量分配:随机将用户流量划分到A/B两个版本中。
    数据收集:收集用户在不同版本下的行为数据。
    分析结果:分析数据确定哪个版本表现更好。
    优点:
    可以在真实环境中验证新功能的效果。
    数据驱动决策,精确了解用户偏好。
    缺点:
    需要数据分析能力强,才能有效评估结果。
    对用户体验可能产生不一致的影响。

  3. 金丝雀发布(Canary Release)
    概念:
    金丝雀发布是一种逐步发布策略,通过向一小部分用户发布新版本,观察其表现并逐步扩大覆盖面,以确保新版本的稳定性和可靠性。
    流程:
    小规模发布:将新版本发布给少量用户(通常是内部用户或早期测试用户)。
    监控和评估:密切监控新版本的性能和用户反馈。
    扩大发布范围:如果新版本表现良好,逐步增加覆盖用户直到全量发布。
    优点:
    风险较小,可以早期发现问题。
    逐步发布,问题排查和修复较为容易。
    缺点:
    发布和监控过程较为复杂,需要持续观察。
    需要良好的监控和反馈机制。

应用

环境

虚拟机

Ip 主机名 cpu 内存 硬盘
192.168.10.11 master01 2cpu双核 4G 100G
192.168.10.12 worker01 2cpu双核 4G 100G
192.168.10.13 worker02 2cpu双核 4G 100G

版本 centos7.9
已部署k8s-1.27

通过ingress-nginx实现灰度发布系统

一、负载均衡器metallb部署

1. 修改kube-proxy代理模式

kubectl edit configmap kube-proxy -n kube-syste

更改两处
strictARP 后的flase改为true
node 后添加ipvs
没看见往下翻

在这里插入图片描述

重启

kubectl rollout restart daemonset kube-proxy -n kube-system

2. metallb部署

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml

服务器连接不了时,可在vpn连接后,浏览器中访问https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
看到内容后复制创建文件

也可以使用离线下载后的文件部署

kubectl apply -f metallb-native.yaml

查看

kubectl -n metallb-system get pod

等待一会,可通过查看描述信息跟踪pod的运行状态,长时间无法完成下载时,各节点重启docker

kubectl -n metallb-system describe pod controller-6b9fd67ff4-rzvg2

3. IP地址池准备

vim ippool.yaml

addresses下是范围

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ippool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.10.240-192.168.10.250

yaml应用

kubectl apply -f ippool.yaml

若出现故障提示,等上面pod全部运行起来再部署
还不行,各节点重启docker

查看地址池信息

kubectl -n metallb-system describe ipaddresspools.metallb.io ippool

在这里插入图片描述

4.开启二层通告

vim L2.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb-system

应用yaml

kubectl apply -f L2.yaml

二、 服务代理ingress nginx部署

(1)获取ingress nginx部署文件
创建目录

mkdir tsdir
cd tsdir

windows浏览器打开文件:

https://github.com/kubernetes/ingress-nginx/blob/main/deploy/static/provider/baremetal/deploy.yaml

复制文件内容到linux中deploy.yaml文件

vim deploy.yaml

(2)修改部署文件deploy.yaml

vim deploy.yaml

修改此行 type: NodePort
为 type: LoadBalancer

修改前
在这里插入图片描述
修改后
在这里插入图片描述

(3)部署ingress nginx

kubectl apply -f deploy.yaml

稍等几分钟后查看 需要vpn,没有的话查看信息时会显示连接不到镜像仓库

kubectl -n ingress-nginx get pod

可以看到已经成功运行了
在这里插入图片描述
修改configmap

kubectl get configmaps ingress-nginx-controller -n ingress-nginx

在这里插入图片描述

kubectl edit configmaps ingress-nginx-controller -n ingress-nginx

将false改为true
修改前
在这里插入图片描述
修改后
在这里插入图片描述

重启ingress-nginx应用:

kubectl rollout restart deployment ingress-nginx-controller -n ingress-nginx

在这里插入图片描述

三、应用服务部署

1.v1版本部署

vim 01-deploy-nginx-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v1
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: "openresty/openresty:centos"
        ports:
        - name: http
          protocol: TCP
          containerPort: 80
        volumeMounts:
        - mountPath: /usr/local/openresty/nginx/conf/nginx.conf
          name: config
          subPath: nginx.conf
      volumes:
      - name: config
        configMap:
          name: nginx-v1

---

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: nginx
    version: v1
  name: nginx-v1
data:
  nginx.conf: |-
    worker_processes  1;

    events {
        accept_mutex on;
        multi_accept on;
        use epoll;
        worker_connections  1024;
    }

    http {
        ignore_invalid_headers off;
        server {
            listen 80;
            location / {
                access_by_lua '
                    local header_str = ngx.say("nginx-v1")
                ';
            }
        }
    }

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-v1
spec:
  type: ClusterIP
  ports:
  - port: 80
    protocol: TCP
    name: http
  selector:
    app: nginx
    version: v1

部署yaml并查看

kubectl apply -f 01-deploy-nginx-v1.yaml 
kubectl get pod

在这里插入图片描述
查看service

kubectl get svc

在这里插入图片描述
看看能不能访问到

curl 10.109.30.198

在这里插入图片描述

2.v2版本部署

vim 02-deploy-nginx-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v2
  template:
    metadata:
      labels:
        app: nginx
        version: v2
    spec:
      containers:
      - name: nginx
        image: "openresty/openresty:centos"
        ports:
        - name: http
          protocol: TCP
          containerPort: 80
        volumeMounts:
        - mountPath: /usr/local/openresty/nginx/conf/nginx.conf
          name: config
          subPath: nginx.conf
      volumes:
      - name: config
        configMap:
          name: nginx-v2
---

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: nginx
    version: v2
  name: nginx-v2
data:
  nginx.conf: |-
    worker_processes  1;

    events {
        accept_mutex on;
        multi_accept on;
        use epoll;
        worker_connections  1024;
    }

    http {
        ignore_invalid_headers off;
        server {
            listen 80;
            location / {
                access_by_lua '
                    local header_str = ngx.say("nginx-v2")
                ';
            }
        }
    }

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-v2
spec:
  type: ClusterIP
  ports:
  - port: 80
    protocol: TCP
    name: http
  selector:
    app: nginx
    version: v2

应用yaml文件并查看

kubectl apply -f 02-deploy-nginx-v2.yaml 
kubectl get pods

在这里插入图片描述
查看service

kubectl get svc

在这里插入图片描述
测试

curl 10.105.171.163

在这里插入图片描述

3.创建stable版本ingress资源对象(对外发布)

vim 03-stable-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-v1                    #自定义ingress名称
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - host: www.test.com                   # 自定义域名
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: nginx-v1    # 对应上面创建的service名称
            port:
              number: 80

应用ingress.yaml文件并查看

kubectl apply -f 03-stable-ingress.yaml
kubectl -n ingress-nginx get svc

在这里插入图片描述
在hosts添加域名解析

vim /etc/hosts

添加
192.168.10.240 www.test.com
在这里插入图片描述
测试

curl www.test.com

在这里插入图片描述
创建目录并进入

mkdir nginx && cd nginx

四、流量切分

1.基于服务权重的流量切分

效果就是百分之九十的流量访问v1
百分之十的流量访问v2

创建yaml文件

vim 04-canary-ingress-weight.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-v2                    #自定义ingress名称
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
  - host: www.test.com                   # 自定义域名
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: nginx-v2    # 对应上面创建的service名称
            port:
              number: 80

应用yaml文件

kubectl apply -f 04-canary-ingress-weight.yaml
kubectl get ingress

注:虽然这里显示的是192.168.10.13但实际上还是通过域名访问到192.168.10.240的
在这里插入图片描述
测试
简单的shell脚本应用,测试10次

for i in {1..10};do curl http://www.test.com;done

虽然设置的是百分之十的流量,但实际应用不一定是10个里只有一个访问v2

在这里插入图片描述

2.基于用户请求头Header的流量切分

效果就是来自shenzhen的用户访问v2
其他访问v1

为了不影响,先删除上个yaml文件生成的应用,然后创建新的yaml文件

kubectl delete -f 04-canary-ingress-weight.yaml
vim 05-canary-ingress-header.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-v2                    #自定义ingress名称
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Region"
    nginx.ingress.kubernetes.io/canary-by-header-pattern: "shenzhen"
spec:
  ingressClassName: nginx
  rules:
  - host: www.test.com                   # 自定义域名
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: nginx-v2    # 对应上面创建的service名称
            port:
              number: 80

应用新的yaml文件并查看

kubectl apply -f 05-canary-ingress-header.yaml 
kubectl get ingress

在这里插入图片描述
测试
-H 大概意思就是模拟请求头内容

curl www.test.com
curl -H "Region:beijing" www.test.com
curl -H "Region:shanghai" www.test.com
curl -H "Region:shenzhen" www.test.com

可以看到效果
在这里插入图片描述

3.基于Cookie的流量切分

使用 Cookie 则无法自定义 value,以模拟灰度shenzhen地域用户为例,仅将带有名为 user_from_shenzhen的 Cookie 的请求转发给当前 Canary Ingress

照旧

kubectl delete -f 05-canary-ingress-header.yaml 
vim 06-canary-ingress-cookie.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-v2                    #自定义ingress名称
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "user_from_shenzhen"
spec:
  ingressClassName: nginx
  rules:
  - host: www.test.com                   # 自定义域名
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: nginx-v2    # 对应上面创建的service名称
            port:
              number: 80

应用yaml文件并查看

kubectl apply -f 06-canary-ingress-cookie.yaml
kubectl get ingress

在这里插入图片描述
测试

curl --cookie "user_from_beijing" http://www.test.com
curl --cookie "user_from_shenzhen" http://www.test.com
curl --cookie "user_from_shenzhen=always" http://www.test.com

在这里插入图片描述

可查看当仅有 cookie user_from_shenzhen 为 always 的请求才由 v2 版本的服务响应。

至此 完成

总结

每种发布策略都有其特定的优缺点,选择合适的策略需要根据项目规模、团队能力和业务需求来综合考虑。蓝绿发布适合对稳定性要求极高的项目,A/B 测试适合需要数据驱动决策的功能优化,金丝雀发布则适合希望逐步发布、降低风险的场景。通过合理运用这些策略,可以有效提升发布过程的效率和质量。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
24天前
|
缓存 负载均衡 应用服务中间件
Nginx 学习
【10月更文挑战第17天】Nginx 是一款非常强大的工具,掌握它的使用和配置对于构建高性能、可靠的 Web 应用至关重要。随着技术的不断发展,Nginx 也在不断更新和完善,为我们提供更好的服务和支持。
|
1月前
|
存储 Kubernetes 持续交付
k8s学习
【10月更文挑战第1天】
82 4
|
10天前
|
应用服务中间件 网络安全 PHP
八个免费开源 Nginx 管理系统,轻松管理 Nginx 站点配置
Nginx 是一个高效的 HTTP 服务器和反向代理,擅长处理静态资源、负载均衡和网关代理等任务。其配置主要通过 `nginx.conf` 文件完成,但复杂设置可能导致错误。本文介绍了几个开源的 Nginx 可视化配置系统,如 Nginx UI、VeryNginx、OpenPanel、Ajenti、Schenkd nginx-ui、EasyEngine、CapRover 和 NGINX Agent,帮助简化和安全地管理 Nginx 实例。
|
1月前
|
负载均衡 应用服务中间件 Linux
nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件,很全
这篇博客文章详细介绍了Nginx的下载、安装、配置以及使用,包括正向代理、反向代理、负载均衡、动静分离等高级功能,并通过具体实例讲解了如何进行配置。
145 4
nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件,很全
|
1月前
|
Kubernetes 应用服务中间件 nginx
k8s学习--YAML资源清单文件托管服务nginx
k8s学习--YAML资源清单文件托管服务nginx
k8s学习--YAML资源清单文件托管服务nginx
|
1月前
|
缓存 负载均衡 算法
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
Nginx 是一款高性能的 HTTP 和反向代理服务器,也是一个通用的 TCP/UDP 代理服务器,以及一个邮件代理服务器和通用的 HTTP 缓存服务器。
66 0
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
|
1月前
|
存储 Kubernetes 调度
|
1月前
|
Kubernetes API 调度
k8s学习--pod的所有状态详解(图例展示)
k8s学习--pod的所有状态详解(图例展示)
136 1
|
1月前
|
Kubernetes 固态存储 调度
k8s学习--如何控制pod调度的位置
k8s学习--如何控制pod调度的位置
|
1月前
|
存储 Kubernetes 调度
k8s学习--k8s群集部署zookeeper应用及详细解释
k8s学习--k8s群集部署zookeeper应用及详细解释