Istio 结合 Flagger 进行灰度发布

灰度发布也叫金丝雀部署 ,是指通过控制流量的比例,实现新老版本的逐步替换。比如对于服务 A 有两个版本(蓝和绿两个版本),当前两个版本同时部署,但是 version1 比例 90% ,version2 比例 10% ,然后我们可以观察 version2 的实际运行效果,如果符合预期,则可以逐步调整流量占比,比如调整为 80:20 -> 70:30 -> 10:90 -> 0:100 ,最终 version1 版本下线,全部替换成 version2 版本。如果验证失败,切换 100%流量回 v1 版本(回滚)。灰度发布的特点是:

flagger

在 Istio 中要实现灰度发布有多种方案,比如 Flagger、Argo Rollouts 等。

Flagger

Flagger 是一个渐进式交付的 Kubernetes Operator,它可以自动执行 Kubernetes 上运行的应用程序的发布过程。它通过在测量指标和运行一致性测试的同时逐渐将流量转移到新版本,降低了在生产中引入新软件版本的风险。

Flagger 通过使用服务网格(App Mesh、Istio、Linkerd、Kuma、Open Service Mesh)或 Ingress 控制器(Contour、Gloo、NGINX、Skipper、 Traefik、APISIX)用于流量路由。对于发布分析,Flagger 可以查询 Prometheus、InfluxDB、Datadog、New Relic、CloudWatch、Stackdriver 或 Graphite,并使用 Slack、MS Teams、Discord 和 Rocket 来发出警报。

Flagger

Flagger 可以使用 Kubernetes CRD 进行配置,并且与任何为 Kubernetes 制作的 CI/CD 解决方案兼容。由于 Flagger 是声明性的对 Kubernetes 事件做出反应,因此它可以与诸如此类的工具一起在 GitOps 管道中使用。

安装 Flagger

要使用 Flagger,需要先选择一个受支持的路由提供商(比如我们这里使用 Istio),然后使用 Helm 或 Kustomize 安装 Flagger。

Flagger 需要 Kubernetes 集群 v1.16 或更高版本以及 Istio v1.5 或更高版本。

首先当然需要安装 Istio,并开启 Prometheus 插件:

# demo 或者 default 都可以
istioctl manifest install --set profile=demo -y

# istio 根目录
kubectl apply -f samples/addons/prometheus.yaml

然后在 istio-system 命名空间安装 Flagger:

$ git clone https://github.com/fluxcd/flagger && cd flagger
$ kubectl apply -k kustomize/istio
$ kubectl get pods -n istio-system -l app=flagger
NAME                      READY   STATUS    RESTARTS   AGE
flagger-ff76bfdff-kkcmz   1/1     Running   0          17m

测试应用

下面我们创建一个名为 test 的命名空间,并为其启用 Istio sidecar 自动注入:

kubectl create ns test
kubectl label namespace test istio-injectinotallow=enabled

接下来我们使用 flagger 官方提供的 podinfo 应用来进行测试:

kubectl apply -k kustomize/podinfo

该命令会为 podinfo 应用创建对应的 Deployment 和一个 HPA 对象。

$ kubectl get deployment -n test
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
podinfo   2/2     2            0           96s
$ kubectl get hpa -n test
NAME      REFERENCE            TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
podinfo   Deployment/podinfo   <unknown>/99%   2         4         2          60s

部署后,我们可以看到 podinfo 应用的容器数量已经变成了 2 个(自动注入了 istio sidecar),而且 HPA 也已经生效。

```bash
$ kubectl get pods -n test
NAME                                  READY   STATUS            RESTARTS   AGE
podinfo-584c4546df-fzw4d              0/2     PodInitializing   0          5m26s
podinfo-584c4546df-n28cf              0/2     PodInitializing   0          5m11s

接着我们再部署一个负载测试服务用于在金丝雀分析期间生成流量:

kubectl apply -k kustomize/tester

创建金丝雀

接下来我们就可以创建一个 Canary 自定义资源来实现我们的金丝雀发布了。Canary 对象是 Flagger 的核心,它描述了金丝雀发布的目标。如下所示,我们为 podinfo 应用创建一个 Canary 对象:

# podinfo-canary.yaml
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: podinfo
  namespace: test
spec:
  targetRef: # deployment 引用
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  progressDeadlineSeconds: 60 # 金丝雀部署升级最大处理时间(以秒为单位)(默认600秒)
  autoscalerRef: # HPA 引用(可选)
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    name: podinfo
  service:
    port: 9898
    targetPort: 9898
    gateways: # Istio 网关(可选)
      - istio-system/public-gateway
    hosts: # VirtualService 主机名 (optional)
      - podinfo.k8s.local
    trafficPolicy: # Istio 流量策略(可选)
      tls:
        # use ISTIO_MUTUAL when mTLS is enabled
        mode: DISABLE
    retries: # Istio 重试策略(可选)
      attempts: 3
      perTryTimeout: 1s
      retryOn: "gateway-error,connect-failure,refused-stream"
  analysis: # 金丝雀分析
    interval: 1m # 金丝雀分析间隔时间(默认 60s)
    threshold: 5 # 金丝雀分析失败阈值(默认 5)
    maxWeight: 50 # 金丝雀最大流量权重(默认 50)
    stepWeight: 10 # 金丝雀流量权重步长(默认 10)
    metrics:
      - name: request-success-rate
        # minimum req success rate (non 5xx responses)
        # percentage (0-100)
        thresholdRange:
          min: 99
        interval: 1m
      - name: request-duration
        # maximum req duration P99
        # milliseconds
        thresholdRange:
          max: 500
        interval: 30s
    # testing (optional)
    webhooks:
      - name: acceptance-test
        type: pre-rollout
        url: http://flagger-loadtester.test/
        timeout: 30s
        metadata:
          type: bash
          cmd: "curl -sd 'test' http://podinfo-canary:9898/token | grep token"
      - name: load-test
        url: http://flagger-loadtester.test/
        timeout: 5s
        metadata:
          # 使用 hey 工具对 podinfo-canary 进行为期1分钟的负载测试,每秒发送10个请求,且测试过程中会维持2个并发连接。
          cmd: "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"

上面的配置文件中,我们定义了 podinfo 应用的金丝雀发布策略,其中 targetRef 指定了要进行金丝雀发布的 Deployment 对象,service 指定了金丝雀发布的服务,analysis 指定了金丝雀分析策略,这里我们指定了两个内置的指标检查:request-success-rate 和 request-duration,其中 request-success-rate 指定了 HTTP 请求成功率,request-duration 指定了请求持续时间。对于每个指标,你可以使用 thresholdRange 和窗口大小或时间序列指定可接受的值范围和时间间隔。内置检查适用于每个服务网格/Ingress 控制器,并通过 Prometheus 查询实现。

在 service 中我们指定了 Istio 的 Gateway(istio-system/public-gateway)以及 VirtualService 要使用的主机名,首先我们可以为该应用创建一个 Gateway 对象:

# public-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: public-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "*"

另外我们在上面的对象中通过 webhooks 字段指定了金丝雀分析期间要执行的测试,其中 acceptance-test 用于在金丝雀分析开始之前执行,load-test 用于在金丝雀分析期间执行。

金丝雀部署

接下来我们可以直接创建 Canary 对象了:

kubectl apply -f podinfo-canary.yaml

当创建了 Canary 对象后,Flagger 会自动创建一个名为 pod-info-primary 的 Deployment 以及两个版本的 Service 对象:

$ kubectl get deploy -n test
NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
flagger-loadtester   1/1     1            1           42m
podinfo              0/0     0            0           46m
podinfo-primary      2/2     2            2           7m3s
$ kubectl get svc -ntest
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
flagger-loadtester   ClusterIP   10.106.172.190   <none>        80/TCP     35m
podinfo-canary       ClusterIP   10.101.184.213   <none>        9898/TCP   39s
podinfo-primary      ClusterIP   10.110.105.36    <none>        9898/TCP   39s

可以看到我们原本的 podinfo 应用已经从 podinfo 这个 Deployment 迁移到了 podinfo-primary 这个 Deployment 之上。

此外还有 Istio 相关的对象:

$ kubectl get vs -ntest
NAME      GATEWAYS                          HOSTS                             AGE
podinfo   ["istio-system/public-gateway"]   ["podinfo.k8s.local","podinfo"]   91s
$ kubectl get dr -ntest
NAME              HOST              AGE
podinfo-canary    podinfo-canary    95s
podinfo-primary   podinfo-primary   95s

我们可以查看下自动生成的 VirtualService 对象:

$ kubectl get vs -ntest podinfo -oyaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: podinfo
  namespace: test
spec:
  gateways:
  - istio-system/public-gateway
  hosts:
  - podinfo.k8s.local
  - podinfo
  http:
  - retries:
      attempts: 3
      perTryTimeout: 1s
      retryOn: gateway-error,connect-failure,refused-stream
    route:
    - destination:
        host: podinfo-primary
      weight: 100
    - destination:
        host: podinfo-canary
      weight: 0

从上面的配置中我们可以看到当前 podinfo 应用的流量全部被路由到了 podinfo-primary 对象上,而 podinfo-canary 对象的流量权重为 0,当然同样可以查看 DestinationRule 对象:

$ kubectl get dr podinfo-primary -ntest -oyaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: podinfo-primary
  namespace: test
spec:
  host: podinfo-primary
  trafficPolicy:
    tls:
      mode: DISABLE
$ kubectl get dr podinfo-canary -ntest -oyaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: podinfo-canary
  namespace: test
spec:
  host: podinfo-canary
  trafficPolicy:
    tls:
      mode: DISABLE

所以默认情况下现在我们访问到的就是 podinfo-primary 这个 Deployment 对象,也就是目前的默认版本。我们可以在浏览器中访问 podinfo 来查看当前的版本:

podinfo

自动金丝雀发布

我们可以看到现在的版本是 podinfo v6.0.0,接下来我们来升级应用触发金丝雀发布。要触发金丝雀发布,可以由以下任何对象的更改来触发:

  • Deployment PodSpec(容器镜像、命令、端口、环境变量、资源等)
  • 作为卷挂载或映射到环境变量的 ConfigMaps
  • 作为卷挂载或映射到环境变量的 Secrets

比如我们可以直接修改 Deployment 对象的镜像版本来触发自动化的金丝雀发布:

kubectl -n test set image deployment/podinfo podinfod=ghcr.io/stefanprodan/podinfo:6.0.1

Flagger 检测到 Deployment 更改后就会开始新的部署:

$ kubectl describe canaries podinfo -ntest
# ......
Events:
  Type     Reason  Age                From     Message
  ----     ------  ----               ----     -------
  Warning  Synced  15m                flagger  podinfo-primary.test not ready: waiting for rollout to finish: observed deployment generation less than desired generation
  Normal   Synced  14m (x2 over 15m)  flagger  all the metrics providers are available!
  Normal   Synced  14m                flagger  Initialization done! podinfo.test
  Normal   Synced  56s                flagger  New revision detected! Scaling up podinfo.test

需要注意在金丝雀分析期间对 Deployment 应用新的更改,Flagger 将重新启动分析。第一步是先会去扩容 podinfo 应用:

$ kubectl get pods -ntest
NAME                                  READY   STATUS    RESTARTS   AGE
flagger-loadtester-78dd9787d4-dq5fc   2/2     Running   0          67m
podinfo-5d5dbc4d84-f2mp6              2/2     Running   0          31s
podinfo-5d5dbc4d84-gd8ln              2/2     Running   0          31s
podinfo-primary-64f865cf4-bhr79       2/2     Running   0          3m31s
podinfo-primary-64f865cf4-tgsdj       2/2     Running   0          3m31s

然后就会根据我们在 Canary 对象中定义的金丝雀分析策略来进行分析,并一步步将金丝雀版本的权重提高。

Warning Synced 4m4s flagger podinfo-primary.test not ready: waiting for rollout to finish: observed deployment generation less than desired generation
Normal Synced 3m4s (x2 over 4m4s) flagger all the metrics providers are available!
Normal Synced 3m4s flagger Initialization done! podinfo.test
Normal Synced 64s flagger New revision detected! Scaling up podinfo.test
Normal Synced 4s flagger Starting canary analysis for podinfo.test
Normal Synced 4s flagger Pre-rollout check acceptance-test passed
Normal Synced 4s flagger Advance podinfo.test canary weight 10

最后会自动将流量全部切换到金丝雀版本上。

金丝雀版本

整个过程就是通过控制 VirtualService 的权重来实现的金丝雀发布。

自动回滚

在金丝雀分析期间,我们可以生成 HTTP 500 错误和高延迟来测试 Flagger 是否暂停发布。

比如我们触发另一个金丝雀发布:

kubectl -n test set image deployment/podinfo podinfod=ghcr.io/stefanprodan/podinfo:6.0.2

然后进入 loadtester 容器:

kubectl -n test exec -it flagger-loadtester-xx-xx sh

使用下面的命令来生成 HTTP 500 错误:

watch curl http://podinfo-canary:9898/status/500

也可以添加延迟:

watch curl http://podinfo-canary:9898/delay/1

当失败检查的次数达到金丝雀分析配置的阈值时,流量将路由回主节点,金丝雀将缩放为零,并将部署标记为失败。

Normal   Synced  8m10s (x3 over 45m)  flagger  New revision detected! Scaling up podinfo.test
Normal   Synced  7m10s (x2 over 44m)  flagger  Pre-rollout check acceptance-test passed
Normal   Synced  7m10s (x2 over 44m)  flagger  Advance podinfo.test canary weight 10
Normal   Synced  7m10s (x2 over 44m)  flagger  Starting canary analysis for podinfo.test
Warning  Synced  6m10s                flagger  Halt podinfo.test advancement success rate 55.86% < 99%
Warning  Synced  5m10s                flagger  Halt podinfo.test advancement success rate 97.61% < 99%
Warning  Synced  4m10s                flagger  Halt podinfo.test advancement success rate 8.00% < 99%
Warning  Synced  3m10s                flagger  Halt podinfo.test advancement success rate 98.13% < 99%
Warning  Synced  2m10s                flagger  Halt podinfo.test advancement success rate 7.69% < 99%
Warning  Synced  70s (x2 over 14m)    flagger  Canary failed! Scaling down podinfo.test
Warning  Synced  70s                  flagger  Rolling back podinfo.test failed checks threshold reached 5

关于 Flagger 的更多使用请关注后续文章。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/298309.html<

赞 (0)
管理的头像管理
上一篇2025-05-22 21:18
下一篇 2025-05-22 21:20

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注