Kubernetes中Flask应用通过psycopg2连接Postgres服务失败求助
问题
本地通过minikube搭建Kubernetes集群,集群内已运行Postgres服务。部署Flask应用通过psycopg2连接Postgres并暴露REST接口时,gunicorn日志报错无法解析Postgres服务域名postgres-postgresql.kafkaplaypen.svc.cluster.local:5432。
报错日志
[2022-12-12 18:49:41 +0000] [10] [ERROR] Error handling request /popular/locations File "/usr/local/lib/python3.7/site-packages/psycopg2/__init__.py", line 122, in connect conn = _connect(dsn, connection_factory=connection_factory, **kwasync) psycopg2.OperationalError: could not translate host name "postgres-postgresql.kafkaplaypen.svc.cluster.local:5432" to address: Name or service not known
Postgres部署信息(Helm输出)
PostgreSQL can be accessed via port 5432 on the following DNS names from within your cluster: postgres-postgresql.kafkaplaypen.svc.cluster.local - Read/Write connection To get the password for "postgres" run: export POSTGRES_PASSWORD=$(kubectl get secret --namespace kafkaplaypen postgres-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d) To connect to your database run the following command: kubectl run postgres-postgresql-client --rm --tty -i --restart='Never' --namespace kafkaplaypen --image docker.io/bitnami/postgresql:15.1.0-debian-11-r7 --env="PGPASSWORD=$POSTGRES_PASSWORD" \ --command -- psql --host postgres-postgresql -U postgres -d postgres -p 5432 > NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID 1001} does not exist" To connect to your database from outside the cluster execute the following commands: kubectl port-forward --namespace kafkaplaypen svc/postgres-postgresql 5432:5432 & PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U postgres -d postgres -p 5432
Flask应用代码
app = Flask(__name__) app.config["DEBUG"] = True def get_db_connection(): conn = psycopg2.connect(host='postgres-postgresql.kafkaplaypen.svc.cluster.local:5432', database=os.environ['DB_NAME'], user=os.environ['DB_USERNAME'], password=os.environ['DB_PASSWORD']) return conn @app.route('/popular/locations') def get_popular_locations(): conn = get_db_connection() cur = conn.cursor() cur.execute('SELECT * FROM tolocations;') data = cur.fetchall() cur.close() conn.close() return data if __name__ == '__main__': app.run(host='0.0.0.0', port=8081, debug=True)
Flask Pod启动命令
kubectl run flaskapp -i --image flaskapp:latest --image-pull-policy Never --restart Never --namespace kafkaplaypen --env="DB_NAME=postgres" --env="DB_USERNAME=postgres" --env="DB_PASSWORD=$POSTGRES_PASSWORD"
Flask应用Dockerfile
FROM python:3.7-slim WORKDIR /app RUN apt-get update && apt-get install -y curl nano RUN pip3 install flask psycopg2-binary gunicorn COPY rest /app EXPOSE 8081 CMD gunicorn -b 0.0.0.0:8081 --log-file /app/logs/gunicorn.log --log-level DEBUG src.expose:app
排查与解决方案
核心问题:psycopg2的
connect参数使用错误,你将域名和端口合并写在host字段中,但psycopg2要求host仅填写域名/IP,端口需通过单独的port参数传递,合并写法会导致DNS解析失败。修复代码:修改Flask的数据库连接函数:
def get_db_connection(): conn = psycopg2.connect( host='postgres-postgresql.kafkaplaypen.svc.cluster.local', port=5432, database=os.environ['DB_NAME'], user=os.environ['DB_USERNAME'], password=os.environ['DB_PASSWORD'] ) return conn
- 额外验证步骤:
- 验证集群DNS解析:进入Flask Pod执行域名解析测试,确认服务域名可正常解析
kubectl exec -it flaskapp -n kafkaplaypen -- nslookup postgres-postgresql.kafkaplaypen.svc.cluster.local - 检查Postgres服务状态:确认服务已正常暴露端口
kubectl get svc postgres-postgresql -n kafkaplaypen
- 验证集群DNS解析:进入Flask Pod执行域名解析测试,确认服务域名可正常解析
内容的提问来源于stack exchange,提问作者Masquerade
相关产品推荐
相关产品推荐

