在 kubernetes 中调试 uWSGI
Debugging uWSGI in kubernetes
我有一对 kubernetes
pods,一个用于 nginx
,一个用于 Python Flask
+ uWSGI
。我已经在 docker-compose
本地测试了我的设置,它运行良好,但是在部署到 kubernetes
之后,两者之间似乎没有通信。最终结果是我在尝试到达我的位置时收到 502 网关错误。
所以我的问题不是关于我的设置有什么问题,而是我可以使用什么工具来调试这种情况。 uwsgi 有测试客户端吗?我可以使用 ncat 吗?我似乎没有从nginx得到任何有用的日志输出,我不知道uwsgi是否有日志。
我该如何调试?
作为参考,这是我的 nginx 位置:
location / {
# Trick to avoid nginx aborting at startup (set server in variable)
set $upstream_server ${APP_SERVER};
include uwsgi_params;
uwsgi_pass $upstream_server;
uwsgi_read_timeout 300;
uwsgi_intercept_errors on;
}
这是我的 wsgi.ini:
[uwsgi]
module = my_app.app
callable = app
master = true
processes = 5
socket = 0.0.0.0:5000
die-on-term = true
uid = www-data
gid = www-data
这是 nginx 的 kubernetes deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: nginx
name: nginx
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
service: nginx
strategy:
type: Recreate
template:
metadata:
labels:
service: nginx
spec:
imagePullSecrets:
- name: docker-reg
containers:
- name: nginx
image: <custom image url>
imagePullPolicy: Always
env:
- name: APP_SERVER
valueFrom:
secretKeyRef:
name: my-environment-config
key: APP_SERVER
- name: FK_SERVER_NAME
valueFrom:
secretKeyRef:
name: my-environment-config
key: SERVER_NAME
ports:
- containerPort: 80
- containerPort: 10443
- containerPort: 10090
resources:
requests:
cpu: 1m
memory: 200Mi
volumeMounts:
- mountPath: /etc/letsencrypt
name: my-storage
subPath: nginx
- mountPath: /dev/shm
name: dshm
restartPolicy: Always
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-storage-claim-nginx
- name: dshm
emptyDir:
medium: Memory
这是 nginx 的 kubernetes service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
service: nginx
name: nginx
spec:
type: LoadBalancer
ports:
- name: "nginx-port-80"
port: 80
targetPort: 80
protocol: TCP
- name: "nginx-port-443"
port: 443
targetPort: 10443
protocol: TCP
- name: "nginx-port-10090"
port: 10090
targetPort: 10090
protocol: TCP
selector:
service: nginx
这是 python flask 的 kubernetes deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: my-app
name: my-app
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
service: my-app
strategy:
type: Recreate
template:
metadata:
labels:
service: my-app
spec:
imagePullSecrets:
- name: docker-reg
containers:
- name: my-app
image: <custom image url>
imagePullPolicy: Always
ports:
- containerPort: 5000
resources:
requests:
cpu: 1m
memory: 100Mi
volumeMounts:
- name: merchbot-storage
mountPath: /app/data
subPath: my-app
- name: dshm
mountPath: /dev/shm
- name: local-config
mountPath: /app/secrets/local_config.json
subPath: merchbot-local-config-test.json
restartPolicy: Always
volumes:
- name: merchbot-storage
persistentVolumeClaim:
claimName: my-storage-claim-app
- name: dshm
emptyDir:
medium: Memory
- name: local-config
secret:
secretName: my-app-local-config
这是 nginx 的 kubernetes service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
service: my-app
name: my-app
spec:
ports:
- name: "my-app-port-5000"
port: 5000
targetPort: 5000
selector:
service: my-app
在 kubernetes 中调试与在外部调试并没有太大区别,只是需要为 kubernetes 世界覆盖一些概念。
kubernetes 中的 Pod 是您在概念上将其视为 VM 世界中的主机。 Pod 中的每个容器 运行 都会在本地主机上看到彼此的服务。从那里,一个 Pod 到任何其他东西都将涉及网络连接(即使端点是本地节点)。因此,开始使用本地主机上的服务进行测试,然后通过 pod IP、服务 IP、服务名称进行测试。
一些复杂性来自容器中可用的调试工具。通常,容器都是细长的,并没有所有可用的东西。因此,您要么需要在容器 运行(如果可以)时安装工具,要么构建一个特殊的 "debug" 容器,您可以在同一环境中按需部署。您始终可以回退到从也具有访问权限的集群节点进行测试。
如果有 python 可用,您可以 test with uswgi_curl
pip install uwsgi-tools
uwsgi_curl hostname:port /path
否则 nc
/curl
就足够了。
Pod 到本地主机
第一步是确保容器本身正在响应。在这种情况下,您可能有 python/pip 可供使用 uwsgi_curl
kubectl exec -ti my-app-XXXX-XXXX sh
nc -v localhost 5000
uwsgi_curl localhost:5000 /path
连播至 Pod/Service
接下来包括 kubernetes 网络。以 IP 开头,以名称结尾。
不太可能在这里有 python
,甚至 nc
但我认为在这里测试环境变量很重要:
kubectl exec -ti nginx-XXXX-XXXX sh
nc -v my-app-pod-IP 5000
nc -v my-app-service-IP 5000
nc -v my-app-service-name 5000
echo $APP_SERVER
echo $FK_SERVER_NAME
nc -v $APP_SERVER 5000
# or
uwsgi_curl $APP_SERVER:5000 /path
调试 Pod 到 Pod/Service
如果您确实需要使用调试 pod,请尝试尽可能模仿您正在测试的 pod。有一个通用的调试 pod/deployment 来快速测试任何东西是很棒的,但如果这没有揭示问题,您可能需要自定义部署以更紧密地模拟您正在测试的 pod。
在这种情况下,环境变量在连接设置中发挥作用,因此应该为调试 pod 模拟。
节点到 Pod/Service
Pods/Services 将从群集节点可用(如果您没有使用限制性网络策略)所以通常快速测试是检查 Pods/Services 是否从那里工作:
nc -v <pod_ip> <container_port>
nc -v <service_ip> <service_port>
nc -v <service__dns> <service_port>
在这种情况下:
nc -v <my_app_pod_ip> 5000
nc -v <my_app_service_ip> 5000
nc -v my-app.svc.<namespace>.cluster.local 5000
我有一对 kubernetes
pods,一个用于 nginx
,一个用于 Python Flask
+ uWSGI
。我已经在 docker-compose
本地测试了我的设置,它运行良好,但是在部署到 kubernetes
之后,两者之间似乎没有通信。最终结果是我在尝试到达我的位置时收到 502 网关错误。
所以我的问题不是关于我的设置有什么问题,而是我可以使用什么工具来调试这种情况。 uwsgi 有测试客户端吗?我可以使用 ncat 吗?我似乎没有从nginx得到任何有用的日志输出,我不知道uwsgi是否有日志。
我该如何调试?
作为参考,这是我的 nginx 位置:
location / {
# Trick to avoid nginx aborting at startup (set server in variable)
set $upstream_server ${APP_SERVER};
include uwsgi_params;
uwsgi_pass $upstream_server;
uwsgi_read_timeout 300;
uwsgi_intercept_errors on;
}
这是我的 wsgi.ini:
[uwsgi]
module = my_app.app
callable = app
master = true
processes = 5
socket = 0.0.0.0:5000
die-on-term = true
uid = www-data
gid = www-data
这是 nginx 的 kubernetes deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: nginx
name: nginx
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
service: nginx
strategy:
type: Recreate
template:
metadata:
labels:
service: nginx
spec:
imagePullSecrets:
- name: docker-reg
containers:
- name: nginx
image: <custom image url>
imagePullPolicy: Always
env:
- name: APP_SERVER
valueFrom:
secretKeyRef:
name: my-environment-config
key: APP_SERVER
- name: FK_SERVER_NAME
valueFrom:
secretKeyRef:
name: my-environment-config
key: SERVER_NAME
ports:
- containerPort: 80
- containerPort: 10443
- containerPort: 10090
resources:
requests:
cpu: 1m
memory: 200Mi
volumeMounts:
- mountPath: /etc/letsencrypt
name: my-storage
subPath: nginx
- mountPath: /dev/shm
name: dshm
restartPolicy: Always
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-storage-claim-nginx
- name: dshm
emptyDir:
medium: Memory
这是 nginx 的 kubernetes service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
service: nginx
name: nginx
spec:
type: LoadBalancer
ports:
- name: "nginx-port-80"
port: 80
targetPort: 80
protocol: TCP
- name: "nginx-port-443"
port: 443
targetPort: 10443
protocol: TCP
- name: "nginx-port-10090"
port: 10090
targetPort: 10090
protocol: TCP
selector:
service: nginx
这是 python flask 的 kubernetes deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: my-app
name: my-app
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
service: my-app
strategy:
type: Recreate
template:
metadata:
labels:
service: my-app
spec:
imagePullSecrets:
- name: docker-reg
containers:
- name: my-app
image: <custom image url>
imagePullPolicy: Always
ports:
- containerPort: 5000
resources:
requests:
cpu: 1m
memory: 100Mi
volumeMounts:
- name: merchbot-storage
mountPath: /app/data
subPath: my-app
- name: dshm
mountPath: /dev/shm
- name: local-config
mountPath: /app/secrets/local_config.json
subPath: merchbot-local-config-test.json
restartPolicy: Always
volumes:
- name: merchbot-storage
persistentVolumeClaim:
claimName: my-storage-claim-app
- name: dshm
emptyDir:
medium: Memory
- name: local-config
secret:
secretName: my-app-local-config
这是 nginx 的 kubernetes service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
service: my-app
name: my-app
spec:
ports:
- name: "my-app-port-5000"
port: 5000
targetPort: 5000
selector:
service: my-app
在 kubernetes 中调试与在外部调试并没有太大区别,只是需要为 kubernetes 世界覆盖一些概念。
kubernetes 中的 Pod 是您在概念上将其视为 VM 世界中的主机。 Pod 中的每个容器 运行 都会在本地主机上看到彼此的服务。从那里,一个 Pod 到任何其他东西都将涉及网络连接(即使端点是本地节点)。因此,开始使用本地主机上的服务进行测试,然后通过 pod IP、服务 IP、服务名称进行测试。
一些复杂性来自容器中可用的调试工具。通常,容器都是细长的,并没有所有可用的东西。因此,您要么需要在容器 运行(如果可以)时安装工具,要么构建一个特殊的 "debug" 容器,您可以在同一环境中按需部署。您始终可以回退到从也具有访问权限的集群节点进行测试。
如果有 python 可用,您可以 test with uswgi_curl
pip install uwsgi-tools
uwsgi_curl hostname:port /path
否则 nc
/curl
就足够了。
Pod 到本地主机
第一步是确保容器本身正在响应。在这种情况下,您可能有 python/pip 可供使用 uwsgi_curl
kubectl exec -ti my-app-XXXX-XXXX sh
nc -v localhost 5000
uwsgi_curl localhost:5000 /path
连播至 Pod/Service
接下来包括 kubernetes 网络。以 IP 开头,以名称结尾。
不太可能在这里有 python
,甚至 nc
但我认为在这里测试环境变量很重要:
kubectl exec -ti nginx-XXXX-XXXX sh
nc -v my-app-pod-IP 5000
nc -v my-app-service-IP 5000
nc -v my-app-service-name 5000
echo $APP_SERVER
echo $FK_SERVER_NAME
nc -v $APP_SERVER 5000
# or
uwsgi_curl $APP_SERVER:5000 /path
调试 Pod 到 Pod/Service
如果您确实需要使用调试 pod,请尝试尽可能模仿您正在测试的 pod。有一个通用的调试 pod/deployment 来快速测试任何东西是很棒的,但如果这没有揭示问题,您可能需要自定义部署以更紧密地模拟您正在测试的 pod。
在这种情况下,环境变量在连接设置中发挥作用,因此应该为调试 pod 模拟。
节点到 Pod/Service
Pods/Services 将从群集节点可用(如果您没有使用限制性网络策略)所以通常快速测试是检查 Pods/Services 是否从那里工作:
nc -v <pod_ip> <container_port>
nc -v <service_ip> <service_port>
nc -v <service__dns> <service_port>
在这种情况下:
nc -v <my_app_pod_ip> 5000
nc -v <my_app_service_ip> 5000
nc -v my-app.svc.<namespace>.cluster.local 5000