找回密码
 立即注册
首页 业界区 业界 Flask - 常见应用部署方案

Flask - 常见应用部署方案

注思 6 天前
前言

开发调试阶段,运行 Flask 的方式多直接使用 app.run(),但 Flask 内置的 WSGI Server 的性能并不高。对于生产环境,一般使用 gunicorn。如果老项目并不需要多高的性能,而且用了很多单进程内的共享变量,使用 gunicorn 会影响不同会话间的通信,那么也可以试试直接用 gevent。
在 Docker 流行之前,生产环境部署 Flask 项目多使用 virtualenv + gunicorn + supervisor。Docker 流行之后,部署方式就换成了 gunicorn + Docker。如果没有容器编排服务,后端服务前面一般还会有个 nginx 做代理。如果使用 Kubernetes,一般会使用 service + ingress(或 istio 等)。
运行方式

Flask 内置 WSGI Server

开发阶段一般使用这种运行方式。
  1. # main.py
  2. from flask import Flask
  3. from time import sleep
  4. app = Flask(__name__)
  5. @app.get("/test")
  6. def get_test():
  7.     sleep(0.1)
  8.     return "ok"
  9. if __name__ == "__main__":
  10.     app.run(host="0.0.0.0", port=10000)
复制代码
运行:
  1. python main.py
复制代码
gevent

使用 gevent 运行 Flask,需要先安装 gevent
  1. python -m pip install -U gevent
复制代码
代码需要稍作修改。
需要注意 monkey.patch_all() 一定要写在入口代码文件的最开头部分,这样 monkey patch 才能生效。
  1. # main.py
  2. from gevent import monkey
  3. monkey.patch_all()
  4. import time
  5. from flask import Flask
  6. from gevent.pywsgi import WSGIServer
  7. app = Flask(__name__)
  8. @app.get("/test")
  9. def get_test():
  10.     time.sleep(0.1)
  11.     return "ok"
  12. if __name__ == "__main__":
  13.     server = WSGIServer(("0.0.0.0", 10000), app)
  14.     server.serve_forever()
复制代码
运行
  1. python main.py
复制代码
gunicorn + gevent

如果现有项目大量使用单进程内的内存级共享变量,贸然使用 gunicorn 多 worker 模式可能会导致数据访问不一致的问题。
同样需要先安装依赖。
  1. python -m pip install -U gunicorn gevent
复制代码
不同于单独使用 gevent,这种方式不需要修改代码,gunicorn 会自动注入 gevent 的 monkey patch。
gunicorn 可以在命令行配置启动参数,但个人一般习惯在 gunicorn 的配置文件内配置启动参数,这样可以动态设置一些配置,而且可以修改日志格式。
gunicorn.conf.py 的配置示例如下:
  1. # Gunicorn 配置文件
  2. from pathlib import Path
  3. from multiprocessing import cpu_count
  4. import gunicorn.glogging
  5. from datetime import datetime
  6. class CustomLogger(gunicorn.glogging.Logger):
  7.     def atoms(self, resp, req, environ, request_time):
  8.         """
  9.         重写 atoms 方法来自定义日志占位符
  10.         """
  11.         # 获取默认的所有占位符数据
  12.         atoms = super().atoms(resp, req, environ, request_time)
  13.         
  14.         # 自定义 't' (时间戳) 的格式
  15.         now = datetime.now().astimezone()
  16.         atoms['t'] = now.isoformat(timespec="seconds")
  17.         
  18.         return atoms
  19.    
  20. # 预加载应用代码
  21. preload_app = True
  22. # 工作进程数量:通常是 CPU 核心数的 2 倍加 1
  23. # workers = int(cpu_count() * 2 + 1)
  24. workers = 4
  25. # 使用 gevent 异步 worker 类型,适合 I/O 密集型应用
  26. # 注意:gevent worker 不使用 threads 参数,而是使用协程进行并发处理
  27. worker_class = "gevent"
  28. # 每个 gevent worker 可处理的最大并发连接数
  29. worker_connections = 2000
  30. # 绑定地址和端口
  31. bind = "127.0.0.1:10001"
  32. # 进程名称
  33. proc_name = "flask-dev"
  34. # PID 文件路径
  35. pidfile = str(Path(__file__).parent / "tmp" / "gunicorn.pid")
  36. logger_class = CustomLogger
  37. access_log_format = (
  38.     '{"@timestamp": "%(t)s", '
  39.     '"remote_addr": "%(h)s", '
  40.     '"protocol": "%(H)s", '
  41.     '"host": "%({host}i)s", '
  42.     '"request_method": "%(m)s", '
  43.     '"request_path": "%(U)s", '
  44.     '"status_code": %(s)s, '
  45.     '"response_length": %(b)s, '
  46.     '"referer": "%(f)s", '
  47.     '"user_agent": "%(a)s", '
  48.     '"x_tracking_id": "%({x-tracking-id}i)s", '
  49.     '"request_time": %(L)s}'
  50. )
  51. # 访问日志路径
  52. accesslog = str(Path(__file__).parent / "logs" / "access.log")
  53. # 错误日志路径
  54. errorlog = str(Path(__file__).parent / "logs" / "error.log")
  55. # 日志级别
  56. loglevel = "debug"
