Kubernetes 清单任务

Azure DevOps Services

使用生成或发布管道中的 Kubernetes 清单任务将清单烘焙和部署到 Kubernetes 群集。

概述

以下列表显示了此任务的主要优势:

  • 项目替换:部署操作将作为容器映像列表的输入,可将其与标记和摘要一起指定。 在应用程序到群集之前,同一输入将替换到非模板化清单文件中。 此替换可确保群集节点提取正确的映像版本。

  • 清单稳定性:检查已部署的 Kubernetes 对象的推出状态。 稳定性检查合并在一起,以确定任务状态是成功还是失败。

  • 可跟踪性批注:批注将添加到已部署的 Kubernetes 对象,以叠加可跟踪性信息。 支持以下批注:

    • azure-pipelines/org
    • azure-pipelines/project
    • azure-pipelines/pipeline
    • azure-pipelines/pipelineId
    • azure-pipelines/execution
    • azure-pipelines/executionuri
    • azure-pipelines/jobName
  • 机密处理createSecret 操作允许使用 Docker 注册表服务连接创建 Docker 注册表机密。 它还允许使用纯文本变量或机密变量创建泛型机密。 在部署到群集之前,可以使用 机密 输入以及 部署 操作,使用相应的 imagePullSecrets 值来增强输入清单文件。

  • 烘焙清单:任务的 烘焙 操作允许将模板烘焙到 Kubernetes 清单文件中。 该操作使用 Helm、Compose 和 kustomize 等工具。 通过烘焙,这些 Kubernetes 清单文件可用于部署到群集。

  • 部署策略:使用部署操作选择 Canary 策略会导致创建名称后缀为“-baseline”和“-canary”的工作负荷。 该任务支持两种流量拆分方法:

    • 服务Mesh接口服务Mesh接口 (SMI) 抽象允许使用 Linkerd 和 Istio 等服务网格提供程序进行配置。 Kubernetes 清单任务将 SMI TrafficSplit 对象映射到部署策略生命周期中的稳定、基线和 Canary 服务。

      基于服务网格并使用此任务的 Canary 部署更准确。 这种准确性是因为服务网格提供程序可实现基于流量的精细百分比拆分。 服务网格使用注入 Pod 的服务注册表和 Sidecar 容器。 此注入与应用程序容器一起发生,以实现精细流量拆分。

    • 没有服务网格的 Kubernetes:如果没有服务网格,可能无法在请求级别获得所需的确切百分比拆分。 但是,可以使用稳定变体旁边的基线和 Canary 变体来执行 Canary 部署。

      当满足选择器标签约束时,服务会将请求发送到所有三个工作负荷变体的 Pod。 Kubernetes 清单在创建基线和 Canary 变体时遵循这些请求。 此路由行为仅实现了将一部分请求路由到 Canary 的预期效果。

    通过使用发布管道中的 手动干预任务 或 YAML 管道中的 延迟任务 比较基线和 Canary 工作负载。 在使用任务的提升或拒绝操作之前执行比较。

部署操作

参数 说明
action
操作
(必需)

部署:
kubernetesServiceConnection
Kubernetes 服务连接
(必需,除非任务在 Kubernetes 环境中 使用)

Kubernetes 服务连接的名称。
namespace
命名空间
(必需,除非任务在 Kubernetes 环境中 使用)

要部署到的群集中的命名空间。
manifests
清单
(必需)

要用于部署的清单文件的路径。 每行表示单个路径。 文件匹配模式是每行可接受的值。 可用于 将多个 YAML 文件合并为一个。 在经典发布管道中使用此任务时,这非常有用。
容器
容器
(可选)

要用于清单文件替换的图像的完全限定 URL。 此输入接受换行符形式的多个项目替换的规范。 下面是一个示例:

containers: |
  contosodemo.azurecr.io/foo:test1
  contosodemo.azurecr.io/bar:test2

在此示例中,所有对输入清单文件的图像字段中的引用 contosodemo.azurecr.io/foocontosodemo.azurecr.io/bar 搜索。 对于找到的每个匹配项,标记 test1test2 替换匹配的引用。
imagePullSecrets
图像拉取机密
(可选)

