Docker部署Uvicorn服务后Kubernetes集群内端口无法访问排查
问题描述
基于FastAPI+Uvicorn开发的应用通过Docker容器部署到Kubernetes集群后,本地环境运行正常,但在集群内的容器中执行curl http://127.0.0.1:8000时提示连接被拒绝。已在Uvicorn启动命令中添加--host 0.0.0.0参数,容器内ps命令显示Uvicorn进程正常运行,Kubernetes Pod日志显示服务监听http://0.0.0.0:8000,但netstat无监听端口记录。期望执行curl localhost:8000时能返回{"Hello":"World"}。
错误信息
~/chat-server # curl http://127.0.0.1:8000 curl: (7) Failed to connect to 127.0.0.1 port 8000 after 0 ms: Connection refused
Dockerfile
FROM python:3.10-alpine3.16 LABEL jiang (jigtigqi@gmail.com) ENV LANG=en_US.UTF-8 \ LC_ALL=en_US.UTF-8 \ TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone \ && mkdir -p /root/chat-server # upgrade pip RUN pip install --upgrade pip && apk add curl ADD . /root/chat-server/ EXPOSE 8000 RUN pip3 install -r /root/chat-server/requirements.txt WORKDIR /root/chat-server/ ENTRYPOINT exec python3 -m uvicorn main:app --port 8000 --host 0.0.0.0 --reload
main.py
from typing import Union from fastapi import FastAPI from src.chat.chatgpt import chat_server app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"}
容器内ps命令输出
~/chat-server # ps PID USER TIME COMMAND 1 root 0:07 python3 -m uvicorn main:app --port 8000 --host 0.0.0.0 --reload 7 root 0:00 [python3] 8 root 0:00 [python3] 9 root 0:00 sh 35 root 0:00 ps
Kubernetes Pod日志
➜ ~ kubectl logs chat-server-service-599b95f4cd-5rnvb --tail=100 INFO: Will watch for changes in these directories: ['/root/chat-server'] INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO: Started reloader process [1] using StatReload
Kubernetes Deployment配置
apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "16" kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"chat-server-service"},"name":"chat-server-service","namespace":"reddwarf-pro"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"chat-server-service"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"annotations":{"kubectl.kubernetes.io/restartedAt":"2022-06-15T13:12:33Z"},"creationTimestamp":null,"labels":{"app":"chat-server-service"}},"spec":{"containers":[{"env":[{"name":"DATABASE_URL","valueFrom":{"configMapKeyRef":{"key":"database_url","name":"fortune-service-pro-config"}}},{"name":"MUSIC_DATABASE_URL","valueFrom":{"configMapKeyRef":{"key":"music_database_url","name":"fortune-service-pro-config"}}},{"name":"QUARK_DATABASE_URL","valueFrom":{"configMapKeyRef":{"key":"quark_database_url","name":"fortune-service-pro-config"}}},{"name":"DICT_DATABASE_URL","valueFrom":{"configMapKeyRef":{"key":"dict_database_url","name":"fortune-service-pro-config"}}},{"name":"FORTUNE_DATABASE_URL","valueFrom":{"configMapKeyRef":{"key":"fortune_database_url","name":"fortune-service-pro-config"}}},{"name":"ENV","valueFrom":{"configMapKeyRef":{"key":"env","name":"fortune-service-pro-config"}}}],"image":"registry.cn-hongkong.aliyuncs.com/reddwarf-pro/chat-server:c51608efaa8c11b5d3c475399550180068a107f1","imagePullPolicy":"IfNotPresent","name":"fortune-service","ports":[{"containerPort":80,"protocol":"TCP"}],"resources":{"limits":{"cpu":"50m","memory":"20Mi"},"requests":{"cpu":"20m","memory":"6Mi"}},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","imagePullSecrets":[{"name":"hongkong-regcred"}],"restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}}} kubernetes.io/change-cause: kubectl set image deployment/chat-server-service chat-server-service=registry.cn-hongkong.aliyuncs.com/reddwarf-pro/chat-server:f4d5b0ccb8b4c0e5cfd37546ef5cdcb9aabfd67a --record=true --namespace=reddwarf-pro creationTimestamp: "2023-03-02T09:49:51Z" generation: 21 labels: app: chat-server-service name: chat-server-service namespace: reddwarf-pro resourceVersion: "111857114" uid: 275da678-95ad-419c-816b-74f08298116f spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: chat-server-service strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: annotations: kubectl.kubernetes.io/restartedAt: "2023-03-02T12:18:14Z" creationTimestamp: null labels: app: chat-server-service spec: containers: - env: - name: DATABASE_URL valueFrom: configMapKeyRef: key: database_url name: fortune-service-pro-config - name: MUSIC_DATABASE_URL valueFrom: configMapKeyRef: key: music_database_url name: fortune-service-pro-config - name: QUARK_DATABASE_URL valueFrom: configMapKeyRef: key: quark_database_url name: fortune-service-pro-config - name: DICT_DATABASE_URL valueFrom: configMapKeyRef: key: dict_database_url name: fortune-service-pro-config - name: FORTUNE_DATABASE_URL valueFrom: configMapKeyRef: key: fortune_database_url name: fortune-service-pro-config - name: ENV valueFrom: configMapKeyRef: key: env name: fortune-service-pro-config image: registry.cn-hongkong.aliyuncs.com/reddwarf-pro/chat-server:f4d5b0ccb8b4c0e5cfd37546ef5cdcb9aabfd67a imagePullPolicy: IfNotPresent name: chat-server-service ports: - containerPort: 80 protocol: TCP resources: limits: cpu: 50m memory: 20Mi requests: cpu: 20m memory: 6Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst imagePullSecrets: - name: hongkong-regcred restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 status: availableReplicas: 1 conditions: - lastTransitionTime: "2023-03-15T07:28:38Z" lastUpdateTime: "2023-03-15T07:28:38Z" message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: "2023-03-02T12:38:52Z" lastUpdateTime: "2023-03-15T07:45:24Z" message: ReplicaSet "chat-server-service-599b95f4cd" has successfully progressed. reason: NewReplicaSetAvailable status: "True" type: Progressing observedGeneration: 21 readyReplicas: 1 replicas: 1 updatedReplicas: 1
容器内netstat命令输出
~/chat-server # netstat -tulpen Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
解决方案
核心问题分析
- Uvicorn热重载进程异常:容器中PID=1的是Uvicorn的重载进程(StatReload),实际处理请求的子进程在Alpine镜像环境下可能因权限或文件监听问题启动失败,导致netstat无监听端口记录,父进程却仍存活。
--reload仅适用于本地开发,生产容器部署会引发进程管理问题。 - Kubernetes端口配置不匹配:Deployment中
containerPort设置为80,与应用实际监听的8000端口不符,虽不是容器内curl失败的直接原因,但会导致集群服务无法正常访问应用。
修复步骤
1. 移除Uvicorn热重载参数
修改Dockerfile的ENTRYPOINT,删除--reload:
ENTRYPOINT exec python3 -m uvicorn main:app --port 8000 --host 0.0.0.0
2. 修正Kubernetes Deployment端口
将Deployment中的containerPort改为8000:
ports: - containerPort: 8000 protocol: TCP
3. 重新构建部署
- 构建新镜像:
docker build -t <你的镜像标签> . - 推送镜像到仓库:
docker push <你的镜像标签> - 更新Deployment:
kubectl set image deployment/chat-server-service chat-server-service=<你的镜像标签> -n reddwarf-pro
4. 验证修复
进入容器执行curl http://127.0.0.1:8000,应返回{"Hello":"World"};执行netstat -tulpen可看到8000端口处于监听状态。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