复制代码
运行。gunicorn 的默认配置文件名就是 gunicorn.conf.py,如果文件名不同,可以使用 -c 参数来指定。
  1. gunicorn main:app
复制代码
传统进程管理:实现自动启动

在传统服务器部署时,常见的进程守护方式有:

  • 配置 crontab + shell 脚本。定时检查进程在不在,不在就启动。
  • 配置 supervisor。
  • 配置 systemd。
由于 supervisor 需要单独安装,而本着能用自带工具就用自带工具、能少装就少装的原则,个人一般不会使用 supervisor,因此本文不会涉及如何使用 supervisor。
在服务器部署时,一般也会为项目单独创建 Python 虚拟环境。
  1. # 使用 Python 内置的 venv,在当前目录创建 Python 虚拟环境目录 .venv
  2. python3 -m venv .venv
  3. source .venv/bin/activate
  4. python -m pip install -r ./requirements.txt
  5. # 如果使用uv, 直接uv sync 即可
复制代码
crontab + shell 脚本 (不推荐生产环境)

刚入行的时候对 systemd 不熟悉,经常用 crontab + shell 脚本来守护进程,现在想想这种方式并不合适,比较考验 shell 脚本的编写水平,需要考虑方方面面

  • 首先要确保用户级 crontab 启用,有些生产环境会禁用用户级的 crontab,而且也不允许随便配置系统级的 crontab。
  • crontab 是分钟级的,服务停止时间可能要一分钟。
  • 如果有控制台日志,需要手动处理日志重定向,还有日志文件轮转问题。
  • 如果 ulimit 不高,还得控制 ulimit。
  • 经常出现僵尸进程,shell 脚本来要写一堆状态检查的逻辑。
如果只需要简单用用,也可以提供个示例
  1. #!/bin/bash
  2. # 环境配置
  3. export FLASK_ENV="production"
  4. export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
  5. export REDIS_URL="redis://localhost:6379/0"
  6. script_dir=$(cd $(dirname $0) && pwd)
  7. app_name="gunicorn"  # 实际进程名是 gunicorn,不是 Flask app
  8. wsgi_module="wsgi:app"  # 替换 WSGI 入口
  9. socket_path="${script_dir}/myapp.sock"  # Unix Socket 路径(避免 /run 重启丢失)
  10. log_file="${script_dir}/app.log"
  11. pid_file="${script_dir}/gunicorn.pid"   # 用 PID 文件控制
  12. # 进程检测
  13. is_running() {
  14.     if [ -f "$pid_file" ]; then
  15.         pid=$(cat "$pid_file")
  16.         if ps -p "$pid" > /dev/null 2>&1 && grep -q "gunicorn.*${wsgi_module}" /proc/"$pid"/cmdline 2>/dev/null; then
  17.             echo "Gunicorn (PID: $pid) is running"
  18.             return 0
  19.         else
  20.             rm -f "$pid_file"  # 清理失效 PID
  21.             echo "Stale PID file found, cleaned up"
  22.             return 1
  23.         fi
  24.     else
  25.         # 备用检测:通过 socket 文件 + 进程名
  26.         if [ -S "$socket_path" ] && pgrep -f "gunicorn.*${wsgi_module}" > /dev/null 2>&1; then
  27.             echo "Gunicorn is running (detected by socket)"
  28.             return 0
  29.         fi
  30.         echo "Gunicorn is not running"
  31.         return 1
  32.     fi
  33. }
  34. # 启动应用
  35. start_app() {
  36.     is_running
  37.     if [ $? -eq 0 ]; then
  38.         echo "Already running, skip start"
  39.         return 0
  40.     fi
  41.     echo "Starting Gunicorn at $(date)"
  42.     echo "Socket: $socket_path"
  43.     echo "Log: $log_file"
  44.     # 确保 socket 目录存在
  45.     mkdir -p "$(dirname "$socket_path")"
  46.     # 启动命令(关键:不加 --daemon,用 nohup 托管)
  47.     cd "$script_dir" || exit 1
  48.     # 生成 PID 文件
  49.     nohup "$script_dir/venv/bin/gunicorn" \
  50.         --workers 3 \
  51.         --bind "unix:$socket_path" \
  52.         --pid "$pid_file" \
  53.         --access-logfile "$log_file" \
  54.         --error-logfile "$log_file" \
  55.         --log-level info \
  56.         "$wsgi_module" > /dev/null 2>&1 &
  57.     # 等待启动完成
  58.     sleep 2
  59.     if is_running; then
  60.         echo "✓ Start success (PID: $(cat "$pid_file" 2>/dev/null))"
  61.         return 0
  62.     else
  63.         echo "✗ Start failed, check $log_file"
  64.         return 1
  65.     fi
  66. }
  67. # 停止应用
  68. stop_app() {
  69.     is_running
  70.     if [ $? -eq 1 ]; then
  71.         echo "Not running, skip stop"
  72.         return 0
  73.     fi
  74.     pid=$(cat "$pid_file" 2>/dev/null)
  75.     echo "Stopping Gunicorn (PID: $pid) gracefully..."
  76.     # 先发 SIGTERM(优雅停止)
  77.     kill -15 "$pid" 2>/dev/null || true
  78.     sleep 5
  79.     # 检查是否还在运行
  80.     if ps -p "$pid" > /dev/null 2>&1; then
  81.         echo "Still running after 5s, force killing..."
  82.         kill -9 "$pid" 2>/dev/null || true
  83.         sleep 2
  84.     fi
  85.     # 清理残留
  86.     rm -f "$pid_file" "$socket_path"
  87.     echo "✓ Stopped"
  88. }
  89. # 重启应用
  90. restart_app() {
  91.     echo "Restarting Gunicorn..."
  92.     stop_app
  93.     sleep 1
  94.     start_app
  95. }
  96. # 入口函数
  97. main() {
  98.     # 检查 Gunicorn 是否存在
  99.     if [ ! -f "$script_dir/venv/bin/gunicorn" ]; then
  100.         echo "ERROR: Gunicorn not found at $script_dir/venv/bin/gunicorn"
  101.         echo "Hint: Did you activate virtualenv? (source venv/bin/activate)"
  102.         exit 1
  103.     fi
  104.     local action=${1:-start}  # 默认动作:start
  105.     case "$action" in
  106.         start)
  107.             start_app
  108.             ;;
  109.         stop)
  110.             stop_app
  111.             ;;
  112.         restart)
  113.             restart_app
  114.             ;;
  115.         status)
  116.             is_running
  117.             ;;
  118.         cron-check)
  119.             # 专为 crontab 设计:只检查+重启,不输出干扰日志
  120.             if ! is_running > /dev/null 2>&1; then
  121.                 echo "[$(date '+%F %T')] CRON: Gunicorn down, auto-restarting..." >> "$log_file"
  122.                 start_app >> "$log_file" 2>&1
  123.             fi
  124.             ;;
  125.         *)
  126.             echo "Usage: $0 {start|stop|restart|status|cron-check}"
  127.             echo "  cron-check: Silent mode for crontab (logs to app.log only)"
  128.             exit 1
  129.             ;;
  130.     esac
  131. }
  132. main "$@"
