diff --git a/README.md b/README.md index 9a66c515e65863da14914377e43f02af8d2b85a9..b66f01cf3a63fbbb3683e494876588ed192805a8 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ Note that this program prefers to quit on errors it can not recover from, so set The memory usage of the container is around 50MB when idle and can quickly spike to 250MB on heavy use. The process startup time for a single request is a few milliseconds and negligible in comparison to processing the CAS request itself. +For advanced users, one can also deploy the image in kubernetes by using the helm chart provided in the `helmmaxima` directory. + Environment Variables ===================== A few internal options can be set from environment variables. diff --git a/helmmaxima/Chart.yaml b/helmmaxima/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..293e2de93680096e8eac82ca8c8eab6e398a560c --- /dev/null +++ b/helmmaxima/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: helmgomaxima +description: Helm Chart for go maximapool + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 1.1.4 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: 1.1.4 diff --git a/helmmaxima/README.md b/helmmaxima/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f74cd92b6962b02f9b72c348f5057489a1cc9600 --- /dev/null +++ b/helmmaxima/README.md @@ -0,0 +1,16 @@ +Helm Chart for `goemaxima` +========================== + +This is a helm chart for deploying goemaxima to kubernetes. +It includes an autoscaler that automatically adds goemaxima instances on high load. + +An example value file is provided in `example.yaml`. +After setting the version and url in `example.yaml`, it can be deployed with [helm](https://helm.sh/) by running + +``` +helm install -f example.yaml goemaxima-example . +``` + +in this directory. + +For more configuration options, see also the values.yaml file. diff --git a/helmmaxima/example.yaml b/helmmaxima/example.yaml new file mode 100644 index 0000000000000000000000000000000000000000..48dec4fcc096c8348ea381c187a811d8497f7eb7 --- /dev/null +++ b/helmmaxima/example.yaml @@ -0,0 +1,9 @@ +--- +stackver: "2021120900" +ingress: + hosts: + - host: "maxima.example.com" + paths: + - path: "/goemaxima" + pathType: Prefix + diff --git a/helmmaxima/templates/_helpers.tpl b/helmmaxima/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..9ec4c306046e11ba531da77cb7b5706a8cb60f49 --- /dev/null +++ b/helmmaxima/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "helmmaxima.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 "helmmaxima.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 "helmmaxima.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "helmmaxima.labels" -}} +helm.sh/chart: {{ include "helmmaxima.chart" . }} +{{ include "helmmaxima.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "helmmaxima.selectorLabels" -}} +app.kubernetes.io/name: {{ include "helmmaxima.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "helmmaxima.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "helmmaxima.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/helmmaxima/templates/autoscaler.yaml b/helmmaxima/templates/autoscaler.yaml new file mode 100644 index 0000000000000000000000000000000000000000..41b0f58f4369d4039f7b4f3b9f5979e6224dfc13 --- /dev/null +++ b/helmmaxima/templates/autoscaler.yaml @@ -0,0 +1,12 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "helmmaxima.fullname" . }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "helmmaxima.fullname" . }} + minReplicas: {{ .Values.scaleMin }} + maxReplicas: {{ .Values.scaleMax }} + targetCPUUtilizationPercentage: {{ .Values.scalePercentage }} diff --git a/helmmaxima/templates/deployment.yaml b/helmmaxima/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4af9b554e9c059a3bcedea98a4164e0729bf5094 --- /dev/null +++ b/helmmaxima/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "helmmaxima.fullname" . }} + labels: + {{- include "helmmaxima.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "helmmaxima.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "helmmaxima.selectorLabels" . | nindent 8 }} + app: {{ include "helmmaxima.fullname" . }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + automountServiceAccountToken: false + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.image_prefix }}:{{ .Values.stackver }}-{{ .Values.tagappend | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 8080 + protocol: TCP + volumeMounts: + - mountPath: /tmp + name: tmptmpfs + livenessProbe: + httpGet: + path: '/maxima?health=1' + port: http + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: '/maxima?health=1' + port: http + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 3 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: tmptmpfs + emptyDir: + medium: "Memory" + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helmmaxima/templates/ingress.yaml b/helmmaxima/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dadfa5815c06f2629de82029ce7b9c0b4bfe2f0b --- /dev/null +++ b/helmmaxima/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "helmmaxima.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "helmmaxima.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + 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: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helmmaxima/templates/monitor.yaml b/helmmaxima/templates/monitor.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0a5c7c320fcdcf464d2a413e9f931a3ab641842d --- /dev/null +++ b/helmmaxima/templates/monitor.yaml @@ -0,0 +1,12 @@ +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "helmmaxima.fullname" . }} +spec: + selector: + matchLabels: + app: {{ include "helmmaxima.fullname" . }} + endpoints: + - port: http + interval: 60s + diff --git a/helmmaxima/templates/network.yaml b/helmmaxima/templates/network.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ba84ae6b7c5f64e22c53fb0d975ba7a0517998c6 --- /dev/null +++ b/helmmaxima/templates/network.yaml @@ -0,0 +1,11 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "helmmaxima.fullname" . }} +spec: + podSelector: + matchLabels: + app: {{ include "helmmaxima.fullname" . }} + # block all egress traffic + policyTypes: + - Egress diff --git a/helmmaxima/templates/service.yaml b/helmmaxima/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..021f870d4a670f1e7ce9ac18b3f1300f2a0bce9f --- /dev/null +++ b/helmmaxima/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "helmmaxima.fullname" . }} + labels: + {{- include "helmmaxima.labels" . | nindent 4 }} + app: {{ include "helmmaxima.fullname" . }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "helmmaxima.selectorLabels" . | nindent 4 }} diff --git a/helmmaxima/values.yaml b/helmmaxima/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1696f035af8239c5b1328a64d13a7634804c4739 --- /dev/null +++ b/helmmaxima/values.yaml @@ -0,0 +1,66 @@ +# Default values for helmmaxima. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 3 + +scalePercentage: 40 +scaleMin: 3 +scaleMax: 32 + +image: + image_prefix: mathinstitut/goemaxima + pullPolicy: Always + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +podSecurityContext: {} + +securityContext: + capabilities: + add: + - CHOWN + - DAC_OVERRIDE + - SETGID + - SETUID + - KILL + drop: + - ALL + readOnlyRootFilesystem: true + +service: + type: ClusterIP + port: 80 + targetPort: 8080 + +ingress: + enabled: true + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: /goemaxima + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + +resources: + limits: + memory: 512Mi + requests: + cpu: 1000m + memory: 256Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {}