Homepage 的 Kubernetes 集成实战:集群模式连接、自动服务发现与资源监控 Widget

Homepage 的 Kubernetes 集成实战:集群模式连接、自动服务发现与资源监控 Widget

【免费下载链接】homepage A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations. 【免费下载链接】homepage 项目地址: https://gitcode.com/GitHub_Trending/ho/homepage

Homepage 原生支持 Kubernetes 集群连接,允许在自建首页中实时展示集群节点状态、CPU/内存统计,并通过 Ingress、Traefik IngressRoute 或 Gateway API HttpRoute 注解实现服务自动发现。本文以仓库根目录的 kubernetes.md 与 docs/configs/kubernetes.md 为骨架,结合 安装文档 与 src/utils/kubernetes 源码实现,完整讲解连接模式、配置项、服务发现注解体系与 Widget 用法,帮助你在一小时内把 Homepage 接入现有集群。

前置要求

Kubernetes 集成并非开箱即用,集群侧需要满足以下条件:

要求说明
Kubernetes 1.19+集群 API 版本下限,确保 networking.k8s.io/v1 Ingress 与客户端库兼容
Metrics Service提供 metrics.k8s.io 聚合 API,用于获取节点 / Pod 的 CPU 与内存指标
Ingress controller承载 Ingress 资源,供服务发现读取(如 Nginx、Traefik、Cilium 等)
Gateway-API(可选)若需使用 HttpRoute 服务发现,需集群安装了 Gateway API CRD

Metrics Service 尤为重要:Homepage 的服务统计 Widget 与集群 Widget 的资源数据均来源于 metrics.k8s.io,未部署 Metrics Server 时相关指标将不可用。

部署方式

方式一:使用非官方 Helm chart(推荐)

官方未维护 Helm chart,社区维护的 chart 位于 jameswynn/helm-charts。只需两步:

helm repo add jameswynn https://jameswynn.github.io/helm-charts
helm install my-release jameswynn/homepage

安装完成后,需要将 kubernetes.yaml 中的连接模式设置为 cluster(详见下文"连接模式"):

mode: cluster

如需启用 Gateway API 兼容性,追加:

gateway: true

方式二:原生 Kubernetes manifests

如果不想依赖 Helm chart,可以自行编写清单并用 kubectl apply -f filename.yaml 应用。完整可运行的示例见 Kubernetes 安装文档,核心资源清单如下:

  • ServiceAccount:名为 homepage,供 Pod 携带集群身份;
  • Secret:类型 kubernetes.io/service-account-token,供 ServiceAccount 挂载令牌;
  • ConfigMap:承载全部配置文件(kubernetes.yaml、settings.yaml、services.yaml、widgets.yaml、bookmarks.yaml、custom.css/js);
  • ClusterRole 与 ClusterRoleBinding:授权 Homepage 读取集群资源,规则覆盖 namespaces、pods、nodes、ingresses、ingressroutes(traefik.io)、httproutes/gateways(gateway.networking.k8s.io)以及 metrics.k8s.io 的 nodes/pods;
  • Service:ClusterIP 类型,暴露 3000 端口;
  • Deployment:镜像 ghcr.io/gethomepage/homepage:latest,以非 root(UID 1000)运行,通过 subPath 将 ConfigMap 中每个文件挂载到 /app/config/ 对应路径;
  • Ingress:对外暴露,同时可附加 gethomepage.dev/* 注解实现自发现(见下文)。

多副本注意:若副本数大于 1,建议在入口路由上开启会话粘滞(sticky session),避免页面加载与窗口 / 标签聚焦时产生不必要的重复渲染。以 Traefik 为例,通过 sticky.cookie 配置(httpOnly: true、secure: true、sameSite: none),示例见 docs/installation/k8s.md。

连接配置:kubernetes.yaml 的三种模式

Kubernetes 连接在 kubernetes.yaml 中配置(未创建时会在首次启动自动生成副本,可参考 src/skeleton/kubernetes.yaml),共三种模式:

模式行为
disabled完全禁用 Kubernetes 连接
default使用默认的 kubeconfig 解析(本地开发、集群外部运行时使用,解析规则见 Kubernetes 官方 kubeconfig 组织文档)
cluster使用集群内的 ServiceAccount 令牌(生产部署推荐)
mode: default

从源码 src/utils/config/kubernetes.js 可以清晰看到三种模式的分流逻辑:cluster 调用 kc.loadFromCluster() 加载挂载的 ServiceAccount 令牌,default 调用 kc.loadFromDefault() 走本地 kubeconfig,而 disabled 或未配置时返回 null,后续所有 Kubernetes 相关功能整体关闭。

连接建立后,可通过开关决定启用哪些服务发现来源。以下配置仅启用 Ingress(这也是默认行为):

ingress: true # 默认,仅启用 ingress

同时启用 Traefik IngressRoute 与 Gateway API:

ingress: true # 默认,启用 ingress
traefik: true # 启用 traefik ingressRoute
gateway: true # 启用 gateway-api

源码层面对应三个独立的后端列表获取器:ingress 走 NetworkingV1Api.listIngressForAllNamespaces()(见 ingress-list.js),traefik 通过 CustomObjectsApi.listClusterCustomObject 分别探测 traefik.containo.us 与 traefik.io 两个 API 组的 ingressroutes(见 traefik-list.js),gateway 则拉取 gateway.networking.k8s.io/v1 的 httproutes(见 httproute-list.js)。

Kubernetes Widget:集群资源总览

Kubernetes Widget 可展示集群整体概览、各节点明细或两者兼有,配置写在 widgets.yaml:

- kubernetes:
    cluster:
      # 是否显示集群节点
      show: true
      # 是否显示聚合的 CPU 统计
      cpu: true
      # 是否显示聚合的内存统计
      memory: true
      # 是否显示自定义标签
      showLabel: true
      label: "cluster"
    nodes:
      # 是否显示节点列表
      show: true
      # 是否显示每个节点的 CPU
      cpu: true
      # 是否显示每个节点的内存
      memory: true
      # 是否显示标签(始终为节点名称)
      showLabel: true

其中 cluster 区块展示集群聚合视图,nodes 区块逐节点展示。二者的 cpu / memory 数据均来自集群 Metrics Service;showLabel 在 cluster 模式下展示自定义 label 文案,在 nodes 模式下则固定展示节点名。该 Widget 的前端组件位于 src/components/widgets/kubernetes,配套的状态/统计 API 端点见 src/pages/api/kubernetes。

Service Widgets:手动关联服务与 Pod 统计

Kubernetes 连接就绪后,可以为 services.yaml 中的任意服务手动开启 Pod 统计(当前仅支持 CPU 与内存)。关键是在服务条目上配置 namespace 与 app 两个字段:

- Emby:
  icon: emby.png
  href: "http://emby.home/"
  description: Media server
  namespace: media # 应用所在的 kubernetes 命名空间
  app: emby # 已部署应用的名称

app 字段用于构造标签选择器:上例将匹配带有 app.kubernetes.io/name=emby 标签的 Pod。这通常能同时命中 Ingress 与 Deployment,但对复杂或不规则的应用部署并不总是成立,此时可用 podSelector 字段弥补——它接受任意字段选择器(field selector),选择能力非常强大。

例如,将多个底层 Deployment 聚合为一个应用,展示高层级的汇总资源占用:

- Element Chat:
    icon: matrix-light.png
    href: https://chat.example.com
    description: Matrix Synapse Powered Chat
    app: matrix-element
    namespace: comms
    podSelector: >-
      app.kubernetes.io/instance in (
          matrix-element,
          matrix-media-repo,
          matrix-media-repo-postgresql,
          matrix-synapse
      )

重要提示:podSelector 置为空白字符串并不会停用该字段,反而会选中命名空间内的全部 Pod。这一行为非常适合捕获"被隔离在单个命名空间内的复杂应用"(如 Longhorn)的整体资源使用情况。

自动服务发现

Ingress 注解发现

Homepage 通过 Ingress 注解实现自动服务发现,所有配置项均以 gethomepage.dev/ 为前缀,使用标准注解语法,与手动配置的选项一一对应:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: emby
  annotations:
    gethomepage.dev/enabled: "true"
    gethomepage.dev/description: Media Server
    gethomepage.dev/group: Media
    gethomepage.dev/icon: emby.png
    gethomepage.dev/name: Emby
    gethomepage.dev/widget.type: "emby"
    gethomepage.dev/widget.url: "https://emby.example.com"
    gethomepage.dev/widget.headers.X-Auth-Key: "your-secret-here"
    gethomepage.dev/pod-selector: ""
    gethomepage.dev/weight: 10 # 可选
    gethomepage.dev/instance: "public" # 可选
spec:
  rules:
    - host: emby.example.com
      http:
        paths:
          - backend:
              service:
                name: emby
                port:
                  number: 8080
            path: /
            pathType: Prefix

集群连接配置正确后,该服务会被自动发现并加入首页。无需再手动指定 namespace 与 app——它们会被自动推断。

各注解的语义:

注解含义
gethomepage.dev/enabled是否启用该服务的自动发现
gethomepage.dev/name / description / group / icon服务卡片显示的名称、描述、所属分组与图标
gethomepage.dev/widget.type / widget.url / widget.headers.*为发现的服务直接附加 Widget 配置(如 Emby 的类型、地址、请求头)
gethomepage.dev/pod-selector指定健康检查所用的 Pod(见下文)
gethomepage.dev/weight可选,影响服务在组内的排序权重
gethomepage.dev/instance可选,限定服务仅出现在特定 Homepage 实例上

多实例过滤:如果部署了多个 Homepage 实例,可用 instance 注解将服务限定到特定实例;未标注时服务对所有实例可见。若某个服务需要在多个指定实例(而非全部)上展示,可叠加多个 instance.<name> 注解,例如同时标注 gethomepage.dev/instance.public: "" 与 gethomepage.dev/instance.internal: "",则该服务只会出现在名为 public 和 internal 的实例上。

健康检查 Pod 选择:使用 gethomepage.dev/pod-selector 指定健康检查对应的 Pod。例如标注 gethomepage.dev/pod-selector: app.kubernetes.io/name=deployment 会将检查链接到带有 app.kubernetes.io/name: deployment 标签的 Pod。

从源码看,注解前缀常量 ANNOTATION_BASE = "gethomepage.dev" 与 ANNOTATION_WIDGET_BASE = "gethomepage.dev/widget." 定义在 src/utils/config/kubernetes.js,被资源解析逻辑(resource-helpers.js)统一消费。此外,URL 的推导逻辑也在该文件中:Ingress 依据 spec.tls 是否存在决定 https/http,而 HTTPRoute 则需向关联的 Gateway 查询 listener 的 protocol 才能确定协议前缀(见 resource-helpers.js)。

Traefik IngressRoute 支持

在 kubernetes.yaml 中设置 traefik: true 后,Homepage 可读取 Traefik IngressRoute 自定义资源定义的 Ingress。由于 Traefik 路由规则非常复杂,必须设置 gethomepage.dev/href 注解,Homepage 才能确定该服务的访问地址:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: emby
  annotations:
    gethomepage.dev/href: "https://emby.example.com"
    gethomepage.dev/enabled: "true"
    gethomepage.dev/description: Media Server
    gethomepage.dev/group: Media
    gethomepage.dev/icon: emby.png
    gethomepage.dev/app: emby-app # 可选,当 app.kubernetes.io/name != ingress metadata.name 时可能需要
    gethomepage.dev/name: Emby
    gethomepage.dev/widget.type: "emby"
    gethomepage.dev/widget.url: "https://emby.example.com"
    gethomepage.dev/pod-selector: ""
    gethomepage.dev/weight: 10 # 可选
    gethomepage.dev/instance: "public" # 可选
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`emby.example.com`)
      services:
        - kind: Service
          name: emby
          namespace: emby
          port: 8080
          scheme: http
          strategy: RoundRobin
          weight: 10

注意:缺少 href 注解的 IngressRoute 会被 Homepage 直接忽略。这一行为在源码 traefik-list.js 中有明确实现——最终返回的列表仅保留带有 gethomepage.dev/href 注解的 IngressRoute。同时该文件还会在拉取前通过 checkCRD 检查 ingressroutes.traefik.containo.us 与 ingressroutes.traefik.io 两个 CRD 是否存在,并在权限不足(403)时给出清晰的 RBAC 报错提示(kubernetes.js)。

Gateway API HttpRoute 支持

Homepage 同样支持 Gateway API 的自动服务发现。在 kubernetes.yaml 中开启:

gateway: true # 启用 gateway-api

即可读取 HttpRoute 自定义资源上的注解,注解格式与上文 Ingress 示例完全一致(Automatic Service Discovery)。若使用的是非官方 Helm chart,请务必确认其 ClusterRole 已包含 gateway.networking.k8s.io 相关权限,RBAC 完整示例见 docs/installation/k8s.md。

Longhorn Widget:存储统计

针对 Longhorn 提供专用 Widget,在 widgets.yaml 中配置,展示集群存储统计:

- longhorn:
    # 是否展开显示
    expanded: true
    # 是否显示代表聚合值的节点
    total: true
    # 是否将节点名称显示为标签
    labels: true
    # 是否显示节点
    nodes: true
    # 显式指定要展示的节点列表;nodes 为 true 时默认展示全部节点
    include:
      - node1
      - node2

各选项说明:expanded 控制卡片展开形态;total 展示聚合汇总;labels 控制节点名称标签的显隐;nodes 控制节点列表;include 则可在 nodes: true 的基础上收窄到指定节点。需要注意的是,Longhorn 场景通常配合前文提到的 podSelector: "" 技巧使用——通过选中命名空间内全部 Pod 来聚合出整体存储用量。

注意事项

与 Docker 服务发现类似,自动发现的服务目前没有严格的排序规则,且会显示在 services.yaml 中手动配置的服务上方。若对顺序有要求,可通过 weight 注解参与排序,但无法完全控制与手动服务的相对顺序。

额外配置文件:通过 ConfigMap 挂载

部分 Homepage 功能(例如 Proxmox)需要额外的配置文件(如 proxmox.yaml)。在 Kubernetes 上运行时,这些文件必须通过 ConfigMap 提供并挂载到容器的 /app/config 目录。

ConfigMap 示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: homepage
data:
  proxmox.yaml: |
    pve:
      url: https://proxmox.host.or.ip:8006
      token: username@pam!Token ID
      secret: secret

随后在 Deployment 中通过 subPath 将文件挂载到 /app/config 下:

volumeMounts:
  - mountPath: /app/config/proxmox.yaml
    name: homepage-config
    subPath: proxmox.yaml

该模式与 安装文档 中 Deployment 示例对 kubernetes.yaml、services.yaml、widgets.yaml 等的挂载方式完全一致,新增任何配置文件都遵循同一套路。

本地开发与测试:基于 k3d 的集群环境

仓库在 k3d/README.md 中提供了完整的本地开发与测试方案:利用 k3d 在 Docker 内拉起 k3s 集群,再通过脚本或 Tilt 部署 Homepage,便于验证上述全部 Kubernetes 功能。

所需工具:docker、kubectl、helm、k3d(可选 k9s、tilt、direnv)。一次性测试部署:

./k3d-up.sh      # 创建集群
./k3d-deploy.sh  # 构建并部署
xdg-open http://homepage.k3d.localhost:8080/   # 打开 Homepage

持续开发模式则用 Tilt 建立本地 CI 循环,改动代码后自动更新部署:

./k3d-up.sh
tilt up          # 按空格打开 Tilt Web UI
xdg-open http://homepage.k3d.localhost:8080/

所有命令需在 k3d 目录下执行。该环境配合 src/utils/kubernetes 目录下的单元测试(ingress-list.test.js、traefik-list.test.js、httproute-list.test.js、resource-helpers.test.js 等),为验证服务发现、URL 推导与选择器解析逻辑提供了完整的开发闭环。

【免费下载链接】homepage A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations. 【免费下载链接】homepage 项目地址: https://gitcode.com/GitHub_Trending/ho/homepage

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

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值