部署 Umami 到 TKE
部署 Umami 到 TKE
Umami 是一个基于 Node.js 的轻量级开源埋点分析工具。
官方仓库:
官方网站:
Demo:
1. 部署 PostgreSQL
在 TKE (腾讯云容器服务) 上部署 postgres:16-alpine,推荐使用 StatefulSet(有状态副本集)。相比 Deployment,StatefulSet 能确保数据库 Pod 的网络标识和存储挂载是稳定的。
这里是豆包提供的两者的区别:
| 特性 | Deployment | StatefulSet |
|---|---|---|
| Pod 命名 | 随机后缀(如 nginx-7f987d689d-2x78z) | 固定命名(如 mysql-0、mysql-1、mysql-2) |
| Pod 身份 | 无唯一身份,替换后身份丢失 | 固定身份(PVC、主机名、DNS 不变) |
| 启动/销毁顺序 | 无序,可同时创建/删除多个 Pod | 有序(按 0→1→2 启动,2→1→0 销毁) |
| 网络标识 | 仅通过 Service 随机访问 | 固定 DNS 名称(如 mysql-0.xxx.default.svc.cluster.local) |
| 持久化存储 | 所有 Pod 共享 PVC(或无 PVC) | 每个 Pod 绑定专属 PVC(自动创建) |
| 更新策略 | 滚动更新/重建更新,无顺序限制 | 有序更新(从最后一个 Pod 开始) |
这里由于只有一个 Pod,貌似区别不大。
具体步骤如下:
购买腾讯云 CBS 云硬盘;
在 TKE 中配置创建 PV;
在对应的命名空间下创建 PVC;
上面几步可以在页面上直接操作。在对应的命名空间下创建密钥;
apiVersion: v1 kind: Secret metadata: name: postgres-secret namespace: umami-namespace type: Opaque stringData: postgres-password: "YourSecurePassword123" # 替换为您的强密码在对应的命名空间下创建 StatefulSet;
这里要注意的是,CBS 云硬盘由于会自动包含一个 lost+found 目录,所以在挂载到容器时,要注意排除这个目录。这里使用 busybox 来执行 initContainer 来移除这个目录,以保证数据库正常启动。
apiVersion: apps/v1 kind: StatefulSet metadata: name: postgres-umami namespace: umami-namespace spec: persistentVolumeClaimRetentionPolicy: whenDeleted: Retain whenScaled: Retain podManagementPolicy: OrderedReady replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: postgres-umami serviceName: postgres-umami template: metadata: labels: app: postgres-umami spec: containers: - args: - -c - shared_buffers=4GB - -c - work_mem=64MB - -c - max_connections=200 env: - name: POSTGRES_DB value: umami - name: POSTGRES_USER value: admin - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: key: postgres-password name: postgres-secret optional: false image: postgres:16-alpine imagePullPolicy: IfNotPresent name: postgres-umami ports: - containerPort: 5432 protocol: TCP resources: limits: cpu: "2" memory: 6Gi requests: cpu: "1" memory: 2Gi securityContext: privileged: false terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/lib/postgresql/data name: data dnsPolicy: ClusterFirst initContainers: - command: - rm - -fr - /var/lib/postgresql/data/lost+found image: busybox:1.37.0-uclibc imagePullPolicy: IfNotPresent name: remove-lost-found resources: requests: cpu: 10m memory: 10Mi securityContext: privileged: false terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/lib/postgresql/data name: data restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - name: data persistentVolumeClaim: claimName: pvc-postgres-data updateStrategy: rollingUpdate: partition: 0 type: RollingUpdate在对应的命名空间下创建 Service;
这里仍然使用 Service 来暴露数据库端口。貌似 StatefulSet 自带一个 DNS 地址,应该也可以直接使用
postgres-umami.umami-namespace.svc.cluster.local来连接数据库。apiVersion: v1 kind: Service metadata: name: svc-postgres-umami namespace: umami-namespace spec: internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - name: 5432-5432-tcp-4mdtvqnd87g port: 5432 protocol: TCP targetPort: 5432 selector: app: postgres-umami sessionAffinity: None type: ClusterIP
2. 部署 Umami 后端
fork 官方代码到自己的仓库
因为以后可能还要基于源代码进行定制,所以这里选择将官方代码 fork 到自己的仓库。
配置 CNB 打包
打包使用的是 CNB,使用的配置文件如下:
.jobs: &jobs - name: docker build script: - docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/${CNB_COMMIT} . - name: docker push script: - docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/${CNB_COMMIT} - name: update tke imports: https://cnb.cool/my-group/my-secret-repo/-/blob/main/tke.yml image: tencentcom/deploy-to-tke settings: secret_id: ${SECRET_ID} secret_key: ${SECRET_KEY} region: ${TKE_REGION} cluster_id: ${TKE_CLUSTER_ID} namespace: umami-namespace workload_kind: deployment workload_name: umami-deployment container_names: umami container_images: ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/${CNB_COMMIT} .pipeline: &pipeline docker: image: node:22-alpine services: - docker stages: *jobs '**': web_trigger_release: - <<: *pipeline release: push: - <<: *pipeline在 TKE 中创建 Umami Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: umami-deployment namespace: umami-namespace spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 3 selector: matchLabels: app: umami strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type: RollingUpdate template: metadata: creationTimestamp: null labels: app: umami spec: containers: - env: - name: DATABASE_URL valueFrom: secretKeyRef: key: database-url name: umami-secret optional: false - name: APP_SECRET valueFrom: secretKeyRef: key: app-secret name: umami-secret optional: false - name: DATABASE_TYPE value: postgresql - name: DISABLE_BOT_CHECK value: "1" - name: PRIVATE_MODE value: "1" - name: DISABLE_TELEMETRY value: "1" image: docker.cnb.cool/my-group/my-umami-repo/release:latest imagePullPolicy: IfNotPresent lifecycle: preStop: exec: command: - sleep 30s name: umami ports: - containerPort: 3000 protocol: TCP readinessProbe: failureThreshold: 6 initialDelaySeconds: 20 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 3000 timeoutSeconds: 5 resources: limits: cpu: "1" memory: 2Gi requests: cpu: 500m memory: 1Gi securityContext: privileged: false terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst imagePullSecrets: - name: cnb-jiajia-artifacts restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30配置 Umami Servcie
apiVersion: v1 kind: Service metadata: labels: app: umami name: umami-service namespace: umami-namespace spec: internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - name: 80-3000-tcp port: 80 protocol: TCP targetPort: 3000 - name: 3000-3000-tcp port: 3000 protocol: TCP targetPort: 3000 selector: app: umami sessionAffinity: None type: ClusterIP根据 TKE 安装的网关配置外网访问。
配置域名解析到 TKE 网关绑定的 CLB 地址。
— END —