以下是一个基于 Python 的云原生 TodoList Demo 项目,涵盖 容器化、Kubernetes 编排、CI/CD、可观测性、弹性扩缩容 等核心云原生特性,代码简洁且附详细操作指南,适合入门学习。

在这里插入图片描述

项目概览

  • 目标:实现一个支持增删改查(CRUD)的 TodoList 后端服务,通过云原生技术栈部署,展示完整的云原生实践流程。
  • 技术栈
    • 后端:Python + FastAPI(轻量高性能框架)
    • 数据库:PostgreSQL(云原生持久化存储)
    • 容器化:Docker
    • 编排:Kubernetes(K8s)
    • CI/CD:GitHub Actions
    • 可观测性:Prometheus(监控) + Grafana(可视化) + Loki(日志)

一、项目结构

todolist-cloudnative/
├── app/                  # 核心业务代码
│   ├── main.py           # FastAPI 入口
│   ├── models.py         # SQLAlchemy 模型(数据库表结构)
│   ├── database.py       # 数据库连接工具
│   └── requirements.txt  # Python 依赖
├── docker/               # Docker 相关配置
│   └── Dockerfile        # 容器化构建脚本
├── k8s/                  # K8s 部署配置
│   ├── todo-deployment.yaml  # 应用 Deployment
│   ├── todo-service.yaml     # 应用 Service
│   ├── postgres-statefulset.yaml  # PostgreSQL StatefulSet
│   ├── postgres-service.yaml      # PostgreSQL Service
│   ├── configmap.yaml    # 配置(非敏感)
│   └── secret.yaml       # 敏感配置(数据库密码)
├── prometheus/           # Prometheus 监控配置
│   └── todolist.yml      # 抓取规则
├── .github/              # GitHub Actions 工作流
│   └── workflows/
│       └── deploy.yml    # CI/CD 自动化流程
└── README.md             # 操作指南

二、核心功能实现(Python 后端)

