![](/img/trans.png)
[英]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.