[英]How to query hdfs from a spark cluster (2.1) which is running on kubernetes?
[英]Application running in Kubernetes cron job does not connect to database in same Kubernetes cluster
我有一个运行 PostgreSQL 数据库的 Kube.netes 集群、一个 Grafana 仪表板和一个 Python 单次运行应用程序(构建为 Docker 图像),该应用程序每小时在 Kube.netes CronJob
中运行一次(参见下面的清单)。 此外,这一切都是使用带有 Istio side-car 注入的 ArgoCD 部署的。
我遇到的问题(如标题所示)是我的 Python 应用程序无法连接到集群中的数据库。 这对我来说很奇怪,因为仪表板实际上可以连接到数据库,所以我不确定 Python 应用程序可能有什么不同。
以下是我的清单(更改了一些内容以删除可识别信息):
database.yaml
的内容:
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: database
name: database
spec:
replicas: 1
selector:
matchLabels:
app: database
strategy: {}
template:
metadata:
labels:
app: database
spec:
containers:
- image: postgres:12.5
imagePullPolicy: ""
name: database
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_DB
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
resources: {}
readinessProbe:
initialDelaySeconds: 30
tcpSocket:
port: 5432
restartPolicy: Always
serviceAccountName: ""
volumes: null
status: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
app: database
name: database
spec:
ports:
- name: "5432"
port: 5432
targetPort: 5432
selector:
app: database
status:
loadBalancer: {}
dashboard.yaml
的内容:
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: dashboard
name: dashboard
spec:
replicas: 1
selector:
matchLabels:
app: dashboard
strategy: {}
template:
metadata:
labels:
app: dashboard
spec:
containers:
- image: grafana:7.3.3
imagePullPolicy: ""
name: dashboard
ports:
- containerPort: 3000
resources: {}
env:
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_DB
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
volumeMounts:
- name: grafana-datasource
mountPath: /etc/grafana/provisioning/datasources
readinessProbe:
initialDelaySeconds: 30
httpGet:
path: /
port: 3000
restartPolicy: Always
serviceAccountName: ""
volumes:
- name: grafana-datasource
configMap:
defaultMode: 420
name: grafana-datasource
- name: grafana-dashboard-provision
status: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
app: dashboard
name: dashboard
spec:
ports:
- name: "3000"
port: 3000
targetPort: 3000
selector:
app: dashboard
status:
loadBalancer: {}
cronjob.yaml
的内容:
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: python
spec:
concurrencyPolicy: Replace
# TODO: Go back to hourly when finished testing/troubleshooting
# schedule: "@hourly"
schedule: "*/15 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- image: python-tool:1.0.5
imagePullPolicy: ""
name: python
args: []
command:
- /bin/sh
- -c
- >-
echo "$(POSTGRES_USER)" > creds/db.creds;
echo "$(POSTGRES_PASSWORD)" >> creds/db.creds;
echo "$(SERVICE1_TOKEN)" > creds/service1.creds;
echo "$(SERVICE2_TOKEN)" > creds/service2.creds;
echo "$(SERVICE3_TOKEN)" > creds/service3.creds;
python3 -u main.py;
echo "Job finished with exit code $?";
env:
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_DB
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
- name: SERVICE1_TOKEN
valueFrom:
secretKeyRef:
name: api-tokens-secret
key: SERVICE1_TOKEN
- name: SERVICE2_TOKEN
valueFrom:
secretKeyRef:
name: api-tokens-secret
key: SERVICE2_TOKEN
- name: SERVICE3_TOKEN
valueFrom:
secretKeyRef:
name: api-tokens-secret
key: SERVICE3_TOKEN
restartPolicy: OnFailure
serviceAccountName: ""
status: {}
现在,正如我提到的,Istio 也是这张图片的一部分,所以我有一个用于仪表板的虚拟服务,因为它应该可以在集群外部访问,但仅此而已。
把所有这些都解决了,这就是我自己所做的尝试和解决这个问题的方法:
确认CronJob
正在使用正确的连接设置(即主机、数据库名称、用户名和密码)连接到数据库。
为此,我向CronJob
部署添加了 echo 语句,显示用户名和密码(我知道,我知道),它们是预期值。 我也知道这些是数据库的正确连接设置,因为我逐字使用它们将仪表板连接到数据库,从而成功连接。
Grafana 仪表盘的数据源设置:
来自 Python 应用程序的错误消息(显示在容器的 ArgoCD 日志中):
考虑到 Istio 可能会导致此问题,我尝试为CronJob
资源禁用 Istio side-car 注入(通过将此注释添加到metadata.annotations
部分: sidecar.istio.io/inject: false
)但注释实际上从未出现在Argo 日志,并且在CronJob
运行时没有观察到任何变化。
我尝试在运行 Python 脚本的CronJob
容器中kubectl exec
以进行更多调试,但实际上从来没有能够做到,因为一旦发生连接错误,容器就会退出。
就是说,在这方面我已经用我的头撞墙够久了。 谁能发现我可能遗漏的东西并指出正确的方向,好吗?
我认为问题在于您的 pod 在 istio sidecar 准备好之前尝试连接到数据库。 因此无法建立连接。
Istio 运行一个初始化容器来配置 pod 路由表,因此所有流量都通过 sidecar 进行路由。 因此,如果 sidecar 没有运行并且另一个 pod 尝试连接到数据库,则无法建立连接。
有两种解决方法。
首先,您的工作可以等待 30 秒,然后再使用一些睡眠命令调用main.py
或者,您可以启用holdApplicationUntilProxyStarts
。 通过这个主容器将不会启动,直到边车运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.