我正在尝试实现一个 Helm Chart 来部署 Python 应用程序。这个 python 应用程序在同一个 docker 镜像上有多个 Web 服务器。因此,使用相同的图像,我可以运行网络服务器 A、B、C 等。彼此之间唯一发生变化的是图像内部的路径。因此,对于 Web 服务器 A 来说,类似于 /path/to/web_server/A.py,而 B 则类似于 /path/to/web_server/B.py,依此类推。 我的想法是创建这个单一的 docker 镜像,并使用多个 value.yaml 使用 Helm Charts 将每个 Web 服务器部署到 Kubernetes 中。
我正在使用 helm CLI 为这些应用程序创建部署和服务:
helm install app -f ./path/to/webserver_A.yaml webserverA
部署后,它的状态为 CrashLoopBackOff,当我运行
kubectl describe pod
检查应用程序的详细信息时,我收到错误:no such file or directory: unknown
。
我使用
docker run my_image /opt/my_app/path/to/webserverA.py --host 0.0.0.0 --port 8001
测试了 docker 镜像,它在网络服务器上运行良好。在此图中,我将工作目录定义为 /opt/my_app,将入口点定义为 "python"。所以图像正在按预期运行。在 Kubernetes 上,我尝试使用以下命令以交互模式运行图像:kubectl run test --rm -i -tty --image my_image:1.0 -- /bin/bash
来检查可能出现的问题。使用交互模式,我能够运行 python /opt/my_app/path/to/webserverA.py
并且它按预期工作,与使用 docker 映像的行为相同。
部署.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-webserver
labels:
app: webserver
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: webserver
template:
metadata:
labels:
app: webserver
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: {{ .Values.pod.cmd }}
args: {{ .Values.pod.args }}
ports:
- name: http
containerPort: {{ .Values.pod.port }}
protocol: TCP
服务.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-service
spec:
selector:
app.kubernetes.io/instance: {{ .Release.Name }}
type: {{ .Values.service.type }}
ports:
- protocol: {{ .Values.service.protocol | default "TCP" }}
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
webserverA.yaml(这是“我在 helm CLI 上使用的 value.yaml”)
replicaCount: 1
image:
repository: webserverImage
tag: "1.0"
pullPolicy: Never
service:
name: webserver-service
type: ClusterIP
port: 8001
targetPort: 8001
pod:
port: 8001
cmd: ["python","/opt/my_app/path/to/webserverA.py", "--host", "0.0.0.0", "--port","8001"]
env:
name: dev
当我直接在 deployment.yaml 上编写 cmd 时,网络服务器按预期启动,但是当我从自定义 value.yaml 获取 cmd 时,它确实获取了参数,但没有运行。
所以这有效:
部署.yaml
command: ["python","/opt/my_app/path/to/webserverA.py", "--host", "0.0.0.0", "--port","8001"]
这不起作用:
部署.yaml
command: {{ .Values.pod.cmd }}
您需要查看生成的清单才能发现问题。如果您从图表目录运行
helm template .
,您将看到:
.
.
.
- name: webserver
image: "webserverImage:1.0"
imagePullPolicy: Never
command: [python /opt/my_app/path/to/webserverA.py --host 0.0.0.0 --port 8001]
args:
ports:
- name: http
containerPort: 8001
protocol: TCP
请注意,
command
的值无效'它不再是具有多个值的列表;这是一个具有单个值 python /opt/my_app/path/to/webserverA.py --host 0.0.0.0 --port 8001
的列表。
您可以通过在模板中使用
toJson
过滤器来解决此问题:
.
.
.
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: {{ .Values.pod.cmd | toJson }}
这让你:
.
.
.
containers:
- name: webserver
image: "webserverImage:1.0"
imagePullPolicy: Never
command: ["python","/opt/my_app/path/to/webserverA.py","--host","0.0.0.0","--port","8001"]
这就是你想要的。