应用背景:应用发布需要基于请求url子路径匹配,访问同域名根据url子路径匹配自动转发请求到灰度服务。
组件支持:需要对ingress-nginx-controller做二次开发改造,这里略过改造部分,重点关注测试流程。
测试步骤:准备两套环境,生产环境/测试环境,准备测试应用镜像,根据环境变量输出日志方便观察日志判断流量是被路由到哪个环境的服务,分别部署应用到生产和测试环境,编写测试脚本进行测试。接下来重点展示部署和测试脚本。
一、测试应用app.py
import os
import logging
from flask import Flask, jsonify, request
app = Flask(__name__)
# 日志配置
logging.basicConfig(
format='%(asctime)s [%(levelname)s] %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
# 获取环境变量来判断是生产还是灰度环境
ENVIRONMENT = os.getenv('ENVIRONMENT', 'production')
@app.route('/')
def main():
# 获取客户端真实IP
client_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
# 从环境变量获取配置
service_name = os.getenv('SERVICE_NAME', 'default')
version = os.getenv('VERSION', 'v1')
# 记录带IP的日志
logger.info(f"Client IP: {client_ip} | Service: {service_name}-{version}")
return jsonify({
"service": service_name,
"version": version,
"client_ip": client_ip.split(',')[0] # 处理多级代理情况
})
# 生产环境路由
@app.route('/v1/<path:path>')
def production(path):
# 获取客户端真实IP
client_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
# 从环境变量获取配置
service_name = os.getenv('SERVICE_NAME', 'default')
version = os.getenv('VERSION', 'v1')
# 记录带IP的日志
logger.info(f"Client IP: {client_ip} | Service: {service_name}-{version} | Environment: production")
return jsonify({
"service": service_name,
"version": version,
"client_ip": client_ip.split(',')[0], # 处理多级代理情况
"environment": "production"
})
# 灰度环境路由
@app.route('/v2/<path:path>')
def gray(path):
# 获取客户端真实IP
client_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
# 从环境变量获取配置
service_name = os.getenv('SERVICE_NAME', 'default')
version = os.getenv('VERSION', 'v1')
# 记录带IP的日志
logger.info(f"Client IP: {client_ip} | Service: {service_name}-{version} | Environment: gray")
return jsonify({
"service": service_name,
"version": version,
"client_ip": client_ip.split(',')[0], # 处理多级代理情况
"environment": "gray"
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)二、Dockerfile文件
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制项目文件到工作目录
COPY . .
# 安装依赖
RUN pip install -r requirements.txt
# 暴露端口
EXPOSE 5000
# 启动应用
CMD ["python", "app.py"]
三、requirements.txt
flask==2.0.3
werkzeug==2.0.3四、ingress配置
灰度ingress配置
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-by-cookie: aaa
nginx.ingress.kubernetes.io/canary-by-cookie-value: 'true'
creationTimestamp: '2025-03-04T02:27:50Z'
generation: 2
managedFields:
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubernetes.io/ingress.class: {}
f:nginx.ingress.kubernetes.io/canary: {}
manager: kubectl-client-side-apply
operation: Update
time: '2025-03-04T02:27:50Z'
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
f:nginx.ingress.kubernetes.io/canary-by-cookie: {}
f:nginx.ingress.kubernetes.io/canary-by-cookie-value: {}
f:spec:
f:rules: {}
manager: fabric8-kubernetes-client
operation: Update
time: '2025-03-04T03:14:46Z'
name: canary-ingress
namespace: python3-gray
resourceVersion: '11679371'
uid: 196ce65e-8da3-4d9f-a084-08ff30d7ff8f
spec:
rules:
- host: canary.test3.com
http:
paths:
- backend:
serviceName: canary-svc
servicePort: 80
path: /
pathType: ImplementationSpecific
生产ingress配置
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: 'false'
creationTimestamp: '2025-03-04T02:11:00Z'
generation: 3
labels:
clusterId: 0f72be07aba84651940445f4573b99e2
creator: xlf-ops
managedFields:
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
f:kubernetes.io/ingress.class: {}
f:nginx.ingress.kubernetes.io/canary: {}
manager: kubectl-client-side-apply
operation: Update
time: '2025-03-04T02:27:50Z'
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations: {}
f:labels:
.: {}
f:clusterId: {}
f:creator: {}
f:spec:
f:rules: {}
manager: fabric8-kubernetes-client
operation: Update
time: '2025-03-04T02:51:58Z'
name: main-ingress
namespace: python3
resourceVersion: '11674145'
uid: 141d1304-c3ea-4793-ac17-9b936cfb32eb
spec:
rules:
- host: canary.test3.com
http:
paths:
- backend:
serviceName: prod-svc
servicePort: 80
path: /
pathType: ImplementationSpecific
五、测试结果
由下图可以看到,可以根据url子路劲进行灰度路由

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。