feat(deploy): add k01 business cluster manifests for k3s with cnpg, strimzi, redis and mongodb operators

This commit is contained in:
zetaloop
2026-05-05 12:08:10 +08:00
parent 2d4dc236e9
commit 20ca50c127
31 changed files with 4396 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
name: controller
namespace: kafka
labels:
strimzi.io/cluster: juwan-kafka
spec:
replicas: 1
roles:
- controller
storage:
type: persistent-claim
size: 1Gi
deleteClaim: false
---
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
name: broker
namespace: kafka
labels:
strimzi.io/cluster: juwan-kafka
spec:
replicas: 1
roles:
- broker
storage:
type: persistent-claim
size: 5Gi
deleteClaim: false
---
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
name: juwan-kafka
namespace: kafka
annotations:
strimzi.io/node-pools: enabled
strimzi.io/kraft: enabled
spec:
kafka:
version: 4.2.0
metadataVersion: 4.2-IV0
listeners:
- name: plain
port: 9092
type: internal
tls: false
config:
offsets.topic.replication.factor: 1
transaction.state.log.replication.factor: 1
transaction.state.log.min.isr: 1
default.replication.factor: 1
min.insync.replicas: 1
entityOperator:
topicOperator: {}
userOperator: {}
---
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
name: email-task
namespace: kafka
labels:
strimzi.io/cluster: juwan-kafka
spec:
partitions: 1
replicas: 1
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -euo pipefail
K01_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$K01_DIR/../.." && pwd)"
SQL_DIR="$REPO_ROOT/desc/sql"
FIXTURE_DIR="$REPO_ROOT/deploy/dev/fixture"
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
declare -A SCHEMA_MAP=(
[user-db]=users
[player-db]=player
[game-db]=game
[shop-db]=shop
[order-db]=order
[wallet-db]=wallet
[community-db]=community
[review-db]=review
[dispute-db]=dispute
[notification-db]=notification
[search-db]=search
)
psql_exec() {
local cluster="$1" sql="$2"
kubectl -n juwan exec -i "${cluster}-1" -c postgres -- psql \
-v ON_ERROR_STOP=1 -U app -d app <<<"$sql"
}
psql_file() {
local cluster="$1" file="$2"
kubectl -n juwan exec -i "${cluster}-1" -c postgres -- psql \
-v ON_ERROR_STOP=1 -U app -d app < "$file"
}
for cluster in "${!SCHEMA_MAP[@]}"; do
domain="${SCHEMA_MAP[$cluster]}"
echo ">>> $cluster ($domain)"
kubectl -n juwan wait --for=condition=Ready "cluster.postgresql.cnpg.io/${cluster}" --timeout=300s
psql_file "$cluster" "$SQL_DIR/common/update_updated_at_column.sql"
for f in "$SQL_DIR/$domain"/*.sql; do
[ -f "$f" ] || continue
echo " schema: $(basename "$f")"
psql_file "$cluster" "$f"
done
if [ -f "$FIXTURE_DIR/$domain.sql" ]; then
echo " fixture: $domain.sql"
psql_file "$cluster" "$FIXTURE_DIR/$domain.sql"
fi
done
echo
echo "schema + fixture loaded into 11 CNPG clusters"
+41
View File
@@ -0,0 +1,41 @@
apiVersion: mongodbcommunity.mongodb.com/v1
kind: MongoDBCommunity
metadata:
name: chat-mongodb
namespace: juwan
spec:
members: 1
type: ReplicaSet
version: "8.2.6"
security:
authentication:
modes:
- SCRAM
users:
- name: app-user
db: admin
passwordSecretRef:
name: chat-mongodb-app-user-password
roles:
- name: readWrite
db: juwan_chat
scramCredentialsSecretName: chat-mongodb-app-user-scram
additionalMongodConfig:
storage.wiredTiger.engineConfig.journalCompressor: zlib
statefulSet:
spec:
volumeClaimTemplates:
- metadata:
name: data-volume
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
- metadata:
name: logs-volume
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 256Mi
+185
View File
@@ -0,0 +1,185 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: user-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: player-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: game-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: shop-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: order-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: wallet-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: community-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: review-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: dispute-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: notification-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
namespace: juwan
name: search-db
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie
primaryUpdateStrategy: unsupervised
bootstrap:
initdb:
database: app
owner: app
storage:
size: 1Gi
+149
View File
@@ -0,0 +1,149 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
namespace: juwan
data:
ratelimit.yaml: |
domain: api
descriptors:
- key: generic_key
value: login
descriptors:
- key: remote_address
rate_limit:
unit: MINUTE
requests_per_unit: 10
- key: generic_key
value: register
descriptors:
- key: remote_address
rate_limit:
unit: MINUTE
requests_per_unit: 5
- key: generic_key
value: forgot_password_send
descriptors:
- key: remote_address
rate_limit:
unit: MINUTE
requests_per_unit: 3
- key: generic_key
value: verify_code_send
descriptors:
- key: remote_address
rate_limit:
unit: MINUTE
requests_per_unit: 3
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rl-redis
namespace: juwan
labels:
app: rl-redis
spec:
replicas: 1
selector:
matchLabels:
app: rl-redis
template:
metadata:
labels:
app: rl-redis
spec:
containers:
- name: redis
image: redis:8.6.2-alpine
ports:
- containerPort: 6379
resources:
requests:
cpu: 20m
memory: 32Mi
---
apiVersion: v1
kind: Service
metadata:
name: rl-redis-svc
namespace: juwan
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: rl-redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ratelimit
namespace: juwan
labels:
app: ratelimit
spec:
replicas: 1
selector:
matchLabels:
app: ratelimit
template:
metadata:
labels:
app: ratelimit
spec:
containers:
- name: ratelimit
image: envoyproxy/ratelimit:fe26676d
command: ["/bin/ratelimit"]
env:
- name: REDIS_SOCKET_TYPE
value: tcp
- name: REDIS_URL
value: rl-redis-svc:6379
- name: USE_STATSD
value: "false"
- name: RUNTIME_ROOT
value: /data
- name: RUNTIME_SUBDIRECTORY
value: ratelimit
- name: RUNTIME_WATCH_ROOT
value: "true"
- name: LOG_LEVEL
value: info
ports:
- containerPort: 8081
name: grpc
- containerPort: 6070
name: debug
volumeMounts:
- name: config
mountPath: /data/ratelimit/config
resources:
requests:
cpu: 50m
memory: 64Mi
volumes:
- name: config
configMap:
name: ratelimit-config
---
apiVersion: v1
kind: Service
metadata:
name: ratelimit-svc
namespace: juwan
spec:
ports:
- name: grpc
port: 8081
targetPort: 8081
- name: debug
port: 6070
targetPort: 6070
selector:
app: ratelimit
+346
View File
@@ -0,0 +1,346 @@
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: user-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: user-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: player-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: player-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: game-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: game-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: shop-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: shop-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: order-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: order-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: wallet-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: wallet-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: community-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: community-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: review-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: review-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: dispute-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: dispute-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: notification-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: notification-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: search-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: search-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: chat-redis
namespace: juwan
spec:
clusterSize: 1
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.15
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
redisSecret:
name: chat-redis
key: password
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi