Gateway API 实战:ingress-nginx 归档后的新标准(kind + Envoy Gateway 全打通)

Ingress 归档了,流量入口的新标准长什么样 先说一个 2026 年的重要事实(本文写作时实测验证):kubernetes/ingress-nginx 仓库已于 2026 年 3 月归档——GitHub API 返回 archived: true ,最后 release 是 v1.15.1(2026-03-19)。标准 Ingress Controller 停止更新了,但存量集群里的 Ingress 资源不会消失(照常工作),只是新项目的流量入口应该选新标准:Gateway API(本文写作时最新 v1.6.1,2026-07 发布,活跃迭代中)。 系列前一篇《Service 与 Ingress 实战》学的 Ingress 并没有白学——Gateway API 的设计目标之一就是吸收 Ingress 的经验、补上它的短板,两者资源模型一一对应。这篇在 kind 上用 Envoy Gateway 把 Gateway API 全链路打通:原理(三级资源模型)→ 实践(全部命令)→ 真实踩坑 → 迁移对照。 1. 动机先行:为什么要有 Gateway API Ingress 的痛点 Gateway API 的回应 一个 IngressClass / Ingress 资源,表达力有限(只能按域名+路径路由) 拆分三级资源:GatewayClass → Gateway → HTTPRoute,每级各司其职、可独立复用 路由规则与暴露方式混在一个资源里 暴露(Gateway)与路由(HTTPRoute)解耦:同一个 Gateway 可以被多个 HTTPRoute 挂载 协议扩展靠注解( nginx.ingress.kubernetes.io/xxx ),非标准 资源模型原生支持 HTTP/TLS/TCP/UDP,扩展用标准 CRD 不同实现行为不一致(nginx/traefik/…) 规范定义了资源的状态语义(Accepted/Programmed),实现行为更一致 一句话:Ingress 是"路由规则 + 入口绑在一起"的早期设计,Gateway API 把它拆成"谁提供服务(GatewayClass)→ 入口长什么样(Gateway)→ 流量怎么路由(HTTPRoute)“三层——分层带来复用和表达力。 ...

五月 20, 2024 · 6 分钟 · 1127 字 · yaomingye

tmux 终端复用实战:SSH 断了会话不丢,一个连接管理所有终端

一个 SSH 连接,管所有终端 说一个真实的痛点。远程 SSH 到服务器后用 k9s 看集群,发现两件事很烦:k9s 启动要等一两秒,而且它会把我的 Ctrl+B 截断——Ctrl+B 本来是我切换 SSH 终端的快捷键,进了 k9s 就失灵;想切终端只能新开一个 SSH 连接,重新认证、重新进目录、重新找上下文,来回切几次心态就崩了。 tmux 就是来解决这类问题的标准工具(运维和开发都推荐):一个 SSH 连接里开多个终端窗口,会话持久保存——SSH 断了,会话还在。这篇记录安装、核心概念、常用操作,以及我在服务器上的真实演示。 1. 动机先行:三个痛点,一个回应 痛点 没有 tmux 时 有 tmux 后 多终端切换 新开 SSH 连接(重新认证、丢上下文) 一个连接内 Ctrl+B 切窗口 快捷键冲突 k9s 等全屏工具截断 Ctrl+B k9s 放进 tmux 窗口,切换归 tmux 管 SSH 断线 正在跑的任务中断、上下文全丢 会话在服务器上继续跑,重连 attach 恢复 第三点是 tmux 最被低估的价值:tmux 的会话属于服务器上的 tmux 进程,不属于你的 SSH 连接——SSH 断了、电脑合盖了、网络抖了,会话照跑不误,重连回来 tmux attach 一切如初。 2. 安装 apt-get install -y tmux tmux -V # tmux 3.5a (Debian 源里就有, 一行搞定) 3. 原理:会话 / 窗口 / 窗格三件套 tmux 的层级关系一句话讲清: ...

二月 24, 2024 · 4 分钟 · 752 字 · yaomingye

K8s 破坏性练习:7 天把「会做」练成「会排障」