复制代码
手动运行测试
  1. bash app_ctl.sh start
复制代码
配置 crontab
  1. # 编辑当前用户 crontab
  2. crontab -e
  3. # 添加以下行(每分钟检查一次)
  4. * * * * * /opt/myflaskapp/app_ctl.sh cron-check >/dev/null 2>&1
复制代码
配置logrotate
  1. # /etc/logrotate.d/myflaskapp
  2. /opt/myflaskapp/app.log {
  3.     daily
  4.     rotate 7
  5.     compress
  6.     delaycompress
  7.     missingok
  8.     notifempty
  9.     copytruncate  # 避免 Gunicorn 丢失文件句柄
  10. }
复制代码
systemd (推荐生产环境使用)


  • 创建 systemd 服务文件
  1. sudo vim /etc/systemd/system/myflaskapp.service
复制代码

  • 示例如下
  1. [Unit]
  2. Description=Gunicorn instance for Flask App
  3. After=network.target
  4. [Service]
  5. User=www-data
  6. Group=www-data
  7. WorkingDirectory=/path/to/your/app
  8. Environment="PATH=/path/to/venv/bin"
  9. ExecStart=/path/to/venv/bin/gunicorn \
  10.           --workers 4 \
  11.           --bind unix:/run/myapp.sock \
  12.           --access-logfile - \
  13.           --error-logfile - \
  14.           wsgi:app
  15. # 禁止添加 --daemon!systemd 需直接监控主进程
  16. Restart=on-failure        # 仅异常退出时重启(非0状态码、被信号杀死等)
  17. RestartSec=5s             # 重启前等待5秒
  18. StartLimitInterval=60s    # 60秒内
  19. StartLimitBurst=5         # 最多重启5次,防雪崩
  20. TimeoutStopSec=30         # 停止时等待30秒(优雅关闭)
  21. # 安全加固
  22. PrivateTmp=true
  23. NoNewPrivileges=true
  24. ProtectSystem=strict
  25. ReadWritePaths=/run /var/log/myapp
  26. [Install]
  27. WantedBy=multi-user.target
复制代码

  • 设置开机自启并启动服务
  1. sudo systemctl daemon-reload
  2. sudo systemctl enable myflaskapp    # 开机自启
  3. sudo systemctl start myflaskapp