多行输入,其中每行都包含已在群集中设置的 Docker 注册表机密的名称。 在 imagePullSecrets 下为每个在输入清单文件中发现的工作负荷添加机密名称。
策略
策略
(可选)

在群集上应用清单文件时使用的部署策略。 目前, Canary 是唯一可接受的部署策略。
trafficSplitMethod
流量拆分方法
(可选)

可接受的值为 Podsmi。 默认值为 Pod

对于值 smi,流量拆分百分比是在请求级别使用服务网格完成的。 服务网格必须由群集管理员设置。此任务处理 SMI TrafficSplit 对象的业务流程。

对于值 Pod,在缺少服务网格的情况下,请求级别无法拆分百分比。 相反,百分比输入用于计算基线和 Canary 的副本。 计算是稳定变体的输入清单中指定的副本百分比。
百分比
百分比
仅当 策略 设置为 canary) 时才需要 (

用于计算清单文件中包含的工作负荷的基线变体副本和 canary 变体副本数的百分比。

对于指定的百分比输入,计算:

(100) 副本/数  百分比×

如果结果不是整数,则创建基线和金丝雀变体时,将使用结果的数学底层。

例如,假设部署 hello-world 位于输入清单文件中,并且以下行位于任务输入中:

replicas: 4
strategy: canary
percentage: 25

在这种情况下,将创建部署 hello-world-baseline 和 hello-world-canary,每个副本一个。 使用与稳定版本相同的映像和标记创建基线变体,这是部署前的四个副本变体。 使用与新部署的更改对应的映像和标记创建 Canary 变体。
baselineAndCanaryReplicas
基线副本和金丝雀副本
(可选,仅当 trafficSplitMethod 设置为 smi)

trafficSplitMethod 设置为 smi 时,流量拆分百分比控制在服务网格平面中。 但是,可以控制 Canary 和基线变体的实际副本数,而不受流量拆分。

例如,假设输入部署清单为稳定变体指定 30 个副本。 另外,假设为任务指定以下输入:

strategy: canary
trafficSplitMethod: smi
percentage: 20
baselineAndCanaryReplicas: 1

在这种情况下,稳定变体接收 80% 的流量,而基线和 Canary 变体分别接收指定 20% 的一半。 但基线和金丝雀变体不会分别接收三个副本。 相反,它们接收指定的副本数,这意味着每个副本都接收一个副本。
rolloutStatusTimeout
推出状态的超时
(可选)

在结束监视推出状态之前,) 等待的时间长度 ((以秒为单位)。 默认值为 0 (不等待) 。

以下 YAML 代码是使用清单文件部署到 Kubernetes 命名空间的示例:

steps:
- task: KubernetesManifest@0
  displayName: Deploy
  inputs:
    kubernetesServiceConnection: someK8sSC1
    namespace: default
    manifests: |
      manifests/deployment.yml
      manifests/service.yml
    containers: |
      foo/demo:$(tagVariable1)
      bar/demo:$(tagVariable2)
    imagePullSecrets: |
      some-secret
      some-other-secret

在上面的示例中,任务尝试查找图像 foo/demobar/demo 清单文件的图像字段中的匹配项。 对于找到的每个匹配项,值tagVariable1tagVariable2或作为标记追加到图像名称中。 还可以在容器输入中为项目替换指定摘要。

注意

虽然可以使用与部署策略相关的 YAML 输入创作部署、提升和拒绝操作,但手动干预任务的支持目前不适用于生成管道。

对于发布管道,建议按以下顺序使用与部署策略相关的操作和输入:

  1. 使用 strategy: canarypercentage: $(someValue). 指定的部署操作。
  2. 手动干预任务,以便可以暂停管道,并将基线变体与 Canary 变体进行比较。
  3. 恢复手动干预任务时运行的升级操作;如果拒绝手动干预任务,则会运行拒绝操作。

升级和拒绝操作

参数 说明
action
操作
(必需)

升级拒绝
kubernetesServiceConnection
Kubernetes 服务连接
(必需)

Kubernetes 服务连接的名称。
namespace
命名空间
(必需)

要部署到的群集中的命名空间。
manifests
清单
(必需)

要用于部署的清单文件的路径。 每行表示单个路径。 文件匹配模式是每行可接受的值。
容器
容器
(可选)

要用于清单文件替换的图像的完全限定资源 URL。 URL contosodemo.azurecr.io/helloworld:test 是一个示例。
imagePullSecrets
图像拉取机密
(可选)

多行输入,其中每行都包含已在群集中设置的 Docker 注册表机密的名称。 每个机密名称都添加到 imagePullSecrets 字段下,用于输入清单文件中找到的工作负荷。
策略
策略
(可选)

在升级操作或拒绝操作之前部署操作中使用的部署策略。 目前, Canary 是唯一可接受的部署策略。

创建机密操作

参数 说明
action
操作
(必需)

createSecret
secretType
机密类型
(必需)

可接受的值为 dockerRegistry泛型。 默认值为 dockerRegistry

如果将 secretType 设置为 dockerRegistry,则会在群集中创建或更新 imagePullSecrets 字段,以帮助从专用容器注册表中拉取映像。
secretName
机密名称
(必需)

要创建或更新的机密的名称。
dockerRegistryEndpoint
Docker 注册表服务连接
仅当 secretType 设置为 dockerRegistry) 时才需要 (

指定的服务连接的凭据用于在群集中创建 Docker 注册表机密。 imagePullSecrets 字段下的清单文件可以引用此机密的名称。
secretArguments
机密参数
仅当 secretType 设置为 泛型) 时才需要 (

接受要用于创建和更新机密的键和文本值。 下面是一个示例:
--from-literal=key1=value1--from-literal=key2=“top secret”
kubernetesServiceConnection
Kubernetes 服务连接
(必需)

Kubernetes 服务连接的名称。
namespace
命名空间
(必需)

在其中创建机密的群集命名空间。

以下 YAML 代码演示如何使用 Docker 注册表服务连接创建 Docker 注册表机密:

steps:
- task: KubernetesManifest@0
  displayName: Create secret
  inputs: 
    action: createSecret
    secretType: dockerRegistry
    secretName: foobar
    dockerRegistryEndpoint: demoACR
    kubernetesServiceConnection: someK8sSC
    namespace: default

此 YAML 代码演示如何创建泛型机密:

steps:
- task: KubernetesManifest@0
  displayName: Create secret
  inputs: 
    action: createSecret
    secretType: generic
    secretName: some-secret
    secretArguments: --from-literal=key1=value1
    kubernetesServiceConnection: someK8sSC
    namespace: default

烘焙操作

参数 说明
action
操作
(必需)

renderType
呈现引擎
(必需)

用于生成清单文件的呈现类型。

可接受的值为 helm2komposekustomize。 默认值为 helm2
helmChart
Helm 图表
仅当 renderType 设置为 helm2) 时才需要 (

用于烘焙的 Helm 图表的路径。
overrideFiles
重写文件
(可选,仅当 renderType 设置为 helm2)

接受替代文件路径的多行输入。 当 Helm 图表中的清单文件烘焙时,将使用这些文件。
重写
重写值
(可选,仅当 renderType 设置为 helm2)

使用 Helm 的清单文件时,通过命令行开关使用的其他替代值 ---set

value 格式指定替代值作为键值对。 如果使用多个重写键值对,请在单独的行中指定每个键值配对。 使用换行符作为不同键值对之间的分隔符。
releaseName
版本名称
(可选,仅当 renderType 设置为 helm2)

烘焙 Helm 图表时使用的版本的名称。
kustomizationPath
Kustomization 路径
(可选,仅当 renderType 设置为 kustomize)

包含文件 kustomization.yaml 的目录的路径。
dockerComposeFile
Docker 撰写文件的路径
(可选,仅当 renderType 设置为 kompose)

Docker compose 文件的路径。

以下 YAML 代码是从 Helm 图表中烘焙清单文件的示例。 记下第一个任务中名称输入的用法。 稍后从部署步骤中引用此名称,用于指定烘焙步骤生成的清单的路径。

steps:
- task: KubernetesManifest@0
  name: bake
  displayName: Bake K8s manifests from Helm chart
  inputs:
    action: bake
    helmChart: charts/sample
    overrides: 'image.repository:nginx'

- task: KubernetesManifest@0
  displayName: Deploy K8s manifests
  inputs:
    kubernetesServiceConnection: someK8sSC
    namespace: default
    manifests: $(bake.manifestsBundle)
    containers: |
      nginx: 1.7.9

缩放操作

参数 说明
action
操作
(必需)

scale
kind
种类
(必需)

要纵向扩展或缩减的 Kubernetes 对象类型。 示例包括 ReplicaSet 和 StatefulSet。
name
名称
(必需)

要纵向扩展或缩减的 Kubernetes 对象的名称。
副本
副本计数
(必需)

要缩放到的副本数。
kubernetesServiceConnection
Kubernetes 服务连接
(必需)

Kubernetes 服务连接的名称。
namespace
命名空间
(必需)

要部署到的群集中的命名空间。
rolloutStatusTimeout
推出状态的超时
(可选)

(以秒为单位的时间长度,) 等待,然后再结束对推出状态的监视。 默认值为 0 (不等待) 。

以下 YAML 代码演示了缩放对象的示例:

steps:
- task: KubernetesManifest@0
  displayName: Scale
  inputs: 
    action: scale
    kind: deployment
    name: bootcamp-demo
    replicas: 5
    kubernetesServiceConnection: someK8sSC
    namespace: default

修补操作

参数 说明
action
操作
(必需)

补丁
resourceToPatch
要修补的资源
(必需)

指示以下修补程序方法之一:
  • 清单文件标识要修补的对象。
  • 单个对象按种类和名称标识为修补程序目标。
可接受的值为文件名 默认值为 file
resourceFiletoPatch
文件路径
仅当 操作 设置为 修补resourceToPatch 设置为 文件) 时,才需要 (

用于修补程序的文件的路径。
kind
种类
仅当 resourceToPatch 设置为 名称) 时,才需要 (

Kubernetes 对象的类型。 示例包括 ReplicaSet 和 StatefulSet。
name
名称
仅当 resourceToPatch 设置为 名称) 时,才需要 (

要修补的 Kubernetes 对象的名称。
mergeStrategy
合并策略
(必需)

用于应用修补程序的策略。

可接受的值为 json合并战略值。 默认值是 战略的。
补丁
修补程序
(必需)

修补程序的内容。
kubernetesServiceConnection
Kubernetes 服务连接
(必需)

Kubernetes 服务连接的名称。
namespace
命名空间
(必需)

要部署到的群集中的命名空间。
rolloutStatusTimeout
推出状态的超时
(可选)

(以秒为单位的时间长度,) 等待,然后再结束对推出状态的监视。 默认值为 0 (不等待) 。

以下 YAML 代码显示了对象修补的示例:

steps:
- task: KubernetesManifest@0
  displayName: Patch
  inputs: 
    action: patch
    kind: pod
    name: demo-5fbc4d6cd9-pgxn4
    mergeStrategy: strategic
    patch: '{"spec":{"containers":[{"name":"demo","image":"foobar/demo:2239"}]}}'
    kubernetesServiceConnection: someK8sSC
    namespace: default

删除操作

参数 说明
action
操作
(必需)

delete
参数
参数
(必需)

要传递给 kubectl 的参数用于删除必要的对象。 示例如下:
arguments: deployment hello-world foo-bar
kubernetesServiceConnection
Kubernetes 服务连接
(必需)

Kubernetes 服务连接的名称。
namespace
命名空间
(必需)

要部署到的群集中的命名空间。

此 YAML 代码显示示例对象删除:

steps:
- task: KubernetesManifest@0
  displayName: Delete
  inputs:
    action: delete
    arguments: deployment expressapp
    kubernetesServiceConnection: someK8sSC
    namespace: default

故障排除

我的 Kubernetes 群集位于防火墙后面,而我使用的是托管代理。 我该如何部署到此群集?

通过允许托管代理的 IP 地址,你可以授予托管代理通过防火墙进行访问的权限。 有关更多详细信息,请参阅代理 IP 范围

开源

此任务在 GitHub 上开放源代码。 欢迎提供反馈和建议。