1. 项目概述一个为Uptime Kuma量身定制的Helm Chart如果你在Kubernetes集群里跑过服务肯定对监控这件事儿有切身体会。服务挂了用户投诉了你才知道出问题了——这种被动响应模式太折磨人了。Uptime Kuma这个开源、自托管的监控工具凭借其清爽的界面和强大的功能比如HTTP(S)/TCP/Ping/DNS监控、多协议告警成了很多人的心头好。但把它部署到K8s里如果只用原始的Docker镜像和一堆YAML文件管理起来就有点头疼了配置更新、版本升级、数据持久化每一样都得手动折腾。这就是dirsigler/uptime-kuma-helm这个项目出现的背景。它不是一个新工具而是一个“打包方案”。简单说它把部署Uptime Kuma到Kubernetes这一整套复杂操作封装成了一个标准的Helm Chart。Helm是K8s的包管理器你可以把它想象成Linux里的apt或yaml。有了这个Chart你只需要一个命令就能拉起一个功能完整、配置可调的Uptime Kuma实例并且后续的升级、回滚、配置变更都变得极其规范和安全。这个Chart的核心价值在于“标准化”和“可运维性”。它帮你处理了所有K8s原生资源对象的编排Deployment定义如何运行Pod、Service提供内部和外部访问、PersistentVolumeClaim确保监控数据不丢失、Ingress如果需要从外部访问。你不再需要去写、去记那些繁琐的YAML而是通过一份高度可配置的values.yaml文件用声明式的方法描述你想要的Uptime Kuma是什么样子。适合谁来用呢首先是所有已经在使用或打算在Kubernetes环境中部署Uptime Kuma的运维工程师和开发者。其次如果你对Helm有基本了解想学习如何将一个有状态应用Uptime Kuma需要存数据通过Chart进行标准化部署这个项目也是一个非常清晰、实用的学习样本。它展示了如何处理环境变量、配置文件挂载、数据持久化、服务暴露等经典场景。2. 核心设计思路与架构解析2.1 为什么选择Helm Chart化直接kubectl apply -f deployment.yaml也能跑起来为什么非要大费周章做成Helm Chart这背后是工程思维和运维效率的考量。第一参数化配置一键多环境部署。Uptime Kuma本身有很多配置项比如服务端口、数据库连接它默认用SQLite但也支持MySQL/PostgreSQL、时区、基础URL等。在传统YAML里这些值要么写死要么需要你用env配合ConfigMap手动注入非常零散。Helm Chart通过values.yaml提供了一个统一的、中心化的配置接口。你可以为开发、测试、生产环境维护不同的values文件部署时只需指定--values prod.yaml就能实现环境的快速复制和隔离。这对于遵循GitOps流程的团队来说至关重要。第二依赖管理和资源编排。一个完整的Uptime Kuma部署不仅仅是一个Pod。它可能需要一个PersistentVolume来存储SQLite数据库文件需要一个Service来暴露服务可能还需要一个Ingress来提供外部域名访问。Helm Chart将这些资源定义模板化并明确了它们之间的依赖关系和生成顺序。Chart的templates/目录下每个K8s资源文件如deployment.yaml,service.yaml,pvc.yaml都是一个Go模板它们会读取values.yaml中的配置渲染出最终的YAML。这保证了所有资源作为一个“应用”的整体性和一致性。第三版本化和可回滚。Helm为每个部署创建了一个Release并记录其版本和使用的配置。当你升级Chart版本比如Uptime Kuma发布了新功能或修改配置时Helm可以轻松地执行升级操作。如果新版本出现问题一条helm rollback命令就能瞬间回到上一个稳定状态。这种能力是直接使用kubectl难以优雅实现的。第四社区和复用价值。将部署方案Chart化并开源意味着你不再是从零开始。你可以直接基于dirsigler/uptime-kuma-helm进行定制省去了研究Uptime Kuma最佳K8s实践的大量时间。同时你可以从社区的Issue和PR中获取优化思路比如如何配置健康检查、如何优化资源请求限制等。2.2 Chart的目录结构与核心模板解读一个标准的Helm Chart有其固定的目录结构。理解这个结构你就能看懂这个Chart是如何工作的甚至能自己动手修改它。uptime-kuma-helm/ ├── Chart.yaml # Chart的元数据名称、版本、描述、依赖等 ├── values.yaml # 默认的配置值用户主要修改的文件 ├── templates/ # K8s资源模板目录 │ ├── deployment.yaml # 核心定义Uptime Kuma的Pod如何运行 │ ├── service.yaml # 定义如何访问这个Pod │ ├── pvc.yaml # 定义持久化存储声明如果启用 │ ├── ingress.yaml # 定义外部访问规则如果启用 │ ├── configmap.yaml # 可能用于存储额外的配置文件 │ └── _helpers.tpl # 模板辅助函数定义可复用的命名逻辑等 └── README.md # 使用说明文档我们来深入看几个关键模板的设计思路1.deployment.yaml应用的核心载体这个文件定义了Uptime Kuma的工作负载。它通常会做以下几件事镜像定义从values.yaml中读取image.repository和image.tag确保你可以轻松切换镜像版本或使用私有仓库。环境变量注入这是配置Uptime Kuma的关键。Chart会将values.yaml中env部分定义的变量如UPTIME_KUMA_PORT注入到容器中。更高级的配置比如数据库连接字符串也会在这里通过Secret或ConfigMap引用方式安全地注入。持久化存储挂载如果persistence.enabled为true模板会创建一个volumeMount将PVC挂载到容器内的特定路径如/app/data这样Uptime Kuma的SQLite数据库和配置文件就能永久保存。探针配置一个生产级部署必须配置就绪探针和存活探针。Chart模板会定义HTTP GET探针定期检查Uptime Kuma的Web端口是否健康确保流量只会被导向准备好的Pod并在Pod无响应时自动重启。资源限制通过resources字段为容器设置CPU和内存的请求与上限防止单个应用耗尽节点资源这是K8s集群稳定的基础。2.service.yaml与ingress.yaml网络暴露service.yaml创建一个ClusterIP类型的Service为Deployment中的Pod提供一个稳定的内部访问端点DNS名称。这是集群内其他服务访问Uptime Kuma的方式。ingress.yaml是可选的。只有当ingress.enabled为true时才会渲染。它定义一个Ingress规则将来自外部的HTTP/HTTPS流量路由到内部的Service。这里会处理主机名、路径、TLS证书如果配置了等。这是让你能通过https://status.yourdomain.com访问监控面板的关键。3.pvc.yaml数据持久化这是保障监控历史数据不丢失的生命线。模板会根据persistence中的配置如存储类storageClass、大小size、访问模式accessModes创建一个PersistentVolumeClaim。K8s集群会根据存储类的配置动态或静态地提供一个PersistentVolume并将它绑定到这个PVC上。注意在云厂商的K8s服务如EKS, AKS, GKE上通常有默认的存储类可以动态创建云硬盘。在自建集群中你需要确保有可用的存储类或者将persistence.storageClass设置为来使用集群中已存在的、满足需求的PersistentVolume。2.3 配置哲学约定大于配置与灵活覆盖dirsigler/uptime-kuma-helm这个Chart很好地体现了Helm的配置哲学提供合理的默认值同时开放所有关键参数供用户覆盖。打开values.yaml你会看到像下面这样的结构replicaCount: 1 image: repository: louislam/uptime-kuma tag: 1.23.0 pullPolicy: IfNotPresent service: type: ClusterIP port: 3001 ingress: enabled: false className: hosts: - host: chart-example.local paths: - path: / pathType: ImplementationSpecific persistence: enabled: true storageClass: accessModes: - ReadWriteOnce size: 1Gi resources: {} # requests: # cpu: 100m # memory: 128Mi # limits: # cpu: 200m # memory: 256Mi env: {} # 例如 # - name: UPTIME_KUMA_PORT # value: 3001解读replicaCount: 1默认单副本运行对于Uptime Kuma这种有状态应用通常足够了。如果你需要高可用可以设置为更多但需要解决数据一致性问题通常需要配合同一个外部数据库如PostgreSQL。image.tag: 1.23.0锁定了具体的应用版本避免因使用latest标签导致不可预期的升级。persistence.enabled: true默认启用持久化这是非常明智的避免了用户因忘记开启而导致数据丢失。resources: {}默认不设限制但在生产环境中强烈建议你根据实际监控目标和负载情况配置合理的requests和limits。例如可以初始设置为requests: {cpu: 50m, memory: 128Mi}limits: {cpu: 200m, memory: 256Mi}然后根据监控观察进行调整。如何定制你不需要修改Chart内部的模板。只需要创建一个自己的custom-values.yaml文件覆盖你需要改动的部分。例如你想使用自己的镜像、启用Ingress并配置资源限制# custom-values.yaml image: repository: my-private-registry/louislam/uptime-kuma tag: 1.23.1 ingress: enabled: true className: nginx hosts: - host: status.mycompany.com paths: - path: / pathType: Prefix tls: - secretName: status-tls-secret hosts: - status.mycompany.com resources: requests: memory: 128Mi cpu: 50m limits: memory: 256Mi cpu: 200m env: - name: TZ value: Asia/Shanghai部署时使用helm upgrade --install uptime-kuma dirsigler/uptime-kuma-helm -f custom-values.yaml即可。这种“默认值覆盖”的模式既保证了开箱即用又提供了极大的灵活性。3. 完整部署流程与关键配置实战假设你已经在本地安装好了kubectl和helm客户端并且能够访问一个Kubernetes集群可以是Minikube、Kind本地集群也可以是云上的托管集群。下面我们一步步完成部署和深度配置。3.1 前期准备与Chart添加首先你需要将这个Chart的仓库添加到本地的Helm仓库列表中。dirsigler通常会将他的Chart发布到某个Helm仓库比如他自己的GitHub Pages或像https://charts.dirsigler.online这样的地址。具体地址需要查看该项目的README。这里我们以假设仓库已添加为例。# 假设Chart仓库URL为 https://charts.dirsigler.online helm repo add dirsigler https://charts.dirsigler.online helm repo update # 更新本地仓库缓存获取最新的Chart信息接下来你可以搜索并查看这个Chart的详细信息helm search repo uptime-kuma helm show chart dirsigler/uptime-kuma-helm # 查看Chart.yaml helm show values dirsigler/uptime-kuma-helm # 查看默认的values.yaml这是定制的基础3.2 定制化values.yaml与部署直接使用默认值部署是最快的但为了适应生产环境我们创建一个定制化的配置文件。我们将部署一个具有以下特性的实例使用特定的命名空间。启用Ingress通过域名访问。配置资源限制。设置正确的时区。使用一个已有的StorageClass来提供持久化存储。创建文件prod-values.yaml# prod-values.yaml # 1. 全局覆盖命名空间也可以在install命令中用 -n 指定 # global: # namespace: monitoring # 2. 镜像设置可选如果从默认仓库拉取慢可以替换为镜像加速地址 image: # repository: louislam/uptime-kuma pullPolicy: IfNotPresent # tag保持不变 # 3. 服务设置 service: type: ClusterIP port: 3001 # 4. Ingress配置核心 ingress: enabled: true className: nginx # 假设集群使用的是nginx-ingress annotations: # 根据你的Ingress Controller添加注解例如证书管理器自动签发TLS cert-manager.io/cluster-issuer: letsencrypt-prod nginx.ingress.kubernetes.io/proxy-body-size: 10m hosts: - host: status.your-awesome-domain.com # 替换为你的真实域名 paths: - path: / pathType: Prefix tls: - secretName: uptime-kuma-tls-secret # TLS证书的Secret名称cert-manager会自动创建 hosts: - status.your-awesome-domain.com # 5. 持久化存储配置核心 persistence: enabled: true # storageClass: standard # 云厂商通常有默认的如gp2, standard等。自建集群需指定。 # 如果你的集群有多个StorageClass需要明确指定一个。 accessModes: - ReadWriteOnce size: 5Gi # 根据监控项数量调整初期5GB通常足够 # 6. 资源配额非常重要防止OOM resources: requests: memory: 128Mi cpu: 50m limits: memory: 256Mi cpu: 200m # 7. 环境变量注入 env: - name: TZ value: Asia/Shanghai # Uptime Kuma可以通过环境变量设置端口但Chart的service.port已经映射通常不需要额外设置。 # - name: UPTIME_KUMA_PORT # value: 3001 # 8. 探针配置使用默认即可Chart模板通常已配置好 # livenessProbe和readinessProbe的路径通常是 /api/status-page/heartbeat 或 / # 可以在deployment模板中确认。 # 9. 如果需要可以配置Pod反亲和性避免单点故障单副本时意义不大 # affinity: {}现在执行部署命令。我们将其安装在名为monitoring的命名空间中。# 先创建命名空间如果不存在 kubectl create namespace monitoring # 使用Helm进行部署或升级安装 # --install 表示如果不存在则安装 # --namespace 指定命名空间 # -f 指定自定义的values文件 helm upgrade --install uptime-kuma dirsigler/uptime-kuma-helm \ --namespace monitoring \ --values ./prod-values.yaml \ --wait # 等待所有资源就绪执行成功后Helm会输出一个Release的状态摘要。你可以用以下命令检查部署状态# 查看Release状态 helm list -n monitoring # 查看Pod是否运行 kubectl get pods -n monitoring -l app.kubernetes.io/instanceuptime-kuma # 查看Service和Ingress kubectl get svc,ingress -n monitoring -l app.kubernetes.io/instanceuptime-kuma # 查看PVC是否绑定成功 kubectl get pvc -n monitoring -l app.kubernetes.io/instanceuptime-kuma3.3 初始访问与基础配置当Pod状态变为Running且就绪探针通过后你就可以访问Uptime Kuma了。通过Ingress访问如果你配置了Ingress并且域名解析已经指向了你的Ingress Controller IP那么直接访问https://status.your-awesome-domain.com即可。端口转发临时访问如果Ingress还没配置好可以使用kubectl port-forward临时将服务映射到本地。kubectl port-forward svc/uptime-kuma 3001:3001 -n monitoring然后在浏览器访问http://localhost:3001。首次访问你会看到Uptime Kuma的初始化界面需要创建一个管理员账户。这个账户信息会保存在我们之前配置的持久化存储中所以即使Pod重启也不会丢失。重要提示初始化完成后强烈建议你立即进入设置配置反向代理选项。如果你是通过Ingress如Nginx访问的需要在Uptime Kuma的设置中启用“信任反向代理头”Trust Reverse Proxy Headers并设置“Behind Proxy”为true以确保Uptime Kuma能正确获取客户端的真实IP否则所有访问日志的IP都将是Ingress Controller的Pod IP。3.4 进阶配置使用外部数据库默认情况下Chart使用SQLite数据存储在PVC挂载的卷上。这对于单副本部署是没问题的。但如果你计划未来扩展到多副本实现高可用或者对数据可靠性有更高要求就需要使用外部数据库MySQL或PostgreSQL。以PostgreSQL为例配置步骤如下在K8s中部署PostgreSQL。你可以使用Bitnami的PostgreSQL Helm Chart或者直接创建一个PostgreSQL的StatefulSet。假设你已经有一个运行在monitoring命名空间下、服务名为postgresql的数据库并创建了名为uptimekuma的数据库和用户。创建包含数据库密码的Secret。永远不要在values.yaml中明文写密码。kubectl create secret generic uptime-kuma-db-secret \ --namespace monitoring \ --from-literalpostgresql-passwordYourStrongPassword123! \ --dry-runclient -o yaml | kubectl apply -f -修改prod-values.yaml添加环境变量来配置外部数据库# 在 env 部分添加 env: - name: TZ value: Asia/Shanghai - name: UPTIME_KUMA_DB_TYPE value: postgres - name: UPTIME_KUMA_DB_HOST value: postgresql # 数据库服务的K8s DNS名称 - name: UPTIME_KUMA_DB_PORT value: 5432 - name: UPTIME_KUMA_DB_NAME value: uptimekuma - name: UPTIME_KUMA_DB_USERNAME value: postgres # 或你创建的用户名 - name: UPTIME_KUMA_DB_PASSWORD valueFrom: secretKeyRef: name: uptime-kuma-db-secret key: postgresql-password同时可以考虑将persistence.enabled设置为false因为数据不再存储在本地卷而是存在PostgreSQL中。但你可能仍然希望保留一个小容量PVC来存储日志或其他配置文件。更新Helm Releasehelm upgrade uptime-kuma dirsigler/uptime-kuma-helm \ --namespace monitoring \ --values ./prod-values.yaml升级后Uptime Kuma Pod会重启并尝试连接到新的PostgreSQL数据库。注意首次切换时需要手动在PostgreSQL中创建好对应的数据库uptimekumaUptime Kuma启动时会自动创建表结构。4. 运维、监控与故障排查实录部署完成只是开始让服务稳定运行才是关键。下面分享一些我在实际运维中积累的经验和踩过的坑。4.1 日常运维操作1. 升级Uptime Kuma版本当Uptime Kuma发布新版本时升级非常简单。首先查看Chart仓库是否有对应的Chart更新可能Chart版本也更新了。helm repo update helm search repo dirsigler/uptime-kuma-helm --versions假设新镜像标签是1.23.1你只需要修改prod-values.yaml中的image.tag然后执行升级# prod-values.yaml image: tag: 1.23.1helm upgrade uptime-kuma dirsigler/uptime-kuma-helm \ --namespace monitoring \ --values ./prod-values.yaml \ --waitHelm会执行滚动更新创建一个新的Pod等它健康后再终止旧的Pod实现无中断升级。2. 回滚如果新版本有问题一键回滚到上一个版本helm history uptime-kuma -n monitoring # 查看发布历史 helm rollback uptime-kuma REVISION_NUMBER -n monitoring # 回滚到指定版本3. 查看和编辑配置你可以查看当前Release使用的配置helm get values uptime-kuma -n monitoring如果需要临时修改一个配置比如调整资源限制可以编辑values文件后升级或者使用--set参数不推荐用于复杂配置不利于版本管理helm upgrade uptime-kuma dirsigler/uptime-kuma-helm \ --namespace monitoring \ --values ./prod-values.yaml \ --set resources.limits.memory512Mi4.2 监控Uptime Kuma自身一个监控工具本身也需要被监控。除了Uptime Kuma自带的status page你还需要在K8s层面监控它。Pod健康状态通过kubectl get pods -n monitoring观察Pod的STATUS和READY字段。CrashLoopBackOff意味着容器反复启动失败。资源使用情况使用kubectl top pod -n monitoring查看Pod的CPU和内存实际使用量与你设置的limits和requests对比以便优化资源配置。日志排查这是最重要的排错手段。# 查看最近日志 kubectl logs -l app.kubernetes.io/instanceuptime-kuma -n monitoring --tail50 # 持续查看日志类似 tail -f kubectl logs -l app.kubernetes.io/instanceuptime-kuma -n monitoring -f # 如果Pod有多个容器默认只有一个需要指定容器名但Uptime Kuma通常只有一个。事件查看K8s事件记录了资源调度、拉取镜像、启动容器等关键信息。kubectl get events -n monitoring --field-selector involvedObject.nameuptime-kuma-xxxxxxPod名4.3 常见问题与排查技巧下面是一个基于真实运维场景的常见问题速查表问题现象可能原因排查步骤与解决方案Pod 处于Pending状态1. 节点资源不足CPU/内存。2. 没有满足PVC要求的PersistentVolumePV。3. 节点选择器/污点容忍不匹配。1.kubectl describe pod pod-name查看事件通常会有明确提示如Insufficient cpu。2.kubectl get pvc查看PVC状态是否为Bound。如果是Pending检查StorageClass配置或手动创建PV。3. 检查Pod的nodeSelector和tolerations配置。Pod 处于CrashLoopBackOff状态1. 应用启动失败配置错误、数据库连接失败等。2. 镜像拉取失败私有镜像无权限、标签错误。3. 启动探针失败。1.首要操作查看日志kubectl logs pod-name --previous查看上一次崩溃的日志通常能直接定位错误如数据库连接字符串错误、端口被占用等。2.kubectl describe pod查看Events看是否有Failed to pull image错误。3. 检查livenessProbe的路径和端口是否正确。Uptime Kuma健康端点通常是/或/api/status-page/heartbeat。Pod 运行中但无法通过Ingress访问1. Ingress配置错误主机名、路径、类名。2. Ingress Controller未正常运行。3. Service端口映射错误。4. 网络策略NetworkPolicy阻止了流量。1.kubectl get ingress查看ADDRESS字段是否为空。为空说明Ingress Controller没分配IP。2.kubectl describe ingress ingress-name查看事件。3. 检查Ingress中service.port.number是否与Chart中service.port一致。4. 尝试用port-forward直接访问Service如果通问题在Ingress或网络层。监控数据丢失重启后1. 持久化存储未启用persistence.enabledfalse。2. PVC配置错误使用了emptyDir等临时卷。3. Pod被调度到不同节点而PV是ReadWriteOnce且未支持多节点挂载。1. 确认values.yaml中persistence.enabled为true。2.kubectl get pvc确认状态为Bound并查看其STORAGECLASS。3. 对于单副本ReadWriteOnce是合适的。如果Pod漂移确保目标节点能访问该PV云盘通常可以。可以考虑使用ReadWriteMany的存储方案如NFS、CephFS但更推荐使用外部数据库。CPU/内存使用率异常高1. 监控目标过多或频率过高。2. 内存泄漏相对少见。3. 资源配置limits过小导致进程频繁被OOM Kill或Throttling。1. 进入Uptime Kuma后台检查监控项数量和频率。适当调整。2. 观察日志是否有重复错误错误循环可能导致负载升高。3. 使用kubectl top pod和kubectl describe pod查看实际使用量和是否达到限制。适当调高resources.limits并设置合理的requests保证调度质量。告警不生效1. 告警渠道如Telegram、Slack、Webhook配置错误。2. 网络策略阻止Pod访问外部网络。3. 通知频率被限制或静音。1. 在Uptime Kuma界面测试告警渠道。2. 检查Pod所在命名空间是否有出口Egress网络策略限制。可以临时在Pod内kubectl exec执行curl命令测试连通性。3. 检查Uptime Kuma的告警设置确认未启用“静音”或“延迟通知”。一个真实的踩坑记录有一次升级后Pod一直CrashLoopBackOff。查看日志发现是数据库迁移失败。原因是新版本的Uptime Kuma对SQLite数据库有结构变更但我的PVC使用的是本地hostPath卷权限在节点更新后发生了变化导致容器内进程没有写权限。解决方案不是直接去节点改权限那样不持久而是通过kubectl exec进入之前的Pod如果还能运行将数据备份出来然后修改PVC的storageClass使用动态云盘重新部署后恢复数据。这个教训是对于生产环境使用云提供商动态供给的持久卷比hostPath更可靠、更易管理。4.4 备份与灾难恢复即使有了持久化卷定期备份也是必须的。方案取决于你的存储后端SQLite默认备份就是备份PVC里的数据库文件。你可以运行一个定时任务CronJob用kubectl cp命令将文件拷贝出来或者如果PVC支持卷快照Volume Snapshot定期创建快照。外部数据库如PostgreSQL使用数据库自身的备份工具如pg_dump。在K8s里可以创建一个Sidecar容器或者独立的CronJob来定期执行pg_dump并将备份文件上传到对象存储如S3、MinIO。一个简单的CronJob示例每周备份SQLite数据# backup-cronjob.yaml apiVersion: batch/v1 kind: CronJob metadata: name: uptime-kuma-backup namespace: monitoring spec: schedule: 0 2 * * 0 # 每周日凌晨2点 jobTemplate: spec: template: spec: containers: - name: backup image: alpine command: - /bin/sh - -c - | # 安装sqlite3客户端和aws cli如果传到S3 apk add --no-cache sqlite aws-cli # 从PVC挂载点拷贝数据库文件 cp /data/uptime-kuma.db /backup/uptime-kuma-$(date %Y%m%d).db # 可选上传到S3 # aws s3 cp /backup/uptime-kuma-$(date %Y%m%d).db s3://my-backup-bucket/ volumeMounts: - name:>