Kubernetes 边缘节点高可用配置实战:keepalived VIP + Traefik Ingress 单一入口方案(kubernetes-handbook)
2026/9/23 22:27:25 网站建设 项目流程
  • 教程
  • 云原生
  • 容器编排

【免费下载链接】kubernetes-handbook

Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南

项目地址:https://gitcode.com/gh_mirrors/ku/kubernetes-handbook
点击查看免费下载

导读

在 Kubernetes 集群中,Ingress 是集群外部流量进入集群内部的唯一“大门”,而对外暴露能力的那批节点被称为边缘节点(Edge Node)。如果边缘节点只有单点、且入口 IP 不固定,整个集群的对外服务可用性就会岌岌可危。本文以 kubernetes-handbook 仓库中的 practice/edge-node-configuration.md 为核心,完整讲解如何用 keepalived 管理虚拟 IP(VIP)解决边缘节点单点故障,并将 Traefik Ingress 改造为 DaemonSet + nodeSelector + hostPort 的部署形态,最终实现对外只暴露一个统一入口 IP/端口、对内由多台边缘节点共同承担流量的高可用架构。读完本文你将掌握:边缘节点的定义与设计要点、keepalived VRRP/VIP 配置细节、Traefik 边缘化改造步骤,以及如何通过域名 + Path 访问 Kubernetes 内的多个 Service。

什么是边缘节点(Edge Node)

所谓边缘节点,即集群内部用来向集群外暴露服务能力的节点。集群外部的服务(用户、外部系统)通过该节点来调用集群内部的服务,边缘节点是集群内外交流的一个 Endpoint。

边缘节点的设计必须考虑两个问题:

  • 边缘节点的高可用:不能有单点故障,否则整个 Kubernetes 集群对外将不可用;
  • 对外的一致暴露端口:即只能有一个外网访问 IP 和端口,外部使用者不需要关心集群内部有多少台机器。

这两个问题恰好是负载均衡 + 虚拟 IP 技术最擅长解决的场景:由 keepalived 基于 VRRP 协议在多个节点间漂移一个虚拟 IP(VIP),对外永远只有一个稳定入口,而入口背后的真实节点(real_server)可以是多台,任一台宕机流量都会自动切换到其他存活节点。

上图展示了本方案的整体架构:左侧虚线框内是三台边缘节点(172.20.0.113/114/115),每台上运行 keepalived(维护 VIP)与 Traefik(Ingress controller);右侧是 Kubernetes 集群;VIP 172.20.0.119 由 keepalived 在边缘节点之间共享漂移。向集群添加 Service(步骤①)、更新 Ingress(步骤②)后,将servicename.xxx.xxx:172.20.0.119记录写入 DNS(步骤③),集群外部即可通过 service 的 DNS 名称访问服务。

架构设计:keepalived 如何满足边缘节点需求

为满足边缘节点的高可用与统一入口需求,本方案使用keepalived来实现。其工作链路如下:

  1. 在 Kubernetes 中添加 Service 的同时,在 DNS 中增加一条记录,这条记录需要与 Ingress 中的host字段相同;
  2. DNS 记录中的 IP 地址即VIP 地址,本示例中为172.20.0.119
  3. 集群外部通过 service 的 DNS 名称访问时,流量先到达 VIP,由 keepalived 承载的 LVS(IPVS)转发到真实的 Traefik 实例上;
  4. Traefik 根据访问的hostpath将流量转发到相应的 Kubernetes Service。

其中VIP 是使用 IPVS 创建的,IPVS 早已成为 Linux 内核的标准模块(ip_vs),无需额外安装,这也是该方案轻量、易落地的重要原因。

准备环境

复用 Kubernetes 测试集群的三台主机,其 IP 地址如下:

  • 172.20.0.113
  • 172.20.0.114
  • 172.20.0.115

本文的示例集群只有这三个 node,因此在三个 node 上都需要安装 keepalived 与 ipvsadm,并将它们全部指定为边缘节点。

