引言

随着容器化技术的普及,Kubernetes(K8s)已成为容器编排的事实标准。将Python应用部署到K8s不仅能提高应用的可扩展性和可靠性,还能简化运维管理。本文将从零基础开始,详细介绍如何将一个Python项目(以Flask为例)完整部署到Kubernetes集群,包括环境准备、应用容器化、K8s资源配置、部署验证及进阶优化,适合刚接触容器和K8s的开发者学习实践。

一、环境准备

1.1 必备工具

工具 版本要求 作用
Python 3.6+ 开发Python应用
Docker 19.03+ 容器化应用
Kubernetes集群 1.18+ 容器编排平台
kubectl 与K8s集群版本匹配 K8s命令行工具
镜像仓库 Docker Hub或私有仓库 存储Docker镜像

1.2 环境搭建

安装Docker
# Ubuntu安装Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# 启动Docker并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装
docker --version  # 应输出Docker版本信息
配置Kubernetes集群

对于初学者,推荐使用以下简化方案:

  • 本地开发:Minikube或Docker Desktop内置K8s
  • 云环境:阿里云ACK、腾讯云TKE、AWS EKS等托管K8s服务

Minikube安装示例

# 安装Minikube(Linux)
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

# 启动Minikube集群
minikube start --driver=docker

# 验证集群状态
minikube status
kubectl get nodes  # 应显示一个就绪节点

二、创建Python应用

2.1 开发简单Flask应用

# 创建项目目录
mkdir my-python-app && cd my-python-app

# 创建并激活虚拟环境
python3 -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate  # Windows

# 安装Flask
pip install Flask==2.0.1

# 生成requirements.txt
pip freeze > requirements.txt

2.2 编写应用代码

创建app.py文件:

from flask import Flask
import os
import socket

app = Flask(__name__)

@app.route('/')
def hello():
    """返回包含主机名和环境信息的问候语"""
    # 获取容器主机名(在K8s中即为Pod名称)
    hostname = socket.gethostname()
    # 获取环境变量(可通过K8s配置注入)
    env = os.environ.get('ENV', 'production')
    
    return f"""
    <h1>Hello from Kubernetes!</h1>
    <p>Pod Name: {hostname}</p>
    <p>Environment: {env}</p>
    <p>Python Flask App running on Kubernetes</p>
    """

if __name__ == '__main__':
    # 绑定到所有网络接口,监听5000端口
    app.run(host='0.0.0.0', port=5000, debug=False)

2.3 本地测试应用

# 运行Flask应用
python app.py

# 在另一个终端测试
curl http://localhost:5000  # 应返回Hello页面内容

三、Docker容器化应用

3.1 编写Dockerfile

在项目根目录创建Dockerfile

# 基础镜像:Python 3.8-slim(轻量级版本)
FROM python:3.8-slim

# 设置工作目录
WORKDIR /app

# 设置Python环境变量
ENV PYTHONDONTWRITEBYTECODE=1  # 不生成pyc文件
ENV PYTHONUNBUFFERED=1          # 实时输出stdout/stderr

