Flagger 在 Kubernetes 集群上是如何工作的?

2022-12-26 15:10:50 浏览数 (1)

通过前面一节的 Flagger基本学习,这节学习它的工作原理,以帮助加深理解应用!

Flagger 是如何工作的-工作原理?

可以通过一个名为 canary 的自定义资源来配置 Kubernetes 工作负载的自动化发布过程.

Canary resource

Canary 自定义资源定义了在 Kubernetes 上运行的应用程序的释放过程,并且可以across clusters, service meshes 和 ingress providers 进行移植.

对于名为 podinfo 的 deployment ,带有渐进式流量转移的 Canary 发布可以定义为:

代码语言:javascript复制
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: podinfo
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  service:
    port: 9898
  analysis:
    interval: 1m
    threshold: 10
    maxWeight: 50
    stepWeight: 5
    metrics:
      - name: request-success-rate
        thresholdRange:
          min: 99
        interval: 1m
      - name: request-duration
        thresholdRange:
          max: 500
        interval: 1m
    webhooks:
      - name: load-test
        url: http://flagger-loadtester.test/
        metadata:
          cmd: "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"

当 deployment 一个新版本的应用时,Flagger 会逐渐将流量转移到 Canary,同时测量请求成功率以及平均响应时间,可以通过自定义指标、验收和负载测试来扩展 Canary 的分析,以加强应用发布过程的验证过程

如果在同一个集群中运行多个服务网格或入口控制器,可以用 spec.provider 覆盖特定 canary 的全局提供者

Canary target

Canary 资源可以针对 Kubernetes Deployment 或 DaemonSet

Kubernetes Deployment 的例子:

代码语言:javascript复制
spec:
  progressDeadlineSeconds: 60
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  autoscalerRef:
    apiVersion: autoscaling/v2beta2
    kind: HorizontalPodAutoscaler
    name: podinfo

基于上述配置,Flagger 生成了以下 Kubernetes对象:

. deployment/<targetRef.name>-primary

. hpa/<autoscalerRef.name>-primary

primary deployment 被认为是应用程序的稳定版本,默认情况下,所有流量都被路由到这个版本,而 target deployment 被扩展为 0, Flagger 会检测到target deployment 的变化(包括secrets 和 configmaps),并在将新版本提升为 primary 版本之前进行 Canary 分析.

注意,target deployment 必须有一个单一的 label selector,格式为 app: <DEPLOYMENT-NAME>:

代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo

除了 app 之外,Flagger 还支持 name 和 app.kubernetes.io/name 选择器, 如果使用不同的约定,可以在 Flagger deployment 清单中容器 args 下的 -selector-labels=my-app-label 命令标志来指定标签,或者在用 Helm 安装 Flagger 时设置 --set selectorLabels=my-app-label

如果 target deployment 使用 secrets 或 configmaps,Flagger 将使用 -primary 后缀创建每个对象的副本并在 primary deployment 中引用这些对象,

如果用 flagger.app/config-tracking: disabled 来注释 ConfigMap 或 Secret,Flagger 将在 primary deployment 中使用相同的对象而不是制作 primary 副本,

可以在 Flagger deployment 清单中的 containers args 下使用 -enable-config-tracking=false 命令标志全局禁用 secrets/configmaps 跟踪,或者在用 Helm 安装 Flagger 时设置,

-set configTracking.enabled=false,但使用每个 Secret/ConfigMap 注释禁用 config-tracking 可能更符合使用情况

autoscaler 的引用是可选的,当指定时, Flagger 将暂停流量的增加,同时 target 和 primary deployment 被放大或缩小, HPA 可以帮助减少在 canary 分析过程中的资源使用,

当指定 autoscaler 参考时,对 autoscaler 的任何改变只有在 deployment 的 rollout 开始并成功完成时才会在 primary autoscaler 中被激活,

可以选择创建两个 HPA,一个用于 canary,一个用于 primary,以更新 HPA 而不做新的展开, 由于 Canary 的 deployment 将被缩减到 0,Canary 上的 HPA 将不活跃

注意: Flagger 需要 HPA 的 autoscaling/v2 或 autoscaling/v2beta2 API 版本

进度截止日期表示 Canary deployment 在回滚前取得进展的最大时间(秒),默认为 10 分钟。

Canary service

Canary 资源决定了 target 工作负载在集群内的暴露方式, Canary target 应该暴露一个 TCP 端口,该端口将被 Flagger 用来创建 ClusterIP 服务:

代码语言:javascript复制
spec:
  service:
    name: podinfo
    port: 9898
    portName: http
    appProtocol: http
    targetPort: 9898
    portDiscovery: true

来自 target 工作负载的容器端口应该与 service.port 或 service.targetPort 匹配, service.name 是可选的,默认为 spec.targetRef.name, service.targetPort 可以是一个容器端口号或名称service.portName 是可选的(默认为 http),如果工作负载使用 gRPC,则将端口名称设为 grpc, service.appProtocol 是可选的,更多细节可以在 这里 找到

如果启用了端口发现功能,Flagger 会扫描 target 工作负载并提取容器端口,但不包括 canary service 和 service mesh sidecar 端口中指定的端口, 这些端口将在生成 ClusterIP 服务时使用。

基于 canary 规格的服务,Flagger 创建以下 Kubernetes ClusterIP 服务:

. <service.name>.<namespace>.svc.cluster.local

代码语言:txt复制
selector app=<name>-primary

. <service.name>-primary.<namespace>.svc.cluster.local

代码语言:txt复制
selector app=<name>-primary

. <service.name>-canary.<namespace>.svc.cluster.local

代码语言:txt复制
selector app=<name>

