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

DevOps 入门系列:从 Pod 到 Ingress(K8s 核心概念)

DevOps 入门系列:从 Pod 到 Ingress(K8s 核心概念)

你已经会用 Docker 把应用打包成镜像,也会用 GitLab CI 自动构建和推送镜像。
现在你想把这些镜像放到 Kubernetes 里运行起来。
本文用一个真实的 Flask 应用作为例子,带你一步步理解 K8s 最核心的几个概念。
不执行命令,只讲概念和 YAML 的关键部分。


你遇到了什么问题?

假设你写了一个 Flask 应用,镜像已经推到了阿里云 ACR 私有仓库

你现在想在 K8s 集群里运行它,希望:

  • 一直运行 —— 万一容器挂了,能自动重启。

  • 跑 3 个副本 —— 分担流量,一台机器坏了还有别的。

  • 升级版本时不中断服务 —— 从 v1 换到 v2,用户无感知。

  • 密码不能写死在镜像里 —— 数据库密码要安全地传进去。

  • 配置能随时改 —— 比如日志级别、数据库地址,不想重新打包镜像。

  • 能通过域名从外面访问 —— 用户输入 flask.mycompany.com 就能打开页面。

这些问题,K8s 里有对应的资源逐个解决。

现在,我们从最基础的开始:怎么让一个容器在 K8s 里跑起来?

1. Pod:K8s 里最小的 “工人”

你遇到的第一个问题

Docker 里你直接用docker run启动容器。
但在 K8s 里,你不能直接 “跑一个容器”。K8s 的最小调度单位叫 Pod。

Pod 是什么?

定义: Pod 是 Kubernetes 中可以创建和管理的最小部署单元。
一个 Pod 里可以放一个或多个容器。最常见的用法是一个 Pod 只放一个容器(就是你的应用容器)。

Pod 的关键特点

  1. 短暂:Pod 可能随时被删除或重建(比如机器坏了、手动删除)。重建后 IP 会变。

  2. 最小单位:K8s 不直接操作容器,而是操作 Pod。你告诉 K8s “帮我起一个 Pod”,K8s 才会在里面创建容器。

Pod 的标签:给工人贴上“工牌”

Pod 有一个非常重要的功能:打标签(Label)。

定义: 标签就是贴在 Pod 上的一组 key: value(比如 app: flask、env: prod、tier: backend)。

为什么需要标签?
K8s 集群里可能有成百上千个 Pod。Deployment 怎么知道哪些 Pod 是自己管的?Service 怎么知道把流量转发给哪些 Pod?靠的就是标签。Deployment 和 Service 会说:“我只关心带有 app: flask 这个标签的 Pod”。

在 YAML 里怎么写:

yamlmetadata:labels:app:flask# 标签 key 是 app,value 是 flaskenv:prod

重点:

  • 标签的 key 和 value 可以随便起(比如 app: my-app、tier: frontend),只要统一就好。

  • Deployment 和 Service 里的 selector(选择器)会写相同的标签,表示“我就找这个标签的 Pod”。

  • 一个 Pod 可以打多个标签,用换行分开。


在实际生产过程中,你几乎不会单独创建 Pod。手动创建的 Pod 挂了就真的挂了,没人帮你重启。那谁来帮你管 Pod 的生命周期?答案是Deployment

2. Deployment:帮你管 Pod 的 “店长”

你遇到的第二个问题

Pod 能跑容器,但 Pod 太 “脆” 了 —— 如果它挂了(比如程序崩溃、机器宕机),没人帮它重启。
你想要的是:一直有 3 个 Pod 在运行,如果少了就自动补上。
另外,以后升级镜像版本(比如 v1 → v2),你希望不停机,一个接一个地换,用户无感知。这就需要Deployment来实现

Deployment 是什么?

定义: Deployment 是 Kubernetes 中用来管理 Pod 的控制器。你可以声明 “我要 3 个 Pod 永远运行”,Deployment 就会维持这个数量,并支持滚动更新和回滚。

关键点

  • Pod管理:你告诉 Deployment“我要 3 个 Pod,用这个镜像”,它负责创建并监控这些 Pod。

  • 自愈:Pod 意外消失,Deployment 自动重建(全新 Pod,IP 会变)。

  • 滚动更新:改镜像版本后,Deployment 逐步替换旧 Pod,不停机。

  • 回滚:新版有问题,可以一键回到旧版本。

YAML 核心字段

apiVersion:apps/v1kind:Deployment# 声明这是Deployment的配置metadata:name:flask-deployment# 这个 Deployment 的名字spec:replicas:3# 我要 3 个 Podselector:matchLabels:app:flask# 这个 Deployment 只管带 app=flask 标签的 Podtemplate:# Pod 的“模板”metadata:labels:app:flask# Pod 的标签(必须和上面 selector 一致)spec:containers:-name:flaskimage:registry.cn-hangzhou.aliyuncs.com/my-lab/flask-app:v1ports:-containerPort:5000

使用重点

  1. 你只需要关心replicas(副本数)、image(镜像地址)、containerPort(容器监听端口)。

  2. 标签(app: flask)很重要:Deployment 用它来找到自己管的 Pod,后面 Service 也会用它来找到 Pod。

  3. 你几乎不会手动创建 Pod,永远是通过 Deployment 来创建。

3. Service:给 Pod 一个 “永不变化的门牌号”

你遇到的第三个问题

Deployment 帮你把 Pod 管得好好的,Pod 挂了会自动重建。但有一个新问题:Pod 每次重建,IP 都会变
比如你的 Flask 后端 Pod 从10.244.1.5变成了10.244.2.8,前端怎么知道新的 IP 是什么?你不可能每次都去改前端的配置。

你需要一个固定的访问入口,不管后端 Pod 怎么变,这个入口永远不变。

Service 是什么?

定义: Service 为一组 Pod 提供一个固定的访问入口,并自动把请求转发给当前在线的 Pod。

核心

  • 固定 IP:Service 创建后会分配一个固定的ClusterIP(如10.96.100.1),不会变。

  • 靠标签找人:Service 不关心 Pod 的 IP,它通过标签(比如app: flask)自动找到当前所有带有这个标签的 Pod。

  • 负载均衡:如果有多个匹配的 Pod,Service 会把请求轮流转发给它们(默认轮询)。

Service 类型

  • ClusterIP(默认):只在集群内部可访问。

  • NodePort:在集群每个节点上开放一个端口(如 30080),外部可以通过节点IP:30080访问。

  • LoadBalancer:云厂商自动分配一个公网 IP(生产环境常用)。

YAML 核心字段

apiVersion:v1kind:Servicemetadata:name:flask-servicespec:type:ClusterIP# 默认值,不写也行selector:app:flask# 只转发给带这个标签的 Pod(和 Deployment 里的标签一致)ports:-port:80# Service 自己的端口(别人访问这个端口)targetPort:5000# 转发到 Pod 的 5000 端口

重点

  1. selector.app必须和 Pod 上的标签(Deployment 里template.metadata.labels)完全一致,否则 Service 找不到 Pod。

  2. 先有 Deployment 再建 Service(Pod 先跑起来,Service 才能找到它们)。

  3. 如果访问 Service 没反应,用kubectl get endpoints检查 Endpoints 是不是空 —— 空的说明标签没匹配上。


现在 Pod 有固定入口了。但还有两个问题:数据库密码写在哪里?普通配置经常改怎么办?

4. Secret:藏密码的 “保险柜”

你遇到的第四个问题

你的 Flask 应用需要连接 MySQL 数据库。数据库密码是my-secret-pw
你不想把这个密码写死在 Dockerfile 里(那样任何人都能看到镜像里的密码),也不想写死在代码里(改密码要重新打包镜像)。你想把密码单独存起来,Pod 启动时自己来取。于是你想到了Secret。

Secret 是什么?

定义: Secret 是 Kubernetes 中用来存储敏感信息(密码、Token、SSH 密钥)的对象。

核心

  • 存敏感信息:密码、API 密钥、证书等。

  • 数据是 Base64 编码:不是加密,只是避免肉眼直接看到。生产环境要配合 etcd 加密或外部密钥管理。

  • Pod 怎么用:可以通过环境变量或挂载文件的方式读取 Secret 里的值。

两种常用类型

  • Opaque(通用,存任意键值对)

  • [kubernetes.io/dockerconfigjson](kubernetes.io/dockerconfigjson)(存镜像仓库的账号密码,给 Deployment 拉私有镜像用)

YAML 核心字段

apiVersion:v1kind:Secretmetadata:name:mysql-secrettype:Opaquedata:password:bXktc2VjcmV0LXB3# "my-secret-pw" 的 base64 编码

在 Deployment 中引用

env:-name:DB_PASSWORDvalueFrom:secretKeyRef:name:mysql-secretkey:password

生产环境须知

  1. 创建 Secret 通常用命令kubectl create secret generic,不用手写 base64,一般也不会手动创建到YAML文件里。

  2. 永远不要把密码写在 YAML 文件里提交到 Git(除非你用了外部加密工具如 sops)。

  3. Secret 只能被同一个命名空间里的 Pod 引用。


