当前位置: 首页 > news >正文

第 44篇 k8s之实战:将 Web 应用迁移到 Kubernetes(上)

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。


在第 10 篇中,我们通过docker run命令和自定义网络,手动启动了 Flask + Redis 计数器应用。在第 16 篇中,我们用 Docker Compose 将整个过程声明化,一条docker compose up -d就能启动整个应用栈。

现在,经过了 33 篇 Kubernetes 核心知识的学习——从 Pod、Deployment、Service、Ingress,到 ConfigMap、Secret、PVC、探针、资源管理、调度策略、RBAC、Helm——是时候把这一切串起来了。

这篇和下篇,我们将完成一次完整的应用迁移:把运行在 Docker Compose 中的 Flask + Redis 计数器应用,迁移到 Kubernetes 集群上,并达到生产级标准。今天先完成基础架构部署和配置管理。

一、回顾与规划:从 Compose 到 K8s 的架构映射

1.1 Docker Compose 时代的旧架构

回顾第 10 篇和第 16 篇,我们的 Compose 文件定义了以下组件:

services: redis: image: redis:alpine volumes: - redis-data:/data networks: - app-net flask-app: image: flask-redis-counter:3.0 ports: -"5000:5000"environment: -REDIS_HOST=redis networks: - app-net volumes: redis-data: networks: app-net:

这个架构在单机上运行良好,但迁移到 K8s 需要把每个 Compose 概念映射到对应的 K8s 对象。我们在第 18 篇做过概念映射,现在是把它落地的时候了。

1.2 Kubernetes 目标架构

迁移后的 K8s 架构如下:

┌─────────────────────────────────────────────────────────────┐ │ Kubernetes 集群 │ │ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ Flask Deployment │ │ Redis Deployment │ │ │ │ replicas:3│ │ replicas:1│ │ │ │ ┌──────┐┌──────┐ │ │ ┌──────┐ │ │ │ │ │ Pod1 ││ Pod2 │ │ │ │ Pod │ │ │ │ │ └──────┘└──────┘ │ │ └──────┘ │ │ │ └────────┬─────────┘ └────────┬─────────┘ │ │ │ │ │ │ ┌────────▼─────────┐ ┌────────▼─────────┐ │ │ │ Flask Service │ │ Redis Service │ │ │ │ ClusterIP │ │ ClusterIP │ │ │ └────────┬─────────┘ └──────────────────┘ │ │ │ │ │ ┌────────▼─────────┐ │ │ │ Ingress │ │ │ │ counter.local │ │ │ └──────────────────┘ │ │ │ │ 存储: Redis PVC(1Gi)配置: ConfigMap + Secret │ │ 监控: Prometheus 日志: Loki │ │ 安全: RBAC + NetworkPolicy │ └─────────────────────────────────────────────────────────────┘

迁移对照表

二、准备镜像

2.1 构建并加载镜像

# 构建 Flask 应用镜像(基于第 5 篇的多阶段 Dockerfile)dockerbuild-tflask-redis-counter:3.0.# 输出关键行:# [+] Building 35.2s (17/17) FINISHED# => [runtime 8/9] COPY --chown=appuser:appuser . .# => => naming to docker.io/library/flask-redis-counter:3.0# 加载到 Minikube 环境minikube image load flask-redis-counter:3.0# 验证镜像已加载minikubesshdockerimages|grepflask-redis-counter# flask-redis-counter 3.0 a1b2c3d4e5f6 138MB

2.2 Docker Compose 启动(回顾用)

如果你还想看看 Compose 版本的运行效果作为对照:

[+]Running3/3 ✔ Network flask-redis-counter_app-net Created0.1s ✔ Container redis Healthy5.2s ✔ Container flask-app Started5.5s

测试:

curlhttp://localhost:5000# Hello World! I have been seen 1 times.

关键:从这里开始,我们不再使用 Compose,一切由 K8s 接管。

三、部署 Redis(StatefulSet + Service + PVC)

首先部署应用的基石——Redis 存储层。我们使用 Deployment(单副本,配合 PVC 实现持久化)。

3.1 创建 Redis PVC

# redis-pvc.yamlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: redis-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: standard
kubectl apply-fredis-pvc.yaml# persistentvolumeclaim/redis-pvc createdkubectl get pvc# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS# redis-pvc Bound pvc-a1b2c3d4-e5f6-7890-abcd-ef1234567890 1Gi RWO standard

3.2 部署 Redis

