mirror of
https://github.com/suitenumerique/docs.git
synced 2026-09-23 18:15:10 +02:00
✨(yhub) allow to configure yhub worker and server
We want to be able to configure both server and worker, the idea is to be able to deploy separately the server and the worker and to scale them.
This commit is contained in:
@@ -197,7 +197,11 @@ jwtKeys:
|
||||
enabled: true
|
||||
|
||||
yhub:
|
||||
replicas: 1
|
||||
replicas: 3
|
||||
|
||||
worker:
|
||||
enabled: true
|
||||
replicas: 2
|
||||
|
||||
image:
|
||||
repository: localhost:5001/impress-yhub
|
||||
|
||||
@@ -166,7 +166,11 @@ jwtKeys:
|
||||
enabled: true
|
||||
|
||||
yhub:
|
||||
replicas: 1
|
||||
replicas: 3
|
||||
|
||||
worker:
|
||||
enabled: true
|
||||
replicas: 2
|
||||
|
||||
image:
|
||||
repository: lasuite/impress-yhub
|
||||
|
||||
@@ -350,6 +350,16 @@
|
||||
| `yhub.command` | Override the yhub container command | `[]` |
|
||||
| `yhub.args` | Override the yhub container args | `[]` |
|
||||
| `yhub.replicas` | Amount of yhub replicas | `3` |
|
||||
| `yhub.worker.enabled` | Deploy the worker apart from the server, each scaling on its own | `false` |
|
||||
| `yhub.worker.replicas` | Amount of yhub worker replicas | `1` |
|
||||
| `yhub.worker.resources` | Resource requirements for the yhub worker container, the server ones when empty | `{}` |
|
||||
| `yhub.worker.podAnnotations` | Annotations to add to the yhub worker Pod, the server ones when empty | `{}` |
|
||||
| `yhub.worker.dpAnnotations` | Annotations to add to the yhub worker Deployment, the server ones when empty | `{}` |
|
||||
| `yhub.worker.nodeSelector` | Node selector for the yhub worker Pod, the server one when empty | `{}` |
|
||||
| `yhub.worker.tolerations` | Tolerations for the yhub worker Pod, the server ones when empty | `[]` |
|
||||
| `yhub.worker.affinity` | Affinity for the yhub worker Pod, the server one when empty | `{}` |
|
||||
| `yhub.worker.terminationGracePeriodSeconds` | Grace period given to a worker pod to finish its task, the server one when empty | `nil` |
|
||||
| `yhub.worker.pdb.enabled` | Enable pdb on the yhub worker | `true` |
|
||||
| `yhub.shareProcessNamespace` | Enable share process namespace between containers | `false` |
|
||||
| `yhub.sidecars` | Add sidecars containers to yhub deployment | `[]` |
|
||||
| `yhub.terminationGracePeriodSeconds` | Grace period given to a yhub pod to drain before it is killed | `60` |
|
||||
|
||||
@@ -204,6 +204,42 @@ Requires top level scope
|
||||
{{ include "impress.fullname" . }}-yhub
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Full name for the yhub worker, when it is deployed apart from the server
|
||||
|
||||
Requires top level scope
|
||||
*/}}
|
||||
{{- define "impress.yhub.worker.fullname" -}}
|
||||
{{ include "impress.yhub.fullname" . }}-worker
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
yhub worker env vars - combines common yhub.envVars with yhub.worker.envVars
|
||||
*/}}
|
||||
{{- define "impress.yhub.worker.env" -}}
|
||||
{{- $topLevelScope := index . 0 -}}
|
||||
{{- $workerScope := index . 1 -}}
|
||||
{{- include "impress.env.transformDict" $workerScope.envVars -}}
|
||||
{{- include "impress.env.transformDict" (($workerScope.worker | default dict).envVars | default dict) -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The role a yhub pod runs, as an environment variable. Only when the worker is
|
||||
deployed apart: a single deployment runs both halves, which is what yhub does
|
||||
when the variable is absent. Skipped when the deployment names the role itself,
|
||||
in either env map — an explicit value wins, as everywhere else here.
|
||||
|
||||
Usage: {{ include "impress.yhub.roleEnv" (dict "root" $ "role" "server") }}
|
||||
*/}}
|
||||
{{- define "impress.yhub.roleEnv" -}}
|
||||
{{- $root := .root -}}
|
||||
{{- $named := merge (dict) (($root.Values.yhub.worker | default dict).envVars | default dict) ($root.Values.yhub.envVars | default dict) -}}
|
||||
{{- if and $root.Values.yhub.worker.enabled (not (hasKey $named "YHUB_ROLE")) }}
|
||||
- name: "YHUB_ROLE"
|
||||
value: {{ .role | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
JWT signing keys — the RSA keys the services sign the calls they make to each
|
||||
other with. The jwt-keys job generates them once into a secret every service
|
||||
|
||||
@@ -54,12 +54,14 @@ spec:
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if or $envVars .Values.jwtKeys.enabled }}
|
||||
{{- $roleEnv := include "impress.yhub.roleEnv" (dict "root" . "role" "server") }}
|
||||
{{- if or $envVars .Values.jwtKeys.enabled $roleEnv }}
|
||||
env:
|
||||
{{- $envVars | indent 12 }}
|
||||
{{- if .Values.jwtKeys.enabled }}
|
||||
{{- include "impress.jwtKeys.yhubEnv" . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- $roleEnv | indent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.yhub.envFrom }}
|
||||
envFrom:
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
{{- if and .Values.yhub.enabled .Values.yhub.worker.enabled -}}
|
||||
{{- $envVars := include "impress.yhub.worker.env" (list . .Values.yhub) -}}
|
||||
{{- $fullName := include "impress.yhub.worker.fullname" . -}}
|
||||
{{- $component := "yhub-worker" -}}
|
||||
{{- $worker := .Values.yhub.worker -}}
|
||||
# The half of yhub that drains the redis stream into postgres, deployed apart
|
||||
# from the one serving the websockets (YHUB_ROLE). It scales on the write
|
||||
# throughput rather than on the connected editors, and redis consumer groups
|
||||
# hand each task to exactly one of these pods.
|
||||
#
|
||||
# No service, no ports and no probes: a worker binds nothing, it claims tasks.
|
||||
# Its health is its process being alive — the task loop logs and backs off on
|
||||
# error rather than dying, so a pod that stopped working is one that exited,
|
||||
# and kubelet restarts it.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
annotations:
|
||||
{{- with ($worker.dpAnnotations | default .Values.yhub.dpAnnotations) }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ $worker.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- with ($worker.podAnnotations | default .Values.yhub.podAnnotations) }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 8 }}
|
||||
spec:
|
||||
{{- if $.Values.image.credentials }}
|
||||
imagePullSecrets:
|
||||
- name: {{ include "impress.secret.dockerconfigjson.name" (dict "fullname" (include "impress.fullname" .) "imageCredentials" $.Values.image.credentials) }}
|
||||
{{- end}}
|
||||
{{- if .Values.yhub.serviceAccountName }}
|
||||
serviceAccountName: {{ .Values.yhub.serviceAccountName }}
|
||||
{{- end }}
|
||||
shareProcessNamespace: {{ .Values.yhub.shareProcessNamespace }}
|
||||
# a task claimed by a pod that goes away is redelivered to another one,
|
||||
# but letting the current one finish saves that round trip
|
||||
terminationGracePeriodSeconds: {{ $worker.terminationGracePeriodSeconds | default .Values.yhub.terminationGracePeriodSeconds }}
|
||||
containers:
|
||||
{{- with .Values.yhub.sidecars }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ (.Values.yhub.image | default dict).repository | default .Values.image.repository }}:{{ (.Values.yhub.image | default dict).tag | default .Values.image.tag }}"
|
||||
imagePullPolicy: {{ (.Values.yhub.image | default dict).pullPolicy | default .Values.image.pullPolicy }}
|
||||
{{- with .Values.yhub.command }}
|
||||
command:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.yhub.args }}
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- $roleEnv := include "impress.yhub.roleEnv" (dict "root" . "role" "worker") }}
|
||||
{{- if or $envVars .Values.jwtKeys.enabled $roleEnv }}
|
||||
env:
|
||||
{{- $envVars | indent 12 }}
|
||||
{{- if .Values.jwtKeys.enabled }}
|
||||
{{- include "impress.jwtKeys.yhubEnv" . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- $roleEnv | indent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.yhub.envFrom }}
|
||||
envFrom:
|
||||
{{- toYaml .Values.yhub.envFrom | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.yhub.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with ($worker.resources | default .Values.yhub.resources) }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- if .Values.jwtKeys.enabled }}
|
||||
{{- include "impress.jwtKeys.volumeMount" . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
mountPath: {{ $value.path }}
|
||||
subPath: content
|
||||
{{- end }}
|
||||
{{- range .Values.yhub.extraVolumeMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
subPath: {{ .subPath | default "" }}
|
||||
readOnly: {{ .readOnly }}
|
||||
{{- end }}
|
||||
{{- with ($worker.nodeSelector | default .Values.yhub.nodeSelector) }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with ($worker.affinity | default .Values.yhub.affinity) }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with ($worker.tolerations | default .Values.yhub.tolerations) }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- if .Values.jwtKeys.enabled }}
|
||||
{{- include "impress.jwtKeys.volume" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
configMap:
|
||||
name: "{{ include "impress.fullname" $ }}-files-{{ $index }}"
|
||||
{{- end }}
|
||||
{{- range .Values.yhub.extraVolumes }}
|
||||
- name: {{ .name }}
|
||||
{{- if .existingClaim }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .existingClaim }}
|
||||
{{- else if .secret }}
|
||||
secret:
|
||||
{{ toYaml .secret | nindent 12 }}
|
||||
{{- else if .hostPath }}
|
||||
hostPath:
|
||||
{{ toYaml .hostPath | nindent 12 }}
|
||||
{{- else if .csi }}
|
||||
csi:
|
||||
{{- toYaml .csi | nindent 12 }}
|
||||
{{- else if .configMap }}
|
||||
configMap:
|
||||
{{- toYaml .configMap | nindent 12 }}
|
||||
{{- else if .emptyDir }}
|
||||
emptyDir:
|
||||
{{- toYaml .emptyDir | nindent 12 }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
---
|
||||
{{ if $worker.pdb.enabled }}
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
spec:
|
||||
maxUnavailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 6 }}
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
@@ -936,11 +936,47 @@ yhub:
|
||||
args: []
|
||||
|
||||
## @param yhub.replicas Amount of yhub replicas
|
||||
## Every replica also runs a worker (redis consumer groups hand each task to
|
||||
## one of them), and clients editing the same document need not land on the
|
||||
## same pod: updates travel through redis.
|
||||
## Clients editing the same document need not land on the same pod: updates
|
||||
## travel through redis. Each replica also runs a worker unless the worker is
|
||||
## deployed apart, see below.
|
||||
replicas: 3
|
||||
|
||||
## @param yhub.worker.enabled Deploy the worker apart from the server, each scaling on its own
|
||||
## @param yhub.worker.replicas Amount of yhub worker replicas
|
||||
## @param yhub.worker.resources Resource requirements for the yhub worker container, the server ones when empty
|
||||
## @param yhub.worker.podAnnotations Annotations to add to the yhub worker Pod, the server ones when empty
|
||||
## @param yhub.worker.dpAnnotations Annotations to add to the yhub worker Deployment, the server ones when empty
|
||||
## @param yhub.worker.nodeSelector Node selector for the yhub worker Pod, the server one when empty
|
||||
## @param yhub.worker.tolerations Tolerations for the yhub worker Pod, the server ones when empty
|
||||
## @param yhub.worker.affinity Affinity for the yhub worker Pod, the server one when empty
|
||||
## @param yhub.worker.terminationGracePeriodSeconds Grace period given to a worker pod to finish its task, the server one when empty
|
||||
## @param yhub.worker.pdb.enabled Enable pdb on the yhub worker
|
||||
## @skip yhub.worker.envVars Environment variables of the worker only, on top of yhub.envVars
|
||||
##
|
||||
## yhub is two halves sharing nothing but redis and postgres: the server
|
||||
## holds the websockets and serves the routes, the worker drains the stream
|
||||
## into postgres. One process runs both by default. Enabling this splits them
|
||||
## into two deployments — `YHUB_ROLE=server` and `YHUB_ROLE=worker`, the only
|
||||
## difference between them — so the server scales with the connected editors
|
||||
## and the worker with the write throughput.
|
||||
##
|
||||
## The worker binds nothing: no service, no ingress, and no probes to give it
|
||||
## (its liveness is its process). Everything not named here is the server's:
|
||||
## same image, same envVars, same secrets, same volumes.
|
||||
worker:
|
||||
enabled: false
|
||||
replicas: 1
|
||||
envVars: {}
|
||||
resources: {}
|
||||
podAnnotations: {}
|
||||
dpAnnotations: {}
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
terminationGracePeriodSeconds: null
|
||||
pdb:
|
||||
enabled: true
|
||||
|
||||
## @param yhub.shareProcessNamespace Enable share process namespace between containers
|
||||
shareProcessNamespace: false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user