安装 keepalived 与 ipvsadm

不使用容器方式安装(虽然社区有 kube-keepalived-vip 容器化方案,本方案更倾向于直接在 node 节点上手动安装,运维直观、依赖最少):

yum install keepalived ipvsadm

说明:ipvsadm是 IPVS 的用户态管理工具,用于查看和维护 LVS 规则;keepalived则负责 VRRP 虚拟路由冗余(VIP 漂移)与 real_server 健康检查。

安装完成后,将三个 node 全部指定为边缘节点(Edge Node)。

配置说明:改造前需要明确的几个要点

在动手配置前,需要先理解本方案对原有 Traefik Ingress 部署的改造思路——将原先以Deployment方式启动的 Traefik 改为DaemonSet,并指定一个与 node 在同一网段的 IP 作为 VIP。本示例将 VIP 指定为172.20.0.119配置 keepalived 前需要先保证这个 IP 没有被分配

改造后的关键特征:

  • Traefik 以DaemonSet方式启动(保证每个边缘节点上都运行一个 Traefik Pod);
  • 通过nodeSelector选择边缘节点(只调度到打了edgenode=true标签的节点);
  • 通过hostPort暴露端口(与宿主机端口直接绑定,配合 LVS DR 模式直接回包);
  • 当前 VIP 漂移到了172.20.0.115上(主备切换时 VIP 会在三台节点间漂移);
  • Traefik 根据访问的hostpath配置,将流量转发到相应的 Service 上。

配置 keepalived

keepalived 的完整配置文件内容如下(该文件同时保存在仓库 etc/keepalived/keepalived.conf,与文档示例一致,可直接参照使用):

! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from kaadmin@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id LVS_DEVEL } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.20.0.119 } } virtual_server 172.20.0.119 80{ delay_loop 6 lb_algo loadbalance lb_kind DR nat_mask 255.255.255.0 persistence_timeout 0 protocol TCP real_server 172.20.0.113 80{ weight 1 TCP_CHECK { connect_timeout 3 } } real_server 172.20.0.114 80{ weight 1 TCP_CHECK { connect_timeout 3 } } real_server 172.20.0.115 80{ weight 1 TCP_CHECK { connect_timeout 3 } } }

配置块逐项解读

global_defs(全局定义)

参数作用
notification_email故障告警通知邮箱,本示例配置为 root@localhost
notification_email_from告警邮件发件人
smtp_server/smtp_connect_timeoutSMTP 服务器地址与连接超时时间
router_id路由标识(VRID 的辅助标识),同一组 keepalived 实例建议保持一致

vrrp_instance(VRRP 虚拟路由实例)

参数作用说明
state MASTER本节点初始角色多台节点配置可都写 MASTER,由 priority 决定谁真正抢占;也可一台 MASTER、其余 BACKUP
interface eth0VIP 绑定的物理网卡必须与节点实际网卡名一致
virtual_router_id 51虚拟路由 ID同一 VRRP 组内的所有节点必须一致,且同一网段内不同 keepalived 组不能冲突
priority 100节点优先级数值越大越优先持有 VIP,用于决定主备顺序
advert_int 1VRRP 通告间隔(秒)主节点每秒发送一次通告,备节点在超时(通常 3 倍间隔)后接管 VIP
auth_type PASS/auth_pass 1111认证方式与密码同组节点必须一致,防止非法节点抢占 VIP
virtual_ipaddress虚拟 IP 列表本示例为 172.20.0.119,即对外统一入口地址

virtual_server(LVS 虚拟服务)