复制代码
可以试试用kill -9停止后端服务进程,观察能否被重新拉起。
注意,kill -15算是正常停止,不算异常退出。
Docker 部署方案


  • Dockerfile。Python 项目通常不需要多阶段构建,单阶段即可。
  1. FROM python:3.11-slim-bookworm
  2. # 安全加固
  3. ## 创建非 root 用户(避免使用 nobody,权限太受限)
  4. RUN useradd -m -u 1000 appuser && \
  5.     # 安装运行时必需的系统库(非编译工具)
  6.     apt-get update && apt-get install -y --no-install-recommends \
  7.         libgomp1 \
  8.         libpq5 \
  9.         libsqlite3-0 \
  10.         && rm -rf /var/lib/apt/lists/* \
  11.         && apt-get autoremove -y \
  12.         && apt-get clean
  13. # Python 优化
  14. ENV PYTHONUNBUFFERED=1 \
  15.     PYTHONDONTWRITEBYTECODE=1 \
  16.     PIP_NO_CACHE_DIR=1 \
  17.     PIP_DISABLE_PIP_VERSION_CHECK=1
  18. WORKDIR /app
  19. # 利用 Docker 层缓存:先复制 requirements
  20. COPY requirements.txt .
  21. RUN pip install --no-cache-dir --prefer-binary -r requirements.txt \
  22.     # 清理 pip 缓存(虽然 --no-cache-dir 已禁用,但保险起见)
  23.     && rm -rf /root/.cache
  24. # 应用代码
  25. COPY --chown=appuser:appuser . .
  26. # 使用非root用户运行
  27. USER appuser
  28. # 启动
  29. EXPOSE 8000
  30. CMD ["gunicorn", "--config", "config/gunicorn.conf.py", "wsgi:app"]
复制代码

  • 编写 docker-compose.yaml
  1. services:
  2.   web:
  3.     image: myflaskapp:latest
  4.     container_name: flask_web
  5.     # 端口映射
  6.     ## 如果 nginx 也使用 Docker 部署,而且使用同一个网络配置,则可以不做端口映射
  7.     ports:
  8.       - "8000:8000"
  9.     # 环境变量
  10.     environment:
  11.       - FLASK_ENV=production
  12.       - DATABASE_URL=postgresql://user:pass@db:5432/mydb
  13.       - REDIS_URL=redis://redis:6379/0
  14.     # 健康检查
  15.     healthcheck:
  16.       test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
  17.       interval: 30s      # 每 30 秒检查一次
  18.       timeout: 5s        # 超时 5 秒
  19.       start_period: 15s  # 启动后 15 秒开始检查(给应用初始化时间)
  20.       retries: 3         # 失败重试 3 次后标记 unhealthy
  21.    
  22.     # 自动重启策略
  23.     restart: unless-stopped  # always / on-failure / unless-stopped
  24.    
  25.     # 资源限制
  26.     deploy:
  27.       resources:
  28.         limits:
  29.           cpus: '2'        # 最多 2 个 CPU
  30.           memory: 1G       # 最多 1GB 内存
  31.         reservations:
  32.           cpus: '0.5'      # 保留 0.5 个 CPU
  33.           memory: 256M     # 保留 256MB 内存
  34.    
  35.     # ulimit 限制(防资源滥用)
  36.     ulimits:
  37.       nproc: 65535       # 最大进程数
  38.       nofile:
  39.         soft: 65535      # 打开文件数软限制
  40.         hard: 65535      # 打开文件数硬限制
  41.       core: 0            # 禁止 core dump
  42.    
  43.     # 安全加固
  44.     security_opt:
  45.       - no-new-privileges:true  # 禁止提权
  46.    
  47.     # 只读文件系统(除 /tmp 外)
  48.     read_only: true
  49.     tmpfs:
  50.       - /tmp:rw,noexec,nosuid,size=100m
  51.    
  52.     # 卷挂载(日志、临时文件)
  53.     volumes:
  54.       - ./logs:/app/logs:rw
  55.       # - ./static:/app/static:ro  # 静态文件(可选)
  56.    
  57.     # 网络
  58.     networks:
  59.       - app-network
  60.         
  61. # 网络配置
  62. networks:
  63.   app-network:
  64.     driver: bridge
  65. # 卷配置
  66. volumes:
  67.   db_data:
  68.     driver: local
  69.   redis_data:
  70.     driver: local
复制代码
Kubernetes 部署方案

Deployment
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: flask-app
  5.   namespace: default
  6.   labels:
  7.     app: flask-app
  8.     tier: backend
  9. spec:
  10.   replicas: 3
  11.   selector:
  12.     matchLabels:
  13.       app: flask-app
  14.   template:
  15.     metadata:
  16.       labels:
  17.         app: flask-app
  18.         tier: backend
  19.     spec:
  20.       securityContext:
  21.         runAsNonRoot: true      # 禁止 root 运行
  22.         runAsUser: 1000         # 使用非 root 用户
  23.         runAsGroup: 1000
  24.         fsGroup: 1000
  25.         seccompProfile:
  26.           type: RuntimeDefault  # 启用 seccomp 安全策略
  27.       containers:
  28.       - name: flask-app
  29.         image: myregistry.com/myflaskapp:1.0.0
  30.         imagePullPolicy: IfNotPresent  # 生产环境建议用 Always
  31.         ports:
  32.         - name: http
  33.           containerPort: 8000
  34.           protocol: TCP
  35.         env:
  36.         - name: FLASK_ENV
  37.           value: "production"
  38.         - name: DATABASE_URL
  39.           valueFrom:
  40.             secretKeyRef:
  41.               name: flask-app-secrets
  42.               key: database-url
  43.         - name: REDIS_URL
  44.           valueFrom:
  45.             secretKeyRef:
  46.               name: flask-app-secrets
  47.               key: redis-url
  48.         - name: SECRET_KEY
  49.           valueFrom:
  50.             secretKeyRef:
  51.               name: flask-app-secrets
  52.               key: secret-key
  53.         resources:
  54.           requests:
  55.             memory: "256Mi"
  56.             cpu: "100m"
  57.           limits:
  58.             memory: "512Mi"   # 超过会 OOM Kill
  59.             cpu: "500m"
  60.         livenessProbe:
  61.           httpGet:
  62.             path: /health
  63.             port: 8000
  64.             scheme: HTTP
  65.           initialDelaySeconds: 30  # 启动后 30 秒开始检查
  66.           periodSeconds: 10        # 每 10 秒检查一次
  67.           timeoutSeconds: 3        # 超时 3 秒
  68.           successThreshold: 1
  69.           failureThreshold: 3      # 失败 3 次后重启容器
  70.         readinessProbe:
  71.           httpGet:
  72.             path: /health
  73.             port: 8000
  74.             scheme: HTTP
  75.           initialDelaySeconds: 10  # 启动后 10 秒开始检查
  76.           periodSeconds: 5         # 每 5 秒检查一次
  77.           timeoutSeconds: 2
  78.           successThreshold: 1
  79.           failureThreshold: 3      # 失败 3 次后从 Service 移除
  80.         startupProbe:
  81.           httpGet:
  82.             path: /health
  83.             port: 8000
  84.             scheme: HTTP
  85.           failureThreshold: 30     # 最多重试 30 次
  86.           periodSeconds: 5         # 每 5 秒一次,共 150 秒容忍慢启动
  87.           timeoutSeconds: 3
  88.         securityContext:
  89.           allowPrivilegeEscalation: false  # 禁止提权
  90.           readOnlyRootFilesystem: true     # 根文件系统只读
  91.           capabilities:
  92.             drop:
  93.             - ALL                          # 删除所有 Linux capabilities
  94.           privileged: false
  95.         volumeMounts:
  96.         - name: tmp-volume
  97.           mountPath: /tmp
  98.         - name: config-volume
  99.           mountPath: /app/config
  100.           readOnly: true
  101.       imagePullSecrets:
  102.       - name: registry-secret  # 如果使用私有镜像仓库
  103.       affinity:
  104.         podAntiAffinity:
  105.           preferredDuringSchedulingIgnoredDuringExecution:
  106.           - weight: 100
  107.             podAffinityTerm:
  108.               labelSelector:
  109.                 matchExpressions:
  110.                 - key: app
  111.                   operator: In
  112.                   values:
  113.                   - flask-app
  114.               topologyKey: kubernetes.io/hostname  # 避免所有 Pod 调度到同一节点
  115.       volumes:
  116.       - name: tmp-volume
  117.         emptyDir:
  118.           medium: Memory  # 使用内存卷,更快
  119.           sizeLimit: 100Mi
  120.       - name: config-volume
  121.         configMap:
  122.           name: flask-app-config
复制代码
Service
  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4.   name: flask-app-service
  5.   namespace: default
  6.   labels:
  7.     app: flask-app
  8.     tier: backend
  9. spec:
  10.   type: ClusterIP
  11.   selector:
  12.     app: flask-app
  13.   ports:
  14.   - name: http
  15.     port: 80        # Service 端口
  16.     targetPort: 8000  # Pod 端口
  17.     protocol: TCP
复制代码
ingress-nginx
  1. apiVersion: networking.k8s.io/v1
  2. kind: Ingress
  3. metadata:
  4.   name: flask-app-ingress
  5.   namespace: default
  6.   annotations:
  7.     # ==================== Nginx 配置 ====================
  8.     kubernetes.io/ingress.class: "nginx"
  9.    
  10.     # 启用 HTTPS 重定向
  11.     nginx.ingress.kubernetes.io/ssl-redirect: "true"
  12.     nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
  13.    
  14.     # 限流(每秒 10 个请求,突发 20)
  15.     nginx.ingress.kubernetes.io/limit-rps: "10"
  16.     nginx.ingress.kubernetes.io/limit-burst-multiplier: "2"
  17.    
  18.     # 客户端真实 IP
  19.     nginx.ingress.kubernetes.io/enable-real-ip: "true"
  20.     nginx.ingress.kubernetes.io/proxy-real-ip-cidr: "0.0.0.0/0"
  21.    
  22.     # 连接超时
  23.     nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
  24.     nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
  25.     nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
  26.    
  27.     # 缓冲区大小
  28.     nginx.ingress.kubernetes.io/proxy-buffering: "on"
  29.     nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
  30.     nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
  31.    
  32.     # Gzip 压缩
  33.     nginx.ingress.kubernetes.io/enable-gzip: "true"
  34.     nginx.ingress.kubernetes.io/gzip-level: "6"
  35.     nginx.ingress.kubernetes.io/gzip-min-length: "1024"
  36.     nginx.ingress.kubernetes.io/gzip-types: "text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript"
  37.    
  38.     # 安全头
  39.     nginx.ingress.kubernetes.io/configuration-snippet: |
  40.       add_header X-Frame-Options "SAMEORIGIN" always;
  41.       add_header X-Content-Type-Options "nosniff" always;
  42.       add_header X-XSS-Protection "1; mode=block" always;
  43.       add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  44.    
  45.     # 认证
  46.     # nginx.ingress.kubernetes.io/auth-type: basic
  47.     # nginx.ingress.kubernetes.io/auth-secret: flask-app-basic-auth
  48.     # nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
  49.    
  50.     # 自定义错误页面
  51.     # nginx.ingress.kubernetes.io/custom-http-errors: "404,500,502,503,504"
  52.     # nginx.ingress.kubernetes.io/default-backend: custom-error-pages
  53.    
  54.     # 重写目标
  55.     # nginx.ingress.kubernetes.io/rewrite-target: /$1
  56.    
  57.     # WAF(如果安装了 ModSecurity)
  58.     # nginx.ingress.kubernetes.io/enable-modsecurity: "true"
  59.     # nginx.ingress.kubernetes.io/modsecurity-snippet: |
  60.     #   SecRuleEngine On
  61.     #   SecRequestBodyAccess On
  62. spec:
  63.   tls:
  64.   - hosts:
  65.     - flask.example.com
  66.     secretName: flask-app-tls-secret  # TLS 证书 Secret
  67.   rules:
  68.   - host: flask.example.com
  69.     http:
  70.       paths:
  71.       - path: /
  72.         pathType: Prefix
  73.         backend:
  74.           service:
  75.             name: flask-app-service
  76.             port:
  77.               number: 80
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册