我正在使用Helm v3.3.0,带有Kubernetes 1.16。
集群安装了 Kubernetes 服务目录,因此实现开放服务代理 API 规范的外部服务可以实例化为 K8S 资源 - 作为ServiceInstance
s 和ServiceBinding
s。
ServiceBinding
反映为 K8SSecret
s,并包含创建的外部服务的绑定信息。这些机密通常作为 K8SDeployment
中的环境变量或卷映射到 Docker 容器中。
现在我正在使用 Helm 来部署我的 Kubernetes 资源,我在这里读到......
Kubernetes 类型的 [Helm] 安装顺序由 kind_sorter.go 中的枚举 InstallOrder 给出
。
在该文件中,订单既没有提到ServiceInstance
也没有ServiceBinding
作为资源,这意味着 Helm 在安装其任何 InstallOrder 列表(特别是Deployment
s)后安装这些资源类型。这似乎与我的图表上运行helm install --dry-run --debug
输出相匹配,其中顺序指示最后应用 K8S 服务目录资源。
问题:我无法理解的是,为什么我的Deployment
不能使用 Helm 安装失败。 毕竟,我的Deployment
资源似乎在ServiceBinding
之前就已经部署了。这是我Deployment
引用的ServiceBinding
产生的Secret
。我希望它会失败,因为当安装Deployment
时,Secret
还没有。但事实并非如此。
这只是一个时间故障/幸运巧合,还是我可以依靠,为什么?
谢谢!
正如我发布的评论中所述:
事实上,您的
Deployment
一开始就失败了Status: CreateContainerConfigError
.您的Deployment
是在从ServiceBinding
Secret
之前创建的。它仅在ServiceBinding
Secret
可用时重新创建时工作。
我想通过示例提供更多见解,说明为什么Deployment
没有失败。
正在发生的事情(按顺序简化):
Deployment
->创建并生成了一个Pod
Pod
->状态为失败的 pod:由于缺少Secret
而CreateContainerConfigError
ServiceBinding
->在后台创建Secret
Pod
获得所需的Secret
并开始
前面提到的InstallOrder
将在第 147 行的评论中将ServiceInstace
和ServiceBinding
保留为最后。
示例
假设:
- 有一个工作的 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
第一种方法
如前所述,Deployment
的Pod
无法启动,因为当Pod
尝试生成时Secret
不可用。Secret
可供使用后,Pod
开始。
该Pod
的状态如下:
Pending
ContainerCreating
CreateContainerConfigError
Running
这是一个时间戳为Pod
和Secret
的表:
| 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 将自定义资源ServiceBinding
和ServiceInstance
包含在可安装资源的有序列表中,并在安装阶段的早期安装它们。
但即使没有这个,Kubernetes 实际上也能很好地处理它。安装顺序(在这种情况下)真的无关紧要。这是一件好事!