密码解决了。但还有一些不是密码、但经常改的配置(比如日志级别、数据库地址),用 Secret 太麻烦,有没有更简单的?

5. ConfigMap:随手记的 “便利贴”

你遇到的第五个问题

你的 Flask 应用需要知道:

  • 日志级别是 info 还是 debug

  • 数据库主机地址是 mysql-service(这个地址在 K8s 内部是固定的)

这些信息不是秘密,但经常要改(比如开发环境用 debug,生产环境用 info)。你不想每次改日志级别都重新打包镜像。

ConfigMap 是什么?

定义: ConfigMap 是 Kubernetes 中用来存储非敏感配置信息的对象,如环境变量、命令行参数、配置文件。

核心

  • 存普通配置:不敏感的信息(端口、日志级别、地址)。

  • Pod 怎么用:同 Secret—— 环境变量或挂载文件。

  • 和 Secret 的区别:Secret 存密码等敏感信息,ConfigMap 存非敏感信息。

  • 更新问题:修改 ConfigMap 后,已运行的 Pod 不会自动刷新环境变量。需要重启 Pod(比如删除 Pod 让 Deployment 重建)。

YAML 核心字段

apiVersion:v1kind:ConfigMapmetadata:name:flask-configdata:LOG_LEVEL:infoDB_HOST:mysql-service

在 Deployment 中引用

env:-name:LOG_LEVELvalueFrom:configMapKeyRef:name:flask-configkey:LOG_LEVEL-name:DB_HOSTvalueFrom:configMapKeyRef:name:flask-configkey:DB_HOST

生产环境须知

  1. 开发、测试、生产环境可以用同一个镜像,只换 ConfigMap(和 Secret)—— 好比连锁店,配方一样,每家店的营业时间、菜单价目表各自调整。

  2. ConfigMap 可以挂载成文件,如果你的应用需要读取配置文件(如 application.properties),把整个文件内容塞进 ConfigMap 就行。

  3. 如果配置项不多,用环境变量最简单。


现在 Pod 能跑、配置能抽离,就剩最后一步:让用户通过域名访问。

6. Ingress:商场门口的 “总导览牌”

你遇到的第六个问题

你的 Flask 应用已经在集群内部跑起来了,Service 也给了固定 IP(ClusterIP)。但 ClusterIP 只能在集群内部访问,用户怎么从外面访问呢?

