前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Flagger 在 Kubernetes 集群上是如何工作的?

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

原创
作者头像
philentso
修改于 2022-12-26 07:10:50
修改于 2022-12-26 07:10:50
2.4K00
代码可运行
举报
文章被收录于专栏:philentsophilentso
运行总次数:0
代码可运行

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

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

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

Canary resource

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
AI代码解释
复制
selector app=<name>-primary

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

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

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
kubectl get canaries --all-namespaces

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
kubectl -n test get canary/podinfo -oyaml | awk '/status/,0'

一个成功的 rollout 状态:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
kubectl wait canary/podinfo --for=condition=promoted

CI example:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 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
代码运行次数:0
运行
AI代码解释
复制
spec:
  revertOnDeletion: true

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

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

. Canary service 选择器将被恢复

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

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

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

Canary analysis

Canary 分析定义了:

. Deployment 策略的类型

. 用来验证 Canary 版本的指标

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

. 警报设置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 将使用警报提供者发布分析结果

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死)
在微软的官方文档中,说 SetParent 可以在进程内设置,也可以跨进程设置。当使用跨进程设置窗口的父子关系时,你需要注意本文提到的一些问题,避免踩坑。
walterlv
2023/10/22
1.7K0
解决 WPF 嵌套的子窗口在改变窗口大小的时候闪烁的问题
因为 Win32 的窗口句柄是可以跨进程传递的,所以可以用来实现跨进程 UI。不过,本文不会谈论跨进程 UI 的具体实现,只会提及其实现中的一个重要缓解,使用子窗口的方式。
walterlv
2023/10/22
9040
解决 WPF 嵌套的子窗口在改变窗口大小的时候闪烁的问题
WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)
发布于 2018-07-11 13:35 更新于 2018-07-12 11:44
walterlv
2018/09/18
4.4K0
WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)
如何利用 Win32 API 设置两个窗口的所有者(Owner)关系
设置两个窗口的父子关系非常简单,只需要调用 SetParent 函数即可。然而设置两个窗口的所有者(Owner)关系却没有一个简单直观的 API。那么本文介绍一下如何设置两个窗口的 Owner 关系。
walterlv
2023/10/23
6930
duilib基本流程
duilib的基本流程如上图,通过解析一个xml文件,将文件中的内容渲染为窗口界面,这个解析过程由WindowImplBase类来完成。 基本框架如下: 1. 首先在公共头文件中加入如下内容:
Masimaro
2018/08/31
1.6K0
WPF 程序如何移动焦点到其他控件
WPF 中可以使用 UIElement.Focus() 将焦点设置到某个特定的控件,也可以使用 TraversalRequest 仅仅移动焦点。本文介绍如何在 WPF 程序中控制控件的焦点。
walterlv
2023/10/22
6300
Windows 系统上用 .NET/C# 查找所有窗口,并获得窗口的标题、位置、尺寸、最小化、可见性等各种状态
在 Windows 应用开发中,如果需要操作其他的窗口,那么可以使用 EnumWindows 这个 API 来枚举这些窗口。
walterlv
2023/10/22
2K0
Windows 系统上用 .NET/C# 查找所有窗口,并获得窗口的标题、位置、尺寸、最小化、可见性等各种状态
在 WPF 程序中应用 Windows 10 真•亚克力效果
从 Windows 10 (1803) 开始,Win32 应用也可以有 API 来实现原生的亚克力效果了。不过相比于 UWP 来说,可定制性会差很多。
walterlv
2023/10/22
6270
在 WPF 程序中应用 Windows 10 真•亚克力效果
WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
发布于 2018-07-12 07:57 更新于 2018-09-05 05:46
walterlv
2018/09/18
6.9K0
WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
System.InvalidOperationException:“BuildWindowCore 无法返回寄宿的子窗口句柄。”
当试图在 WPF 窗口中嵌套显示 Win32 子窗口的时候,你有可能出现错误:“BuildWindowCore 无法返回寄宿的子窗口句柄。”。
walterlv
2023/10/22
4480
System.InvalidOperationException:“BuildWindowCore 无法返回寄宿的子窗口句柄。”
WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
在 WPF 中,如果想做一个背景透明的异形窗口,基本上都要设置 WindowStyle="None"、AllowsTransparency="True" 这两个属性。如果不想自定义窗口样式,还需要设置 Background="Transparent"。这样的设置会让窗口变成 Layered Window,WPF 在这种类型窗口上的渲染性能是非常糟糕的。
walterlv
2023/10/22
1.9K0
WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
win32程序之子窗口编程
  在前边我们已经讲解了窗口的本质.以及如何注册窗口类跟创建窗口. 还讲了消息循环.