# 安装系统依赖(如需)
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    && rm -rf /var/lib/apt/lists/*

# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制项目文件
COPY . .

# 暴露应用端口
EXPOSE 5000

# 启动命令
CMD ["python", "app.py"]

3.2 构建Docker镜像

# 构建镜像(注意末尾的点)
docker build -t my-python-app:v1.0 .

# 查看构建的镜像
docker images | grep my-python-app

3.3 本地测试Docker镜像

# 运行容器
docker run -d -p 5000:5000 --name python-app-test my-python-app:v1.0

# 测试访问
curl http://localhost:5000

# 查看容器日志
docker logs python-app-test

# 停止并删除测试容器
docker stop python-app-test && docker rm python-app-test

3.4 推送镜像到仓库

K8s集群需要从镜像仓库拉取镜像,因此需要将本地镜像推送到仓库:

使用Docker Hub
# 登录Docker Hub
docker login

# 标记镜像(格式:仓库用户名/镜像名:标签)
docker tag my-python-app:v1.0 yourusername/my-python-app:v1.0

# 推送镜像
docker push yourusername/my-python-app:v1.0
使用私有仓库(如阿里云ACR)
# 登录私有仓库
docker login --username=yourusername registry.cn-beijing.aliyuncs.com

# 标记镜像
docker tag my-python-app:v1.0 registry.cn-beijing.aliyuncs.com/yournamespace/my-python-app:v1.0

# 推送镜像
docker push registry.cn-beijing.aliyuncs.com/yournamespace/my-python-app:v1.0

注意:如果使用Minikube本地集群,可以直接使用本地镜像,无需推送:

# 将本地镜像加载到Minikube
minikube image load my-python-app:v1.0

四、Kubernetes部署配置

4.1 创建Deployment配置

创建deployment.yaml文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-app-deployment  # Deployment名称
  labels:
    app: python-app            # Deployment标签
spec:
  replicas: 3                  # 副本数量(3个Pod)
  selector:
    matchLabels:
      app: python-app          # 匹配Pod标签
  strategy:
    rollingUpdate:
      maxSurge: 1              # 滚动更新时最大可超出的副本数
      maxUnavailable: 0        # 滚动更新时最大不可用副本数
    type: RollingUpdate        # 滚动更新策略(避免服务中断)
  template:
    metadata:
      labels:
        app: python-app        # Pod标签
    spec:
      containers:
      - name: python-app-container
        image: my-python-app:v1.0  # 镜像名称(使用本地镜像)
        # 如果使用远程仓库镜像,替换为:
        # image: yourusername/my-python-app:v1.0
        ports:
        - containerPort: 5000   # 容器端口
        resources:              # 资源限制
          requests:
            cpu: "100m"         # 最小CPU需求(100毫核)
            memory: "128Mi"     # 最小内存需求
          limits:
            cpu: "500m"         # 最大CPU限制
            memory: "256Mi"     # 最大内存限制
        env:                    # 环境变量
        - name: ENV
          value: "production"
        livenessProbe:          # 存活探针(健康检查)
          httpGet:
            path: /
            port: 5000
          initialDelaySeconds: 10  # 启动后延迟检查时间
          periodSeconds: 5         # 检查间隔时间
        readinessProbe:         # 就绪探针(是否可接收请求)
          httpGet:
            path: /
            port: 5000
          initialDelaySeconds: 5
          periodSeconds: 3

4.2 创建Service配置

创建service.yaml文件:

apiVersion: v1
kind: Service
metadata:
  name: python-app-service  # Service名称
spec:
  selector:
    app: python-app         # 匹配Pod标签
  ports:
  - port: 80                # Service端口
    targetPort: 5000        # 容器端口
    protocol: TCP
  type: NodePort            # 服务类型(NodePort可从集群外部访问)
  # 对于生产环境,可使用LoadBalancer类型(需要云服务商支持)
  # type: LoadBalancer

4.3 合并配置文件(可选)

也可以将Deployment和Service合并到一个文件中(使用---分隔):

# k8s-deploy.yaml
apiVersion: apps/v1
kind: Deployment
# ... Deployment配置(同上)...
---
apiVersion: v1
kind: Service
# ... Service配置(同上)...

五、部署到Kubernetes集群

5.1 应用配置文件

# 应用单个配置文件
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

# 或应用合并配置文件
kubectl apply -f k8s-deploy.yaml

5.2 检查部署状态

# 查看Deployment
kubectl get deployments
kubectl describe deployment python-app-deployment

# 查看Pod
kubectl get pods -o wide  # -o wide显示Pod所在节点和IP
kubectl logs <pod-name>   # 查看指定Pod日志

# 查看Service
kubectl get services
kubectl describe service python-app-service

5.3 访问应用

NodePort方式访问
# 获取Node IP(Minikube环境)
minikube ip  # 输出Minikube节点IP

# 获取Service NodePort端口
kubectl get service python-app-service | grep NodePort

# 访问应用
curl http://<node-ip>:<node-port>
本地端口转发(开发调试)
# 将本地端口转发到Pod
kubectl port-forward <pod-name> 5000:5000

# 或转发到Service
kubectl port-forward service/python-app-service 5000:80

# 然后在本地访问
curl http://localhost:5000
Minikube环境特殊访问方式
# 直接打开服务(自动处理端口转发)
minikube service python-app-service

六、进阶配置与优化

6.1 使用ConfigMap管理配置

创建configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: python-app-config
data:
  ENV: "production"
  APP_NAME: "My Python App"
  LOG_LEVEL: "info"

在Deployment中引用:

spec:
  template:
    spec:
      containers:
      - name: python-app-container
        # ...其他配置...
        envFrom:
        - configMapRef:
            name: python-app-config  # 引用ConfigMap

6.2 使用Secret管理敏感信息

创建secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: python-app-secret
type: Opaque
data:
  # 注意:值需要Base64编码
  api_key: dGhpc2lzbXlzZWNyZXRrZXk=  # "thisismysecretkey"的Base64编码
  db_password: cGFzc3dvcmQxMjM=      # "password123"的Base64编码

在Deployment中引用:

spec:
  template:
    spec:
      containers:
      - name: python-app-container
        # ...其他配置...
        env:
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: python-app-secret
              key: api_key
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: python-app-secret
              key: db_password

6.3 配置自动扩缩容

创建hpa.yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: python-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: python-app-deployment
  minReplicas: 2        # 最小副本数
  maxReplicas: 10       # 最大副本数
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70  # CPU使用率超过70%时扩容
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80  # 内存使用率超过80%时扩容

应用配置:

kubectl apply -f hpa.yaml

七、常见问题与解决方案

7.1 Pod状态为ImagePullBackOff

问题:K8s无法拉取镜像。

解决方案

  1. 检查镜像名称和标签是否正确
  2. 确认镜像已推送到仓库
  3. 如果使用私有仓库,创建镜像拉取密钥:
    kubectl create secret docker-registry myregistrykey \
      --docker-server=registry.cn-beijing.aliyuncs.com \
      --docker-username=yourusername \
      --docker-password=yourpassword \
      --docker-email=youremail@example.com
    
  4. 在Deployment中引用密钥:
    spec:
      template:
        spec:
          imagePullSecrets:
          - name: myregistrykey
    

7.2 Pod状态为CrashLoopBackOff

问题:容器启动后立即崩溃并重启。

解决方案

  1. 查看容器日志:kubectl logs <pod-name> --previous(–previous查看上一次启动日志)
  2. 检查应用是否监听正确的地址和端口(必须是0.0.0.0,不能是127.0.0.1)
  3. 检查资源限制是否合理,避免因资源不足被终止
  4. 确保容器内进程在前台运行(不要使用nohup或&后台运行)

7.3 无法从外部访问应用

问题:Service已创建,但无法通过NodePort访问。

解决方案

  1. 检查防火墙规则,确保NodePort端口已开放
  2. 确认Service的selector与Pod标签匹配:kubectl describe service python-app-service
  3. 检查Pod是否正常运行且就绪:kubectl get pods
  4. 尝试直接访问Pod IP验证应用是否正常:kubectl exec -it <pod-name> -- curl http://localhost:5000

7.4 滚动更新失败

问题:更新Deployment后,新Pod无法启动。

解决方案

  1. 查看部署历史:kubectl rollout history deployment/python-app-deployment
  2. 回滚到上一版本:kubectl rollout undo deployment/python-app-deployment
  3. 检查新镜像是否存在问题,可本地测试新镜像
  4. 调整滚动更新策略,增加maxUnavailable或减小maxSurge

八、总结

本文详细介绍了将Python项目部署到Kubernetes的完整流程,从环境准备、应用开发、Docker容器化,到K8s资源配置和部署验证,涵盖了初学者需要了解的所有关键步骤。通过本文学习,你应该能够:

  1. 使用Docker容器化Python应用
  2. 编写Kubernetes Deployment和Service配置文件
  3. 部署应用到K8s集群并验证访问
  4. 应用ConfigMap和Secret管理配置
  5. 配置自动扩缩容以应对负载变化
  6. 诊断和解决常见部署问题

Kubernetes作为容器编排平台,功能远不止于此。后续你可以进一步学习:

  • 使用Ingress配置HTTP路由和SSL
  • 实现蓝绿部署或金丝雀发布
  • 集成监控和日志系统(如Prometheus、Grafana、ELK)
  • 使用Helm简化K8s应用管理

希望本文能帮助你顺利踏上Kubernetes的学习之旅,为你的Python应用构建更强大、更可靠的部署架构!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