外部nginx对接k8s中traefik ingress用于全链路灰度环境

背景介绍:
随着容器化技术逐渐成熟,很多公司都希望把公司的业务迁移到容器平台上,容器编排首选的还是k8s。今天介绍的就是如何把以前的平台通过灰度的方式逐渐把整个环境过渡到k8s平台中。
下面记录了我在一次生产过程中的整体迁移过程,供大家参考互相学习。
现有环境部署情况:
外部nginx对接k8s中traefik ingress用于全链路灰度环境
大概的结果就和图片上差不多。
容器环境部署的时候,把所有应用都进行容器化打包。这里多少会涉及到一些开发的改造,比如配置文件、原有程序是否支持多实例部署等。配置文件我们使用了apollo作为配置中心,程序也做了部分改造。至于基础组件两个环境需要尽量解耦使用不同的基础组件,比如redis、zookeeper、mongodb等。大多数的都在相同机房进行,所以数据库我们两个环境是共用的。这样不管在那个环境下单都可以在另外一个环境中看到订单内容。如果是机房在本地,容器平台在云上也行,需要做一个云数据库和机房数据库的双向同步。虽然有一些数据延迟,但大多数情况下还是没任何问题的。
过渡思路,利用nginx的upstream分别配置现有环境和容器环境主机的比例
upstream zt-gateway-k8s
{
server old.example.com:9002 weight=5;
server old.example.com:9002 weight=4;
server k8s.example.com weight=1;
check interval=3000 rise=2 fall=2 timeout=1000 type=http;
check_http_send "GET /actuator/health HTTP/1.1\r\nhost:k8s.example.com\r\n\r\n";
check_http_expect_alive http_2xx;
}
这样就变成k8s环境10%的流量,90%流量还是在老的平台中。
然后观察k8s环境的相关业务是否正常,运行几天以后如果业务稳定。可以把k8s环境的流量增加如30%具体方法就是修改上面的weight数字然后重新加载nginx即可。
nginx upstream中的主机weight数字说明:
对应的server的weight除以所有server配置的weigth数量相加是当前主机的流量比例。
server old.example.com:9002 weight=5; 比例 50%
server old.example.com:9002 weight=4; 比例40%
server k8s.example.com weight=1; 比例10%
如果要切换成1%到k8s环境可以配置成
server old.example.com:9002 weight=50; 比例50%
server old.example.com:9002 weight=49; 比例49%
server k8s.example.com weight=1; 比例 1%

由于k8s是使用的traefik ingress的方式暴露服务,而之前的老环境是直接部署。所以k8s环境中需要传入域名才能正常通过nginx健康检查。
check_http_send "GET /actuator/health HTTP/1.1\r\nhost:k8s.example.com\r\n\r\n"; 配置的关键就在这里。
之前一直调试了很久都无法成功,如果大家遇到相同的问题可以利用curl命令
curl -I -X GET -H host:k8s.example.com k8s.example.com/actuator/health -vv

  • About to connect() to 192.168.9.178 port 80 (#0)
  • Trying 192.168.9.178...
  • Connected to 192.168.9.178 (192.168.9.178) port 80 (#0)

    GET /actuator/health HTTP/1.1
    User-Agent: curl/7.29.0
    Accept: /
    host:k8s.example.com

    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    < Content-Length: 15
    Content-Length: 15
    < Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
    Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
    < Date: Thu, 28 May 2020 03:32:29 GMT
    Date: Thu, 28 May 2020 03:32:29 GMT
    < Server:
    Server:

    < Vary: Accept-Encoding
    Vary: Accept-Encoding
    < X-Envoy-Decorator-Operation: bst-gateway.platform.svc.cluster.local:8080/
    X-Envoy-Decorator-Operation: bst-gateway.platform.svc.cluster.local:8080/

    < X-Envoy-Upstream-Healthchecked-Cluster: bst-gateway.platform
    X-Envoy-Upstream-Healthchecked-Cluster: bst-gateway.platform
    < X-Envoy-Upstream-Service-Time: 1
    X-Envoy-Upstream-Service-Time: 1
    <
    * Excess found in a non pipelined read: excess = 15 url = /actuator/health (zero-length body)
    * Connection #0 to host 192.168.9.178 left intact

大于符号是发送到主机的内容,下面的小于符号开始是主机返回的内容。
可以根据自己的情况调整check_http_send "GET /actuator/health HTTP/1.1\r\nhost:k8s.example.com\r\n\r\n";的内容。等到所有100%的流量全部切到容器平台以后,之前的老平台也就可以成功下线删除,释放主机资源。然后把这些资源加入到容器平台中。
nginx server段的配置:

location /gateway/comment {
        add_header Access-Control-Allow-Origin *;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        #proxy_set_header Host $http_host;
        proxy_set_header Host k8s.example.com;  #这个地方要配置成上面健康检查里面的host域名。
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_pass http://zt-gateway-k8s;
    }

这里的host域名配置如何和外网访问相同,可以设置成 $http_host。如果不同,比如用户访问时的域名是gateway.tz.com。而k8s的ingress上配置的域名是k8s.example.com,那就必须配置。否则请求是不会到达k8s上的。
经过这样操作大家就不用纠集这整个公司的人力物力停服通宵加班来切换了。而且涉及的人员越多变数越多,失败的概率越大。希望这次经验分享对大家有帮助。

猜你喜欢

转载自blog.51cto.com/denwork/2499217