IBinary
2018/09/28
2K0
win32程序之子窗口编程
System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
当试图在 WPF 窗口中嵌套显示 Win32 子窗口的时候,你有可能出现错误:“System.InvalidOperationException:“寄宿 HWND 必须是子窗口。””。
walterlv
2023/10/22
4520
System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
当无边框窗口被子窗口遮挡导致难以调节窗口大小时,可通过处理 NCHITTEST 消息重新支持调节窗口大小
做无边框窗口之后,我们有方法可以让窗口的标题栏区域和边缘调大小的区域继续正常工作,直到——这个窗口上面覆盖了其他的子窗口。这个子窗口会吃掉消息导致父窗口的边缘无法再继续处理这些消息。
walterlv
2023/10/22
4720
当无边框窗口被子窗口遮挡导致难以调节窗口大小时,可通过处理 NCHITTEST 消息重新支持调节窗口大小
通过子类化窗口(SubClass)来为现有的某个窗口添加新的窗口处理程序(或者叫钩子,Hook)
创建窗口的时候,可以传一个消息处理函数。然而如果窗口不是自己创建的,还能增加消息处理函数吗?答案是可以的,除了 SetWindowsHookEx 来添加钩子之外,更推荐用子类化的方式来添加。
walterlv
2023/10/22
4560
Win32/C# 应用使用 PrintWindow 对窗口截图(PrintWindow)
相比于 Windows 2000 引入到 GDI+ 中的 BitBlt 方法截取窗口图片,Windows XP 时也引入了 PrintWindow 方法来专门截取窗口,截取的原理也不同。
walterlv
2023/10/22
1.7K0
Win32/C# 应用使用 PrintWindow 对窗口截图(PrintWindow)
直击本质:WPF 框架是如何实现模态窗口的
想知道你在 WPF 编写 Window.ShowDialog() 之后,WPF 框架是如何帮你实现模态窗口的吗?
walterlv
2023/10/22
7380
单选钮和复选框控件的应用教案_在mfc中弹出一个窗口
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/170968.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/23
1.5K0
GetStyle,ModifyStyle,GetExStyle,ModifyStyleEx「建议收藏」
要添加或除去窗口的普通风格,可以使用GetStyle()和ModifyStyle()方法来实现 要设置或去除窗口的扩展风格,可以使用GetExStyle()和ModifyStyleEx() 方法实现
全栈程序员站长
2022/09/09
7500
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景(可以做 Acrylic 亚克力效果、模糊效果、主题色效果等)
Windows 系统中有一个没什么文档的 API,SetWindowCompositionAttribute,可以允许应用的开发者将自己窗口中的内容渲染与窗口进行组合。这可以实现很多系统中预设的窗口特效,比如 Windows 7 的毛玻璃特效,Windows 8/10 的前景色特效,Windows 10 的模糊特效,以及 Windows 10 1709 的亚克力(Acrylic)特效。而且这些组合都发生在 dwm 进程中,不会额外占用应用程序的渲染性能。
walterlv
2023/10/22
1.9K0
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景(可以做 Acrylic 亚克力效果、模糊效果、主题色效果等)
推荐阅读
使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死)
1.7K0
解决 WPF 嵌套的子窗口在改变窗口大小的时候闪烁的问题
9040
WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)
4.4K0
如何利用 Win32 API 设置两个窗口的所有者(Owner)关系
6930
duilib基本流程
1.6K0
WPF 程序如何移动焦点到其他控件
6300
Windows 系统上用 .NET/C# 查找所有窗口,并获得窗口的标题、位置、尺寸、最小化、可见性等各种状态
2K0
在 WPF 程序中应用 Windows 10 真•亚克力效果
6270
WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
6.9K0
System.InvalidOperationException:“BuildWindowCore 无法返回寄宿的子窗口句柄。”
4480
WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
1.9K0
win32程序之子窗口编程
2K0
System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
4520
当无边框窗口被子窗口遮挡导致难以调节窗口大小时,可通过处理 NCHITTEST 消息重新支持调节窗口大小
4720
通过子类化窗口(SubClass)来为现有的某个窗口添加新的窗口处理程序(或者叫钩子,Hook)
4560
Win32/C# 应用使用 PrintWindow 对窗口截图(PrintWindow)
1.7K0
直击本质:WPF 框架是如何实现模态窗口的
7380
单选钮和复选框控件的应用教案_在mfc中弹出一个窗口
1.5K0
GetStyle,ModifyStyle,GetExStyle,ModifyStyleEx「建议收藏」
7500
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景(可以做 Acrylic 亚克力效果、模糊效果、主题色效果等)
1.9K0
相关推荐
使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档