【问题标题】:Helm 3 Deployment Order of Kubernetes Service Catalog ResourcesHelm 3 Kubernetes服务目录资源部署顺序
【发布时间】:2020-12-07 20:10:48
【问题描述】:

我正在使用 Helm v3.3.0 和 Kubernetes 1.16。

集群安装了Kubernetes Service Catalog,因此实现Open Service Broker API规范的外部服务可以实例化为K8S资源——ServiceInstances和ServiceBindings。

ServiceBindings 反映为 K8S Secrets 并包含创建的外部服务的绑定信息。这些秘密通常映射到 Docker 容器中,作为 K8S Deployment 中的环境变量或卷。

现在我正在使用 Helm 部署我的 Kubernetes 资源,我读到 here...

Kubernetes 类型的 [Helm] 安装顺序由 kind_sorter.go 中的枚举 InstallOrder 给出

在该文件中,订单既没有提到 ServiceInstance 也没有提到 ServiceBinding 作为资源,这意味着 Helm 在安装了任何 InstallOrder 列表之后安装这些资源类型 - 在特别是Deployments。这似乎与我的图表上运行的helm install --dry-run --debug 的输出相匹配,其中的顺序表明最后应用了 K8S 服务目录资源。

问题:我无法理解的是,为什么我的Deployment 确实无法使用 Helm 安装。 毕竟我的Deployment 资源似乎是在ServiceBinding 之前部署的。我的Deployment 引用的是ServiceBinding 生成的Secret。我预计它会失败,因为当 Deployment 正在安装时,Secret 还不存在。但事实并非如此。

这只是时间故障/幸运的巧合,还是我可以依赖的东西,为什么?

谢谢!

【问题讨论】:

  • 事实上,您的DeploymentStatus: CreateContainerConfigError 开头就失败了。您的Deployment 是在Secret 之前从ServiceBinding 创建的。它仅在 ServiceBinding 中的 Secret 可用时重新创建时起作用。

标签: kubernetes kubernetes-helm


【解决方案1】:

正如我发表的评论中所说:

事实上,您的DeploymentStatus: CreateContainerConfigError 开头就失败了。您的Deployment 是在Secret 之前从ServiceBinding 创建的。它仅在 ServiceBindingSecret 可用时重新创建时起作用。

我想举例说明为什么Deployment 没有失败。

发生了什么(按顺序简化):

  • Deployment -> 创建并产生了一个 Pod
  • Pod -> pod 失败,状态为:CreateContainerConfigError 缺少 Secret
  • ServiceBinding -> 在后台创建 Secret
  • Pod 获取所需的Secret 并开始

前面提到的InstallOrder 将留下ServiceInstaceServiceBinding 作为最后一个评论line 147


示例

假设:

  • 有一个工作的 Kubernetes 集群
  • Helm3 已安装并可以使用

以下指南:

templates/ 目录中有一个 Helm 图表,其中包含以下文件:

  • ServiceInstance
  • ServiceBinding
  • Deployment

文件:

ServiceInstance.yaml:

apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
  name: example-instance
spec:
  clusterServiceClassExternalName: redis
  clusterServicePlanExternalName: 5-0-4

ServiceBinding.yaml:

apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
  name: example-binding
spec:
  instanceRef:
    name: example-instance

Deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ubuntu
spec:
  selector:
    matchLabels:
      app: ubuntu
  replicas: 1
  template:
    metadata:
      labels:
        app: ubuntu
    spec:
      containers:
      - name: ubuntu
        image: ubuntu
        command:
        - sleep 
        - "infinity" 
        # part below responsible for getting secret as env variable
        env: 
        - name: DATA
          valueFrom: 
            secretKeyRef:
              name: example-binding
              key: host

应用上述资源来检查正在发生的事情可以通过两种方式完成:

  • 第一种方法是使用timestamp from $ kubectl get RESOURCE -o yaml
  • 第二种方法是使用$ kubectl get RESOURCE --watch-only=true

第一种方法

如前所述,Deployment 中的Pod 无法启动,因为当Pod 尝试生成时,Secret 不可用。在Secret 可用后,Pod 启动。

Pod 的状态如下:

  • Pending
  • ContainerCreating
  • CreateContainerConfigError
  • Running

这是一个时间戳为PodSecret的表格:

|                  Pod                      |                Secret                     |
|-------------------------------------------|-------------------------------------------|
| creationTimestamp: "2020-08-23T19:54:47Z" |                   -                       |
|                   -                       | creationTimestamp: "2020-08-23T19:54:55Z" |
| startedAt: "2020-08-23T19:55:08Z"         |                   -                       |

您可以通过调用以下命令获取此时间戳:

  • $ kubectl get pod pod_name -n namespace -o yaml
  • $ kubectl get secret secret_name -n namespace -o yaml

您还可以通过以下方式获取更多信息:

  • $ kubectl get event -n namespace
  • $ kubectl describe pod pod_name -n namespace

第二种方法

此方法需要在运行 Helm 图表之前进行准备。打开另一个终端窗口(对于这种特殊情况 2)并运行:

  • $ kubectl get pod -n namespace --watch-only | while read line ; do echo -e "$(gdate +"%H:%M:%S:%N")\t $line" ; done
  • $ kubectl get secret -n namespace --watch-only | while read line ; do echo -e "$(gdate +"%H:%M:%S:%N")\t $line" ; done

然后应用您的 Helm 图表。

免责声明!

上面的命令将监视资源的变化,并用操作系统的时间戳显示它们。请记住,此命令仅用于示例目的。

Pod 的输出:

21:54:47:534823000   NAME                      READY   STATUS                       RESTARTS    AGE
21:54:47:542107000   ubuntu-65976bb789-l48wz   0/1     Pending                      0           0s
21:54:47:553799000   ubuntu-65976bb789-l48wz   0/1     Pending                      0           0s
21:54:47:655593000   ubuntu-65976bb789-l48wz   0/1     ContainerCreating            0           0s
-> 21:54:52:001347000    ubuntu-65976bb789-l48wz   0/1     CreateContainerConfigError   0           4s
21:55:09:205265000   ubuntu-65976bb789-l48wz   1/1     Running                      0           22s

Secret 的输出:

21:54:47:385714000   NAME                            TYPE                 DATA   AGE
21:54:47:393145000   sh.helm.release.v1.example.v1   helm.sh/release.v1   1      0s
21:54:47:719864000   sh.helm.release.v1.example.v1   helm.sh/release.v1   1      0s
21:54:51:182609000   understood-squid-redis          Opaque               1      0s
21:54:52:001031000   understood-squid-redis          Opaque               1      0s
-> 21:54:55:686461000    example-binding                 Opaque               6      0s

其他资源:

【讨论】:

    【解决方案2】:

    所以回答我自己的问题(感谢@dawid-kruk 和 Slack 上 Service Catalog Sig 上的人们):

    • 事实上,我的Pods(引用SecretServiceBinding 创建的那些)的初始启动失败了!它失败了,因为在 K8S 尝试启动 pod 的那一刻,Secret 实际上并不存在。
    • Kubernetes 具有自我修复机制,从某种意义上说,它会尝试(并重试)达到由各种已部署资源描述的集群目标状态。
    • 通过 Kubernetes 重试让 Pod 运行,最终(当 Secret 最终出现时)所有条件都将得到满足,使 Pod 能够正常启动。因此,最终,evth。正在正常运行。

    如何简化?一种可能性是 Helm 将自定义资源 ServiceBindingServiceInstance 包含在其可安装资源的有序列表中,并在安装阶段的早期安装它们。

    但即使没有这些,Kubernetes 实际上也能很好地处理它。安装顺序(在这种情况下)实际上并不重要。这是一件好事!

    【讨论】:

      猜你喜欢
      • 2019-08-06
      • 2019-01-12
      • 2021-02-27
      • 1970-01-01
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 2021-01-27
      • 1970-01-01
      相关资源
      最近更新 更多