# nginx&&nginx-ingress实现灰度发布

#### 一、名词解释

灰度发布：又名金丝雀发布、黑白发布。18世纪时，由于科技落后，矿井没有好的通风条件和瓦斯检测工具，旷工在矿井作业时经常出现瓦斯中毒现象，因此，旷工们在下井时，会携带一只金丝雀，因为金丝雀在状态好的时候，非常喜欢叫唤，通过观察金丝雀的状态，确定矿井的毒气状态。

软件新版本发布后，我们先开放给一部分用户先体验和测试，等系统稳定运行一段时间足够稳定了再逐渐全量上线新版本，最后平滑下线旧版本。称之为灰度发布

- 基于用户体系的灰度发布，针对一些特定的人群，为其写入特定的header或者cookie。

[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/zBiPBA7e0TmRytrl-image-1723397136166.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/zBiPBA7e0TmRytrl-image-1723397136166.png)

- 根据流量规则，随机抽取部分人群参与灰度测试

[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/CV3zUFGu5PnxdXNi-image-1723397522783.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/CV3zUFGu5PnxdXNi-image-1723397522783.png)


#### 二、该选那个呢

**建议优选cookie,理由如下**
- 可以控制
- 基于header可能更便于c/s端，因为b/s无法直接设置header

#### 三、基于nginx-ingress的灰度发布

- **先创建2个nginx服务**

  - **服务1**
    
  [![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/rm86TlTRok8SurA3-image-1723398146445.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/rm86TlTRok8SurA3-image-1723398146445.png)

  - **服务2**
 
  [![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/G6Qa2FabGIvgIaAX-image-1723398277589.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/G6Qa2FabGIvgIaAX-image-1723398277589.png)

---
- **创建2个ingress**

[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/hOsCIFfvHOdzI3DF-image-1723398380598.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/hOsCIFfvHOdzI3DF-image-1723398380598.png)

不出意外的话，第二个会创建不成功，需要在第二个ingress加入nginx-ingress注释

```yaml
# 启用灰度发布
nginx.ingress.kubernetes.io/canary: "true"

# 启用基于header的灰度规则，并指定hearder包含指定键(version)，客户端传递该hearder键并将值指定为always(总是)或者never（永远不）
nginx.ingress.kubernetes.io/canary-by-header: "version"

# 指定基于hearder规则时，需要包含的值，不在局限于值为always(总是)或者never（永远不）
nginx.ingress.kubernetes.io/canary-by-header-value: "2.0"


# 启用基于cookie的灰度规则，并指定cookie包含指定键(version)，客户端传递该cookie键并将值指定为always(总是)或者never（永远不）
nginx.ingress.kubernetes.io/canary-by-cookie: "version"

# 网上有部分文章描述说有类似hearder规则的nginx.ingress.kubernetes.io/canary-by-cookie-value注解指定值，实际上没有这个注解

# 基于流量规则，值为0-100之间，既按百分比，0为不接受任何请求，其最大值（100）可以由canary-weight-total定义
nginx.ingress.kubernetes.io/canary-weight:10

# 基于流量规则时候的最大值，默认为100，该设置可以忽略
nginx.ingress.kubernetes.io/canary-weight-total

# 规则优先级
# canary-by-header -> canary-by-cookie -> canary-weight

# 官方帮助
# https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#canary

```
---
#### 三、测试一下基于header的方式的灰度发布

- 增加ingress注解
[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/YCu20Z4OrZ9ooq1L-image-1723399259547.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/YCu20Z4OrZ9ooq1L-image-1723399259547.png)



- postman没有传值,查看返回结果

[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/qGUmdONmIHKg59Dy-image-1723399351413.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/qGUmdONmIHKg59Dy-image-1723399351413.png)

- postmain传入设定的值，查看返回结果

[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/dAqQnAJBrJtE1uRL-image-1723399463761.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/dAqQnAJBrJtE1uRL-image-1723399463761.png)


#### 四、测试一下基于cookie的方式灰度发布

- 增加ingress注解

[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/fx9TCE44wsz1rSwy-image-1723400334398.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/fx9TCE44wsz1rSwy-image-1723400334398.png)

- 浏览器没有指定的对应的cookie,返回默认页面

  [![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/sXH6ymUU7goT2T1v-image-1723400634389.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/sXH6ymUU7goT2T1v-image-1723400634389.png)

- 浏览器写入设定的值，查看对应的返回页面

[![](https://iovhm.com/book/uploads/images/gallery/2024-08/scaled-1680-/IrH7XOOx3wk2hsve-image-1723400188394.png)](https://iovhm.com/book/uploads/images/gallery/2024-08/IrH7XOOx3wk2hsve-image-1723400188394.png)


#### 五、基于流量的规则
不推荐使用流量的规则，因为无法精确控制，因此不做测试

#### 六、直接使用nginx灰度发布功能
如果你没有条件使用nginx-ingress，可以直接使用nginx配置文件以支持灰度发布

- 基于权重的灰度发布

```conf

upstream backend_by_weight {  
    server v1.example.com weight=80;  
    server v2.example.com weight=20;  
}  
 
server {  
    listen 80;  
    location / {  
        proxy_pass http://backend_by_weight;  
    }  
}

```

- 基于cookie的灰度发布

```conf

map $http_cookie $backend_by_cooke {  
    default             v1.example.com;  
    "~*version=2"       v2.example.com;  
}  
 
server {  
    listen 80;  
    location / {  
        proxy_pass http://$backend_by_cooke;  
    }  
}

```
- 基于headerd灰度发布

```conf

map $http_version $backend_by_hearder {  
    default             v1.example.com;  
    "2"                 v2.example.com;  
}  
 
server {  
    listen 80;  
    location / {  
        proxy_pass http://$backend_by_hearder;  
    }  
}

  
 ```