Kubernetes 部署 Python Flask 项目

发布时间 2023-10-08 16:18:08作者: gisliuliang

1、编写源代码及Dockerfile
test.py

from flask import Flask
import socket
app = Flask(__name__)


@app.route('/')
def hello():
    return socket.gethostbyname(socket.gethostname())


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001)

requirements.txt

flask

Docfile

FROM python:3.8-slim-buster

# 设置工作目录
WORKDIR /app

# 将当前目录下的所有文件复制到容器的工作目录
COPY . /app

# 安装 Flask 和其他依赖项
RUN pip install -r requirements.txt

# 指定端口号
EXPOSE 5001

# 在容器启动时运行命令
CMD ["python", "/app/test.py"]

2、打包镜像:docker build -t liu/test .
3、登录阿里云仓库:docker login --username=用户名 registry.cn-hangzhou.aliyuncs.com,输入密码
4、docker images查看镜像ID,给镜像打tag:docker tag 镜像ID registry.cn-hangzhou.aliyuncs.com/csugis/我的仓库:版本号
5、推送到远程仓库:docker push registry.cn-hangzhou.aliyuncs.com/csugis/我的仓库:版本号
6、编写部署文件test01.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-web-app
  labels:
    app: flask-web-app
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: flask-web-app
      version: v1
  template:
    metadata:
      labels:
        app: flask-web-app
        version: v1
    spec:
      containers:
      - name: flask-web-app
        image: registry.cn-hangzhou.aliyuncs.com/csugis/我的仓库:版本号
        ports:
        - containerPort: 5001
---
apiVersion: v1
kind: Service
metadata:
  name: flask-web-app-service
spec:
  type: NodePort
  ports:
  - port: 5001
    protocol: TCP
    targetPort: 5001
    nodePort: 32510
    name: http
  selector:
    app: flask-web-app
    version: v1

7、在部署机上执行:kubectl apply -f test01.yaml

[root@node app]# kubectl apply -f test01.yaml
deployment.apps/flask-web-app created
service/flask-web-app-service created

8、查看部署情况:

[root@k8s-master01 ~]# kubectl get svc
NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
flask-web-app-service   NodePort    10.68.51.169   <none>        5001:32510/TCP   10s
kubernetes              ClusterIP   10.68.0.1      <none>        443/TCP          9d

9[root@k8s-master01 ~]# kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP            NODE              NOMINATED NODE   READINESS GATES
flask-web-app-59d498b4c4-8p6kj   1/1     Running   0          32s   172.20.5.27   192.168.209.135   <none>           <none>
flask-web-app-59d498b4c4-s2bbb   1/1     Running   0          32s   172.20.4.35   192.168.209.134   <none>           <none>
flask-web-app-59d498b4c4-vsgw8   1/1     Running   0          32s   172.20.3.19   192.168.209.133   <none>           <none>

9、测试

[root@k8s-master01 ~]# curl 10.68.51.169:5001
172.20.5.27
[root@k8s-master01 ~]# curl 10.68.51.169:5001
172.20.4.35
[root@k8s-master01 ~]# curl 10.68.51.169:5001
172.20.3.19

开始试了一天,出现一个问题:服务只在一个节点上有响应,请求另外两个节点上的pod服务均返回curl: (7) Failed connect to 172.20.4.34:5001; Connection refused这样的报错

经过kubectl logs flask-web-app-58fd7f9888-brmj6查看日志

[root@k8s-master01 ~]# kubectl logs flask-web-app-58fd7f9888-brmj6
 * Serving Flask app 'test'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5001
Press CTRL+C to quit

[root@k8s-master01 ~]# kubectl logs flask-web-app-58fd7f9888-6s9c6
 * Serving Flask app 'test'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5001
 * Running on http://172.20.3.18:5001
Press CTRL+C to quit

kubectl exec -it flask-web-app-58fd7f9888-brmj6 -n default bash进入容器排查

[root@k8s-master01 ~]# kubectl exec -it flask-web-app-58fd7f9888-brmj6 -n default bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@flask-web-app-58fd7f9888-brmj6:/app# ls
test.py
root@flask-web-app-58fd7f9888-brmj6:/app# cat test.py
from flask import Flask
import socket
app = Flask(__name__)


@app.route('/')
def hello():
    return socket.gethostbyname(socket.gethostname())


if __name__ == '__main__':
    app.run(port=5001)

发现问题出在镜像的版本上。可以正确返回的那个节点上的代码是最新正确版,另外两个是之前的版本(没写port=0.0.0.0),但是他们都是同一个版本号v1,导致不同机器上的代码不一致。然后重新打tag上传镜像,并重新部署才得到正确的返回

删除deployment:kubectl delete deployment flask-web-app

删除svc:kubectl delete svc flask-web-app-service