把环境弄坏再修好:排障能力是练出来的 前十六篇文章给了完整的概念和可复现的教程,但有个问题必须诚实回答:照着教程跑一遍,不等于会实战。教程给的每个坑都带答案(症状+解法),实战遇到的 90% 报错是没见过的——教程教的是"会做"(照着 recipe 做菜),实战考的是"会排障"(菜坏了知道哪不对)。 排障能力怎么练?等真实故障喂太慢,而且线上事故不敢乱动。有一个免费的、安全的、反馈极快的方法——破坏性练习:故意把环境弄坏,再自己修好。kind 集群里怎么炸都行,成本为零,几分钟一个循环。 这篇是 7 天训练营:每天一个破坏动作,全部在本系列集群上实测过(症状真实,非杜撰),做完你就从"会做"跨进"会排障"的门。 1. 原理:为什么破坏性练习有效 反馈循环极快:破坏 → 症状 → 假设 → 验证 → 修复,几分钟一圈(真实故障要等,事故不敢练); 症状库积累:排障快的人不是更聪明,是"见过的错误模式更多"——每个练习都在往你的模式库里存一个"症状→原因"映射; 安全失败:kind 里 Pod 随便炸、节点随便驱逐,没有任何生产代价——这是练习环境存在的全部意义。 %% 破坏性练习的反馈循环 flowchart LR A["① 破坏\n故意制造故障"] B["② 观察症状\n记录报错/状态"] C["③ 提出假设\n这个症状最可能是什么"] D["④ 验证\ndescribe / logs / 实验"] E["⑤ 修复\n恢复原状"] F["⑥ 复盘\n症状→原因 存入模式库"] A --> B --> C --> D --> E --> F F -.->|"下次见到同症状"| C style A fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style B fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style C fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold style F fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold style D fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style E fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold 排障黄金圈(所有练习共用): ...

二月 20, 2024 · 3 分钟 · 530 字 · yaomingye

K8s Helm 包管理实战:一套模板管所有环境与发布生命周期

YAML 堆成山之后:Helm 把清单变成包 系列前几课,我们一直用 kubectl apply -f xxx.yaml 部署应用——一个应用三四个清单文件,改环境就复制粘贴。这套姿势在小规模没问题,但想象一下真实场景:10 个微服务 × dev/staging/prod 三个环境 = 30 套 YAML,改一个端口要改 30 处,漏改一处就是环境事故,更别提回滚和复用。 Helm 就是来治这个病的——它是 K8s 的包管理器(类比 Java 的 Maven、Linux 的 apt):把一套应用清单打包成 Chart,用参数渲染出任意环境,顺带管好安装/升级/回滚的完整生命周期。这一课把 demo-app 从 kubectl 迁移到 Helm,全程实测。 1. 动机先行:没有 Helm 之前有多痛 痛点 没有 Helm 时 有 Helm 后 多环境维护 每个环境复制一套 YAML,手改差异 一套模板 + 参数(values 文件)渲染所有环境 参数化 改镜像 tag 要改 YAML 文件 --set image.tag=1.3 或改 values 版本管理 YAML 散落各处,无版本概念 Chart 有版本,release 有 revision 回滚 手动恢复旧 YAML(痛苦) helm rollback 一条命令 复用 复制整个目录 打包成 Chart 分发(像 npm 包) 依赖 手动装各组件 Chart 依赖声明(如依赖 ingress-nginx) 一句话:kubectl 是"我要这个资源",Helm 是"我要这套应用"——粒度从单资源提升到整个应用。 ...

二月 18, 2024 · 4 分钟 · 847 字 · yaomingye

K8s 状态化应用与存储实战:StatefulSet 三大保证与存储三层抽象

有状态应用上集群:名字、盘、顺序一个都不能乱 系列前七课全在讲无状态应用——Deployment 的 Pod 随便重建、随便换节点,名字是随机后缀,数据不留本地。这当然好,但现实里有状态的东西怎么办?数据库、Redis、Elasticsearch——它们要求"我是谁"固定不变、“我的数据"不能丢、初始化顺序不能乱。 这一课补齐工作负载的最后一块拼图:StatefulSet(有状态应用控制器)和它背后的存储抽象(PV / PVC / StorageClass)。全部在 kind 上实测,最后映射到 ACK 的云盘动态供应。 1. 目标与前置条件 目标:理解 StatefulSet 与 Deployment 的本质区别;掌握存储三层抽象与动态供应机制;亲手验证"稳定标识、专属存储、有序滚动"三大保证。 前置条件(沿用系列环境): 项 说明 kind 集群 learn ,1 主 2 从,K8s v1.36.1 StorageClass kind 自带 standard ( rancher.io/local-path , WaitForFirstConsumer ),无需安装任何组件 镜像 busybox:1.36 (测试写入)、 nginx:1.27/1.25 (滚动演示) kubectl get nodes kubectl get storageclass # 应看到 standard (default) 2. 原理先行:两个问题,两套机制 2.1 存储三层抽象:开发者只写"声明” K8s 的存储不是"挂一块盘"这么简单,它把存储拆成三层,让开发者与存储实现解耦: PV(PersistentVolume,持久卷):一块真实的存储——云上是一块云盘、物理机是一个目录。它属于集群,由管理员/系统创建; PVC(PersistentVolumeClaim,持久卷声明):开发者写的"我要 100Mi 的盘,可读写一次"——声明需求,不关心盘从哪来; StorageClass(存储类):动态供应的"模板"——定义了用哪种 provisioner(云盘/本地目录)、什么回收策略。PVC 指定存储类后,provisioner 自动创建 PV 并绑定,开发者全程不碰真实存储。 %% 存储三层抽象: 开发者只写 PVC, StorageClass 自动建 PV flowchart TD DEV["开发者\n写 PVC 声明: 我要 100Mi 可读写一次的盘"] PVC["PVC\nPersistentVolumeClaim"] SC["StorageClass standard\nrancher.io/local-path"] PV["PV\n自动创建的真实卷"] DISK["物理存储\nkind: 节点本地目录\nACK: 云盘"] DEV -->|"kubectl apply"| PVC PVC -->|"指定 storageClassName"| SC SC -->|"provisioner 动态供应"| PV PV --> DISK style DEV fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style PVC fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold style PV fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold style SC fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff WaitForFirstConsumer(本集群 storageclass 的绑定模式)值得单独说:PVC 创建后先 Pending ,等第一个使用它的 Pod 被调度到节点后,才在那个节点上创建卷并绑定——好处是卷落在"真正用它的节点"旁边,避免"卷在 A 节点、Pod 在 B 节点"的跨机访问。云上的云盘绑定也是这个模式。 ...

二月 14, 2024 · 4 分钟 · 801 字 · yaomingye

Java 开发工程师的 K8s 职责清单:八项必修、三类免学、五个专属坑

开发背一半运维:你的 K8s 职责边界在哪 云原生时代,开发工程师的职责边界变了。以前是"写完代码扔给运维",现在是"应用怎么跑也写进代码"——Dockerfile、探针、资源申请、优雅停机,这些曾经属于运维的东西,现在都是开发要交付的代码的一部分。 但反过来,开发也不该全包运维:集群的节点、证书、网络插件,那不是你的活。这篇给 Java 开发工程师一张清单——必须会什么、不用学什么、Java 专属的坑有哪些、边界到底划在哪。本系列的十篇文章是这个清单的展开,这篇是入口。 1. 一句话框架:开发背一半运维 判断职责归属,用一条标准就够: “我写的这个应用,在集群里能不能健康地跑起来、出问题我自己能不能查”——这是开发的活;“集群本身能不能稳定运转”——这是平台的活。 应用的健康 = 镜像、探针、资源配置、优雅停机、指标暴露——开发用代码负责; 集群的稳定 = 节点、etcd、CNI、证书、升级——平台/运维负责,开发只需要知道它们存在。 至于中小公司没有专职运维、开发被迫全包——那是资源约束下的现实,不是理想的职责划分。能力可以全栈,但边界心里要有数:“运维的事"永远会挤占开发时间,不清边界就会被无限稀释。 2. 必须会:八项清单 每一项都标注了"怎么算会了”——能独立完成才算过关。 # 技能 一句话原理 验证标准 对应文章 1 镜像构建 多阶段 Dockerfile 把构建与运行分离,体积从 500MB 级压到 300MB 级 能写出 JRE 运行镜像,知道层缓存 课1:镜像构建 2 Deployment 声明式滚动更新,改清单而不是手工 docker run 能改镜像滚动升级、回滚 课1:Deployment 实战 3 配置注入 ConfigMap/Secret 让配置外部化,改配置不重建镜像 能注入环境变量和文件,知道 Secret 只是 base64 课3:配置注入 4 Service/Ingress ClusterIP 内部调用、NodePort/LB 对外暴露、Ingress 管域名路由 能说清三种类型各给谁用 课2:Service/Ingress 5 探针 readiness 摘流量、liveness 重启、startup 保护慢启动 能给 Spring Boot 配齐三件套 课4:探针 6 资源申请 requests 管调度、limits 管上限,不设就是裸奔 能给应用填合理数值并解释依据 课5:资源管理 7 优雅停机 readiness 摘流 + preStop 缓冲 + graceful 处理在途 发版时在途请求不断连 课5:优雅停机 8 可观测性 应用暴露指标端点,监控才有意义 能说出 /actuator/prometheus 暴露了什么 课6:可观测性 贯穿八项的还有一个基本功:排障—— kubectl logs 、 kubectl describe 、 kubectl exec 是开发者的手电筒,遇到问题第一反应是"进 Pod 看一眼"而不是"重启试试"。 ...

十二月 4, 2023 · 4 分钟 · 735 字 · yaomingye

Kubernetes 系列总结:两台服务器的资产清点与六课收获

八篇博客、两台服务器:K8s 学习资产清点 这个系列写到这里,第八篇了。从一台退役的笔记本服务器(i3 双核、7.6G 内存)搭起 kind 集群开始,到 Prometheus 抓出第一根指标曲线、Grafana 画出第一张仪表盘结束——六课实战、八篇博客,一路踩的坑全记在了文章里。 这篇不教新东西,做三件事:清点两台服务器上现在跑着的资产(写文章时我重新登服务器核实过,不是凭记忆)、按课时梳理"看+复现"分别能学到什么、把整个系列的复现成本交代清楚。想入坑的读者可以从这篇倒着挑文章看。 1. 资产清点:两台服务器,各司其职 先说分工:一台云服务器(有公网 IP)当唯一公网入口——跑博客站点、接收反向隧道;一台内网笔记本服务器(没有公网 IP)当学习环境主力——跑 kind 集群和全套监控。本机(开发机)通过 SSH 经云服务器中转,随时能进内网服务器干活。 %% 全局拓扑: 本机 -> 云服务器(入口) -> 内网 debian(学习主力) flowchart TD LAP["本机 Windows + WSL2\n开发写作 + SSH 运维入口"] ECS["云服务器 ECS\n唯一公网入口"] DEB["debian 笔记本服务器\n内网, 学习环境主力"] BLOG["blog-nginx 容器\nyaocat.cloud 博客站点"] MIH["mihomo 代理\n7890/7891/9090"] KIND["kind 集群 learn\n1 主 2 从 v1.36.1"] LAP -->|"SSH 经云服务器中转"| DEB DEB -->|"autossh 常驻加密隧道"| ECS ECS -->|"公网 80/443"| BLOG DEB -->|"拉镜像走代理"| MIH DEB --> KIND 1.1 内网笔记本服务器(学习主力) 写这篇时登上去核实过的真实清单: ...

十一月 30, 2023 · 5 分钟 · 875 字 · yaomingye

Kubernetes 可观测性实战:把 Prometheus+Grafana 装进 kind,一次踩满四个坑

四个坑,一条可观测性链路 上一篇文章(探针三兄弟)结尾我留了个预告:Prometheus 是和应用同源的"观察回路",探针负责让 kubelet 直接干预,Prometheus 负责把应用的运行状态变成数值曲线。这篇就是兑现——给 demo-app 装上指标端点,在 kind 集群里部署 Prometheus 抓取,再用 Grafana 把指标画成面板。 我原本以为最花时间的会是写 PromQL 查询,结果真正花时间的是一连串"我以为能访问、实际不能"的报错。四个坑踩下来,反而把 kind 的网络模型、集群内 DNS 的边界、ConfigMap 挂载的机制全摸了一遍。这篇文章就按踩坑的顺序写——坑是主线,知识点是副产品。 先把坑亮出来 # 坑 症状一句话 背后的机制 ① NodePort 端口超出合法区间 Service 创建被 API 拒绝 NodePort 默认只允许 30000-32767 ② 宿主机访问不到 NodePort 127.0.0.1:31090 连接被拒 kind 节点是独立网络命名空间的容器,NodePort 绑在节点 eth0 上 ③ 集群外解析不了 Service 域名 宿主机 curl demo-app-svc 直接失败 ClusterIP 的 DNS 由集群内 CoreDNS 提供,只服务集群内的 Pod ④ Grafana 预置数据源不生效 数据源列表为空 provisioning 只扫描 datasources/ 、 dashboards/ 子目录,ConfigMap 整卷挂载是扁平的 四个坑的共同点是:一切看起来都部署成功了,直到访问/验证那一刻才发现不对劲。所以每踩一个坑,我都会把"症状长什么样、我查了什么、怎么解决"完整记下来,方便对号入座。 ...

十一月 28, 2023 · 10 分钟 · 2008 字 · yaomingye

Kubernetes 优雅停机与资源管理:发版不断连 + 防 OOM 实战

