一、技术栈全景
| 层 | 选型 | 说明 |
|---|---|---|
| Web 框架 | Flask 3.0 + Jinja2 | 零构建,模板直出 HTML |
| 前端 | Bootstrap 5 + Bootstrap Icons + Google Fonts | CDN 引入,无需打包 |
| WSGI | Gunicorn | 2 worker,0.0.0.0:8000 |
| 容器 | Docker (python:3.12-slim) | 非 root 运行,多阶段缓存依赖 |
| 编排 | k3s + Kubernetes 清单 | 无状态,NodePort 30081 暴露 |
| 反代 | Nginx | 静态资源直出 + gzip + 反代 8000 |
| 证书 | Let's Encrypt (certbot) | 自动续期 HTTPS |
| 邮件提醒 | smtplib (SMTP_SSL) | 询盘实时发邮件,未配置则静默跳过 |
二、服务整体编排结构
┌────────────────────────────┐
浏览器(HTTPS 443) ──►│ Nginx 反向代理 │
│ - 静态 /static/ 直接返回 │
│ - 动态 / 转发到 upstream │
└────────────┬───────────────┘
│ proxy_pass
▼
┌──────────────────────────┐
│ k3s NodePort :30081 │
│ ┌──────────────────────┐ │
│ │ Service iprofile-web │ │
│ └──────────┬───────────┘ │
│ │ selector │
│ ┌──────────▼───────────┐ │
│ │ Deployment │ │
│ │ iprofile-web:latest │ │
│ │ replicas=1 │ │
│ │ probes: 就绪+存活 │ │
│ └──────────┬───────────┘ │
│ │ │
│ Secret: SECRET_KEY ◄──┘ (env 注入)
└──────────────────────────┘
邮件(SMTP_SSL): 环境变量 MAIL_HOST/PORT/USER/PASSWORD/TO
三、关键设计点
1. 配置全走环境变量,代码零硬编码
app.secret_key = os.environ.get('SECRET_KEY', os.urandom(24))
# SMTP 未配置时静默降级,不影响站点可用性
if not (host and user and password and to):
print('[mail] SMTP not configured; skipping')
return False
2. 容器安全
python:3.12-slim精简镜像PYTHONDONTWRITEBYTECODE/PYTHONUNBUFFERED生产优化- 新建
appuser非 root 运行 .dockerignore排除敏感/冗余目录
3. k8s 清单三段式(Namespace / Secret / Deployment+Service)
- Secret 用
stringData注入 SECRET_KEY - Deployment 配了
readinessProbe和livenessProbe(GET/) - RollingUpdate :
maxSurge:1, maxUnavailable:0滚动无中断 - 资源限制 :request
50m/64Mi,limit500m/256Mi(一台小 VPS 也能扛) - Service 用 NodePort 30081(和已有服务 30080 同一套暴露模式)
4. Nginx 双层配置(上线顺序的关键)
init.conf:先上 HTTP 版,跑完 certbot 拿到证书web.liousa.site.conf:再切换 HTTPS 版,带完整 SSL + 安全头 + gzip
5. Nginx 性能细节
- 静态资源
expires 30d强缓存 + gzip proxy_http_version 1.1+keepalive 8连接复用- 安全头:
X-Frame-Options/X-Content-Type-Options/Referrer-Policy
四、部署步骤
# 1. 构建镜像(k3s 节点本地)
docker build -t iprofile-web:latest .
# 2. 应用 k8s 清单(自动建 ns/secret/deploy/svc)
kubectl apply -f k8s/iprofile.yaml
# 3. 验证
kubectl -n iprofile get pods,svc
# 4. Nginx 先上 HTTP 引导配置
sudo cp deploy/nginx/web.liousa.site.init.conf /etc/nginx/sites-available/web.liousa.site
sudo ln -sf /etc/nginx/sites-available/web.liousa.site /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
# 5. 申请证书(免费 HTTPS)
sudo certbot --nginx -d web.liousa.site
# 6. 切换正式 HTTPS 配置
sudo cp deploy/nginx/web.liousa.site.conf /etc/nginx/sites-available/web.liousa.site
sudo nginx -t && sudo systemctl reload nginx
五、上线遇到的问题
- 容器内 vs 宿主机端口要分清 :Gunicorn 在容器里监听
0.0.0.0:8000,k8s 再映射到 NodePort30081,最终 Nginx 反代到30081。三层端口别搞混。 - SSL 必须先 HTTP 引导再切 HTTPS:certbot 需要先用 HTTP 验证域名,所以上线脚本里 init.conf 和最终 conf 是两份。
- 探针救了服务 :加了
readinessProbe后,容器没起来前 k8s 不会把流量打给它,避免"502 风暴"。
项目演示地址:https://iprofile.liousa.site(https://iprofile.liousa.site)