参数作用
delay_loop 6健康检查轮询间隔(秒)
lb_algo loadbalance负载均衡算法,本示例配置为 loadbalance(轮询加权)
lb_kind DR转发方式为DR(Direct Routing,直接路由),是转发效率最高的方式:请求经 VIP 进入后直接路由到 real_server,响应则由 real_server 直接回给客户端,不经过负载均衡器
nat_mask 255.255.255.0DR 模式下使用的子网掩码
persistence_timeout 0会话保持时间(秒),0 表示不启用,避免同一来源被长期固定到单台后端
protocol TCP转发协议
real_server ... weight 1真实后端节点(即 Traefik 所在节点)及其权重,weight 1表示三台平均分担
TCP_CHECK connect_timeout 3以 TCP 连接探测 real_server 健康状态,3 秒超时;后端不可用时自动从转发池中摘除

其中real_server的 IP 和端口即 Traefik 供外网访问的 IP 和端口。本方案选用lb_kind DR直接路由方式转发,使用TCP_CHECK来检测 real_server 的健康状态。

分发配置并设置自启动

将以上配置分别拷贝到另外两台 node 的/etc/keepalived目录下(三台节点配置主体相同,可按需调整各节点的priority以决定主备)。

设置 keepalived 为开机自启动:

chkconfig keepalived on

启动 keepalived 并验证 VIP 漂移

三台 node 都启动 keepalived:

systemctl start keepalived

启动后观察 eth0 的 IP,会在三台 node 的某一台上发现一个 VIP 是172.20.0.119

$ ip addr show eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether f4:e9:d4:9f:6b:a0 brd ff:ff:ff:ff:ff:ff inet 172.20.0.115/17 brd 172.20.127.255 scope global eth0 valid_lft forever preferred_lft forever inet 172.20.0.119/32 scope global eth0 valid_lft forever preferred_lft forever

如上输出所示,节点172.20.0.115的 eth0 上同时出现了真实 IP 与 VIP172.20.0.119/32(注意 VIP 掩码为 32 位,即仅作为本机虚拟地址)。

验证高可用:关掉拥有这个 VIP 主机上的 keepalived,观察 VIP 是否漂移到了另外两台主机的其中之一上。VIP 能在秒级(约 3 × advert_int 秒)内自动切换到存活节点,即完成了边缘节点层的单点故障消除。

改造 Traefik:从 Deployment 到 DaemonSet

在改造之前,我们启动的 Traefik 使用的是 Deployment,只启动了一个 Pod,无法保证高可用——单 Pod 只能固定在某一台主机上,该主机一旦故障,Ingress 入口即失效。现在使用 keepalived 之后,就可以通过 VIP 来访问 Traefik,同时启动多个 Traefik Pod保证高可用(任何时刻只有持有 VIP 的节点对外应答,但所有节点上的 Traefik 都在运行,随时可接管)。

改造后的配置文件traefik.yaml(与仓库 manifests/traefik-ingress/traefik.yaml 一致)内容如下:

apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: traefik-ingress-lb namespace: kube-system labels: k8s-app: traefik-ingress-lb spec: template: metadata: labels: k8s-app: traefik-ingress-lb name: traefik-ingress-lb spec: terminationGracePeriodSeconds: 60 hostNetwork: true restartPolicy: Always serviceAccountName: ingress containers: - image: traefik name: traefik-ingress-lb resources: limits: cpu: 200m memory: 30Mi requests: cpu: 100m memory: 20Mi ports: - name: http containerPort: 80 hostPort: 80 - name: admin containerPort: 8580 hostPort: 8580 args: - --web - --web.address=:8580 - --kubernetes nodeSelector: edgenode: "true"

关键配置项解析

配置项作用与说明
kind: DaemonSet在每个符合条件的节点上各运行一个 Pod,保证每个边缘节点都有 Traefik 实例
hostNetwork: true使用宿主机网络,Pod 直接共享节点网卡;这是配合 LVS DR 模式(real_server 直接回包)的必要条件
serviceAccountName: ingress使用名为ingress的 ServiceAccount,赋予 Traefik 读取 Ingress/Service/Endpoints 的权限(RBAC 配置见下文)
ports暴露 80(HTTP 流量入口)与 8580(Traefik Web UI 管理端口)两个端口,均通过hostPort与宿主机端口一一绑定
args: --web / --web.address=:8580 / --kubernetes开启 Web UI(监听 8580)、启用 Kubernetes Provider,使 Traefik 自动监听 Ingress 资源变化
resources.limits/resources.requests资源配额:上限 CPU 200m / 内存 30Mi,预留 CPU 100m / 内存 20Mi,保证边缘节点资源可控
nodeSelector: edgenode: "true"只调度到打了edgenode=true标签的边缘节点上

配套 RBAC 配置:Traefik 作为 Ingress controller 需要读取集群中的 Ingress、Service、Endpoints 等资源,仓库提供了对应的 manifests/traefik-ingress/ingress-rbac.yaml:创建一个名为ingress的 ServiceAccount(namespace: kube-system),并通过 ClusterRoleBinding 将其绑定到cluster-adminClusterRole。这样 DaemonSet 中的serviceAccountName: ingress才能正常工作。

给边缘节点打标签

注意,我们使用了nodeSelector选择边缘节点来调度 traefik-ingress-lb 运行在它上面,因此需要使用以下命令给三个 node 打标签:

kubectl label nodes 172.20.0.113 edgenode=true kubectl label nodes 172.20.0.114 edgenode=true kubectl label nodes 172.20.0.115 edgenode=true

若不打标签,Traefik 的 Pod 将无法匹配任何节点,会一直处于Pending状态(相关说明见 practice/traefik-ingress-installation.md)。

查看 DaemonSet 启动情况

$ kubectl -n kube-system get ds NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE-SELECTOR AGE traefik-ingress-lb 3 3 3 3 3 edgenode=true 2h

三个边缘节点上都各启动了一个 Traefik Pod,并且全部就绪(READY 3/3)。此时就可以在外网通过172.20.0.119:80来访问 Traefik Ingress 了。

配置 Ingress 规则与 Traefik Web UI

Traefik 边缘化改造完成后,还需要创建 Ingress 规则来定义流量路由。仓库中的 manifests/traefik-ingress/ingress.yaml 给出了一个多 Host + Path 的示例:

apiVersion: extensions/v1beta1 kind: Ingress metadata: name: traefik-ingress namespace: default spec: rules: - host: traefik.nginx.io http: paths: - path: / backend: serviceName: my-nginx servicePort: 80 - host: traefik.frontend.io http: paths: - path: / backend: serviceName: frontend servicePort: 80 - host: rolling-update-test.traefik.io http: paths: - path: / backend: serviceName: rolling-update-test servicePort: 9090 - host: k8s-app-monitor-agent.jimmysong.io http: paths: - path: / backend: serviceName: k8s-app-monitor-agent servicePort: 8080 - host: mean.jimmysong.io http: paths: - path: / backend: serviceName: orbiting-platypus-mean servicePort: 80 - host: helm.jimmysong.io http: paths: - path: / backend: serviceName: monocular-monocular-ui servicePort: 80 - path: /api/ backend: serviceName: monocular-monocular-api servicePort: 80

Ingress 规则的核心语义(详见 concepts/ingress.md):

  • 每条 rule 由host+path+backend组成,Traefik 将入站请求按 Host 头与 URL 路径进行匹配,命中后转发到对应的service:port
  • backend中配置的是目标 namespace 中的 Service 名称与端口,未显式指定 namespace 时默认使用defaultnamespace;如果要在其他 namespace 中暴露服务,需要新建 Ingress 文件并在其中指定namespace
  • 当集群中有新 Service 增加时,修改该文件后使用kubectl replace -f ingress.yaml即可热更新路由规则;
  • 若请求的 Host 无法匹配任何 rule,或 URL 无法匹配任何 path,流量将被转发到默认 backend(Ingress 中没有 rule 时的全局backend)。

同时可参照 manifests/traefik-ingress/ui.yaml 创建 Traefik 的 Web UI:先定义一个 Selector 为k8s-app: traefik-ingress-lb的 Service(port: 80映射到targetPort: 8580),再为它创建一个host: traefik-ui.local的 Ingress。配置完成后在边缘节点上访问http://<边缘节点IP>:8580/即可看到 Traefik Dashboard(左侧为所有 rule,右侧为所有 backend)。

使用域名访问 Kubernetes 中的服务

完成上述部署后,当前集群已经具备:

  • 三个边缘节点,使用 Traefik 作为 Ingress controller;
  • 使用 keepalived 做的 VIP(虚拟 IP)172.20.0.119

这样在访问该 IP 的时候,通过指定不同的Host即可路由到 Kubernetes 后端服务。但这种方式访问每个 Service 时都需要显式指定Host;而同一个项目中的服务一般会在同一个 Ingress 中配置,使用Path来区分 Service 已经足够,此时只要为 VIP(172.20.0.119)配置一个域名,所有外部访问直接通过该域名访问即可:

在集群内验证路由

在集群的任意一个节点上,通过指定 Host 头即可验证 Traefik 的转发能力。例如访问 nginx 的/路径:

$ curl -H Host:traefik.nginx.io http://172.20.0.115/ <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> ... </html>

Traefik 会解析 HTTP 请求 header 里的Host参数,将流量转发给 Ingress 配置中对应的 Service。

在集群外访问:配置 DNS 或 hosts

如果你需要在 Kubernetes 集群以外访问,就需要设置 DNS,或者修改本机的 hosts 文件:

172.20.0.115 traefik.nginx.io 172.20.0.115 traefik.frontend.io

所有访问这些地址的流量都会发送到对应节点。在生产环境(即本方案的目标形态)中,应将该记录解析到 VIP172.20.0.119而不是某台具体节点,这样才能借助 keepalived 的高可用能力——即使持有 VIP 的节点宕机,DNS 指向的地址依然有效,流量会在秒级内切换到新的存活边缘节点。

方案要点回顾与适用前提

  • 统一入口:对外永远只有一个 VIP(本文示例 172.20.0.119)+ 端口 80,外部无需感知集群内部拓扑;
  • 边缘节点高可用:keepalived 通过 VRRP 实现 VIP 漂移,LVS DR 模式 + TCP_CHECK 实现后端健康检查与摘除;
  • Ingress 高可用:Traefik 以 DaemonSet + nodeSelector + hostNetwork 部署,每个边缘节点都运行实例,任一节点故障由 VIP 切换接管;
  • 路由能力:Traefik 依据 Ingress 中的 host/path 将流量路由到不同 Service,一个域名 + 多个 Path 即可覆盖同一项目的全部服务。

适用前提与限制(基于本仓库示例环境):

  • 本文示例基于 CentOS 系(yum install)与extensions/v1beta1版本的 API(Kubernetes 1.8~1.15 时代),在新版本集群中应使用apps/v1的 DaemonSet 与networking.k8s.io/v1的 Ingress API,但 nodeSelector + hostNetwork + hostPort + VIP 的整体架构思路依然通用;
  • VIP 必须与 node 在同一网段且未被占用,lb_kind DR模式下所有边缘节点与客户端需处于可达的二层/三层网络环境中;
  • 仓库中的完整配套清单:keepalived 配置 etc/keepalived/keepalived.conf,Traefik DaemonSet manifests/traefik-ingress/traefik.yaml,RBAC manifests/traefik-ingress/ingress-rbac.yaml,Ingress 规则 manifests/traefik-ingress/ingress.yaml,Web UI manifests/traefik-ingress/ui.yaml,相关安装流程可进一步参考 practice/traefik-ingress-installation.md。
  • 教程
  • 云原生
  • 容器编排

【免费下载链接】kubernetes-handbook

Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南

项目地址:https://gitcode.com/gh_mirrors/ku/kubernetes-handbook
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询