让应用体面地死,别被 OOM 悄悄杀 上一篇的探针解决了"应用是死是活"的自动判定,这一篇解决剩下的两个生产问题:发版/缩容时正在处理的请求怎么办(优雅停机),以及节点资源怎么科学分配、应用怎么不被内存杀掉(资源管理)。前者让应用"体面地死",后者让应用"活着且不挤爆别人"。两件事都是 Java 应用上 K8s 后事故率最高的场景。 📌 前置知识:本文是 kind 系列第 6 篇,需要已完成前 5 篇——kind 集群、 k8s-demo-app 已部署(本文用 1.1 版,新增了 /api/slow 慢接口用于演示)、探针已配置。 这次要做什么 目标1: 配置优雅停机, 验证 Pod 被删时在途请求存活 目标2: 理解 requests/limits 资源账本, 实测 Pending 与 OOMKilled 产出: 生产级 YAML + 两组可复现演示 + 一个诚实的对照组分析 第一部分:优雅停机 原理:Pod 被删除时发生了什么 Kubernetes 删除 Pod 的完整时序(每个环节都有讲究): flowchart TD A["kubectl delete pod"] --> B["Pod 标记 Terminating"] B --> C["① Endpoints 立即摘除新流量不再进来"] C --> D["② preStop 钩子执行(本文 sleep 5s, 给摘流留时间)"] D --> E["③ kubelet 发送 SIGTERM应用开始优雅停机"] E --> F["④ 应用处理完在途请求(Spring graceful 最多等 30s)"] F --> G["⑤ 应用退出, 容器停止"] G --> H["⑥ 超过 terminationGracePeriodSeconds则 SIGKILL 强杀"] style A fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style B fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style C fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style D fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style E fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style F fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style G fill:#450a0a,stroke:#dc2626,stroke-width:2px,color:#ffffff,font-weight:bold style H fill:#450a0a,stroke:#dc2626,stroke-width:2px,color:#ffffff,font-weight:bold 三个保护机制配合(缺一不可): ...

十一月 26, 2023 · 5 分钟 · 979 字 · yaomingye

Kubernetes 探针三兄弟:readiness / liveness / startup 的生产级实战

让集群知道你的应用是死是活:探针三兄弟实战 应用部署进集群只是第一步——K8s 号称"自愈",但它怎么知道你的应用是死是活?答案就是探针(Probe)。三个探针分别回答三个问题:启动好了没?能不能接客?还活着吗? 这一篇用上一篇文章构建的 Spring Boot 应用,把三个探针逐一配上并现场演示它们的工作机制:readiness 如何拦住流量、liveness 如何自动救活假死的应用、startup 如何防止"启动慢被误杀"。 📌 前置知识:本文是 kind 系列第 5 篇,需要已完成前 4 篇的环境——kind 集群、 k8s-demo-app 应用已部署(含 ConfigMap 注入)、 demo-app-svc Service 已创建。应用已内置 Actuator 探针端点(上篇预埋的 management.endpoint.health.probes.enabled=true )。 这次要做什么 目标:给 demo-app 配置三种探针,并亲眼验证三种机制 产出:生产级探针 YAML + 三个可复现的演示 + 探针与 Prometheus 的定位对比 主角:k8s-demo-app(Spring Boot 3.3.5,Actuator 已暴露探针端点) 原理:三个探针各管什么 探针 回答的问题 失败后果 生产意义 startup 应用启动好了没? 容器被重启 给 JVM 冷启动免死金牌,治"启动慢被误杀" readiness 能接客了吗? 只摘流量,不杀容器 发版不断服、依赖故障自动摘流 liveness 还活着吗? 容器被杀重启 死锁/假死自动恢复 三个探针的配合时序: flowchart LR A["容器启动"] --> B["startupProbe成功前不启动其他探针"] B -->|"成功"| C["readinessProbe决定流量是否接入"] C -->|"持续"| D["livenessProbe决定容器是否存活"] D -->|"失败3次"| A style A fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style B fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style C fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style D fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style reject fill:#450a0a,stroke:#dc2626,stroke-width:2px,color:#ffffff,font-weight:bold ⚠️ 新手提示:最容易混淆的是 readiness 和 liveness 的失败后果——readiness 失败只摘流量(Pod 还在),liveness 失败会杀容器。生产事故里"DB 抖动引发雪崩"的根源,就是 liveness 探针错误地检查了数据库:DB 挂 30 秒 → liveness 失败 → 所有实例被反复杀。liveness 只该查进程级健康(如 JVM 活着),下游依赖的健康交给 readiness。 ...

十一月 24, 2023 · 5 分钟 · 942 字 · yaomingye
Cat Radio