这确保了到 podinfo.test:9898 的流量将被路由到应用程序的最新稳定版本, podinfo-canary.test:9898 地址只在 canary 分析期间可用,可用于一致性测试或负载测试

可以配置 Flagger 来为生成的服务设置annotations 和 labels:

代码语言:javascript复制
spec:
  service:
    port: 9898
    apex:
      annotations:
        test: "test"
      labels:
        test: "test"
    canary:
      annotations:
        test: "test"
      labels:
        test: "test"
    primary:
      annotations:
        test: "test"
      labels:
        test: "test"

请注意,apex 注解被添加到生成的 Kubernetes 服务和生成的 service mesh/ingress 对象, 这允许在 Istio VirtualService 和 TraefikServices 中使用外部 DNS,

要注意 这里 的配置冲突

除了端口映射和元数据,service specification 可以包含 URI 匹配和重写规则、超时和重试策略:

代码语言:javascript复制
spec:
  service:
    port: 9898
    match:
      - uri:
          prefix: /
    rewrite:
      uri: /
    retries:
      attempts: 3
      perTryTimeout: 1s
    timeout: 5s

当使用 Istio 作为网格提供者时,还可以指定 HTTP头操作、CORS 和流量策略、Istio 网关和 hosts, Istio 的路由配置可以在 这里 找到

Canary status

可以使用 kubectl 来获取集群范围内 canary deployment 的当前状态:

代码语言:javascript复制
kubectl get canaries --all-namespaces

状态条件反映了 Canary 分析的最后已知状态:

代码语言:javascript复制
kubectl -n test get canary/podinfo -oyaml | awk '/status/,0'

一个成功的 rollout 状态:

代码语言:javascript复制
status:
  canaryWeight: 0
  failedChecks: 0
  iterations: 0
  lastAppliedSpec: "14788816656920327485"
  lastPromotedSpec: "14788816656920327485"
  conditions:
  - lastTransitionTime: "2019-07-10T08:23:18Z"
    lastUpdateTime: "2019-07-10T08:23:18Z"
    message: Canary analysis completed successfully, promotion finished.
    reason: Succeeded
    status: "True"
    type: Promoted

促成状态条件可以有以下原因之一:Initialized(初始化)、Waiting(等待)、Progressing(进展)、WaitingPromotion(等待推广)、Promotion(推广)、Finalising(最终完成)、Succeeded(成功)或 Failed(失败),失败的 Canary 将把推广状态设置为 false,原因为 failed,最后应用的规格将与最后推广的规格不同

等待成功推广:

代码语言:javascript复制
kubectl wait canary/podinfo --for=condition=promoted

CI example:

代码语言:javascript复制
# update the container image
kubectl set image deployment/podinfo podinfod=stefanprodan/podinfo:3.0.1

# wait for Flagger to detect the change
ok=false
until ${ok}; do
    kubectl get canary/podinfo | grep 'Progressing' && ok=true || ok=false
    sleep 5
done

# wait for the canary analysis to finish
kubectl wait canary/podinfo --for=condition=promoted --timeout=5m

# check if the deployment was successful 
kubectl get canary/podinfo | grep Succeeded

Canary finalizers

Flagger 在 Canary 删除时的默认行为是让不属于控制器的资源保持其当前状态, 这简化了删除动作并避免了在资源最终确定时可能出现的死锁,

如果 Canary 与现有资源(即服务、虚拟服务等)一起被引入,它们将在初始化阶段被突变,不再反映其初始状态,

如果删除时希望的功能是将资源恢复到它们的初始状态,可以启用 revertOnDeletion 属性

代码语言:javascript复制
spec:
  revertOnDeletion: true

当一个删除动作被提交给集群时,Flagger 将尝试恢复以下资源:

. Canary target 副本将被更新为 primary 副本数量

. Canary service 选择器将被恢复

. Mesh/Ingress 流量被路由到 target 上

禁用 Canary 分析的推荐方法是利用 skipAnalysis 属性,它限制了对资源调节的需求, 当不打算再依赖 Flagger进行 deployment 管理时,应启用 revertOnDeletion 属性

注意: 当这个特性被启用时,由于调节的原因,删除动作会有延迟

Canary analysis

Canary 分析定义了:

. Deployment 策略的类型

. 用来验证 Canary 版本的指标

. 用于一致性测试、负载测试和手动门控的 webhooks

. 警报设置

代码语言:javascript复制
Spec:

  analysis:
    # schedule interval (default 60s)
    interval:
    # max number of failed metric checks before rollback
    threshold:
    # max traffic percentage routed to canary
    # percentage (0-100)
    maxWeight:
    # canary increment step
    # percentage (0-100)
    stepWeight:
    # promotion increment step
    # percentage (0-100)
    stepWeightPromotion:
    # total number of iterations
    # used for A/B Testing and Blue/Green
    iterations:
    # threshold of primary pods that need to be available to consider it ready
    # before starting rollout. this is optional and the default is 100
    # percentage (0-100)
    primaryReadyThreshold: 100
    # threshold of canary pods that need to be available to consider it ready
    # before starting rollout. this is optional and the default is 100
    # percentage (0-100)
    canaryReadyThreshold: 100
    # canary match conditions
    # used for A/B Testing
    match:
      - # HTTP header
    # key performance indicators
    metrics:
      - # metric check
    # alerting
    alerts:
      - # alert provider
    # external checks
    webhooks:
      - # hook

Canary 分析周期性地运行,直到达到最大流量权重或迭代次数。在每次运行时,Flagger 都会调用 webhooks,检查指标,如果达到失败检查的阈值,则停止分析并回滚 canary。如果配置了警报,Flagger 将使用警报提供者发布分析结果

0 人点赞