# redis-deployment.yamlapiVersion: apps/v1 kind: Deployment metadata: name: redis spec: replicas:1selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:alpine ports: - containerPort:6379volumeMounts: - name: redis-data mountPath: /data volumes: - name: redis-data persistentVolumeClaim: claimName: redis-pvc --- apiVersion: v1 kind: Service metadata: name: redis-service spec: type: ClusterIP selector: app: redis ports: - port:6379targetPort:6379
kubectl apply-fredis-deployment.yaml# deployment.apps/redis created# service/redis-service createdkubectl get pods-lapp=redis# NAME READY STATUS RESTARTS AGE# redis-xxxxxxxxx-xxxxx 1/1 Running 0 30skubectl get svc redis-service# NAME TYPE CLUSTER-IP PORT(S) AGE# redis-service ClusterIP 10.96.100.50 6379/TCP 30s

四、创建配置(ConfigMap + Secret)

4.1 创建 ConfigMap(非敏感应用配置)

# configmap.yamlapiVersion: v1 kind: ConfigMap metadata: name: flask-config data: FLASK_ENV:"production"LOG_LEVEL:"info"REDIS_HOST:"redis-service"REDIS_PORT:"6379"
kubectl apply-fconfigmap.yaml# configmap/flask-config createdkubectl describe configmap flask-config# Name: flask-config# Namespace: default# Data# ====# FLASK_ENV:# ----# production# LOG_LEVEL:# ----# info

4.2 创建 Secret(敏感信息)

# secret.yamlapiVersion: v1 kind: Secret metadata: name: flask-secret type: Opaque stringData: SECRET_KEY:"my-production-secret-key-2025"
kubectl apply-fsecret.yaml# secret/flask-secret created

五、部署 Flask 应用(Deployment + Service)

5.1 创建 Flask Deployment

# flask-deployment.yamlapiVersion: apps/v1 kind: Deployment metadata: name: flask-deployment labels: app: flask-counter spec: replicas:3selector: matchLabels: app: flask-counter template: metadata: labels: app: flask-counter spec: containers: - name: flask image: flask-redis-counter:3.0 imagePullPolicy: IfNotPresent ports: - containerPort:5000envFrom: - configMapRef: name: flask-config - secretRef: name: flask-secret resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi startupProbe: httpGet: path: /health port:5000periodSeconds:5failureThreshold:12livenessProbe: httpGet: path: /health port:5000periodSeconds:15failureThreshold:3readinessProbe: httpGet: path: /health port:5000periodSeconds:5failureThreshold:2
kubectl apply-fflask-deployment.yaml# deployment.apps/flask-deployment created

验证部署状态:

kubectl get pods-lapp=flask-counter-w# NAME READY STATUS RESTARTS AGE# flask-deployment-xxxxxxxxx-xxxxx 0/1 ContainerCreating 0 2s# flask-deployment-xxxxxxxxx-xxxxx 1/1 Running 0 15s# flask-deployment-xxxxxxxxx-yyyyy 0/1 ContainerCreating 0 2s# flask-deployment-xxxxxxxxx-yyyyy 1/1 Running 0 15s# flask-deployment-xxxxxxxxx-zzzzz 0/1 ContainerCreating 0 2s# flask-deployment-xxxxxxxxx-zzzzz 1/1 Running 0 15s

查看 Deployment 整体状态:

kubectl get deployments# NAME READY UP-TO-DATE AVAILABLE AGE# flask-deployment 3/3 3 3 30s# redis 1/1 1 1 2m

5.2 创建 Flask Service

# flask-service.yamlapiVersion: v1 kind: Service metadata: name: flask-service spec: type: ClusterIP selector: app: flask-counter ports: - port:5000targetPort:5000
kubectl apply-fflask-service.yaml# service/flask-service createdkubectl get svc# NAME TYPE CLUSTER-IP PORT(S) AGE# flask-service ClusterIP 10.96.200.80 5000/TCP 10s# redis-service ClusterIP 10.96.100.50 6379/TCP 2m

六、验证内部通信与外部访问

6.1 验证内部通信

# 从 Flask Pod 访问 Rediskubectlexecdeploy/flask-deployment -- redis-cli-hredis-service PING# PONG

Flask 应用通过redis-service这个 Service 名称成功连接到了 Redis Pod。DNS 解析和 Service 负载均衡均工作正常。

6.2 端口转发验证

在没有 Ingress 的情况下,用端口转发快速验证:

kubectl port-forward svc/flask-service5000:5000

打开另一个终端:

curlhttp://localhost:5000# Hello World! I have been seen 1 times.curlhttp://localhost:5000# Hello World! I have been seen 2 times.

计数器正常工作,说明 Flask ↔ Redis 通信链路已打通。

6.3 检查各个对象状态

