DevOps CI/CD 管道在 Kubernetes 升级到 v1.22 后中断

DevOps CI/CD pipelines broken after Kubernetes upgrade to v1.22

现状

在 v1.22 中,Kubernetes 放弃了对 v1beta1 API 的支持。这导致我们的发布管道崩溃,我们不确定如何修复它。

我们使用构建管道来构建 .NET Core 应用程序并将它们部署到 Azure 容器注册表。然后是使用 helm 从该 ACR 在集群中升级它们的发布管道。这就是它的样子。

构建管道:

  1. .NET 下载、恢复、构建、测试、发布
  2. Docker 任务 v0:构建任务
  3. Docker 任务 v0:推送到 ACR 任务
  4. 工件发布到 Azure Pipelines

发布渠道:

  1. Helm 工具安装程序:安装 helm v3.2.4(检查最新版本的 Helm 未选中)并安装最新的 Kubectl(检查最新版本)
  2. Bash 任务:
az acr login --name <acrname>
az acr helm repo add --name <acrname>
  1. 头盔升级任务:
    • 图表名称<acrname>/<chartname>
    • 版本empty
    • 发布名称`

升级到 Kubernetes v1.22 后,我们在发布步骤 3 中收到以下错误:

Error: UPGRADE FAILED: unable to recognize "": no matches for kind "Ingress" in version "extensions/v1beta1".

我已经尝试过的

错误非常明显,Helm compatibility table 清楚地指出我需要升级发布管道以至少使用 Helm v3.7.x。不幸的是,在此版本中,OCI 功能(稍后会介绍)仍处于实验阶段,因此至少必须使用 v3.8.x。

将 helm 版本升级到 v3.8.0

这使得发布步骤 3。报告:

Error: looks like "https://<acrname>.azurecr.io/helm/v1/repo" is not a valid chart repository or cannot be reached: error unmarshaling JSON: while decoding JSON: json: unknown field "acrMetadata"

阅读有关 how to live with helm and ACR 的 Microsoft 教程后,我了解到 az acr helm 命令使用 helm v2,因此已弃用,应使用 OCI 工件。

切换到 OCI 第 1 部分

阅读后我将发布步骤 2. 更改为单行:

helm registry login <acrname>.azurecr.io --username <username> --password <password>

现在在发布步骤 2 中给了我 Login Succeeded。但是发布步骤 3。失败并显示

Error: failed to download "<acrname>/<reponame>".

切换到 OCI 第 2 部分

我认为 helm 任务不兼容或与新方法不兼容,所以我删除了发布步骤 3。并决定在步骤 2 中从命令行进行。所以现在步骤 2 看起来像这样:

helm registry login <acrname>.azurecr.io  --username <username> --password <password>
helm upgrade --install --wait -n <namespace> <deploymentName> oci://<acrname>.azurecr.io/<reponame> --version latest --values ./values.yaml

不幸的是,这仍然给我:

Error: failed to download "oci://<acrname>.azurecr.io/<reponame>" at version "latest"

Helm 拉取、导出、升级而不只是升级

接下来的尝试是将 help upgrade 拆分为 helm pullhelm exporthelm upgrade,但

helm pull oci://<acrname>.azurecr.io/<reponame> --version latest

给我:

Error: manifest does not contain minimum number of descriptors (2), descriptors found: 0

docker builddocker push 任务更改为 v2

我还尝试将构建管道中的 docker 任务更改为 v2。但这根本没有改变任何东西。

您是否尝试过将 Ingress 对象的 apiVersion 更改为 networking.k8s.io/v1beta1networking.k8s.io/v1Support for Ingress in the extensions/v1beta1 API version is dropped in k8s 1.22.

我们的 helm chart 中的 ingress.yaml 文件看起来像这样支持多个 k8s 版本。您可以忽略 AWS-specific 注释,因为您使用的是 Azure。我们的图表具有 ingress.enablePathType 的全局值,因为在编写 yaml 文件时,AWS Load Balancer did not support pathType 因此我们将该值设置为 false。

{{- if .Values.global.ingress.enabled -}}
{{- $useV1Ingress := and (.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress") .Values.global.ingress.enablePathType -}}
{{- if $useV1Ingress -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
  name: example-ingress
  labels:
    {{- include "my-chart.labels" . | nindent 4 }}
  annotations:
    {{- if .Values.global.ingress.group.enabled }}
    alb.ingress.kubernetes.io/group.name: {{ required "ingress.group.name is required when ingress.group.enabled is true" .Values.global.ingress.group.name }}
    {{- end }}
    {{- with .Values.global.ingress.annotations }}
    {{- toYaml . | nindent 4 }}
    {{- end }}
    # Add these tags to the AWS Application Load Balancer
    alb.ingress.kubernetes.io/tags: k8s.namespace/{{ .Release.Namespace }}={{ .Release.Namespace }}
spec:
  rules:
    - host: {{ include "my-chart.applicationOneServerUrl" . | quote }}
      http:
        paths:
          {{- if $useV1Ingress }}
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {{ $applicationOneServiceName }}
                port:
                  name: http-grails
          {{- else }}
          - path: /*
            backend:
              serviceName: {{ $applicationOneServiceName }}
              servicePort: http-grails
          {{- end }}
    - host: {{ include "my-chart.applicationTwoServerUrl" . | quote }}
      http:
        paths:
          {{- if $useV1Ingress }}
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {{ .Values.global.applicationTwo.serviceName }}
                port:
                  name: http-grails
          {{- else }}
          - path: /*
            backend:
              serviceName: {{ .Values.global.applicationTwo.serviceName }}
              servicePort: http-grails
          {{- end }}
{{- end }}

只是为了使图片完整 - @wubbalubba 提到图表定义中入口的 YAML 的变化并不是我修复我们的管道必须做的唯一事情:

  1. 所以首先,很明显,将 ingress 的 YAML 文件中图表定义内的 API 更改为 v1,并增加图表版本。然后重新打包推送到ACR:
helm package .
helm push .\generated-new-chart.tgz oci://<acrname>.azurecr.io/
  1. this guide 中学到的下一件事是更新,或者更确切地说,我只是删除了与我的服务相关的所有机密和配置映射:
kubectl delete secret -l owner=helm,status=deployed,name=<release_name> --namespace <release_namespace>
kubectl delete configmap -l owner=helm,status=deployed,name=<release_name> --namespace <release_namespace>
  1. 最后,删除部署 helm 升级步骤。相反 shell 脚本承担了责任:
helm registry login $(ContainerRegistryUrl) --username $(ContainerRegistryUsername) --password $(ContainerRegistryPassword)
az aks get-credentials --resource-group $(Kubernetes__ResourceGroup) --name $(Kubernetes__Cluster)
helm upgrade --install --wait -n $(NamespaceName) $(ServiceName) oci://$(ContainerRegistryUrl)/services-generic-chart --version 2 -f ./values.yaml

直到那时我才能够成功地重新部署所有内容。