Flask 个人站 iProfile 上线笔记(k3s + Nginx + Let‘s Encrypt)

一、技术栈全景

选型 说明
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)

  • SecretstringData 注入 SECRET_KEY
  • Deployment 配了 readinessProbelivenessProbe(GET /
  • RollingUpdatemaxSurge:1, maxUnavailable:0 滚动无中断
  • 资源限制 :request 50m/64Mi,limit 500m/256Mi(一台小 VPS 也能扛)
  • ServiceNodePort 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

五、上线遇到的问题

  1. 容器内 vs 宿主机端口要分清 :Gunicorn 在容器里监听 0.0.0.0:8000,k8s 再映射到 NodePort 30081,最终 Nginx 反代到 30081。三层端口别搞混。
  2. SSL 必须先 HTTP 引导再切 HTTPS:certbot 需要先用 HTTP 验证域名,所以上线脚本里 init.conf 和最终 conf 是两份。
  3. 探针救了服务 :加了 readinessProbe 后,容器没起来前 k8s 不会把流量打给它,避免"502 风暴"。

项目演示地址:https://iprofile.liousa.site(https://iprofile.liousa.site)

相关推荐
深蓝海拓1 小时前
基于QtPy (PySide6) 的PLC-HMI工程项目(十五)后续完善和改进:PLC端数据解析的防粘包、残包、废包、拆包
笔记·学习·plc
小黄蚁1 小时前
LVGL学习笔记(六)
笔记·学习
Wang's Blog2 小时前
PostgreSQL笔记49:向量检索核心算法、索引调优与过滤策略深度解析
笔记·算法·postgresql
疯狂打码的少年2 小时前
【数据结构】交换类排序:冒泡与快速排序
数据结构·笔记·算法·排序算法
chnyi6_ya2 小时前
VideoHallu 论文阅读笔记
论文阅读·笔记
Wang's Blog3 小时前
PostgreSQL笔记51: 基于 pgvector 构建企业级智能问答系统
数据库·笔记·postgresql
自小吃多3 小时前
Capture软件原理图添加差分属性笔记
笔记·嵌入式硬件
日常筹谋记4 小时前
ATS选不对运维两行泪:数据中心市电与柴发切换场景的双电源自动转换开关选型笔记
运维·数据库·笔记
疯狂打码的少年4 小时前
【数据结构】哈希表:构造与冲突处理
数据结构·笔记·哈希算法·散列表