kubectl get all# NAME READY STATUS RESTARTS AGE# pod/flask-deployment-xxxxxxxxx-xxxxx 1/1 Running 0 2m# pod/flask-deployment-xxxxxxxxx-yyyyy 1/1 Running 0 2m# pod/flask-deployment-xxxxxxxxx-zzzzz 1/1 Running 0 2m# pod/redis-xxxxxxxxx-xxxxx 1/1 Running 0 5m## NAME TYPE CLUSTER-IP PORT(S) AGE# service/flask-service ClusterIP 10.96.200.80 5000/TCP 2m# service/redis-service ClusterIP 10.96.100.50 6379/TCP 5m## NAME READY UP-TO-DATE AVAILABLE AGE# deployment.apps/flask-deployment 3/3 3 3 2m# deployment.apps/redis 1/1 1 1 5m

七、本篇总结

  • 架构转换:将 Compose 的 services、ports、environment、volumes 分别映射为 K8s 的 Deployment、Service、ConfigMap、PVC。

  • 存储持久化:Redis 使用 PVC 实现数据持久化,存储类为standard(Minikube 默认)。

  • 配置管理:ConfigMap 管理非敏感配置(Redis 连接信息、日志级别),Secret 管理敏感信息(SECRET_KEY)。Flask Pod 通过envFrom一次性注入。

  • 生产化配置:包含三种探针(startup/liveness/readiness)、资源限制(Requests/Limits),确保应用稳定运行。

下一篇——第 45 篇:实战:将 Web 应用迁移到 Kubernetes(下),我们将继续为应用配置 Ingress 外部入口、HPA 自动伸缩、滚动更新验证,并接入 Prometheus 监控和 Loki 日志系统,完成从开发环境到生产级 K8s 集群的完整迁移。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !

http://www.zskr.cn/news/1469831.html

相关文章:

  • 【金融AI工具配置黄金法则】:20年风控专家亲授7大避坑指南与实时合规校验清单
  • 从‘玄学’到可控:拆解CUT论文中对比学习如何让AI理解‘风格’与‘内容’
  • 用74HC00与非门做个会叫的电子门铃:从电路图到焊板子的保姆级教程
  • AI工具产品路线预测实战指南(2024决策者必读版):基于172家SaaS厂商真实演进路径建模
  • 航空搜救指挥痛点:三维电子沙盘如何破解复杂地形调度难题
  • 实战应用:基于快马平台构建可部署的页面每日更新监控系统
  • 终极免费FF14钓鱼计时器:渔人的直感完整使用教程
  • 从零安装 Claude Code
  • 学完吴恩达第一周,我整理了这份深度学习避坑指南:从数据、算力到算法选择
  • Sora 2科学可视化不是“视频生成”,而是新一代计算叙事引擎(附IEEE VIS 2024预印本验证数据)
  • ai赋能内容平台:借助快马平台大模型为ao3镜像站实现智能标签与推荐
  • 【毕业设计】基于springboot+微信小程序的在线预约挂号系统基于微信小程序的智能在线预约挂号系统(源码+文档+远程调试,全bao定制等)
  • Gemini世界观构建:3天内完成从Prompt工程师到认知架构师的跃迁路径
  • 法律检索响应时间从15分钟压缩至8秒:北京知识产权法院AI辅助裁判系统内部操作手册首度流出
  • GEO优化公司推荐名单有哪些?GEO是什么公司?2026年6月国内GEO服务商TOP6综合测评 - 互联网科技品牌测评
  • 博主实测:为什么说德源 DYG5001 是 IGBT 封装中 3M 5413 的最强替身?
  • 如何快速解密科学文库PDF:3分钟完整破解指南
  • Anthropic千亿估值买不来未来:类脑智能正在逆袭
  • 荣获参与奖哈哈
  • 新手零基础入门:借助快马ai生成你的第一个数据库交互网页应用
  • 2026宜昌防水补漏哪家好?住建实地测评权威榜单TOP5|卫生间免砸砖/阳台屋顶/厨卫漏水维修(6月宜昌专项调研) - 苏易修缮
  • AI辅助开发新体验:描述你的创意,让快马AI自动生成炫酷加载动画代码
  • tmux 在生物信息项目中的妙用 —— 尤其是搭配 Claude Code 时
  • 上周用飞算JavaAI搓了个订单系统,真实手感如何?
  • 为啥换热板片带波纹?换热效率差别这么大?
  • OpenClaw 和 MCP 怎么接:把浏览器能力做成 Agent 可控工具
  • 【实战指南】从树莓派/Arduino迁移到youyeetoo K1:开发者完整攻略
  • 实战演练:基于快马AI快速开发一个带交互功能的飞鸟云官网Demo
  • 095、检测结果存储与分析平台:PostgreSQL/ClickHouse + Grafana 搭建检测数据分析
  • 2026年减速机源头厂家强力推荐榜:斜齿轮减速机、摆线减速机、四大系列及轴承传动设备优选指南 - 品牌企业推荐师(官方)