1. 安装依赖(app/requirements.txt
fastapi==0.104.1
uvicorn==0.23.2
sqlalchemy==2.0.23
psycopg2-binary==2.9.7  # PostgreSQL 驱动
python-multipart==0.0.6  # 文件上传(可选)
prometheus-fastapi-instrumentator==0.3.1  # Prometheus 指标暴露
2. 数据库模型(app/models.py
from sqlalchemy import Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()class TodoItem(Base):__tablename__ = "todo_items"id = Column(Integer, primary_key=True, index=True)title = Column(String(255), index=True, nullable=False)description = Column(String(500))completed = Column(Boolean, default=False)
3. 数据库连接(app/database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import os# 从环境变量获取数据库连接信息(K8s ConfigMap/Secret 注入)
DATABASE_URL = f"postgresql://{os.getenv('POSTGRES_USER')}:{os.getenv('POSTGRES_PASSWORD')}@{os.getenv('POSTGRES_HOST')}:{os.getenv('POSTGRES_PORT')}/{os.getenv('POSTGRES_DB')}"engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
4. FastAPI 入口(app/main.py
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from . import models, schemas, database
from prometheus_fastapi_instrumentator import Instrumentator# 初始化数据库表(仅首次运行时创建)
models.Base.metadata.create_all(bind=database.engine)app = FastAPI(title="TodoList 云原生服务")# 注入数据库会话
def get_db():db = database.SessionLocal()try:yield dbfinally:db.close()# 自动暴露 Prometheus 指标(请求计数、延迟)
Instrumentator().instrument(app).expose(app)# Todo 业务接口
@app.post("/todos/", response_model=schemas.TodoItem)
def create_todo(todo: schemas.TodoCreate, db: Session = Depends(get_db)):db_todo = models.TodoItem(**todo.dict())db.add(db_todo)db.commit()db.refresh(db_todo)return db_todo@app.get("/todos/{todo_id}", response_model=schemas.TodoItem)
def read_todo(todo_id: int, db: Session = Depends(get_db)):db_todo = db.query(models.TodoItem).filter(models.TodoItem.id == todo_id).first()if not db_todo:raise HTTPException(status_code=404, detail="Todo 不存在")return db_todo# 其他接口(更新、删除)类似,此处省略...
5. Pydantic 模型(app/schemas.py
from pydantic import BaseModelclass TodoCreate(BaseModel):title: strdescription: str = Noneclass TodoItem(TodoCreate):id: intcompleted: bool

在这里插入图片描述

三、容器化(Docker)

docker/Dockerfile
# 使用 Python 官方轻量镜像
FROM python:3.11-slim-bookworm# 设置工作目录
WORKDIR /app# 安装系统依赖(PostgreSQL 驱动需要)
RUN apt-get update && apt-get install -y --no-install-recommends gcc python3-dev \&& rm -rf /var/lib/apt/lists/*# 复制依赖文件并安装
COPY app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt# 复制项目代码
COPY app/ ./app/# 暴露 FastAPI 端口(8000)
EXPOSE 8000# 启动命令(UVicorn 自动重载仅在开发时启用)
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

四、Kubernetes 编排(云原生核心)

1. 配置管理(k8s/configmap.yamlk8s/secret.yaml

非敏感配置(ConfigMap)

apiVersion: v1
kind: ConfigMap
metadata:name: todo-config
data:POSTGRES_DB: "tododb"POSTGRES_HOST: "postgres-service"  # K8s Service 名称(服务发现)

敏感配置(Secret,需手动创建或通过 CI 注入)

# 生成 base64 编码的密码(实际生产建议用外部密钥管理系统)
echo -n "mypassword" | base64
apiVersion: v1
kind: Secret
metadata:name: todo-secret
type: Opaque
data:POSTGRES_USER: "admin"          # base64 编码值POSTGRES_PASSWORD: "bXlwYXNzd29yZA=="  # "mypassword" 的 base64POSTGRES_PORT: "5432"
2. PostgreSQL 部署(k8s/postgres-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:name: postgres
spec:serviceName: postgres-servicereplicas: 1  # 生产环境建议 3 副本 + 主从复制selector:matchLabels:app: postgrestemplate:metadata:labels:app: postgresspec:containers:- name: postgresimage: postgres:15-alpineenv:- name: POSTGRES_USERvalueFrom:secretKeyRef:name: todo-secretkey: POSTGRES_USER- name: POSTGRES_PASSWORDvalueFrom:secretKeyRef:name: todo-secretkey: POSTGRES_PASSWORD- name: POSTGRES_DBvalueFrom:configMapKeyRef:name: todo-configkey: POSTGRES_DBports:- containerPort: 5432volumeMounts:- name: postgres-datamountPath: /var/lib/postgresql/datavolumeClaimTemplates:  # 持久化存储(云原生存储卷)- metadata:name: postgres-dataspec:accessModes: [ "ReadWriteOnce" ]resources:requests:storage: 1Gi
3. Todo 服务部署(k8s/todo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: todo-deployment
spec:replicas: 2  # 初始副本数(弹性扩缩容基础)selector:matchLabels:app: todotemplate:metadata:labels:app: todospec:containers:- name: todoimage: your-docker-username/todolist:v1  # 替换为实际镜像地址ports:- containerPort: 8000env:- name: POSTGRES_USERvalueFrom:secretKeyRef:name: todo-secretkey: POSTGRES_USER- name: POSTGRES_PASSWORDvalueFrom:secretKeyRef:name: todo-secretkey: POSTGRES_PASSWORD- name: POSTGRES_HOSTvalueFrom:configMapKeyRef:name: todo-configkey: POSTGRES_HOST- name: POSTGRES_PORTvalueFrom:secretKeyRef:name: todo-secretkey: POSTGRES_PORT- name: POSTGRES_DBvalueFrom:configMapKeyRef:name: todo-configkey: POSTGRES_DBlivenessProbe:  # 存活探针(自动重启异常实例)httpGet:path: /healthport: 8000initialDelaySeconds: 30periodSeconds: 10readinessProbe:  # 就绪探针(流量路由前检查)httpGet:path: /healthport: 8000initialDelaySeconds: 5periodSeconds: 5
4. 服务暴露(k8s/todo-service.yamlk8s/todo-ingress.yaml

ClusterIP Service(内部访问)

apiVersion: v1
kind: Service
metadata:name: todo-service
spec:type: ClusterIPselector:app: todoports:- protocol: TCPport: 80targetPort: 8000

Ingress(外部访问,需安装 NGINX Ingress Controller)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: todo-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target: /
spec:rules:- http:paths:- path: /todospathType: Prefixbackend:service:name: todo-serviceport:number: 80

五、CI/CD 自动化(GitHub Actions)

.github/workflows/deploy.yml
name: Deploy to Kuberneteson:push:branches: [ "main" ]jobs:build-and-push:runs-on: ubuntu-lateststeps:- name: Checkout codeuses: actions/checkout@v4- name: Set up Docker Buildxuses: docker/setup-buildx-action@v3- name: Login to Docker Hubuses: docker/login-action@v3with:username: ${{ secrets.DOCKERHUB_USERNAME }}password: ${{ secrets.DOCKERHUB_TOKEN }}- name: Build and push Docker imageuses: docker/build-push-action@v5with:context: .file: docker/Dockerfilepush: truetags: your-docker-username/todolist:latest,your-docker-username/todolist:${{ github.sha }}deploy-to-k8s:needs: build-and-pushruns-on: ubuntu-lateststeps:- name: Checkout codeuses: actions/checkout@v4- name: Set up kubectluses: azure/setup-kubectl@v3with:version: 'v1.28.0'- name: Deploy to Kubernetes clusterrun: |# 替换镜像标签为最新提交 SHAsed -i "s|your-docker-username/todolist:v1|your-docker-username/todolist:${{ github.sha }}|g" k8s/todo-deployment.yaml# 应用 K8s 配置kubectl apply -f k8s/env:KUBECONFIG: ${{ secrets.KUBECONFIG }}  # 从 GitHub Secrets 读取集群配置

六、可观测性配置

1. Prometheus 监控(prometheus/todolist.yml
scrape_configs:- job_name: "todo_service"scrape_interval: 15sstatic_configs:- targets: ["todo-service:80"]  # K8s Service 域名(集群内部可解析)
2. Grafana 仪表盘(示例查询)
  • 请求速率rate(http_requests_total{job="todo_service"}[5m])
  • 平均延迟rate(http_request_duration_seconds_sum{job="todo_service"}[5m]) / rate(http_request_duration_seconds_count{job="todo_service"}[5m])
3. Loki 日志收集
  • 通过 Fluentd 或 Vector 将 Pod 日志(stdout/stderr)转发到 Loki。
  • Grafana 中查询日志:{job="todo_service"} | json

七、云原生特性验证

1. 容器化
  • 本地构建镜像:docker build -t todolist:v1 -f docker/Dockerfile .
  • 运行测试:docker run -p 8000:8000 todolist:v1,访问 http://localhost:8000/docs 验证接口。
2. Kubernetes 部署
  • 本地搭建 K8s 集群(Minikube 或 Kind):minikube start
  • 应用配置:kubectl apply -f k8s/
  • 查看状态:kubectl get pods,svc,ingress
3. 弹性扩缩容
  • 手动扩缩容:kubectl scale deployment/todo-deployment --replicas=3
  • 自动扩缩容(HPA):
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:name: todo-hpa
    spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: todo-deploymentminReplicas: 2maxReplicas: 10metrics:- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 70  # CPU 使用率超 70% 自动扩容
    
4. 故障自愈
  • 手动删除 Pod:kubectl delete pod <pod-name>,观察 K8s 自动重建新 Pod(状态变为 Running)。
5. 持续交付
  • 推送代码到 GitHub main 分支,触发 GitHub Actions 自动构建、测试、部署。

八、总结

通过这个 TodoList Demo,你可以完整体验云原生应用的核心流程:

  1. 容器化:用 Docker 封装应用,确保环境一致性。
  2. Kubernetes 编排:通过 Deployment、Service 等资源实现自动化管理。
  3. CI/CD:GitHub Actions 实现代码提交到生产的全自动化。
  4. 可观测性:Prometheus + Grafana 监控性能,Loki 收集日志。
  5. 弹性扩缩容:HPA 根据负载自动调整资源,保障高可用。

后续可扩展方向:

  • 拆分微服务(如用户服务、待办服务),用 Istio 实现服务网格。
  • 引入数据库读写分离(主从复制)。
  • 添加认证鉴权(OAuth2、JWT)。
  • 使用 Helm 打包 K8s 配置,简化多环境部署。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/922050.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/922050.shtml
英文地址,请注明出处:http://en.pswp.cn/news/922050.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go 日志的分装和使用 Zap + lumberjack

自带的log无法满足 按大小轮转 &#xff0c;按天数清理旧日志 &#xff0c;自动压缩 &#xff0c;限制备份数量 &#xff0c;防止磁盘写满 &#xff0c;生产环境推荐 等 使用 Zap lumberjack package mainimport ("go.uber.org/zap""go.uber.org/zap/zapcore&q…

【.Net技术栈梳理】01-核心框架与运行时(CLR)

文章目录1 .NET Runtime&#xff08;CLR-公共语言运行时&#xff09;1.1 中间语言 IL1.1.1 从源代码到通用中间语言&#xff08;IL&#xff09;1.1.2 运行时加载&#xff1a;CLR登场1.1.3 核心步骤&#xff1a;即时编译 (JIT Compilation)1.1.4 执行与内存管理&#xff08;GC&a…

Claude Code 平替:OpenAI发布 Codex CLI ,GPT-5 国内直接使用

openai推出的命令行编程工具codex已经可以使用最新 GPT-5 模型&#xff0c;拥有可媲美 Claude Code 的 AI 编码能力。本文将指导你在 Windows 系统上部署原生的 Codex CLI 程序&#xff0c;并接入超低价中转 API&#xff0c;让你在国内直接用上超高性价比的 OpenAI Codex CLI 应…

在VS2022的WPF仿真,为什么在XAML实时预览点击 ce.xaml页面控件,却不会自动跳转到具体代码,这样不方便我修改代码,

在VS2022的WPF仿真&#xff0c;为什么在XAML实时预览点击 WpfApp1\FunctionalModule\08Replace\Replace.xaml页面控件&#xff0c;却不会自动跳转到具体代码&#xff0c;这样不方便我修改代码&#xff0c;

Git Bash 别名

有些常用的指令参数非常多&#xff0c;每次都要输入好多参数&#xff0c;我们可以使用别名。Linux 系统中很多 shell&#xff0c;包括 bash&#xff0c;sh&#xff0c;zsh&#xff0c;dash 和 korn 等&#xff0c;不管哪种 shell 都会有一个 .bashrc 的隐藏文件&#xff0c;它就…

Centos7部署ceph存储

一、准备5台centos7主机 node节点双网卡&#xff08;1个内部检测&#xff0c;1个外部使用&#xff09;node节点都添加新网卡关闭防火墙和上下文都需要添加hosts文件都需要cat > /etc/hosts << EOF > 127.0.0.1 localhost localhost.localdomain localhost4 loca…

2025.9.10总结

今日感悟&#xff1a;刷到00后下班去菜市场捡菜的热点视频&#xff0c;确实挺有意思&#xff0c;不得不说&#xff0c;又省钱又好玩。虽然每天晚上能免费领个25块钱的水果回去&#xff0c;但确实没有什么新鲜感了。别人下班还能捡捡菜放松下&#xff0c;我下班&#xff0c;除了…

【数据结构与算符Trip第2站】稀疏数组

稀疏sparsearray数组 什么是稀疏数组&#xff1f; 稀疏数组是一种特殊的数据结构&#xff0c;用于高效存储和表示大部分元素为零&#xff08;或默认值&#xff09;的数组。它通过只存储非零元素的位置和值来节省内存空间。是一种压缩数组。 实现原理 在Go语言中&#xff0c;稀疏…

Sub-GHz无线收发单片机,低功耗物联网通信的硬件“基石”

随着物联网应用持续向规模化部署、广域化覆盖与高效化协同迈进&#xff0c; 作为IoT终端设备实现无线交互的核心通信单元之一——Sub-GHz无线收发单片机&#xff08;Sub-GHz射频收发芯片与单片机高度集成&#xff09;已成为系统设计中进一步简化外围元件数量、缩小硬件体积、降…

用Typescript 的方式封装Vue3的表单绑定,支持防抖等功能

在 Vue3 中结合 TypeScript 封装表单绑定方案时&#xff0c;需要综合考虑类型安全、功能扩展性和开发体验。以下是一个包含防抖功能、支持多种表单控件、具备完整类型推导的封装方案&#xff0c;全文约 2300 字&#xff1a; 方案设计思路 组合式函数封装&#xff1a;使用 Vue3 …

中悦大华通过订单日记实现流程重构之路

一、客户背景 安徽中悦大华高速流体机械有限公司&#xff0c;成立于2023年&#xff0c;位于安徽省宣城市&#xff0c;是一家以从事电子设备制造为主的企业&#xff0c;在多年的商业经营中已成为业界翘楚。 在业务不断壮大的过程中&#xff0c;面临生产协作效率低&#xff0c;库…

【Springboot】介绍启动类和启动过程

【Springboot】介绍启动类和启动过程【一】Spring Boot 启动类的注解【1】核心注解&#xff1a;SpringBootApplication&#xff08;1&#xff09;​SpringBootConfiguration​&#xff1a;Spring容器会从该类中加载Bean定义&#xff08;2&#xff09;​EnableAutoConfiguration…

Gears实测室:第一期·音游跨设备性能表现与工具价值实践

在音游品类中&#xff0c;《跳舞的线》以 “音乐与操作节奏深度绑定” 的玩法特性&#xff0c;对设备性能提出了特殊要求 —— 稳定的帧率与低延迟的渲染响应&#xff0c;直接影响玩家对音符时机的判断&#xff0c;一旦出现卡顿或帧波动&#xff0c;易导致操作失误&#xff0c;…

格式刷+快捷键:Excel和WPS表格隔行填充颜色超方便

有时候我们会对Excel或WPS表格的数据区域每隔一行填充一个底纹&#xff0c;便于阅读和查看。可以使用条件格式搭配公式实现&#xff0c;也可以手动设置。通常手动设置的时候是先设置一行&#xff0c;然后再双击格式刷应用。可以有更快的方式&#xff1a;先设置一行底纹&#xf…

将现有Spring Boot项目作为模块导入到另一个Spring Boot项目

将现有Spring Boot项目作为模块导入到另一个Spring Boot项目的操作步骤如下&#xff1a;‌项目结构调整‌将待导入的项目文件夹复制到主项目的根目录下修改子模块目录名保持命名规范&#xff08;如ms-xxx格式&#xff09;‌父POM配置‌在主项目的pom.xml中添加<modules>声…

激光频率梳 3D 轮廓测量 - 铣刀刀片的刀口钝化值 R 的测量

一、引言铣刀刀片的刀口钝化值 R 是影响切削性能的关键参数&#xff0c;其精度直接关系到工件表面质量与刀具寿命。传统测量方法在面对微米级钝化圆角时存在分辨率不足、接触式测量易损伤刃口等问题。激光频率梳 3D 轮廓测量技术凭借飞秒级时频基准与亚微米级测量精度&#xff…

3-10〔OSCP ◈ 研记〕❘ WEB应用攻击▸XSS攻击理论基础

郑重声明&#xff1a; 本文所有安全知识与技术&#xff0c;仅用于探讨、研究及学习&#xff0c;严禁用于违反国家法律法规的非法活动。对于因不当使用相关内容造成的任何损失或法律责任&#xff0c;本人不承担任何责任。 如需转载&#xff0c;请注明出处且不得用于商业盈利。 …

《嵌入式硬件(四):温度传感器DS1820》

一、DS1820的引脚DS1820单总线数字温度计&#xff1a;异步串行半双工特性&#xff1a;1&#xff09;独特的单线接口&#xff0c;只需 1 个接口引脚即可通信2&#xff09;多点&#xff08;multidrop&#xff09;能力使分布式温度检测应用得以简化3&#xff09;不需要外部元件4&a…

langchain 输出解析器 Output Parser

示例中使用的公共代码&#xff1a; from langchain_deepseek import ChatDeepSeek chat ChatDeepSeek(model"deepseek-chat",temperature0,api_keyAPI_KEY, )使用方法&#xff1a; 引入解析器实例化解析器调用解析器的get_format_instructions()获得提示词&#xff…

LeetCode算法日记 - Day 37: 验证栈序列、N叉树的层序遍历

目录 1. 验证栈序列 1.1 题目解析 1.2 解法 1.3 代码实现 2. N叉树的层序遍历 2.1 题目解析 2.2 解法 2.3 代码实现 1. 验证栈序列 https://leetcode.cn/problems/validate-stack-sequences/description/ 给定 pushed 和 popped 两个序列&#xff0c;每个序列中的 值…