mirror of
https://github.com/thomiceli/opengist.git
synced 2025-06-16 07:07:13 +02:00
Add Helm Chart (#454)
This commit is contained in:
52
.github/workflows/helm.yml
vendored
Normal file
52
.github/workflows/helm.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
name: Build / Deploy Helm Chart
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Helm
|
||||||
|
uses: azure/setup-helm@v4.3.0
|
||||||
|
with:
|
||||||
|
version: 'latest'
|
||||||
|
|
||||||
|
- name: Update Helm chart dependencies
|
||||||
|
run: |
|
||||||
|
cd ./helm/opengist
|
||||||
|
helm dependency update
|
||||||
|
|
||||||
|
- name: Package Helm chart
|
||||||
|
run: |
|
||||||
|
cd ./helm
|
||||||
|
helm package ./opengist
|
||||||
|
|
||||||
|
# First time, create the index
|
||||||
|
if [ ! -f index.yaml ]; then
|
||||||
|
helm repo index --url https://helm.opengist.io .
|
||||||
|
else
|
||||||
|
# For subsequent runs, merge with existing index
|
||||||
|
helm repo index --url https://helm.opengist.io --merge index.yaml .
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Deploy to server
|
||||||
|
uses: appleboy/scp-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SERVER_HOST }}
|
||||||
|
username: ${{ secrets.SERVER_USERNAME }}
|
||||||
|
key: ${{ secrets.SERVER_SSH_KEY }}
|
||||||
|
source: "./helm/*.tgz,./helm/index.yaml"
|
||||||
|
target: ${{ secrets.HELM_SERVER_PATH }}
|
||||||
|
|
||||||
|
- name: Update remote helm repository
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SERVER_HOST }}
|
||||||
|
username: ${{ secrets.SERVER_USERNAME }}
|
||||||
|
key: ${{ secrets.SERVER_SSH_KEY }}
|
||||||
|
script: |
|
||||||
|
${{ secrets.UPDATE_HELM_REPO }}
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,7 +5,9 @@ gist.db
|
|||||||
/**/.DS_Store
|
/**/.DS_Store
|
||||||
public/assets/*
|
public/assets/*
|
||||||
public/manifest.json
|
public/manifest.json
|
||||||
|
./opengist
|
||||||
opengist
|
opengist
|
||||||
build/
|
build/
|
||||||
docs/.vitepress/dist/
|
docs/.vitepress/dist/
|
||||||
docs/.vitepress/cache/
|
docs/.vitepress/cache/
|
||||||
|
helm/opengist/charts/
|
@ -1,75 +0,0 @@
|
|||||||
# kustomize
|
|
||||||
|
|
||||||
## Simple
|
|
||||||
|
|
||||||
`kustomization.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
|
|
||||||
resources:
|
|
||||||
- https://github.com/thomiceli/opengist/deploy/
|
|
||||||
```
|
|
||||||
|
|
||||||
## Full example
|
|
||||||
|
|
||||||
`kustomization.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
|
|
||||||
namespace: opengist
|
|
||||||
|
|
||||||
resources:
|
|
||||||
- namespace.yaml
|
|
||||||
- https://github.com/thomiceli/opengist/deploy/?ref:v1.9.1
|
|
||||||
|
|
||||||
images:
|
|
||||||
- name: ghcr.io/thomiceli/opengist
|
|
||||||
newTag: 1.9.1
|
|
||||||
|
|
||||||
patches:
|
|
||||||
# Add your ingress
|
|
||||||
- path: ingress.yaml
|
|
||||||
- patch: |-
|
|
||||||
- op: add
|
|
||||||
path: /spec/rules/0/host
|
|
||||||
value: opengist.mydomain.com
|
|
||||||
target:
|
|
||||||
group: networking.k8s.io
|
|
||||||
version: v1
|
|
||||||
kind: Ingress
|
|
||||||
name: opengist
|
|
||||||
```
|
|
||||||
|
|
||||||
`namespace.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
```
|
|
||||||
|
|
||||||
`ingress.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-production
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- opengist.mydomain.com
|
|
||||||
secretName: opengist-tls
|
|
||||||
```
|
|
@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: opengist
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: opengist
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: opengist
|
|
||||||
image: ghcr.io/thomiceli/opengist
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: 6157
|
|
||||||
- name: ssh
|
|
||||||
containerPort: 2222
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /opengist
|
|
||||||
name: data
|
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: opengist-data
|
|
@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: opengist
|
|
||||||
app.kubernetes.io/component: ingress
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: opengist.local
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- pathType: Prefix
|
|
||||||
path: "/"
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: opengist
|
|
||||||
port:
|
|
||||||
name: http
|
|
@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
|
|
||||||
resources:
|
|
||||||
- deployment.yaml
|
|
||||||
- pvc.yaml
|
|
||||||
- ingress.yaml
|
|
||||||
- service.yaml
|
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: opengist-data
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: opengist
|
|
||||||
app.kubernetes.io/component: data
|
|
||||||
spec:
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 1Gi
|
|
||||||
volumeMode: Filesystem
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: opengist
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: opengist
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app.kubernetes.io/name: opengist
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
targetPort: http
|
|
||||||
name: http
|
|
@ -25,6 +25,7 @@ export default defineConfig({
|
|||||||
{text: 'Introduction', link: '/docs'},
|
{text: 'Introduction', link: '/docs'},
|
||||||
{text: 'Installation', link: '/docs/installation', items: [
|
{text: 'Installation', link: '/docs/installation', items: [
|
||||||
{text: 'Docker', link: '/docs/installation/docker'},
|
{text: 'Docker', link: '/docs/installation/docker'},
|
||||||
|
{text: 'Kubernetes', link: '/docs/installation/kubernetes'},
|
||||||
{text: 'Binary', link: '/docs/installation/binary'},
|
{text: 'Binary', link: '/docs/installation/binary'},
|
||||||
{text: 'Source', link: '/docs/installation/source'},
|
{text: 'Source', link: '/docs/installation/source'},
|
||||||
],
|
],
|
||||||
|
15
docs/installation/kubernetes.md
Normal file
15
docs/installation/kubernetes.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Install on Kubernetes
|
||||||
|
|
||||||
|
A [Helm](https://helm.sh) chart is available to install Opengist on a Kubernetes cluster.
|
||||||
|
Check the [Helm documentation](https://helm.sh/docs/) for more information on how to use Helm.
|
||||||
|
|
||||||
|
A non-customized installation of Opengist can be done with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add opengist https://helm.opengist.io
|
||||||
|
|
||||||
|
helm install opengist opengist/opengist
|
||||||
|
```
|
||||||
|
|
||||||
|
Refer to the [Opengist chart](https://github.com/thomiceli/opengist/tree/master/helm/opengist) for more information
|
||||||
|
about the chart and to customize your installation.
|
23
helm/opengist/.helmignore
Normal file
23
helm/opengist/.helmignore
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Patterns to ignore when building packages.
|
||||||
|
# This supports shell glob matching, relative path matching, and
|
||||||
|
# negation (prefixed with !). Only one pattern per line.
|
||||||
|
.DS_Store
|
||||||
|
# Common VCS dirs
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.bzr/
|
||||||
|
.bzrignore
|
||||||
|
.hg/
|
||||||
|
.hgignore
|
||||||
|
.svn/
|
||||||
|
# Common backup files
|
||||||
|
*.swp
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*.orig
|
||||||
|
*~
|
||||||
|
# Various IDEs
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
*.tmproj
|
||||||
|
.vscode/
|
9
helm/opengist/Chart.lock
Normal file
9
helm/opengist/Chart.lock
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
dependencies:
|
||||||
|
- name: postgresql
|
||||||
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
|
version: 16.5.6
|
||||||
|
- name: meilisearch
|
||||||
|
repository: https://meilisearch.github.io/meilisearch-kubernetes
|
||||||
|
version: 0.12.0
|
||||||
|
digest: sha256:31084e570aa16e3a26317aeb6d0d5dec62540c314ee4f703374e6e7827399fa6
|
||||||
|
generated: "2025-03-27T11:34:51.840778733+01:00"
|
19
helm/opengist/Chart.yaml
Normal file
19
helm/opengist/Chart.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: opengist
|
||||||
|
description: Opengist Helm chart for Kubernetes
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: 1.10.0
|
||||||
|
home: https://opengist.io
|
||||||
|
icon: https://raw.githubusercontent.com/thomiceli/opengist/master/public/opengist.svg
|
||||||
|
sources:
|
||||||
|
- https://github.com/thomiceli/opengist
|
||||||
|
dependencies:
|
||||||
|
- name: postgresql
|
||||||
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
|
version: 16.5.6
|
||||||
|
condition: postgresql.enabled
|
||||||
|
- name: meilisearch
|
||||||
|
repository: https://meilisearch.github.io/meilisearch-kubernetes
|
||||||
|
version: 0.12.0
|
||||||
|
condition: meilisearch.enabled
|
81
helm/opengist/README.md
Normal file
81
helm/opengist/README.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Opengist Helm Chart
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
Opengist Helm chart for Kubernetes.
|
||||||
|
|
||||||
|
* [Install](#install)
|
||||||
|
* [Configuration](#configuration)
|
||||||
|
* [Dependencies](#dependencies)
|
||||||
|
* [Meilisearch Indexer](#meilisearch-indexer)
|
||||||
|
* [PostgreSQL Database](#postgresql-database)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add opengist https://helm.opengist.io
|
||||||
|
|
||||||
|
helm install opengist opengist/opengist
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
This part explains how to configure the Opengist instance using the Helm chart. The `config.yml` file used by Opengist
|
||||||
|
is mounted from a Kubernetes Secret with a key `config.yml` and the values formatted as YAML.
|
||||||
|
|
||||||
|
### Using values
|
||||||
|
|
||||||
|
Using Helm values, you can define the values from a key name `config`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
config:
|
||||||
|
log-level: "warn"
|
||||||
|
log-output: "stdout"
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a Kubernetes secret named `opengist` mounted to the pod as a file with the YAML content of the secret,
|
||||||
|
used by Opengist.
|
||||||
|
|
||||||
|
### Using an existing secret
|
||||||
|
|
||||||
|
If you wish to not store sensitive data in your Helm values, you can create a Kubernetes secret with a key `config.yml`
|
||||||
|
and values formatted as YAML. You can then reference this secret in the Helm chart with the `configExistingSecret` key.
|
||||||
|
|
||||||
|
If defined, this existing secret will be used instead of creating a new one.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
configExistingSecret: <name of the secret>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
### Meilisearch Indexer
|
||||||
|
|
||||||
|
By default, Opengist uses the `bleve` indexer. **It is NOT available** if there is multiple replicas of the opengist pod (only one pod can open the index at the same time).
|
||||||
|
|
||||||
|
Instead, for multiple replicas setups, you **MUST** use the `meilisearch` indexer.
|
||||||
|
|
||||||
|
By setting `meilisearch.enabled: true`, the [Meilisearch chart](https://github.com/meilisearch/meilisearch-kubernetes) will be deployed aswell.
|
||||||
|
You must define the `meilisearch.host` (Kubernetes Service) and `meilisearch.key` (value created by Meilisearch) values to connect to the Meilisearch instance in your Opengist config :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
index: meilisearch
|
||||||
|
index.meili.host: http://opengist-meilisearch:7700 # pointing to the K8S Service
|
||||||
|
index.meili.api-key: MASTER_KEY # generated by Meilisearch
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to use the `bleve` indexer, you need to set the `replicas` to `1`.
|
||||||
|
|
||||||
|
### PostgreSQL Database
|
||||||
|
|
||||||
|
By default, Opengist uses the `sqlite` database. If needed, this chart also deploys a PostgreSQL instance.
|
||||||
|
|
||||||
|
By setting `postgresql.enabled: true`, the [Bitnami PostgreSQL chart](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) will be deployed aswell.
|
||||||
|
You must define the `postgresql.host`, `postgresql.port`, `postgresql.database`, `postgresql.username` and `postgresql.password` values to connect to the PostgreSQL instance.
|
||||||
|
|
||||||
|
Then define the connection string in your Opengist config:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
db-uri: postgres://user:password@opengist-postgresql:5432/opengist
|
||||||
|
```
|
||||||
|
Note: `opengist-postgresql` is the name of the K8S Service deployed by this chart.
|
22
helm/opengist/templates/NOTES.txt
Normal file
22
helm/opengist/templates/NOTES.txt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
1. Get the application URL by running these commands:
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
{{- range $host := .Values.ingress.hosts }}
|
||||||
|
{{- range .paths }}
|
||||||
|
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if contains "NodePort" .Values.service.http.type }}
|
||||||
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "opengist.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.http.type }}
|
||||||
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
|
You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "opengist.fullname" . }}'
|
||||||
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "opengist.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||||
|
echo http://$SERVICE_IP:{{ .Values.service.http.port }}
|
||||||
|
{{- else if contains "ClusterIP" .Values.service.http.type }}
|
||||||
|
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "opengist.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||||
|
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||||
|
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||||
|
{{- end }}
|
85
helm/opengist/templates/_helpers.tpl
Normal file
85
helm/opengist/templates/_helpers.tpl
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "opengist.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).
|
||||||
|
If release name contains chart name it will be used as a full name.
|
||||||
|
*/}}
|
||||||
|
{{- define "opengist.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 "opengist.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "opengist.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "opengist.chart" . }}
|
||||||
|
app: {{ include "opengist.name" . }}
|
||||||
|
{{ include "opengist.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "opengist.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "opengist.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "opengist.serviceAccountName" -}}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "opengist.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create image URI
|
||||||
|
*/}}
|
||||||
|
{{- define "opengist.image" -}}
|
||||||
|
{{- if .Values.image.digest -}}
|
||||||
|
{{- printf "%s@%s" .Values.image.repository .Values.image.digest -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- printf "%s:%s" .Values.image.repository (.Values.image.tag | default .Chart.AppVersion) -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create secret name
|
||||||
|
*/}}
|
||||||
|
{{- define "opengist.secretName" -}}
|
||||||
|
{{- if .Values.configExistingSecret -}}
|
||||||
|
{{- printf "%s" (tpl .Values.configExistingSecret $) -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- printf "%s" (include "opengist.fullname" .) -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
115
helm/opengist/templates/deployment.yaml
Normal file
115
helm/opengist/templates/deployment.yaml
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace | default .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
{{- if .Values.deployment.labels }}
|
||||||
|
{{- toYaml .Values.deployment.labels | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.deployment.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if not .Values.autoscaling.enabled }}
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "opengist.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
checksum/config: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 8 }}
|
||||||
|
{{- with .Values.podLabels }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
serviceAccountName: {{ include "opengist.serviceAccountName" . }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
|
initContainers:
|
||||||
|
- name: init-config
|
||||||
|
image: busybox:1.37
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ['sh', '-c', 'cp /init/config/config.yml /config-volume/config.yml']
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-secret
|
||||||
|
mountPath: /init/config
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /config-volume
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.http.port }}
|
||||||
|
protocol: TCP
|
||||||
|
{{- if .Values.livenessProbe.enabled }}
|
||||||
|
livenessProbe:
|
||||||
|
{{- toYaml (omit .Values.livenessProbe "enabled") | nindent 12 }}
|
||||||
|
httpGet:
|
||||||
|
port: http
|
||||||
|
path: /healthcheck
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.readinessProbe.enabled }}
|
||||||
|
readinessProbe:
|
||||||
|
{{- toYaml (omit .Values.readinessProbe "enabled") | nindent 12 }}
|
||||||
|
httpGet:
|
||||||
|
port: http
|
||||||
|
path: /healthcheck
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /config.yml
|
||||||
|
subPath: config.yml
|
||||||
|
- name: opengist-data
|
||||||
|
mountPath: /opengist
|
||||||
|
{{- if gt (len .Values.extraVolumeMounts) 0 }}
|
||||||
|
{{- toYaml .Values.extraVolumeMounts | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: opengist-data
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "opengist.fullname" . }}-data
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
- name: config-secret
|
||||||
|
secret:
|
||||||
|
secretName: {{ include "opengist.secretName" . }}
|
||||||
|
defaultMode: 511
|
||||||
|
- name: config-volume
|
||||||
|
emptyDir: {}
|
||||||
|
{{- if gt (len .Values.extraVolumes) 0 }}
|
||||||
|
{{- toYaml .Values.extraVolumes | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
37
helm/opengist/templates/hpa.yaml
Normal file
37
helm/opengist/templates/hpa.yaml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{{- if .Values.autoscaling.enabled }}
|
||||||
|
apiVersion: autoscaling/v2
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace | default .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.autoscaling.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: {{ include "opengist.fullname" . }}
|
||||||
|
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||||
|
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||||
|
metrics:
|
||||||
|
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: cpu
|
||||||
|
target:
|
||||||
|
type: Utilization
|
||||||
|
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: memory
|
||||||
|
target:
|
||||||
|
type: Utilization
|
||||||
|
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
47
helm/opengist/templates/ingress.yaml
Normal file
47
helm/opengist/templates/ingress.yaml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace | default .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
{{- if .Values.ingress.labels }}
|
||||||
|
{{- toYaml .Values.service.http.labels | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ . }}
|
||||||
|
{{- 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:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
{{- with .pathType }}
|
||||||
|
pathType: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "opengist.fullname" $ }}-http
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.service.http.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
14
helm/opengist/templates/pdb.yaml
Normal file
14
helm/opengist/templates/pdb.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{{- if .Values.podDisruptionBudget -}}
|
||||||
|
apiVersion: policy/v1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace | default .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "opengist.selectorLabels" . | nindent 6 }}
|
||||||
|
{{- toYaml .Values.podDisruptionBudget | nindent 2 }}
|
||||||
|
{{- end -}}
|
28
helm/opengist/templates/pvc.yaml
Normal file
28
helm/opengist/templates/pvc.yaml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}-data
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- with .Values.persistence.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
{{- if .Values.persistence.labels }}
|
||||||
|
{{- toYaml .Values.persistence.labels | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
{{- if gt .Values.replicaCount 1.0 }}
|
||||||
|
- ReadWriteMany
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.persistence.accessModes | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMode: Filesystem
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass | quote }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.size }}
|
||||||
|
{{- end }}
|
13
helm/opengist/templates/secret.yaml
Normal file
13
helm/opengist/templates/secret.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{{- if (not .Values.configExistingSecret) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{ include "opengist.labels" . | indent 4 }}
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
config.yml: |-
|
||||||
|
{{- .Values.config | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
13
helm/opengist/templates/serviceaccount.yaml
Normal file
13
helm/opengist/templates/serviceaccount.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{{- if .Values.serviceAccount.create -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Values.namespace | default .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
47
helm/opengist/templates/svc-http.yaml
Normal file
47
helm/opengist/templates/svc-http.yaml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}-http
|
||||||
|
namespace: {{ .Values.namespace | default .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
{{- if .Values.service.http.labels }}
|
||||||
|
{{- toYaml .Values.service.http.labels | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.service.http.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.http.type }}
|
||||||
|
{{- if eq .Values.service.http.type "LoadBalancer" }}
|
||||||
|
{{- if and .Values.service.http.loadBalancerIP }}
|
||||||
|
loadBalancerIP: {{ .Values.service.http.loadBalancerIP }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.http.loadBalancerSourceRanges }}
|
||||||
|
loadBalancerSourceRanges:
|
||||||
|
{{- range .Values.service.http.loadBalancerSourceRanges }}
|
||||||
|
- {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.http.externalIPs }}
|
||||||
|
externalIPs:
|
||||||
|
{{- toYaml .Values.service.http.externalIPs | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.http.externalTrafficPolicy }}
|
||||||
|
externalTrafficPolicy: {{ .Values.service.http.externalTrafficPolicy }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.service.http.clusterIP (eq .Values.service.http.type "ClusterIP") }}
|
||||||
|
clusterIP: {{ .Values.service.http.clusterIP }}
|
||||||
|
{{- end }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: {{ .Values.service.http.port }}
|
||||||
|
{{- if .Values.service.http.nodePort }}
|
||||||
|
nodePort: {{ .Values.service.http.nodePort }}
|
||||||
|
{{- end }}
|
||||||
|
targetPort: {{ index .Values.config "http.port" }}
|
||||||
|
selector:
|
||||||
|
{{- include "opengist.selectorLabels" . | nindent 4 }}
|
64
helm/opengist/templates/svc-ssh.yaml
Normal file
64
helm/opengist/templates/svc-ssh.yaml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{{- if .Values.service.ssh.enabled }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "opengist.fullname" . }}-ssh
|
||||||
|
namespace: {{ .Values.namespace | default .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
{{- if .Values.service.ssh.labels }}
|
||||||
|
{{- toYaml .Values.service.ssh.labels | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.service.http.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.ssh.type }}
|
||||||
|
{{- if eq .Values.service.ssh.type "LoadBalancer" }}
|
||||||
|
{{- if .Values.service.ssh.loadBalancerClass }}
|
||||||
|
loadBalancerClass: {{ .Values.service.ssh.loadBalancerClass }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.ssh.loadBalancerIP }}
|
||||||
|
loadBalancerIP: {{ .Values.service.ssh.loadBalancerIP }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- if .Values.service.ssh.loadBalancerSourceRanges }}
|
||||||
|
loadBalancerSourceRanges:
|
||||||
|
{{- range .Values.service.ssh.loadBalancerSourceRanges }}
|
||||||
|
- {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.service.ssh.clusterIP (eq .Values.service.ssh.type "ClusterIP") }}
|
||||||
|
clusterIP: {{ .Values.service.ssh.clusterIP }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.ssh.externalIPs }}
|
||||||
|
externalIPs:
|
||||||
|
{{- toYaml .Values.service.ssh.externalIPs | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.ssh.ipFamilyPolicy }}
|
||||||
|
ipFamilyPolicy: {{ .Values.service.ssh.ipFamilyPolicy }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.service.ssh.ipFamilies }}
|
||||||
|
ipFamilies:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- if .Values.service.ssh.externalTrafficPolicy }}
|
||||||
|
externalTrafficPolicy: {{ .Values.service.ssh.externalTrafficPolicy }}
|
||||||
|
{{- end }}
|
||||||
|
ports:
|
||||||
|
- name: ssh
|
||||||
|
port: {{ .Values.service.ssh.port }}
|
||||||
|
{{- if .Values.service.ssh.nodePort }}
|
||||||
|
nodePort: {{ .Values.service.ssh.nodePort }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if index .Values.config "ssh.port" }}
|
||||||
|
targetPort: {{ index .Values.config "ssh.port" }}
|
||||||
|
{{- else }}
|
||||||
|
targetPort: 2222
|
||||||
|
{{- end }}
|
||||||
|
protocol: TCP
|
||||||
|
|
||||||
|
selector:
|
||||||
|
{{- include "opengist.selectorLabels" . | nindent 4 }}
|
||||||
|
{{- end }}
|
15
helm/opengist/templates/tests/test-connection.yaml
Normal file
15
helm/opengist/templates/tests/test-connection.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: "{{ include "opengist.fullname" . }}-test-connection"
|
||||||
|
labels:
|
||||||
|
{{- include "opengist.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
"helm.sh/hook": test
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: wget
|
||||||
|
image: busybox
|
||||||
|
command: ['wget']
|
||||||
|
args: ['{{ include "opengist.fullname" . }}:{{ .Values.service.port }}']
|
||||||
|
restartPolicy: Never
|
201
helm/opengist/values.yaml
Normal file
201
helm/opengist/values.yaml
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
## Kubernetes workload configuration for Opengist
|
||||||
|
nameOverride: ""
|
||||||
|
fullnameOverride: ""
|
||||||
|
namespace: ""
|
||||||
|
|
||||||
|
## Opengist YAML Application Config. See more at https://opengist.io/docs/configuration/cheat-sheet.html
|
||||||
|
## This will create a Kubernetes secret with the key `config.yml` containing the YAML configuration mounted in the pod.
|
||||||
|
config:
|
||||||
|
log-level: "warn"
|
||||||
|
log-output: "stdout"
|
||||||
|
|
||||||
|
## If defined, the existing secret will be used instead of creating a new one.
|
||||||
|
## The secret must contain a key named `config.yml` with the YAML configuration.
|
||||||
|
configExistingSecret: ""
|
||||||
|
|
||||||
|
## Define the image repository and tag to use.
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/thomiceli/opengist
|
||||||
|
pullPolicy: Always
|
||||||
|
tag: "1.10.0"
|
||||||
|
digest: ""
|
||||||
|
imagePullSecrets: []
|
||||||
|
# - name: "image-pull-secret"
|
||||||
|
|
||||||
|
## Define the deployment replica count
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
## Define the deployment strategy type
|
||||||
|
strategy:
|
||||||
|
type: "RollingUpdate"
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: "100%"
|
||||||
|
maxUnavailable: 0
|
||||||
|
|
||||||
|
## Security Context settings
|
||||||
|
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
securityContext: {}
|
||||||
|
# allowPrivilegeEscalation: false
|
||||||
|
|
||||||
|
## Pod Disruption Budget settings
|
||||||
|
## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
|
||||||
|
podDisruptionBudget: {}
|
||||||
|
# maxUnavailable: 1
|
||||||
|
# minAvailable: 1
|
||||||
|
|
||||||
|
## Set the Kubernetes service type
|
||||||
|
## ref: https://kubernetes.io/docs/concepts/services-networking/service/
|
||||||
|
service:
|
||||||
|
http:
|
||||||
|
type: ClusterIP
|
||||||
|
clusterIP:
|
||||||
|
port: 6157
|
||||||
|
nodePort:
|
||||||
|
loadBalancerIP:
|
||||||
|
externalIPs: []
|
||||||
|
labels: {}
|
||||||
|
annotations: {}
|
||||||
|
loadBalancerSourceRanges: []
|
||||||
|
externalTrafficPolicy:
|
||||||
|
|
||||||
|
ssh:
|
||||||
|
enabled: true
|
||||||
|
type: ClusterIP
|
||||||
|
clusterIP:
|
||||||
|
port: 2222
|
||||||
|
nodePort:
|
||||||
|
loadBalancerIP:
|
||||||
|
externalIPs: []
|
||||||
|
labels: {}
|
||||||
|
annotations: {}
|
||||||
|
loadBalancerSourceRanges: []
|
||||||
|
externalTrafficPolicy:
|
||||||
|
|
||||||
|
## HTTP Ingress for Opengist
|
||||||
|
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: ""
|
||||||
|
labels: {}
|
||||||
|
# node-role.kubernetes.io/ingress: platform
|
||||||
|
annotations: {}
|
||||||
|
# kubernetes.io/ingress.class: nginx
|
||||||
|
hosts:
|
||||||
|
- host: opengist.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls: []
|
||||||
|
# - secretName: opengist-tls
|
||||||
|
# hosts:
|
||||||
|
# - opengist.example.com
|
||||||
|
|
||||||
|
## Service Account for Opengist pods
|
||||||
|
## ref: https://kubernetes.io/docs/concepts/security/service-accounts/
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
annotations: {}
|
||||||
|
name: ""
|
||||||
|
|
||||||
|
## Set persistence using a Persistent Volume Claim
|
||||||
|
## If more than 2 replicas are set, the access mode must be ReadWriteMany
|
||||||
|
## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
existingClaim: ""
|
||||||
|
storageClass: ""
|
||||||
|
labels: {}
|
||||||
|
annotations:
|
||||||
|
helm.sh/resource-policy: keep
|
||||||
|
size: 5Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
subPath: ""
|
||||||
|
|
||||||
|
extraVolumes: []
|
||||||
|
extraVolumeMounts: []
|
||||||
|
|
||||||
|
## Additional pod labels and annotations
|
||||||
|
podLabels: {}
|
||||||
|
podAnnotations: {}
|
||||||
|
|
||||||
|
## Configure resource requests and limits
|
||||||
|
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||||
|
resources: {}
|
||||||
|
# limits:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
|
# requests:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
|
|
||||||
|
|
||||||
|
## Configure the liveness and readiness probes
|
||||||
|
## ref: https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/
|
||||||
|
livenessProbe:
|
||||||
|
enabled: true
|
||||||
|
initialDelaySeconds: 200
|
||||||
|
timeoutSeconds: 1
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 5
|
||||||
|
|
||||||
|
readinessProbe:
|
||||||
|
enabled: true
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
timeoutSeconds: 1
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 3
|
||||||
|
|
||||||
|
## Define autoscaling configuration using Horizontal Pod Autoscaler
|
||||||
|
## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
|
||||||
|
autoscaling:
|
||||||
|
enabled: false
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 10
|
||||||
|
targetCPUUtilizationPercentage: 80
|
||||||
|
# targetMemoryUtilizationPercentage: 80
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
## Additional deployment configuration
|
||||||
|
deployment:
|
||||||
|
env: []
|
||||||
|
terminationGracePeriodSeconds: 60
|
||||||
|
labels: {}
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
## Set pod assignment with node labels
|
||||||
|
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
|
||||||
|
nodeSelector: {}
|
||||||
|
tolerations: []
|
||||||
|
affinity: {}
|
||||||
|
|
||||||
|
## Use PostgreSQL as a database, using Bitnami's PostgreSQL Helm chart
|
||||||
|
## ref: https://artifacthub.io/packages/helm/bitnami/postgresql/16.5.6
|
||||||
|
postgresql:
|
||||||
|
enabled: false
|
||||||
|
global:
|
||||||
|
postgresql:
|
||||||
|
auth:
|
||||||
|
username: opengist
|
||||||
|
password: opengist
|
||||||
|
database: opengist
|
||||||
|
service:
|
||||||
|
ports:
|
||||||
|
postgresql: 5432
|
||||||
|
primary:
|
||||||
|
persistence:
|
||||||
|
size: 10Gi
|
||||||
|
|
||||||
|
|
||||||
|
## Use Meilisearch as a code indexer, using Meilisearch's Helm chart
|
||||||
|
## ref: https://github.com/meilisearch/meilisearch-kubernetes/tree/meilisearch-0.12.0
|
||||||
|
meilisearch:
|
||||||
|
enabled: false
|
||||||
|
environment:
|
||||||
|
MEILI_ENV: "production"
|
||||||
|
auth:
|
||||||
|
existingMasterKeySecret:
|
@ -126,7 +126,7 @@ func Initialize(ctx *cli.Context) {
|
|||||||
|
|
||||||
index.DepreactionIndexDirname()
|
index.DepreactionIndexDirname()
|
||||||
if index.IndexEnabled() {
|
if index.IndexEnabled() {
|
||||||
index.NewIndexer(index.IndexType())
|
go index.NewIndexer(index.IndexType())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,16 +22,23 @@ func NewBleveIndexer(path string) *BleveIndexer {
|
|||||||
return &BleveIndexer{path: path}
|
return &BleveIndexer{path: path}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *BleveIndexer) Init() {
|
func (i *BleveIndexer) Init() error {
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
bleveIndex, err := i.open()
|
bleveIndex, err := i.open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Failed to open Bleve index")
|
log.Error().Err(err).Msg("Failed to open Bleve index")
|
||||||
i.Close()
|
i.Close()
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
i.index = bleveIndex
|
i.index = bleveIndex
|
||||||
log.Info().Msg("Bleve indexer initialized")
|
log.Info().Msg("Bleve indexer initialized")
|
||||||
|
errChan <- nil
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
return <-errChan
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *BleveIndexer) open() (bleve.Index, error) {
|
func (i *BleveIndexer) open() (bleve.Index, error) {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
var atomicIndexer atomic.Pointer[Indexer]
|
var atomicIndexer atomic.Pointer[Indexer]
|
||||||
|
|
||||||
type Indexer interface {
|
type Indexer interface {
|
||||||
Init()
|
Init() error
|
||||||
Close()
|
Close()
|
||||||
Add(gist *Gist) error
|
Add(gist *Gist) error
|
||||||
Remove(gistID uint) error
|
Remove(gistID uint) error
|
||||||
@ -64,7 +64,9 @@ func NewIndexer(idxType IndexerType) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
idx.Init()
|
if err := idx.Init(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
atomicIndexer.Store(&idx)
|
atomicIndexer.Store(&idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,12 +75,12 @@ func Close() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
idx := *atomicIndexer.Load()
|
idx := atomicIndexer.Load()
|
||||||
if idx == nil {
|
if idx == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
idx.Close()
|
(*idx).Close()
|
||||||
atomicIndexer.Store(nil)
|
atomicIndexer.Store(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,12 +89,12 @@ func AddInIndex(gist *Gist) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
idx := *atomicIndexer.Load()
|
idx := atomicIndexer.Load()
|
||||||
if idx == nil {
|
if idx == nil {
|
||||||
return fmt.Errorf("indexer is not initialized")
|
return fmt.Errorf("indexer is not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx.Add(gist)
|
return (*idx).Add(gist)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveFromIndex(gistID uint) error {
|
func RemoveFromIndex(gistID uint) error {
|
||||||
@ -100,12 +102,12 @@ func RemoveFromIndex(gistID uint) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
idx := *atomicIndexer.Load()
|
idx := atomicIndexer.Load()
|
||||||
if idx == nil {
|
if idx == nil {
|
||||||
return fmt.Errorf("indexer is not initialized")
|
return fmt.Errorf("indexer is not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx.Remove(gistID)
|
return (*idx).Remove(gistID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SearchGists(query string, metadata SearchGistMetadata, userId uint, page int) ([]uint, uint64, map[string]int, error) {
|
func SearchGists(query string, metadata SearchGistMetadata, userId uint, page int) ([]uint, uint64, map[string]int, error) {
|
||||||
@ -113,12 +115,12 @@ func SearchGists(query string, metadata SearchGistMetadata, userId uint, page in
|
|||||||
return nil, 0, nil, nil
|
return nil, 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
idx := *atomicIndexer.Load()
|
idx := atomicIndexer.Load()
|
||||||
if idx == nil {
|
if idx == nil {
|
||||||
return nil, 0, nil, fmt.Errorf("indexer is not initialized")
|
return nil, 0, nil, fmt.Errorf("indexer is not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx.Search(query, metadata, userId, page)
|
return (*idx).Search(query, metadata, userId, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DepreactionIndexDirname() {
|
func DepreactionIndexDirname() {
|
||||||
|
@ -25,29 +25,34 @@ func NewMeiliIndexer(host, apikey, indexName string) *MeiliIndexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *MeiliIndexer) Init() {
|
func (i *MeiliIndexer) Init() error {
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
meiliIndex, err := i.open()
|
meiliIndex, err := i.open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Failed to open Meilisearch index")
|
log.Error().Err(err).Msg("Failed to open Meilisearch index")
|
||||||
i.Close()
|
i.Close()
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
i.index = meiliIndex
|
i.index = meiliIndex
|
||||||
log.Info().Msg("Meilisearch indexer initialized")
|
log.Info().Msg("Meilisearch indexer initialized")
|
||||||
|
errChan <- nil
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
return <-errChan
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *MeiliIndexer) open() (meilisearch.IndexManager, error) {
|
func (i *MeiliIndexer) open() (meilisearch.IndexManager, error) {
|
||||||
client := meilisearch.New(i.host, meilisearch.WithAPIKey(i.apikey))
|
i.client = meilisearch.New(i.host, meilisearch.WithAPIKey(i.apikey))
|
||||||
indexResult, err := client.GetIndex(i.indexName)
|
indexResult, err := i.client.GetIndex(i.indexName)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if indexResult != nil {
|
if indexResult != nil && err == nil {
|
||||||
return indexResult.IndexManager, nil
|
return indexResult.IndexManager, nil
|
||||||
}
|
}
|
||||||
_, err = client.CreateIndex(&meilisearch.IndexConfig{
|
|
||||||
|
_, err = i.client.CreateIndex(&meilisearch.IndexConfig{
|
||||||
Uid: i.indexName,
|
Uid: i.indexName,
|
||||||
PrimaryKey: "GistID",
|
PrimaryKey: "GistID",
|
||||||
})
|
})
|
||||||
@ -55,14 +60,14 @@ func (i *MeiliIndexer) open() (meilisearch.IndexManager, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = client.Index(i.indexName).UpdateSettings(&meilisearch.Settings{
|
_, _ = i.client.Index(i.indexName).UpdateSettings(&meilisearch.Settings{
|
||||||
FilterableAttributes: []string{"GistID", "UserID", "Visibility", "Username", "Title", "Filenames", "Extensions", "Languages", "Topics"},
|
FilterableAttributes: []string{"GistID", "UserID", "Visibility", "Username", "Title", "Filenames", "Extensions", "Languages", "Topics"},
|
||||||
DisplayedAttributes: []string{"GistID"},
|
DisplayedAttributes: []string{"GistID"},
|
||||||
SearchableAttributes: []string{"Content", "Username", "Title", "Filenames", "Extensions", "Languages", "Topics"},
|
SearchableAttributes: []string{"Content", "Username", "Title", "Filenames", "Extensions", "Languages", "Topics"},
|
||||||
RankingRules: []string{"words"},
|
RankingRules: []string{"words"},
|
||||||
})
|
})
|
||||||
|
|
||||||
return client.Index(i.indexName), nil
|
return i.client.Index(i.indexName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *MeiliIndexer) Close() {
|
func (i *MeiliIndexer) Close() {
|
||||||
|
Reference in New Issue
Block a user