From 7f160a8d2a58de6faedeaedb581a6621db85aeb7 Mon Sep 17 00:00:00 2001 From: RC-CHN <1051989940@qq.com> Date: Wed, 24 Dec 2025 11:49:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0kubernetes=E9=83=A8?= =?UTF-8?q?=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.sum | 4 +- test/k8s/README.md | 188 ++++++++++++++++++++++++++++++++++ test/k8s/balancer.yaml | 154 ++++++++++++++++++++++++++++ test/k8s/configmap.yaml | 32 ++++++ test/k8s/ez-api.yaml | 197 ++++++++++++++++++++++++++++++++++++ test/k8s/kustomization.yaml | 27 +++++ test/k8s/log-postgres.yaml | 112 ++++++++++++++++++++ test/k8s/namespace.yaml | 8 ++ test/k8s/postgres.yaml | 112 ++++++++++++++++++++ test/k8s/redis.yaml | 100 ++++++++++++++++++ test/k8s/secret.yaml | 26 +++++ 11 files changed, 958 insertions(+), 2 deletions(-) create mode 100644 test/k8s/README.md create mode 100644 test/k8s/balancer.yaml create mode 100644 test/k8s/configmap.yaml create mode 100644 test/k8s/ez-api.yaml create mode 100644 test/k8s/kustomization.yaml create mode 100644 test/k8s/log-postgres.yaml create mode 100644 test/k8s/namespace.yaml create mode 100644 test/k8s/postgres.yaml create mode 100644 test/k8s/redis.yaml create mode 100644 test/k8s/secret.yaml diff --git a/go.sum b/go.sum index aa66eb7..b5e379d 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/ez-api/foundation v0.3.0 h1:qQyc02/UE8Jgv07cHDuLineQdAfWmROnjrpJIRBLt90= -github.com/ez-api/foundation v0.3.0/go.mod h1:bTh1LA42TW4CXi1SebDEUE+fhEssFUphzcGEzyAFFZI= +github.com/ez-api/foundation v0.4.0 h1:f0ACX+A9AX3Df1l3TX4KrDyeTKGCCpA5Rh0fD3nl28U= +github.com/ez-api/foundation v0.4.0/go.mod h1:bTh1LA42TW4CXi1SebDEUE+fhEssFUphzcGEzyAFFZI= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= diff --git a/test/k8s/README.md b/test/k8s/README.md new file mode 100644 index 0000000..27f0cbb --- /dev/null +++ b/test/k8s/README.md @@ -0,0 +1,188 @@ +# EZ-API Kubernetes Deployment + +## 目录结构 + +``` +k8s/ +├── namespace.yaml # 命名空间定义 +├── configmap.yaml # 配置映射 +├── secret.yaml # 敏感信息(密码、Token等) +├── postgres.yaml # 主数据库 StatefulSet + Headless Service +├── log-postgres.yaml # 日志数据库 StatefulSet + Headless Service +├── redis.yaml # Redis StatefulSet + Headless Service +├── ez-api.yaml # ez-api Deployment + LoadBalancer Service +├── balancer.yaml # balancer Deployment + LoadBalancer Service +├── kustomization.yaml # Kustomize 配置文件 +└── README.md # 本文档 +``` + +## 架构说明 + +### 有状态服务(StatefulSet) + +**PostgreSQL 和 Redis 使用 StatefulSet 的原因:** + +1. **稳定的网络标识**:Pod 名称固定(如 `postgres-0`),DNS 可预测 +2. **有序部署和扩展**:Pod 按顺序创建和删除 +3. **稳定的持久化存储**:每个 Pod 有自己的 PVC,Pod 重建后数据保留 +4. **更新策略控制**:支持分区更新(Partition),可实现金丝雀发布 + +**更新策略配置:** + +```yaml +updateStrategy: + type: RollingUpdate + rollingUpdate: + partition: 0 # 0 表示全部更新,设置为 N 表示只更新 ordinal >= N 的 Pod +``` + +- `partition: 0` - 所有 Pod 都会更新(默认行为) +- `partition: 1` - 只有 ordinal >= 1 的 Pod 会更新,ordinal=0 保持不变(金丝雀发布) + +### 无状态服务(Deployment) + +**ez-api 和 balancer 使用 Deployment 的原因:** + +1. 无需持久化存储(状态存储在数据库/Redis) +2. 可以快速水平扩展 +3. 支持滚动更新和回滚 + +## 部署方式 + +### 使用 Kustomize 部署 + +```bash +# 预览生成的 YAML +kubectl kustomize ez-api/test/k8s/ + +# 部署到集群 +kubectl apply -k ez-api/test/k8s/ + +# 查看部署状态 +kubectl get all -n ez-api-test-dev +``` + +### 使用 kubectl 直接部署 + +```bash +# 按顺序部署 +kubectl apply -f ez-api/test/k8s/namespace.yaml +kubectl apply -f ez-api/test/k8s/configmap.yaml +kubectl apply -f ez-api/test/k8s/secret.yaml +kubectl apply -f ez-api/test/k8s/postgres.yaml +kubectl apply -f ez-api/test/k8s/log-postgres.yaml +kubectl apply -f ez-api/test/k8s/redis.yaml +kubectl apply -f ez-api/test/k8s/ez-api.yaml +kubectl apply -f ez-api/test/k8s/balancer.yaml +``` + +## 存储配置 + +### PVC 持久化卷 + +| 服务 | 存储大小 | 用途 | +|------|---------|------| +| postgres | 50Gi | 主数据库数据 | +| log-postgres | 100Gi | 日志数据库(数据量较大) | +| redis | 10Gi | Redis AOF 持久化 | + +### 修改 StorageClass + +如果集群使用特定的 StorageClass,需要取消注释并修改: + +```yaml +volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: "your-storage-class" # 取消注释并修改 + resources: + requests: + storage: 50Gi +``` + +## 服务访问 + +### LoadBalancer 服务 + +| 服务 | 端口 | 类型 | +|------|------|------| +| ez-api | 8080 | LoadBalancer | +| balancer | 8081 | LoadBalancer | + +### 获取外部 IP + +```bash +# 查看 Service 状态 +kubectl get svc -n ez-api-test-dev + +# 等待 LoadBalancer 分配 IP +kubectl get svc ez-api -n ez-api-test-dev -w +kubectl get svc balancer -n ez-api-test-dev -w +``` + +## 配置修改 + +### 修改密码和 Token + +编辑 [`secret.yaml`](ez-api/test/k8s/secret.yaml) 文件: + +```yaml +stringData: + POSTGRES_PASSWORD: "your-secure-password" + EZ_ADMIN_TOKEN: "your-secure-token" +``` + +### 修改应用配置 + +编辑 [`configmap.yaml`](ez-api/test/k8s/configmap.yaml) 文件: + +```yaml +data: + EZ_LOG_RETENTION_DAYS: "60" + EZ_BALANCER_STATS_FLUSH_ENABLED: "true" +``` + +## 扩容 + +### 水平扩展 ez-api / balancer + +```bash +kubectl scale deployment ez-api --replicas=3 -n ez-api-test-dev +kubectl scale deployment balancer --replicas=3 -n ez-api-test-dev +``` + +### 注意事项 + +- PostgreSQL 和 Redis 的 StatefulSet 副本数保持为 1(单实例模式) +- 如需高可用数据库,建议使用托管数据库服务或配置主从复制 + +## 监控和日志 + +```bash +# 查看 Pod 日志 +kubectl logs -f deployment/ez-api -n ez-api-test-dev +kubectl logs -f deployment/balancer -n ez-api-test-dev + +# 查看 StatefulSet 日志 +kubectl logs -f statefulset/postgres -n ez-api-test-dev +kubectl logs -f statefulset/redis -n ez-api-test-dev + +# 进入 Pod 调试 +kubectl exec -it postgres-0 -n ez-api-test-dev -- psql -U postgres -d ezapi +kubectl exec -it redis-0 -n ez-api-test-dev -- redis-cli +``` + +## 清理 + +```bash +# 删除所有资源(保留 PVC) +kubectl delete -k ez-api/test/k8s/ + +# 删除 PVC(会删除数据!) +kubectl delete pvc -l app.kubernetes.io/name=ez-api-test-dev -n ez-api-test-dev + +# 删除命名空间(会删除所有资源和数据!) +kubectl delete namespace ez-api-test-dev +``` diff --git a/test/k8s/balancer.yaml b/test/k8s/balancer.yaml new file mode 100644 index 0000000..20882f0 --- /dev/null +++ b/test/k8s/balancer.yaml @@ -0,0 +1,154 @@ +# Balancer Deployment (Data Plane / Gateway) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: balancer + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: balancer +spec: + replicas: 1 + selector: + matchLabels: + app: balancer + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: balancer + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: balancer + spec: + # 等待 Redis 就绪 + initContainers: + - name: wait-for-redis + image: busybox:1.36 + command: + - sh + - -c + - | + until nc -z redis 6379; do + echo "Waiting for redis..." + sleep 2 + done + echo "Redis is ready!" + containers: + - name: balancer + image: harbor.rcfortress.site/library/balancer:latest + imagePullPolicy: Always + ports: + - containerPort: 8081 + name: http + env: + - name: EZ_BALANCER_PORT + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_PORT + # Redis + - name: EZ_REDIS_ADDR + value: "redis:6379" + - name: EZ_REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: REDIS_PASSWORD + - name: EZ_REDIS_DB + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_REDIS_DB + # Log Sink + - name: EZ_BALANCER_LOG_SINK_ENABLED + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_LOG_SINK_ENABLED + - name: EZ_BALANCER_LOG_SINK_BASE_URL + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_LOG_SINK_BASE_URL + - name: EZ_BALANCER_LOG_SINK_TIMEOUT_SECONDS + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_LOG_SINK_TIMEOUT_SECONDS + # Stats Flush + - name: EZ_BALANCER_STATS_FLUSH_ENABLED + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_STATS_FLUSH_ENABLED + - name: EZ_BALANCER_STATS_FLUSH_BASE_URL + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_STATS_FLUSH_BASE_URL + - name: EZ_BALANCER_STATS_FLUSH_TOKEN + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: EZ_BALANCER_STATS_FLUSH_TOKEN + - name: EZ_BALANCER_STATS_FLUSH_INTERVAL_SECONDS + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_STATS_FLUSH_INTERVAL_SECONDS + - name: EZ_BALANCER_STATS_FLUSH_BATCH_SIZE + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_STATS_FLUSH_BATCH_SIZE + - name: EZ_BALANCER_STATS_FLUSH_TIMEOUT_SECONDS + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_BALANCER_STATS_FLUSH_TIMEOUT_SECONDS + resources: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 3 +--- +# Balancer Service (LoadBalancer) +apiVersion: v1 +kind: Service +metadata: + name: balancer + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: balancer +spec: + type: LoadBalancer + ports: + - port: 8081 + targetPort: 8081 + protocol: TCP + name: http + selector: + app: balancer diff --git a/test/k8s/configmap.yaml b/test/k8s/configmap.yaml new file mode 100644 index 0000000..15bb08b --- /dev/null +++ b/test/k8s/configmap.yaml @@ -0,0 +1,32 @@ +# ConfigMap for ez-api stack configuration +apiVersion: v1 +kind: ConfigMap +metadata: + name: ez-api-config + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: config +data: + # PostgreSQL configuration + POSTGRES_DB: "ezapi" + LOG_POSTGRES_DB: "ezapi_logs" + + # ez-api configuration + EZ_API_PORT: "8080" + EZ_CORS_ALLOW_ORIGINS: "*" + EZ_LOG_RETENTION_DAYS: "30" + EZ_LOG_MAX_RECORDS: "1000000" + EZ_LOG_PARTITIONING: "off" + + # Balancer configuration + EZ_BALANCER_PORT: "8081" + EZ_REDIS_DB: "0" + EZ_BALANCER_LOG_SINK_ENABLED: "false" + EZ_BALANCER_LOG_SINK_BASE_URL: "http://ez-api:8080" + EZ_BALANCER_LOG_SINK_TIMEOUT_SECONDS: "3" + EZ_BALANCER_STATS_FLUSH_ENABLED: "false" + EZ_BALANCER_STATS_FLUSH_BASE_URL: "http://ez-api:8080" + EZ_BALANCER_STATS_FLUSH_INTERVAL_SECONDS: "300" + EZ_BALANCER_STATS_FLUSH_BATCH_SIZE: "200" + EZ_BALANCER_STATS_FLUSH_TIMEOUT_SECONDS: "5" diff --git a/test/k8s/ez-api.yaml b/test/k8s/ez-api.yaml new file mode 100644 index 0000000..22624b9 --- /dev/null +++ b/test/k8s/ez-api.yaml @@ -0,0 +1,197 @@ +# ez-api Deployment (Control Plane) +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ez-api + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: ez-api +spec: + replicas: 1 + selector: + matchLabels: + app: ez-api + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: ez-api + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: ez-api + spec: + # 等待依赖服务就绪 + initContainers: + - name: wait-for-postgres + image: busybox:1.36 + command: + - sh + - -c + - | + until nc -z postgres 5432; do + echo "Waiting for postgres..." + sleep 2 + done + echo "PostgreSQL is ready!" + - name: wait-for-log-postgres + image: busybox:1.36 + command: + - sh + - -c + - | + until nc -z log-postgres 5432; do + echo "Waiting for log-postgres..." + sleep 2 + done + echo "Log PostgreSQL is ready!" + - name: wait-for-redis + image: busybox:1.36 + command: + - sh + - -c + - | + until nc -z redis 6379; do + echo "Waiting for redis..." + sleep 2 + done + echo "Redis is ready!" + containers: + - name: ez-api + image: harbor.rcfortress.site/library/ez-api:latest + imagePullPolicy: Always + ports: + - containerPort: 8080 + name: http + env: + - name: EZ_API_PORT + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_API_PORT + # PostgreSQL DSN + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + valueFrom: + configMapKeyRef: + name: ez-api-config + key: POSTGRES_DB + - name: EZ_PG_DSN + value: "host=postgres user=$(POSTGRES_USER) password=$(POSTGRES_PASSWORD) dbname=$(POSTGRES_DB) port=5432 sslmode=disable" + # Log PostgreSQL DSN + - name: LOG_POSTGRES_USER + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: LOG_POSTGRES_USER + - name: LOG_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: LOG_POSTGRES_PASSWORD + - name: LOG_POSTGRES_DB + valueFrom: + configMapKeyRef: + name: ez-api-config + key: LOG_POSTGRES_DB + - name: EZ_LOG_PG_DSN + value: "host=log-postgres user=$(LOG_POSTGRES_USER) password=$(LOG_POSTGRES_PASSWORD) dbname=$(LOG_POSTGRES_DB) port=5432 sslmode=disable" + # Redis + - name: EZ_REDIS_ADDR + value: "redis:6379" + - name: EZ_REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: REDIS_PASSWORD + - name: EZ_REDIS_DB + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_REDIS_DB + # Admin + - name: EZ_ADMIN_TOKEN + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: EZ_ADMIN_TOKEN + - name: EZ_INTERNAL_STATS_TOKEN + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: EZ_INTERNAL_STATS_TOKEN + # Other configs + - name: EZ_CORS_ALLOW_ORIGINS + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_CORS_ALLOW_ORIGINS + - name: EZ_LOG_RETENTION_DAYS + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_LOG_RETENTION_DAYS + - name: EZ_LOG_MAX_RECORDS + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_LOG_MAX_RECORDS + - name: EZ_LOG_PARTITIONING + valueFrom: + configMapKeyRef: + name: ez-api-config + key: EZ_LOG_PARTITIONING + resources: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 3 +--- +# ez-api Service (LoadBalancer) +apiVersion: v1 +kind: Service +metadata: + name: ez-api + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: ez-api +spec: + type: LoadBalancer + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: ez-api diff --git a/test/k8s/kustomization.yaml b/test/k8s/kustomization.yaml new file mode 100644 index 0000000..2382b90 --- /dev/null +++ b/test/k8s/kustomization.yaml @@ -0,0 +1,27 @@ +# Kustomization file for ez-api K8s deployment +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: ez-api-test-dev + +# Common labels for all resources +commonLabels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/managed-by: kustomize + +resources: + - namespace.yaml + - configmap.yaml + - secret.yaml + - postgres.yaml + - log-postgres.yaml + - redis.yaml + - ez-api.yaml + - balancer.yaml + +# Image customization (uncomment to override image tags) +# images: +# - name: harbor.rcfortress.site/library/ez-api +# newTag: v1.0.0 +# - name: harbor.rcfortress.site/library/balancer +# newTag: v1.0.0 diff --git a/test/k8s/log-postgres.yaml b/test/k8s/log-postgres.yaml new file mode 100644 index 0000000..6af5f15 --- /dev/null +++ b/test/k8s/log-postgres.yaml @@ -0,0 +1,112 @@ +# Log PostgreSQL StatefulSet for log database +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: log-postgres + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: log-postgres +spec: + serviceName: log-postgres + replicas: 1 + selector: + matchLabels: + app: log-postgres + # 有状态服务使用 OrderedReady 策略,确保按顺序部署和终止 + podManagementPolicy: OrderedReady + # 使用 RollingUpdate 策略,partition=0 表示全部更新 + updateStrategy: + type: RollingUpdate + rollingUpdate: + partition: 0 + template: + metadata: + labels: + app: log-postgres + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: log-postgres + spec: + terminationGracePeriodSeconds: 30 + containers: + - name: log-postgres + image: postgres:15-alpine + ports: + - containerPort: 5432 + name: postgres + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: LOG_POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: LOG_POSTGRES_PASSWORD + - name: POSTGRES_DB + valueFrom: + configMapKeyRef: + name: ez-api-config + key: LOG_POSTGRES_DB + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: log-postgres-data + mountPath: /var/lib/postgresql/data + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "500m" + livenessProbe: + exec: + command: + - pg_isready + - -U + - postgres + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + readinessProbe: + exec: + command: + - pg_isready + - -U + - postgres + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 3 + volumeClaimTemplates: + - metadata: + name: log-postgres-data + spec: + accessModes: ["ReadWriteOnce"] + # 根据集群配置修改 storageClassName + # storageClassName: "standard" + resources: + requests: + storage: 100Gi # 日志数据库需要更多存储空间 +--- +# Log PostgreSQL Service (Headless for StatefulSet) +apiVersion: v1 +kind: Service +metadata: + name: log-postgres + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: log-postgres +spec: + ports: + - port: 5432 + targetPort: 5432 + name: postgres + clusterIP: None # Headless service for StatefulSet + selector: + app: log-postgres diff --git a/test/k8s/namespace.yaml b/test/k8s/namespace.yaml new file mode 100644 index 0000000..52453ee --- /dev/null +++ b/test/k8s/namespace.yaml @@ -0,0 +1,8 @@ +# Namespace for ez-api stack +apiVersion: v1 +kind: Namespace +metadata: + name: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: namespace diff --git a/test/k8s/postgres.yaml b/test/k8s/postgres.yaml new file mode 100644 index 0000000..dcc878c --- /dev/null +++ b/test/k8s/postgres.yaml @@ -0,0 +1,112 @@ +# PostgreSQL StatefulSet for main database +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgres + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: postgres +spec: + serviceName: postgres + replicas: 1 + selector: + matchLabels: + app: postgres + # 有状态服务使用 OrderedReady 策略,确保按顺序部署和终止 + podManagementPolicy: OrderedReady + # 使用 RollingUpdate 策略,partition=0 表示全部更新 + updateStrategy: + type: RollingUpdate + rollingUpdate: + partition: 0 + template: + metadata: + labels: + app: postgres + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: postgres + spec: + terminationGracePeriodSeconds: 30 + containers: + - name: postgres + image: postgres:15-alpine + ports: + - containerPort: 5432 + name: postgres + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: ez-api-secrets + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + valueFrom: + configMapKeyRef: + name: ez-api-config + key: POSTGRES_DB + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "500m" + livenessProbe: + exec: + command: + - pg_isready + - -U + - postgres + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + readinessProbe: + exec: + command: + - pg_isready + - -U + - postgres + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 3 + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: ["ReadWriteOnce"] + # 根据集群配置修改 storageClassName + # storageClassName: "standard" + resources: + requests: + storage: 50Gi +--- +# PostgreSQL Service (Headless for StatefulSet) +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: postgres +spec: + ports: + - port: 5432 + targetPort: 5432 + name: postgres + clusterIP: None # Headless service for StatefulSet + selector: + app: postgres diff --git a/test/k8s/redis.yaml b/test/k8s/redis.yaml new file mode 100644 index 0000000..4aeba4d --- /dev/null +++ b/test/k8s/redis.yaml @@ -0,0 +1,100 @@ +# Redis StatefulSet +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: redis +spec: + serviceName: redis + replicas: 1 + selector: + matchLabels: + app: redis + # 有状态服务使用 OrderedReady 策略 + podManagementPolicy: OrderedReady + # Redis 更新策略:使用 RollingUpdate,但设置 partition=0 表示全部更新 + # 如果需要金丝雀发布,可以将 partition 设置为大于 0 的值 + updateStrategy: + type: RollingUpdate + rollingUpdate: + partition: 0 + template: + metadata: + labels: + app: redis + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: redis + spec: + terminationGracePeriodSeconds: 30 + containers: + - name: redis + image: redis:7-alpine + command: + - redis-server + - --appendonly + - "yes" + - --save + - "60" + - "1" + ports: + - containerPort: 6379 + name: redis + volumeMounts: + - name: redis-data + mountPath: /data + resources: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "512Mi" + cpu: "250m" + livenessProbe: + exec: + command: + - redis-cli + - ping + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + readinessProbe: + exec: + command: + - redis-cli + - ping + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 3 + volumeClaimTemplates: + - metadata: + name: redis-data + spec: + accessModes: ["ReadWriteOnce"] + # 根据集群配置修改 storageClassName + # storageClassName: "standard" + resources: + requests: + storage: 10Gi +--- +# Redis Service (Headless for StatefulSet) +apiVersion: v1 +kind: Service +metadata: + name: redis + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: redis +spec: + ports: + - port: 6379 + targetPort: 6379 + name: redis + clusterIP: None # Headless service for StatefulSet + selector: + app: redis diff --git a/test/k8s/secret.yaml b/test/k8s/secret.yaml new file mode 100644 index 0000000..87231d5 --- /dev/null +++ b/test/k8s/secret.yaml @@ -0,0 +1,26 @@ +# Secret for sensitive data +# WARNING: In production, use external secret management (Vault, Sealed Secrets, etc.) +# Base64 encode values: echo -n 'your-value' | base64 +apiVersion: v1 +kind: Secret +metadata: + name: ez-api-secrets + namespace: ez-api-test-dev + labels: + app.kubernetes.io/name: ez-api-test-dev + app.kubernetes.io/component: secrets +type: Opaque +stringData: + # PostgreSQL credentials + POSTGRES_USER: "postgres" + POSTGRES_PASSWORD: "postgres" + LOG_POSTGRES_USER: "postgres" + LOG_POSTGRES_PASSWORD: "postgres" + + # Redis credentials + REDIS_PASSWORD: "" + + # Admin tokens + EZ_ADMIN_TOKEN: "admin123" + EZ_INTERNAL_STATS_TOKEN: "" + EZ_BALANCER_STATS_FLUSH_TOKEN: ""