你可以把 Service 的类型改成 NodePort 或 LoadBalancer,但它们都有缺点:

  • NodePort:端口号很大(如http://node-ip:31234),不好记,也不安全。

  • LoadBalancer:每个 Service 都要买一个云负载均衡器,很贵。

如果以后你有多个应用(比如 api.myapp.com、web.myapp.com),难道每个都配一个 LoadBalancer?

你需要一个统一入口,根据域名把请求转发到不同的 Service。

Ingress 是什么?

定义: Ingress 是 Kubernetes 中管理外部访问集群内服务的 API 对象,通常提供 HTTP/HTTPS 路由。

核心

  • Ingress 只定义规则:写清楚 “域名 flask.mycompany.com → 转发到 flask-service”。

  • Ingress Controller 才是干活的:集群里必须有一个 Ingress Controller(如 Nginx Ingress、Traefik)监听这些规则,并实际转发流量。k3s(低配版k8s) 自带 Traefik,minikube 需要手动启用。

  • 支持 HTTPS:可以配置 TLS 证书(存在 Secret 里),自动处理 HTTPS。

  • 节省成本:一个 Ingress + 一个 LoadBalancer 就能服务几十个 Service。

YAML 核心字段

apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:flask-ingressspec:rules:-host:flask.mycompany.com# 用户访问这个域名http:paths:-path:/pathType:Prefixbackend:service:name:flask-service# 转发给这个 Serviceport:number:80

生产环境须知

  1. Ingress 本身不干活,要确认集群里有 Ingress Controller(kubectl get pods -n kube-system | grep ingress)。

  2. 本地测试可以用 [nip.io](nip.io) 魔法域名,比如flask.127.0.0.1.nip.io自动解析到 [127.0.0.1](127.0.0.1),不用配 DNS。

  3. 如果你只有一两个服务,直接用type: LoadBalancerkubectl port-forward可能更简单。Ingress 适合中大型项目。

7. 完整串联:从用户请求到容器处理

用户访问 https://flask.mycompany.com │ ▼ DNS 解析到云厂商的 LoadBalancer 公网 IP(Ingress Controller 暴露的) │ ▼ Ingress Controller(Nginx/Traefik)接收请求 │ ├── 匹配 Ingress 规则:host = flask.mycompany.com │ ▼ 转发给 flask-service(ClusterIP,地址 10.96.100.1:80) │ ▼ flask-service 通过标签 `app=flask` 找到所有 Pod(比如 3 个) │ 轮询选中其中一个 Pod IP(如 10.244.1.5:5000) ▼ Pod 里的 Flask 容器处理请求 ├── 从环境变量读取配置(来自 ConfigMap 和 Secret) └── 返回响应

资源清单(按顺序准备)

资源必须吗作用
Deployment必须管理 Pod 副本数、更新
Service必须给 Pod 固定入口
Secret按需存密码、镜像仓库认证
ConfigMap按需存普通配置
Ingress按需域名路由 + HTTPS

学习重点

刚开始练习,只需 Deployment + Service(ClusterIP),先在集群内部用kubectl port-forward测试。熟练后再加 Secret、ConfigMap、Ingress。

8. 总结

  • Pod:最小的工人,里面跑容器(通常是 1 个)。

  • Deployment:店长,负责维持 Pod 数量、滚动更新、自愈。

  • Service:前台总机,给动态变化的 Pod 一个固定 IP,并负载均衡。

  • Secret:保险柜,存密码。

  • ConfigMap:便利贴,存普通配置。

  • Ingress:总导览牌,根据域名路由到不同 Service。

http://www.rkmt.cn/news/1486807.html

相关文章:

  • Day 8:手撸一个豆包!流式输出 + 工具调用 + Web聊天应用
  • ncmppGui极速解密教程:3分钟掌握NCM音乐文件转换技巧
  • Sunshine游戏串流终极指南:构建你的个人云游戏服务器
  • 2026职场高阶能力含金量排行榜20名:进阶避坑与职业发展指南
  • MFC与Windows钩子实战:构建来电显示程序的技术解析
  • 如何用RTAB-Map视觉SLAM让机器人看懂复杂世界:5步构建精准3D地图
  • GetQzonehistory终极指南:如何永久保存你的QQ空间记忆
  • 2026年如何挑选口碑出众专业靠谱的国内双级滤波器供应商
  • Windows平台B站直播弹幕点歌工具:集成VLC播放器+实时歌词+图形配置界面
  • # 2026湖州免砸砖漏水维修全攻略|卫生间/阳台/厨房/屋顶根治方法+避坑指南|苏易修缮 - 苏易修缮
  • MCU Bootloader开发:时钟校准与软件SCI实现详解
  • reghdfe深度解析:Stata中多层固定效应回归的技术实现与实践指南
  • HunterPie:让《怪物猎人:世界》狩猎体验焕然一新的智能覆盖工具
  • 汽车LIN总线车门控制模块设计:从按键扫描到状态机与通信协议集成
  • 行为模拟的艺术:如何让爬虫的鼠标轨迹像真人
  • 西安大模型版本迭代预警与预案科普:3 分钟看懂企业如何应对 AI 算法变革
  • JAVAd的二分查找
  • 靠谱的定制硅胶制品源头厂家推荐:这五家为何值得考量?
  • 2026 烟台漏水检测电话|管道查漏水/消防 / 自来水管道测漏 TOP3 公司优选 - 资讯快报
  • 本地人私藏!杭州旅游必买清单:避开网红雷品,这6款地道特产闭眼囤 - 玖叁鹿
  • 【Linux】 章6 管理本地用户和组(RH124知识点问答题)
  • 有源滤波器与无功补偿厂家怎么选:重点看产品线完整度与系统配套能力 - 资讯焦点
  • 终极SPT-AKI存档编辑器完全指南:5分钟掌握单机塔科夫存档修改
  • 别再复制粘贴了!用Vue3 + weixin-js-sdk封装一个可复用的微信分享组件(附完整代码)
  • 福州市三菱重工空调维修师傅电话|各区金牌师傅,靠谱选欧米到家 - 欧米到家
  • 3分钟快速上手:用Video2X免费将低清视频无损放大到4K的完整指南
  • 终极指南:如何用Umi-OCR实现离线批量文字识别工作流自动化
  • 2026年广东的拉丝机/抛光机/打磨机制造工厂,凭什么成为行业标杆? - 变量人生001
  • Wand-Enhancer技术解析:如何通过本地增强工具扩展WeMod功能边界
  • Stable Baselines3:强化学习算法的可靠实现