为何我的Flask应用在AKS中仅单副本时能正常运行?
问题分析
你的问题核心是Flask默认采用内存级会话存储,当部署多副本(多个Pod)时,Kubernetes Service的轮询分发策略会将用户请求分配到不同Pod。登录后的会话仅存在单个Pod的内存中,若后续请求被路由到无会话记录的Pod,就会出现重定向失败、状态时好时坏的现象。
解决方案
1. 切换Flask会话到分布式存储
将Flask的会话存储从本地内存迁移到共享存储(如Redis),实现跨Pod的会话共享。
代码调整示例
先安装依赖:
pip install flask-session redis
修改Flask应用代码:
import os from flask import Flask, session, redirect, url_for from flask_session import Session import redis app = Flask(__name__) # 从环境变量读取配置,避免硬编码 app.config['SESSION_TYPE'] = 'redis' app.config['SESSION_REDIS'] = redis.from_url(os.getenv('REDIS_URL', 'redis://redis:6379')) # 会话加密密钥,需确保所有副本一致 app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-strong-secret-key-here') # 初始化会话组件 Session(app) # 登录逻辑示例 @app.route('/login', methods=['POST']) def login(): # 此处替换为你的用户验证逻辑 session['user_id'] = 123 return redirect(url_for('home'))
2. 在AKS内部部署Redis服务
创建Redis的Deployment和Service,为Flask提供共享会话存储:
# redis-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: redis spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:alpine ports: - containerPort: 6379 # 可选:挂载持久化存储防止数据丢失 volumeMounts: - name: redis-data mountPath: /data volumes: - name: redis-data persistentVolumeClaim: claimName: redis-pvc --- # redis-service.yaml apiVersion: v1 kind: Service metadata: name: redis spec: selector: app: redis ports: - port: 6379 targetPort: 6379 --- # redis-pvc.yaml(可选,用于持久化Redis数据) apiVersion: v1 kind: PersistentVolumeClaim metadata: name: redis-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
执行部署命令:
kubectl apply -f redis-deployment.yaml
3. 更新Flask Deployment配置
修改你的Deployment.yaml,调整副本数并注入环境变量:
apiVersion: apps/v1 kind: Deployment metadata: name: frontpage namespace: default spec: replicas: 2 # 设置为需要的副本数 selector: matchLabels: app: frontpage template: metadata: labels: app: frontpage spec: containers: - name: frontpage image: ***.azurecr.io/frontpage:latest ports: - containerPort: 5000 env: - name: REDIS_URL value: redis://redis:6379 - name: SECRET_KEY valueFrom: secretKeyRef: name: flask-secret key: SECRET_KEY
先创建存储密钥的Secret:
kubectl create secret generic flask-secret --from-literal=SECRET_KEY="your-strong-secret-key-here"
4. 临时方案:配置会话亲和性(不推荐)
如果暂时无法修改代码,可以通过Service的会话亲和性让同一用户请求固定路由到同一Pod,但此方案会降低负载均衡效果,且Pod重启后会话仍会丢失:
# 修改Service.yaml apiVersion: v1 kind: Service metadata: name: frontpage namespace: default spec: selector: app: frontpage ports: - name: http port: 80 targetPort: 5000 type: ClusterIP sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 10800 # 3小时过期
内容的提问来源于stack exchange,提问作者Rakesh V
相关产品推荐
相关产品推荐

