mirror of
https://github.com/LibreTranslate/LibreTranslate.git
synced 2024-11-25 17:31:00 +00:00
Add Helm Chart for LibreTranslate Deployment
Introduce a Helm chart to streamline the deployment and management of LibreTranslate within a Kubernetes cluster. The chart includes configurable parameters, persistent storage support, authentication, scalability features, health checks, and detailed documentation. See the PR for complete details.
This commit is contained in:
parent
fafc6a0cc6
commit
ae7af14660
11 changed files with 805 additions and 0 deletions
4
chart/Chart.yaml
Normal file
4
chart/Chart.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
apiVersion: v2
|
||||||
|
name: libretranslate
|
||||||
|
description: A Helm chart for Kubernetes to deploy LibreTranslate API
|
||||||
|
version: 0.1.0
|
58
chart/README.md
Normal file
58
chart/README.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# LibreTranslate Helm Chart
|
||||||
|
|
||||||
|
This Helm chart deploys a LibreTranslate instance on a Kubernetes cluster using the Helm package manager.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Kubernetes 1.12+
|
||||||
|
- Helm 3.0+
|
||||||
|
|
||||||
|
## Installing the Chart
|
||||||
|
|
||||||
|
To install the chart with the release name `libretranslate`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install libretranslate ./chart --namespace libretranslate --create-namespace
|
||||||
|
```
|
||||||
|
|
||||||
|
This command deploys LibreTranslate on the Kubernetes cluster with the default configuration. The [values.yaml](values.yaml) file lists the parameters that can be configured during installation.
|
||||||
|
|
||||||
|
> **Tip**: List all releases using `helm list`
|
||||||
|
|
||||||
|
## Uninstalling the Chart
|
||||||
|
|
||||||
|
To uninstall/delete the `libretranslate` deployment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm delete libretranslate
|
||||||
|
```
|
||||||
|
|
||||||
|
This command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
See [values.yaml](values.yaml) for the full list of parameters that can be configured. You can specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install libretranslate ./chart --namespace libretranslate --create-namespace --set service.port=8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install libretranslate ./chart --namespace libretranslate --create-namespace -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrade
|
||||||
|
|
||||||
|
Run the following command to upgrade your LibreTranslate installation. This command will use the Helm chart in the ./chart directory, apply the custom values from values.yaml, and deploy the upgrade to the `libretranslate` namespace:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm upgrade --install libretranslate ./chart --namespace libretranslate -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Tip**: You can use the default [values.yaml](values.yaml)
|
||||||
|
|
||||||
|
# References
|
||||||
|
- [https://jmrobles.medium.com/libretranslate-your-own-translation-service-on-kubernetes-b46c3e1af630](https://jmrobles.medium.com/libretranslate-your-own-translation-service-on-kubernetes-b46c3e1af630)
|
||||||
|
- [https://github.com/LibreTranslate/LibreTranslate](https://github.com/LibreTranslate/LibreTranslate)
|
45
chart/templates/NOTES.txt
Normal file
45
chart/templates/NOTES.txt
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
1. Get the application URL by running these commands:
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
http{{ if .Values.ingress.tls }}s{{ end }}://{{ index .Values.ingress.hosts 0 "host" }}{{ index .Values.ingress.hosts 0 "paths" 0 "path" }}
|
||||||
|
{{- if .name }}
|
||||||
|
- http{{ if .Values.ingress.tls }}s{{ end }}://{{ .name }}{{ .path }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if contains "NodePort" .Values.service.type }}
|
||||||
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "libretranslate.fullname" . }})
|
||||||
|
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||||
|
echo http://$NODE_IP:$NODE_PORT
|
||||||
|
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||||
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
|
You can watch the status of by running 'kubectl get svc -w {{ include "libretranslate.fullname" . }}'
|
||||||
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "libretranslate.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||||
|
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||||
|
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||||
|
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "libretranslate.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||||
|
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:{{ .Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
2. Get your admin username and password:
|
||||||
|
|
||||||
|
USER=$(kubectl get secret {{ include "libretranslate.fullname" . }}-auth -o jsonpath="{.data.username}" | base64 --decode)
|
||||||
|
PASSWORD=$(kubectl get secret {{ include "libretranslate.fullname" . }}-auth -o jsonpath="{.data.password}" | base64 --decode)
|
||||||
|
|
||||||
|
echo "Username: $USER"
|
||||||
|
echo "Password: $PASSWORD"
|
||||||
|
|
||||||
|
3. Manage your LibreTranslate API keys:
|
||||||
|
|
||||||
|
If you setted `--api-keys true` to use the api keys in the StatefulSet, you can manage them with the following commands:
|
||||||
|
|
||||||
|
# this will add an api key with a limit of 120 requests per minute
|
||||||
|
kubectl exec -it {{ include "libretranslate.fullname" . }}-0 -c {{ include "libretranslate.fullname" . }} -- /bin/bash -c "source ./venv/bin/activate && ltmanage keys add --key req-limit-120 120"
|
||||||
|
|
||||||
|
# returns a list of all api keys
|
||||||
|
kubectl exec -it {{ include "libretranslate.fullname" . }}-0 -c {{ include "libretranslate.fullname" . }} -- /bin/bash -c "source ./venv/bin/activate && ltmanage keys"
|
||||||
|
|
||||||
|
# remove an api key
|
||||||
|
kubectl exec -it {{ include "libretranslate.fullname" . }}-0 -c {{ include "libretranslate.fullname" . }} -- /bin/bash -c "source ./venv/bin/activate && ltmanage keys remove req-limit-120"
|
||||||
|
|
||||||
|
*** Be aware that the api keys are stored in a sqlite database in the pod. If you scale the pod to multiple replicas, the api keys will not be synced between the pods. You can use a shared storage to sync the api keys between the pods. For example, you can use a NFS storage class with a ReadWriteMany access mode to store the api keys in a shared perspective. ***
|
||||||
|
|
||||||
|
```
|
51
chart/templates/_helpers.tpl
Normal file
51
chart/templates/_helpers.tpl
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
{{/* vim: set filetype=mustache: */}}
|
||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "libretranslate.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
*/}}
|
||||||
|
{{- define "libretranslate.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride }}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
|
{{- if contains $name .Release.Name }}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "libretranslate.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "libretranslate.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "libretranslate.chart" . }}
|
||||||
|
{{ include "libretranslate.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "libretranslate.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "libretranslate.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
39
chart/templates/configmap.yaml
Normal file
39
chart/templates/configmap.yaml
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: libretranslate-config
|
||||||
|
data:
|
||||||
|
host: {{ .Values.appConfig.host | squote }}
|
||||||
|
port: {{ .Values.appConfig.port | squote }}
|
||||||
|
charLimit: {{ .Values.appConfig.charLimit | squote }}
|
||||||
|
reqLimit: {{ .Values.appConfig.reqLimit | squote }}
|
||||||
|
reqLimitStorage: {{ .Values.appConfig.reqLimitStorage | squote }}
|
||||||
|
batchLimit: {{ .Values.appConfig.batchLimit | squote }}
|
||||||
|
gaId: {{ .Values.appConfig.gaId | squote }}
|
||||||
|
frontendLanguageSource: {{ .Values.appConfig.frontendLanguageSource | squote }}
|
||||||
|
frontendLanguageTarget: {{ .Values.appConfig.frontendLanguageTarget | squote }}
|
||||||
|
frontendTimeout: {{ .Values.appConfig.frontendTimeout | squote }}
|
||||||
|
apiKeysDbPath: {{ .Values.appConfig.apiKeysDbPath | squote }}
|
||||||
|
apiKeysRemote: {{ .Values.appConfig.apiKeysRemote | squote }}
|
||||||
|
getApiKeyLink: {{ .Values.appConfig.getApiKeyLink | squote }}
|
||||||
|
sharedStorage: {{ .Values.appConfig.sharedStorage | squote }}
|
||||||
|
loadOnly: {{ .Values.appConfig.loadOnly | squote }}
|
||||||
|
threads: {{ .Values.appConfig.threads | squote }}
|
||||||
|
metricsAuthToken: {{ .Values.appConfig.metricsAuthToken | squote }}
|
||||||
|
urlPrefix: {{ .Values.appConfig.urlPrefix | squote }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
data:
|
||||||
|
debug: {{ .Values.appSettings.debug | squote }}
|
||||||
|
ssl: {{ .Values.appSettings.ssl | squote }}
|
||||||
|
apiKeys: {{ .Values.appSettings.apiKeys | squote }}
|
||||||
|
requireApiKeyOrigin: {{ .Values.appSettings.requireApiKeyOrigin | squote }}
|
||||||
|
requireApiKeySecret: {{ .Values.appSettings.requireApiKeySecret | squote }}
|
||||||
|
suggestions: {{ .Values.appSettings.suggestions | squote }}
|
||||||
|
disableFilesTranslation: {{ .Values.appSettings.disableFilesTranslation | squote }}
|
||||||
|
disableWebUi: {{ .Values.appSettings.disableWebUi | squote }}
|
||||||
|
updateModels: {{ .Values.appSettings.updateModels | squote }}
|
||||||
|
metrics: {{ .Values.appSettings.metrics | squote }}
|
40
chart/templates/ingress.yaml
Normal file
40
chart/templates/ingress.yaml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "libretranslate.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "libretranslate.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml .Values.ingress.annotations | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- $fullName := include "libretranslate.fullname" $ }}
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "libretranslate.fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
36
chart/templates/pvc.yaml
Normal file
36
chart/templates/pvc.yaml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{{- if and .Values.persistence.enabled (eq .Values.persistence.db.accessMode "ReadWriteMany") }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: db-volume
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "libretranslate.name" . }}-pv
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.db.accessMode }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.db.size }}
|
||||||
|
{{- if .Values.persistence.db.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.db.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.persistence.enabled (eq .Values.persistence.models.accessMode "ReadWriteMany") }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: models-volume
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "libretranslate.name" . }}-pvc
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.models.accessMode }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.models.size }}
|
||||||
|
{{- if .Values.persistence.models.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.models.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
9
chart/templates/secret.yaml
Normal file
9
chart/templates/secret.yaml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ include "libretranslate.fullname" . }}-auth
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
auth: {{ .Values.adminUser.auth | quote }}
|
||||||
|
username: {{ .Values.adminUser.name | quote }}
|
||||||
|
password: {{ .Values.adminUser.password | quote }}
|
15
chart/templates/service.yaml
Normal file
15
chart/templates/service.yaml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "libretranslate.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "libretranslate.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "libretranslate.selectorLabels" . | nindent 4 }}
|
344
chart/templates/statefulset.yaml
Normal file
344
chart/templates/statefulset.yaml
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: {{ include "libretranslate.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "libretranslate.labels" . | nindent 4 }}
|
||||||
|
{{- if .Values.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml .Values.annotations | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "libretranslate.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
{{- if .Values.podAnnotations }}
|
||||||
|
{{- toYaml .Values.podAnnotations | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||||
|
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||||
|
labels:
|
||||||
|
{{- include "libretranslate.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{ toYaml .Values.imagePullSecrets | indent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.securityContext }}
|
||||||
|
# forces the mount of the volumes to be mounted as libretranslate user and group
|
||||||
|
# and set permissions to libretranslate:libretranslate
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
initContainers:
|
||||||
|
- name: volume-permissions-and-pre-install-models
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
command:
|
||||||
|
- /bin/bash
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
mkdir -p /home/libretranslate/.local/share/argos-translate/packages
|
||||||
|
chown -R 1032:1032 /home/libretranslate/.local /app/db
|
||||||
|
|
||||||
|
if [ ! "$(ls -A /home/libretranslate/.local/share/argos-translate/packages)" ]; then
|
||||||
|
echo "Installing models... this can take quite a while depending on your internet connection."
|
||||||
|
/app/venv/bin/python /app/scripts/install_models.py --load_only_lang_codes {{ .Values.appConfig.loadOnly | quote }}
|
||||||
|
else
|
||||||
|
echo "The models directory is not empty, skipping model installation."
|
||||||
|
fi
|
||||||
|
volumeMounts:
|
||||||
|
- name: models-volume
|
||||||
|
mountPath: /home/libretranslate/.local/share/argos-translate
|
||||||
|
- name: db-volume
|
||||||
|
mountPath: {{ .Values.appConfig.apiKeysDbPathMount }}
|
||||||
|
{{- if .Values.initContainerSecurityContext }}
|
||||||
|
securityContext:
|
||||||
|
# forces the mount of the volumes to be mounted as libretranslate user and group
|
||||||
|
# and set permissions to libretranslate:libretranslate
|
||||||
|
{{- toYaml .Values.initContainerSecurityContext | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.port }}
|
||||||
|
protocol: TCP
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
securityContext:
|
||||||
|
{{- if .Values.podSecurityContext }}
|
||||||
|
# forces the mount of the volumes to be mounted as libretranslate user and group
|
||||||
|
# and set permissions to libretranslate:libretranslate
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readinessProbe:
|
||||||
|
{{- toYaml .Values.readinessProbe | nindent 12 }}
|
||||||
|
livenessProbe:
|
||||||
|
{{- toYaml .Values.livenessProbe | nindent 12 }}
|
||||||
|
env:
|
||||||
|
{{- if and (.Values.appSettings.debug) (ne .Values.appSettings.debug "") }}
|
||||||
|
- name: LT_DEBUG
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: debug
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.ssl) (ne .Values.appSettings.ssl "") }}
|
||||||
|
- name: LT_SSL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: ssl
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.apiKeys) (ne .Values.appSettings.apiKeys "") }}
|
||||||
|
- name: LT_API_KEYS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: apiKeys
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.requireApiKeyOrigin) (ne .Values.appSettings.requireApiKeyOrigin "") }}
|
||||||
|
- name: LT_REQUIRE_API_KEY_ORIGIN
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: requireApiKeyOrigin
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.requireApiKeySecret) (ne .Values.appSettings.requireApiKeySecret "") }}
|
||||||
|
- name: LT_REQUIRE_API_KEY_SECRET
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: requireApiKeySecret
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.suggestions) (ne .Values.appSettings.suggestions "") }}
|
||||||
|
- name: LT_SUGGESTIONS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: suggestions
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.disableFilesTranslation) (ne .Values.appSettings.disableFilesTranslation "") }}
|
||||||
|
- name: LT_DISABLE_FILES_TRANSLATION
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: disableFilesTranslation
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.disableWebUi) (ne .Values.appSettings.disableWebUi "") }}
|
||||||
|
- name: LT_DISABLE_WEB_UI
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: disableWebUi
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.updateModels) (ne .Values.appSettings.updateModels "") }}
|
||||||
|
- name: LT_UPDATE_MODELS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: updateModels
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.metrics) (ne .Values.appSettings.metrics "") }}
|
||||||
|
- name: LT_METRICS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-appsettings
|
||||||
|
key: metrics
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.host) (ne .Values.appConfig.host "") }}
|
||||||
|
- name: LT_HOST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: host
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.port) (ne .Values.appSettings.port "") }}
|
||||||
|
- name: LT_PORT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: port
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.charLimit) (ne .Values.appConfig.charLimit "") }}
|
||||||
|
- name: LT_CHAR_LIMIT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: charLimit
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.reqLimit) (ne .Values.appConfig.reqLimit "") }}
|
||||||
|
- name: LT_REQ_LIMIT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: reqLimit
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.reqLimitStorage) (ne .Values.appConfig.reqLimitStorage "") }}
|
||||||
|
- name: LT_REQ_LIMIT_STORAGE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: reqLimitStorage
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.batchLimit) (ne .Values.appConfig.batchLimit "") }}
|
||||||
|
- name: LT_BATCH_LIMIT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: batchLimit
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.gaId) (ne .Values.appConfig.gaId "") }}
|
||||||
|
- name: LT_GA_ID
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: gaId
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.frontendLanguageSource) (ne .Values.appConfig.frontendLanguageSource "") }}
|
||||||
|
- name: LT_FRONTEND_LANGUAGE_SOURCE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: frontendLanguageSource
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.frontendLanguageTarget) (ne .Values.appConfig.frontendLanguageTarget "") }}
|
||||||
|
- name: LT_FRONTEND_LANGUAGE_TARGET
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: frontendLanguageTarget
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.frontendTimeout) (ne .Values.appConfig.frontendTimeout "") }}
|
||||||
|
- name: LT_FRONTEND_TIMEOUT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: frontendTimeout
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.apiKeysDbPath) (ne .Values.appSettings.apiKeysDbPath "") }}
|
||||||
|
- name: LT_API_KEYS_DB_PATH
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: apiKeysDbPath
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.apiKeysRemote) (ne .Values.appSettings.apiKeysRemote "") }}
|
||||||
|
- name: LT_API_KEYS_REMOTE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: apiKeysRemote
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.getApiKeyLink) (ne .Values.appConfig.getApiKeyLink "") }}
|
||||||
|
- name: LT_GET_API_KEY_LINK
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: getApiKeyLink
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.sharedStorage) (ne .Values.appConfig.sharedStorage "") }}
|
||||||
|
- name: LT_SHARED_STORAGE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: sharedStorage
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.loadOnly) (ne .Values.appConfig.loadOnly "") }}
|
||||||
|
- name: LT_LOAD_ONLY
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: loadOnly
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.threads) (ne .Values.appConfig.threads "") }}
|
||||||
|
- name: LT_THREADS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: threads
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appSettings.metricsAuthToken) (ne .Values.appSettings.metricsAuthToken "") }}
|
||||||
|
- name: LT_METRICS_AUTH_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: metricsAuthToken
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (.Values.appConfig.urlPrefix) (ne .Values.appConfig.urlPrefix "") }}
|
||||||
|
- name: LT_URL_PREFIX
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: libretranslate-config
|
||||||
|
key: urlPrefix
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: db-volume
|
||||||
|
mountPath: {{ .Values.appConfig.apiKeysDbPathMount }}
|
||||||
|
- name: models-volume
|
||||||
|
mountPath: /home/libretranslate/.local/share/argos-translate
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.persistence.enabled (or (eq .Values.persistence.models.accessMode "ReadWriteMany") (eq .Values.persistence.db.accessMode "ReadWriteMany")) }}
|
||||||
|
volumes:
|
||||||
|
{{- if eq .Values.persistence.db.accessMode "ReadWriteMany" }}
|
||||||
|
- name: db-volume
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: db-volume
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq .Values.persistence.models.accessMode "ReadWriteMany" }}
|
||||||
|
- name: models-volume
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: models-volume
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml .Values.tolerations | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.persistence.enabled (or (eq .Values.persistence.models.accessMode "ReadWriteOnce") (eq .Values.persistence.db.accessMode "ReadWriteOnce")) }}
|
||||||
|
# still in beta, but this will allow us to delete the volumes when the statefulset is scaled down
|
||||||
|
persistentVolumeClaimRetentionPolicy:
|
||||||
|
whenDeleted: Retain
|
||||||
|
whenScaled: Delete
|
||||||
|
volumeClaimTemplates:
|
||||||
|
{{- if eq .Values.persistence.models.accessMode "ReadWriteOnce" }}
|
||||||
|
- metadata:
|
||||||
|
name: models-volume
|
||||||
|
labels:
|
||||||
|
{{- include "libretranslate.labels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.models.accessMode }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.models.size }}
|
||||||
|
{{- if .Values.persistence.models.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.models.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq .Values.persistence.db.accessMode "ReadWriteOnce" }}
|
||||||
|
- metadata:
|
||||||
|
name: db-volume
|
||||||
|
labels:
|
||||||
|
{{- include "libretranslate.labels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.db.accessMode }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.db.size }}
|
||||||
|
{{- if .Values.persistence.db.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.db.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
164
chart/values.yaml
Normal file
164
chart/values.yaml
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
# values.yaml
|
||||||
|
|
||||||
|
# Number of replicas
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
# Extra annotations for pods
|
||||||
|
podAnnotations: {}
|
||||||
|
|
||||||
|
# Extra annotations
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
# Extra tolerations for pods
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
# Chart name override
|
||||||
|
nameOverride: ""
|
||||||
|
|
||||||
|
# Full name of the deployment to override the default one
|
||||||
|
fullnameOverride: ""
|
||||||
|
|
||||||
|
# Image settings
|
||||||
|
image:
|
||||||
|
repository: libretranslate/libretranslate
|
||||||
|
pullPolicy: Always
|
||||||
|
tag: "latest"
|
||||||
|
# Using a Private Registry
|
||||||
|
# If you want to use a custom image from a private registry, you'll need to create an image pull secret with the registry's credentials:
|
||||||
|
# kubectl create secret docker-registry my-registry-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
|
||||||
|
# imagePullSecrets:
|
||||||
|
# - name: my-registry-secret
|
||||||
|
imagePullSecrets: []
|
||||||
|
|
||||||
|
# Service settings
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 5000
|
||||||
|
|
||||||
|
# Ingress settings
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: "" # set this to the name of the ingress controller class to use like nginx
|
||||||
|
annotations:
|
||||||
|
# cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: 10m
|
||||||
|
# Check for the adminUser key below.
|
||||||
|
# This will enable basic auth for the whole site.
|
||||||
|
# nginx.ingress.kubernetes.io/auth-type: basic
|
||||||
|
# nginx.ingress.kubernetes.io/auth-secret: libretranslate-auth
|
||||||
|
# nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
|
||||||
|
hosts:
|
||||||
|
- host: translate.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
# tls:
|
||||||
|
# - secretName: libretranslate-secret-tls
|
||||||
|
# hosts:
|
||||||
|
# - translate.example.com
|
||||||
|
|
||||||
|
# Security Context
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1032
|
||||||
|
|
||||||
|
# Security Context for init container
|
||||||
|
initContainerSecurityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
runAsGroup: 0
|
||||||
|
|
||||||
|
# Pod Security Context
|
||||||
|
podSecurityContext:
|
||||||
|
runAsUser: 1032
|
||||||
|
runAsGroup: 1032
|
||||||
|
|
||||||
|
# Persistent settings
|
||||||
|
# if you don't want to download a copy of the models per pod, you can use a shared storage like an nfs storage class
|
||||||
|
# and set it to ReadWriteMany. this way if you scale the pods later on, they will all use the same models and won't
|
||||||
|
# duplicate the space and download requests.
|
||||||
|
persistence:
|
||||||
|
enabled: false
|
||||||
|
db:
|
||||||
|
storageClass: ""
|
||||||
|
accessMode: "ReadWriteOnce"
|
||||||
|
size: "1Gi"
|
||||||
|
models:
|
||||||
|
storageClass: ""
|
||||||
|
accessMode: "ReadWriteOnce"
|
||||||
|
size: "10Gi" # as of August 2023, the models are about 6.6GB in size for all languages
|
||||||
|
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
|
||||||
|
# Readiness probe for kubernetes
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- /app/venv/bin/python
|
||||||
|
- /app/scripts/healthcheck.py
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
|
||||||
|
# Liveness probe for kubernetes
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- /app/venv/bin/python
|
||||||
|
- scripts/healthcheck.py
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
|
||||||
|
# Auth secret for basic authentication
|
||||||
|
# generate base64-user-password-pair with:
|
||||||
|
# htpasswd -nb <username> <password> | base64
|
||||||
|
#
|
||||||
|
# e.g.:
|
||||||
|
#
|
||||||
|
# htpasswd -nb admin mySecretPassword | base64
|
||||||
|
# This is used by the nginx ingress controller to enable basic auth for the whole site.
|
||||||
|
# It will create a secret with the name libretranslate-auth.
|
||||||
|
adminUser:
|
||||||
|
name: "YWRtaW4K" # copy the username in base64 as a reference
|
||||||
|
auth: "YWRtaW46JGFwcjEkYlpydmYvUFYkSHBHSlhqZU1EN0ZON2kyYndsMVRNMQoK" # copy the output from the htpasswd command here as a reference
|
||||||
|
password: "bXlTZWNyZXRQYXNzd29yZAo=" # copy the password as base64 for the admin user here as a reference
|
||||||
|
|
||||||
|
# Settings / Flags
|
||||||
|
appSettings:
|
||||||
|
debug: "false" # Enable debug environment (Default: Disabled)
|
||||||
|
ssl: "false" # Enable SSL (Default: Disabled)
|
||||||
|
apiKeys: "false" # Enable API keys database for per-client rate limits when --req-limit is reached (Default: Don't use API keys)
|
||||||
|
requireApiKeyOrigin: "" # Require use of an API key for programmatic access to the API, unless the request origin matches this domain (Default: No restrictions on domain origin)
|
||||||
|
requireApiKeySecret: "" # Require use of an API key for programmatic access to the API, unless the client also sends a secret match (Default: No secrets required)
|
||||||
|
suggestions: "false" # Allow user suggestions (Default: Disabled)
|
||||||
|
disableFilesTranslation: "false" # Disable files translation (Default: File translation allowed)
|
||||||
|
disableWebUi: "false" # Disable web ui (Default: Web Ui enabled)
|
||||||
|
updateModels: "false" # Update language models at startup (Default: Only on if no models found)
|
||||||
|
metrics: "false" # Enable the /metrics endpoint for exporting Prometheus usage metrics (Default: Disabled)
|
||||||
|
|
||||||
|
# Configuration Parameters
|
||||||
|
appConfig:
|
||||||
|
host: "0.0.0.0" # Set host to bind the server to (Default: 127.0.0.1)
|
||||||
|
port: "5000" # Set port to bind the server to (Default: 5000)
|
||||||
|
charLimit: "null" # Set character limit (Default: No limit)
|
||||||
|
reqLimit: "null" # Set maximum number of requests per minute per client (outside of limits set by api keys) (Default: No limit)
|
||||||
|
reqLimitStorage: "memory://" # Storage URI to use for request limit data storage. See Flask Limiter (Default: memory://)
|
||||||
|
batchLimit: "null" # Set maximum number of texts to translate in a batch request (Default: No limit)
|
||||||
|
gaId: "" # Enable Google Analytics on the API client page by providing an ID (Default: Empty (no tracking))
|
||||||
|
frontendLanguageSource: "auto" # Set frontend default language - source (Default: auto)
|
||||||
|
frontendLanguageTarget: "locale" # Set frontend default language - target (Default: locale (match site's locale))
|
||||||
|
frontendTimeout: "500" # Set frontend translation timeout (Default: 500)
|
||||||
|
apiKeysDbPath: "/app/db/api_keys.db" # Use a specific path inside the container for the local database. Can be absolute or relative (Default: /app/db/api_keys.db)
|
||||||
|
apiKeysDbPathMount: "/app/db" # Use a specific path inside the container for the local database. Must be the same as apiKeysDbPath (Default: /app/db)
|
||||||
|
apiKeysRemote: "" # Use this remote endpoint to query for valid API keys instead of using the local database (Default: Empty (use local db instead))
|
||||||
|
getApiKeyLink: "" # Show a link in the UI where to direct users to get an API key (Default: Empty (no link shown on web ui))
|
||||||
|
sharedStorage: "memory://" # Shared storage URI to use for multi-process data sharing (e.g. when using gunicorn) (Default: memory://)
|
||||||
|
loadOnly: "" # Set available languages (Default: Empty (use all from argostranslate))
|
||||||
|
threads: "4" # Set number of threads (Default: 4)
|
||||||
|
metricsAuthToken: "" # Protect the /metrics endpoint by allowing only clients that have a valid Authorization Bearer token (Default: Empty (no auth required))
|
||||||
|
urlPrefix: "" # Add prefix to URL: example.com:5000/url-prefix/ (Default: /)
|
Loading…
Reference in a new issue