Helm 3 Kubernetes 服务目录资源的部署顺序



我正在使用Helm v3.3.0,带有Kubernetes 1.16。

集群安装了 Kubernetes 服务目录,因此实现开放服务代理 API 规范的外部服务可以实例化为 K8S 资源 - 作为ServiceInstances 和ServiceBindings。

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

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

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还没有。但事实并非如此。

这只是一个时间故障/幸运巧合,还是我可以依靠,为什么?

谢谢!

正如我发布的评论中所述:

事实上,您的Deployment一开始就失败了Status: CreateContainerConfigError.您的Deployment是在从ServiceBindingSecret之前创建的。它仅在ServiceBindingSecret可用时重新创建时工作。

我想通过示例提供更多见解,说明为什么Deployment没有失败。

正在发生的事情(按顺序简化):

  • Deployment->创建并生成了一个Pod
  • Pod->状态为失败的 pod:由于缺少SecretCreateContainerConfigError
  • ServiceBinding->在后台创建Secret
  • Pod获得所需的Secret并开始

前面提到的InstallOrder将在第 147 行的评论中将ServiceInstaceServiceBinding保留为最后。

<小时 />

示例

假设:

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

以下指南:

  • Kubernetes.io:使用 Helm 的安装服务目录
  • Magalix.com:博客:Kubernetes 服务目录

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

  • 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$ kubectl get RESOURCE -o yaml
  • 第二种方法是使用$ kubectl get RESOURCE --watch-only=true
<小时 />

第一种方法

如前所述,DeploymentPod无法启动,因为当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

之后应用您的掌舵图。

免責聲明!

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

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
<小时 />

其他资源:

  • Stackoverflow.com:答:按一定顺序安装
  • Alibabacloud.com:掌舵图表和模板挂钩和测试第 3 部分

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

  • 事实上,我的Pod(引用从ServiceBinding中创建的Secret)的初始启动失败了!它失败是因为 K8S 尝试启动 pod 时Secret实际上不存在。
  • Kubernetes 具有自我修复机制,从某种意义上说,它尝试(并重试)达到集群的目标状态,如各种部署的资源所描述的那样。
  • 通过 Kubernetes 重新尝试让 Pod 运行,最终(当Secret最终出现时)所有条件都将得到满足,以使 Pod 很好地启动。因此,最终,evth。正在按预期运行。

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

但即使没有这个,Kubernetes 实际上也能很好地处理它。安装顺序(在这种情况下)真的无关紧要。这是一件好事!

最新更新