Skip to content
Clone

chore(deploy): ship the event system with the app image

- add an event Deployment/Service (`app event`, socket 7031, rpc 7032) and an
  apihost internal-rpc port/service so the two processes can reach each other
- wire the identity-key secret mount and the internal rpc key/MAC key
  placeholders through values, ConfigMap and Secret templates
- expose 7031/7032 in the image and note that the event role uses tcpSocket
  probes because it has no HTTP health endpoint
- add `just event [mode]`, `just event-actor` and `just event-consumer`
ZhenYi committed
parent ec0bdb8 commit 10b0f74 Browse files

6 files changed

+213 −2

File tree 6
Modified charts/core/templates/_helpers.tpl View charts/core/templates/_helpers.tpl
@@ -57,6 +57,26 @@
5757{{- define "gitdata.env" -}}
5858- name: APP_APIHOST__PORT
5959 value: {{ .Values.apihost.port | quote }}
60- name: APP_INTERNAL__RPC__LISTEN_ADDRESS
61 value: {{ printf "0.0.0.0:%v" .Values.apihost.rpcPort | quote }}
62- name: APP_INTERNAL__EVENT_CLIENT__ENDPOINT
63 value: {{ printf "http://%s-event:%v" (include "gitdata.fullname" .) .Values.event.rpcPort | quote }}
64{{- if .Values.event.enabled }}
65- name: APP_EVENT__SOCKET__LISTEN_ADDRESS
66 value: {{ printf "0.0.0.0:%v" .Values.event.socketPort | quote }}
67- name: APP_EVENT__RPC__LISTEN_ADDRESS
68 value: {{ printf "0.0.0.0:%v" .Values.event.rpcPort | quote }}
69- name: APP_EVENT__PLATFORM__RPC_ENDPOINT
70 value: {{ printf "http://%s-apihost:%v" (include "gitdata.fullname" .) .Values.apihost.rpcPort | quote }}
71- name: APP_EVENT__PLATFORM__RESOURCE_API_ENDPOINT
72 value: {{ printf "http://%s-apihost:%v/api/v1" (include "gitdata.fullname" .) .Values.apihost.port | quote }}
73{{- end }}
74{{- if .Values.identityKey.secretName }}
75- name: APP_EVENT__RPC__IDENTITY_PRIVATE_KEY__FILE
76 value: {{ printf "%s/identity-private.pem" .Values.identityKey.mountPath | quote }}
77- name: APP_INTERNAL__EVENT_CLIENT__PUBLIC_KEY__FILE
78 value: {{ printf "%s/identity-public.pem" .Values.identityKey.mountPath | quote }}
79{{- end }}
6080- name: APP_GIT__KENSHELL_ENDPOINT
6181 value: {{ .Values.kenshell.endpoint | quote }}
6282- name: APP_GIT__KENSHELL_RPC_KEY
Modified charts/core/templates/apihost.yaml View charts/core/templates/apihost.yaml
@@ -72,6 +72,8 @@
7272 ports:
7373 - name: http
7474 containerPort: {{ .Values.apihost.port }}
75 - name: rpc
76 containerPort: {{ .Values.apihost.rpcPort }}
7577 livenessProbe:
7678 httpGet: { path: /healthz, port: http }
7779 initialDelaySeconds: 10
@@ -94,7 +96,17 @@
9496 volumeMounts:
9597 - name: repos
9698 mountPath: {{ .Values.persistence.repos.mountPath }}
99 {{- if .Values.identityKey.secretName }}
100 - name: identity-keys
101 mountPath: {{ .Values.identityKey.mountPath }}
102 readOnly: true
103 {{- end }}
97104 volumes:
105 {{- if .Values.identityKey.secretName }}
106 - name: identity-keys
107 secret:
108 secretName: {{ .Values.identityKey.secretName }}
109 {{- end }}
98110 - name: repos
99111 {{- if .Values.persistence.repos.existingClaim }}
100112 persistentVolumeClaim:
@@ -122,6 +134,9 @@
122134 - name: http
123135 port: {{ .Values.apihost.port }}
124136 targetPort: http
137 - name: rpc
138 port: {{ .Values.apihost.rpcPort }}
139 targetPort: rpc
125140{{- if .Values.apihost.autoscaling.enabled }}
126141---
127142apiVersion: autoscaling/v2
Added charts/core/templates/event.yaml View charts/core/templates/event.yaml
@@ -0,0 +1,119 @@
1{{- if .Values.event.enabled }}
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: {{ printf "%s-event" (include "gitdata.fullname" .) }}
6 labels:
7 {{- include "gitdata.labels" . | nindent 4 }}
8 app.kubernetes.io/component: event
9spec:
10 replicas: {{ .Values.event.replicaCount }}
11 revisionHistoryLimit: 3
12 strategy:
13 type: RollingUpdate
14 rollingUpdate:
15 maxSurge: {{ .Values.event.maxSurge }}
16 maxUnavailable: {{ .Values.event.maxUnavailable }}
17 selector:
18 matchLabels:
19 {{- include "gitdata.selectorLabels" . | nindent 6 }}
20 app.kubernetes.io/component: event
21 template:
22 metadata:
23 labels:
24 {{- include "gitdata.selectorLabels" . | nindent 8 }}
25 app.kubernetes.io/component: event
26 {{- with .Values.podLabels }}
27 {{- toYaml . | nindent 8 }}
28 {{- end }}
29 annotations:
30 checksum/env: {{ toYaml .Values.config.env | sha256sum }}
31 {{- with .Values.podAnnotations }}
32 {{- toYaml . | nindent 8 }}
33 {{- end }}
34 spec:
35 serviceAccountName: {{ include "gitdata.serviceAccountName" . }}
36 {{- include "gitdata.imagePullSecrets" . | nindent 6 }}
37 terminationGracePeriodSeconds: 45
38 securityContext:
39 {{- toYaml .Values.podSecurityContext | nindent 8 }}
40 {{- if or (eq .Values.event.podAntiAffinity "soft") (eq .Values.event.podAntiAffinity "hard") }}
41 affinity:
42 {{- include "gitdata.podAntiAffinity" (dict "ctx" . "mode" .Values.event.podAntiAffinity "component" "event") | nindent 8 }}
43 {{- end }}
44 {{- with .Values.nodeSelector }}
45 nodeSelector:
46 {{- toYaml . | nindent 8 }}
47 {{- end }}
48 {{- with .Values.tolerations }}
49 tolerations:
50 {{- toYaml . | nindent 8 }}
51 {{- end }}
52 containers:
53 - name: event
54 image: {{ include "gitdata.image" . }}
55 imagePullPolicy: {{ .Values.image.pullPolicy }}
56 args: ["app", "event", "--mode", {{ .Values.event.mode | quote }}]
57 {{- include "gitdata.envFrom" . | nindent 10 }}
58 env:
59 {{- include "gitdata.env" . | nindent 12 }}
60 {{- with .Values.event.extraEnv }}
61 {{- toYaml . | nindent 12 }}
62 {{- end }}
63 ports:
64 - name: socket
65 containerPort: {{ .Values.event.socketPort }}
66 - name: rpc
67 containerPort: {{ .Values.event.rpcPort }}
68 livenessProbe:
69 tcpSocket: { port: socket }
70 initialDelaySeconds: 10
71 periodSeconds: 15
72 timeoutSeconds: 3
73 readinessProbe:
74 tcpSocket: { port: socket }
75 initialDelaySeconds: 5
76 periodSeconds: 10
77 timeoutSeconds: 3
78 failureThreshold: 3
79 lifecycle:
80 preStop:
81 exec:
82 command: ["/bin/sh", "-c", "sleep 5"]
83 securityContext:
84 {{- toYaml .Values.securityContext | nindent 12 }}
85 resources:
86 {{- toYaml .Values.event.resources | nindent 12 }}
87 {{- if .Values.identityKey.secretName }}
88 volumeMounts:
89 - name: identity-keys
90 mountPath: {{ .Values.identityKey.mountPath }}
91 readOnly: true
92 {{- end }}
93 {{- if .Values.identityKey.secretName }}
94 volumes:
95 - name: identity-keys
96 secret:
97 secretName: {{ .Values.identityKey.secretName }}
98 {{- end }}
99---
100apiVersion: v1
101kind: Service
102metadata:
103 name: {{ printf "%s-event" (include "gitdata.fullname" .) }}
104 labels:
105 {{- include "gitdata.labels" . | nindent 4 }}
106 app.kubernetes.io/component: event
107spec:
108 type: ClusterIP
109 selector:
110 {{- include "gitdata.selectorLabels" . | nindent 4 }}
111 app.kubernetes.io/component: event
112 ports:
113 - name: socket
114 port: {{ .Values.event.socketPort }}
115 targetPort: socket
116 - name: rpc
117 port: {{ .Values.event.rpcPort }}
118 targetPort: rpc
119{{- end }}
Modified charts/core/values.yaml View charts/core/values.yaml
@@ -38,6 +38,12 @@
3838 # 事件投递:消息事件写入 event_outbox,由 apihost 内嵌 relay 投递到 RocketMQ。
3939 APP_ROCKETMQ__NAME_SERVER: "rocketmq-namesrv:9876"
4040 APP_ROCKETMQ__TOPIC_PREFIX: "gitdata"
41 # 事件系统(app event):消费 RocketMQ 并通过 socket.io 推送。
42 APP_EVENT__CONSUMER__NAME_SERVER: "rocketmq-namesrv:9876"
43 APP_EVENT__CONSUMER__TOPIC_PREFIXES: '["gitdata","kenshell"]'
44 APP_EVENT__CONSUMER__CONSUMER_GROUP: "gitdata-event"
45 APP_EVENT__REDIS__URL: "redis://redis-master:6379"
46 APP_EVENT__SOCKET__SESSION_COOKIE: "session"
4147 RUST_LOG: "info"
4248
4349# 敏感配置(渲染为 Secret)。注意 AppConfig 的 Debug 会带出密钥,
@@ -49,6 +55,14 @@
4955 env:
5056 APP_DATABASE__URL: "postgres://postgres:CHANGE_ME@postgres:5432/gitdata"
5157 APP_INTERNAL__SERVICE_KEY: "" # /api/v1/internal/* 服务密钥,>=32 字节
58 # 内部 RPC 共享门禁密钥(event 与 apihost 两侧必须同名同值,>=32 字符)
59 APP_INTERNAL__RPC__RPC_KEY: ""
60 APP_EVENT__RPC__RPC_KEY: ""
61 APP_EVENT__PLATFORM__RPC_KEY: ""
62 APP_INTERNAL__EVENT_CLIENT__RPC_KEY: ""
63 # 身份信封完整性密钥(平台签名/event 验签,两侧必须一致)
64 APP_EVENT__RPC__PLATFORM_MAC_KEY: ""
65 APP_INTERNAL__EVENT_CLIENT__MAC_KEY: ""
5266 APP_POW__MAC_KEY: "" # base64 >=32 字节
5367 APP_AUTH__TOTP_ENCRYPTION_KEY: "" # base64 >=32 字节(实测必填)
5468 APP_S3__ACCESS_KEY_ID: ""
@@ -85,6 +99,8 @@
8599 enabled: true
86100 replicaCount: 2
87101 port: 3000
102 # 内部 RPC 端口(Identity/Authorization),只暴露给 event 与集群内调用方。
103 rpcPort: 7052
88104 resources:
89105 requests: { cpu: 250m, memory: 256Mi }
90106 limits: { memory: 1Gi }
@@ -106,6 +122,28 @@
106122 minAvailable: 1
107123
108124
125event:
126 # 事件系统(app event):RocketMQ 消费 + socket.io 通道 + 内部 RPC。
127 enabled: true
128 replicaCount: 1
129 # single | consumer | actor:拆分布署时 consumer/actor 各起一个 Deployment。
130 mode: single
131 socketPort: 7031
132 rpcPort: 7032
133 resources:
134 requests: { cpu: 200m, memory: 256Mi }
135 limits: { memory: 1Gi }
136 maxSurge: 1
137 maxUnavailable: 0
138 podAntiAffinity: soft # soft | hard | ""
139 extraEnv: []
140
141# 身份信封密钥(event 私钥 / apihost 公钥 + 共享 MAC key)。
142# 提供一个包含 identity-private.pem 与 identity-public.pem 的 Secret 名即可启用挂载。
143identityKey:
144 secretName: ""
145 mountPath: /etc/gitdata/keys
146
109147kenshell:
110148 # KenShell 是 Git 数据面:对象库、引用、pack、LFS、smart HTTP 与 SSH 都由它提供。
111149 endpoint: "http://kenshell:50091"
Modified Dockerfile View Dockerfile
@@ -1,9 +1,11 @@
11# syntax=docker/dockerfile:1
22
33# ---------------------------------------------------------------------------
4# KenApi — GitDataAI 主业务后端(cargo workspace,二进制 app:serve / migrate / openapi)
4# KenApi — GitDataAI 主业务后端(cargo workspace,二进制 app:serve / event / migrate / openapi)
55#
66# docker build -t kenapi:local .
7# docker run --rm -p 7051:7051 ... kenapi:local # app serve
8# docker run --rm -p 7031:7031 -p 7032:7032 ... kenapi:local app event # 事件系统
79# docker run --rm -p 7051:7051 \
810# -e APP_DATABASE__URL=postgres://... kenapi:local
911#
@@ -114,9 +116,11 @@
114116
115117USER gitdata
116118
117EXPOSE 7051
119EXPOSE 7051 7031 7032
118120STOPSIGNAL SIGTERM
119121
122# 默认 CMD 是 apihost:/healthz 可用。`app event` 角色没有 HTTP /healthz,
123# 部署时由 k8s 用 tcpSocket 探针覆盖镜像 HEALTHCHECK。
120124HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
121125 CMD curl -fsS "http://127.0.0.1:${KENAPI_HEALTH_PORT:-7051}/healthz" >/dev/null || exit 1
122126
Modified justfile View justfile
@@ -48,6 +48,19 @@
4848migrate:
4949 @{{ invoke }}"{{ dev }}" migrate
5050
51# 事件系统(socket.io 通道 + RocketMQ 消费 + 内部 RPC)
52# 需要 Redis;single/consumer 模式还依赖 RocketMQ,RPC 依赖 apihost 已启动。
53event mode="single":
54 @cargo run -p app -- event --mode {{mode}}
55
56# 只跑 socket 节点(不消费 MQ)
57event-actor:
58 @cargo run -p app -- event --mode actor
59
60# 只跑 RocketMQ 消费节点
61event-consumer:
62 @cargo run -p app -- event --mode consumer
63
5164# 构建全部后端二进制
5265# 遵循 CARGO_TARGET_DIR;just up 从同一目录取二进制。
5366build:
@@ -93,6 +106,8 @@
93106# URL 速查
94107urls:
95108 @echo " app http://127.0.0.1:7051 (Swagger: /api/docs)"
109 @echo " event ws://127.0.0.1:7031/socket.io rpc: 127.0.0.1:7032"
110 @echo " apihost-rpc 127.0.0.1:7052 (internal.v1)"
96111
97112# 重新生成 openapi.json 与 packages/apiclient 客户端
98113openapi: