diff --git a/charts/helm3/octopod/.helmignore b/charts/helm3/octopod/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/helm3/octopod/.helmignore @@ -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/ diff --git a/charts/helm3/octopod/Chart.lock b/charts/helm3/octopod/Chart.lock new file mode 100644 index 0000000..df0840a --- /dev/null +++ b/charts/helm3/octopod/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 10.4.2 +digest: sha256:616138842fd07e138b0e8d6b7dac7989942b01a94967c37ca41c94e3fe93e9e4 +generated: "2021-05-07T21:02:01.403373727+03:00" diff --git a/charts/helm3/octopod/Chart.yaml b/charts/helm3/octopod/Chart.yaml new file mode 100644 index 0000000..6de3ac1 --- /dev/null +++ b/charts/helm3/octopod/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v2 +name: octopod +description: An opensource self-hosted solution for managing multiple deployments in a Kubernetes cluster. +type: application +version: 0.0.1 +appVersion: 1.1 +keywords: + - kubernetes + - octopod +home: https://octopod.site +sources: + - https://github.com/typeable/octopod +maintainers: + - name: Alex Sizov + email: a.sizov@typeable.io +dependencies: + - name: postgresql + version: 10.4.2 + repository: https://charts.bitnami.com/bitnami + condition: postgresql.enabled diff --git a/charts/helm3/octopod/README.md b/charts/helm3/octopod/README.md new file mode 100644 index 0000000..e486944 --- /dev/null +++ b/charts/helm3/octopod/README.md @@ -0,0 +1,158 @@ +# Octopod + +### This is beta version of a chart! + +[Octopod](https://octopod.site/) is a fully open-source self-hosted solution for managing multiple deployments in a Kubernetes cluster with a user-friendly web interface. Managing deployments does not require any technical expertise. + +## TL;DR +TBD (install chart from typeable's chart repository) + +## Introduction + +This chart bootstraps an Octopod deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.12+ +- Helm 3.1.0 +- PV support (for postgresql persistense) +- nginx-ingress controller + +## Installing the Chart +This chart will not create or delete any namespaces for you. +You'll need to create 2 namespaces before installing: +First in which octopod will be installed +```console +$ kubectl create namespace octopod +``` +Second in which Octopod will deploy all it's deployments (configured in octopod.deploymentNamespace) +```console +$ kubectl create namespace octopod-deployments +``` +Also you need to generate certificates for octo client<->octopod server communication. + +Generate certificates +```bash +mkdir certs +cd certs && \ +openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -nodes -subj "/CN=localhost/O=Server" && \ +openssl req -newkey rsa:4096 -keyout client_key.pem -out client_csr.pem -nodes -subj "/CN=Client" && \ +openssl x509 -req -in client_csr.pem -CA server_cert.pem -CAkey server_key.pem -out client_cert.pem -set_serial 01 -days 3650 + +``` +Create configmap from generated certificates +```console +kubectl create configmap octopod-certs -n octopod --from-file=./certs +``` +Name for configmap is cofigured in octopod.certsConfigMapName +To install the chart with the release name `my-release` from current directory execute: + +```console +$ helm dependency build +$ helm -n octopod install my-release . +``` + +The command deploys Octopod on the Kubernetes cluster in the default configuration inside octopod namespace. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +$ helm -n octopod delete my-release +``` + +The command removes all the Kubernetes components but PVC's associated with the postgres chart and deletes the release. + +## Parameters + +The following tables lists the configurable parameters of the Octopod chart and their default values. + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Octopod deployment affinity | +| controlScripts.image.pullPolicy | string | `"IfNotPresent"` | control scripts image pull policy | +| controlScripts.image.repository | string | `"typeable/octopod-helm-example"` | Control scripts image repository (you probably want to use your own control scripts) | +| controlScripts.image.tag | float | `1.1` | Control scitpts image tag | +| fullnameOverride | string | `""` | Override chart full name | +| image.pullPolicy | string | `"IfNotPresent"` | Octopod image pull policy | +| image.repository | string | `"typeable/octopod"` | Octopod image repository | +| image.tag | string | `""` | Octopod image tag (default values is taken from chart metadata) | +| imagePullSecrets | list | `[]` | Pull secrets if you want to use private registry | +| ingress.app.annotations | object | `{}` | Additional ingress annotations for app service | +| ingress.app.host | string | `"octopod-app.example.com"` | Hostname for app service | +| ingress.enabled | bool | `true` | Create ingress objects or not | +| ingress.ingressClass | string | `"nginx"` | Ingress class | +| ingress.powerApp.annotations | object | `{}` | Additional ingress annotations for power-app service | +| ingress.powerApp.host | string | `"octopod-powerapp.example.com"` | Hostname for power-app | +| ingress.tls.clusterIssuer | string | `"letsencrypt"` | Name of cluster issuer you want to use | +| ingress.tls.enabled | bool | `true` | Use https for all services | +| ingress.ui.annotations | object | `{}` | Additional ingress annotations for ui service | +| ingress.ui.host | string | `"octopod.example.com"` | Hostname for main UI | +| ingress.ws.annotations | object | `{}` | Additional ingress annotations for ws service | +| ingress.ws.host | string | `"octopod-ws.example.com"` | Hostname for websockets ingress | +| nameOverride | string | `""` | Name ovveride (default is Release.Name) | +| nodeSelector | object | `{}` | Node selector if you want octopod to use specific nodes onn your cluster | +| octopod.archiveRetention | int | `1209600` | | +| octopod.baseDomain | string | `""` | Domain that will be used as a ase for Octopod deploymets | +| octopod.certsConfigMapName | string | `"octopod-certs"` | Config map with self-signed certificates | +| octopod.deploymentNamespace | string | `"octopod-deployment"` | Name of a namespace which will be used for all Octopod deployments (you need to create it yourself) | +| octopod.migrations.enabled | bool | `true` | Enable or not automatic DB schema migrations | +| octopod.projectName | string | `"Octopod"` | Project name | +| octopod.statusUpdateTimeout | int | `600` | Time to wait before deployment is marked as failed | +| podAnnotations | object | `{}` | Additional pod annotations | +| podSecurityContext | object | `{}` | Additional security context | +| postgresql.enabled | bool | `true` | Use bitnami postgres chart | +| postgresql.postgresqlDatabase | string | `"octopod"` | Database name for octopod | +| postgresql.postgresqlUsername | string | `"octopod"` | Octopod DB username | +| rbac.create | bool | `true` | Creates ClusterRoles and Bindings for Octopod service account | +| replicaCount | int | `1` | Number of Octopod replicas | +| resources.limits.cpu | string | `"200m"` | CPU limits | +| resources.limits.memory | string | `"512Mi"` | Memory limits | +| resources.requests.cpu | string | `"200m"` | CPU requests | +| resources.requests.memory | string | `"256Mi"` | Memory requests | +| securityContext.runAsGroup | int | `1000` | Use non-root GID | +| securityContext.runAsUser | int | `1000` | Use non-root UID | +| service.ports.app | int | `4000` | App service port | +| service.ports.powerApp | int | `4443` | Power app service port | +| service.ports.ui | int | `80` | UI service port | +| service.ports.ws | int | `4020` | WebSockets service port | +| service.type | string | `"ClusterIP"` | Octopod service type | +| serviceAccount.annotations | object | `{}` | Additional anotations for Octopod's SA | +| serviceAccount.create | bool | `true` | Create ServiceAccount | +| serviceAccount.name | string | `""` | ServiceAccount name override | +| sqitch.image.pullPolicy | string | `"IfNotPresent"` | squitch image pull policy | +| sqitch.image.repository | string | `"typeable/sqitch"` | squitch image repository | +| sqitch.image.tag | string | `"v2.0.0"` | squitch image tag | +| tolerations | list | `[]` | Octpod deploymet tolerations | + + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +$ helm -n octopod install my-release \ + --set controlScripts.image.repository=registry.example.com/control,controlScripts.image.tag=0.0.1 \ + . +``` + +The above command sets control scripts image to your custom repository + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +$ helm install my-release -f values.yaml . +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Configuration and installation details + +If you want to have authentication for Octopod UI you can use project like [Oauth2-Proxy](https://github.com/oauth2-proxy/oauth2-proxy) or directly use your oauth provider. +After that you can add following annotations to UI ingress (considering that your oauth provider installed on oath.example.com): +```yaml +ingress: + ui: + annotations: + nginx.ingress.kubernetes.io/auth-url: "https://oauth.example.com/oauth2/auth" + nginx.ingress.kubernetes.io/auth-signin: "https://oauth.example.com/oauth2/start?rd=/redirect/$http_host$request_uri" +``` diff --git a/charts/helm3/octopod/templates/_helpers.tpl b/charts/helm3/octopod/templates/_helpers.tpl new file mode 100644 index 0000000..3216ee2 --- /dev/null +++ b/charts/helm3/octopod/templates/_helpers.tpl @@ -0,0 +1,98 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "octopod.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 "octopod.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 "octopod.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "octopod.labels" -}} +helm.sh/chart: {{ include "octopod.chart" . }} +{{ include "octopod.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "octopod.selectorLabels" -}} +app.kubernetes.io/name: {{ include "octopod.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "octopod.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "octopod.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "controlScriptsPath" -}} +/utils +{{- end }} + +{{- define "octopodAppAuthSecretName" -}} +{{- printf "%s-app-auth-secret" (include "octopod.fullname" .) }} +{{- end }} + +{{- define "octopodAppAuthPassword" -}} +{{- randAlphaNum 32 }} +{{- end }} + +{{- define "httpScheme" -}} +{{- if .Values.ingress.tls.enabled -}} +https +{{- else -}} +http +{{- end }} +{{- end }} + +{{- define "wsScheme" -}} +{{- if .Values.ingress.tls.enabled -}} +wss +{{- else -}} +ws +{{- end }} +{{- end }} + +{{- define "postgresqlHost" -}} +{{ .Release.Name }}-postgresql +{{- end }} + +{{- define "postgresqlSecretName" -}} +{{ .Release.Name }}-postgresql +{{- end }} diff --git a/charts/helm3/octopod/templates/deployment.yaml b/charts/helm3/octopod/templates/deployment.yaml new file mode 100644 index 0000000..39f2e81 --- /dev/null +++ b/charts/helm3/octopod/templates/deployment.yaml @@ -0,0 +1,163 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "octopod.fullname" . }} + labels: + {{- include "octopod.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "octopod.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "octopod.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "octopod.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + - name: copy-control-scripts + image: "{{ .Values.controlScripts.image.repository }}:{{ .Values.controlScripts.image.tag }}" + imagePullPolicy: {{ .Values.controlScripts.image.pullPolicy }} + command: + - sh + - -c + - 'cp /utils/* /copy/' + volumeMounts: + - name: control-scripts + mountPath: /copy + + - name: run-init + image: typeable/octopod:1.1 + command: + - sh + - -c + - '/utils/init' + volumeMounts: + - name: home + mountPath: /home/octopod + - name: control-scripts + mountPath: {{ include "controlScriptsPath" . }} + - name: copy-www + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + command: + - sh + - -c + - | + set -ex + cp -a /www/* /copy/ + find /www -type f -exec touch {} + + volumeMounts: + - name: www + mountPath: /copy + containers: + - name: octopod + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: 4443 + protocol: TCP + - containerPort: 4000 + protocol: TCP + args: + - --port + - {{ .Values.service.ports.powerApp | quote }} + - --ui-port + - {{ .Values.service.ports.app | quote }} + - --ws-port + - {{ .Values.service.ports.ws | quote }} + - --db + - host='{{ include "postgresqlHost" . }}' port=5432 user='{{ .Values.postgresql.postgresqlUsername }}' password=$(PG_PASS) + - --db-pool-size + - "10" + - --tls-cert-path + - /tls/server_cert.pem + - --tls-key-path + - /tls/server_key.pem + - --tls-store-path + - /tls_store + envFrom: + - configMapRef: + name: {{ include "octopod.fullname" . }} + env: + - name: PG_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresqlSecretName" . }} + key: postgresql-password + volumeMounts: + - name: home + mountPath: /home/octopod + - name: control-scripts + mountPath: {{ include "controlScriptsPath" . }} + - name: certs + mountPath: /tls/server_cert.pem + subPath: server_cert.pem + - name: certs + mountPath: /tls/server_key.pem + subPath: server_key.pem + - name: certs + mountPath: /tls_store/server_cert.pem + subPath: server_cert.pem + readinessProbe: + httpGet: + port: {{ .Values.service.ports.app }} + path: /api/v1/ping + periodSeconds: 20 + livenessProbe: + httpGet: + port: {{ .Values.service.ports.app }} + path: /api/v1/ping + initialDelaySeconds: 15 + periodSeconds: 5 + resources: + {{- toYaml .Values.resources | nindent 12 }} + - name: nginx + image: nginx:1.17.5 + volumeMounts: + - name: nginx-config + mountPath: /etc/nginx/conf.d/app.conf + subPath: app.conf + - name: nginx-config + mountPath: /www/config.json + subPath: config.json + - name: www + mountPath: /www + ports: + - containerPort: {{ .Values.service.ports.ui }} + protocol: TCP + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: home + emptyDir: {} + - name: control-scripts + emptyDir: {} + - name: www + emptyDir: {} + - name: nginx-config + configMap: + name: {{ include "octopod.fullname" . }}-nginx-config + - name: certs + configMap: + name: {{ .Values.octopod.certsConfigMapName }} diff --git a/charts/helm3/octopod/templates/ingress-app.yaml b/charts/helm3/octopod/templates/ingress-app.yaml new file mode 100644 index 0000000..250e2ad --- /dev/null +++ b/charts/helm3/octopod/templates/ingress-app.yaml @@ -0,0 +1,47 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "octopod.fullname" . -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-app + labels: + {{- include "octopod.labels" . | nindent 4 }} + annotations: + {{- if .Values.ingress.tls.enabled }} + kubernetes.io/tls-acme: "true" + cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.clusterIssuer | quote }} + {{- end }} + kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }} + nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout" + nginx.ingress.kubernetes.io/auth-secret: {{ include "octopodAppAuthSecretName" . }} + nginx.ingress.kubernetes.io/auth-secret-type: auth-file + nginx.ingress.kubernetes.io/auth-type: basic + nginx.ingress.kubernetes.io/enable-cors: "true" + nginx.ingress.kubernetes.io/cors-allow-origin: {{ printf "%s://%s" (include "httpScheme" .) .Values.ingress.ui.host | quote }} + nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, PATCH, OPTIONS" + {{- with .Values.ingress.app.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.app.host }} + secretName: {{ $fullName }}-app-tls + {{- end }} + rules: + - host: {{ .Values.ingress.app.host | quote }} + http: + paths: + - path: / + backend: + serviceName: {{ $fullName }} + servicePort: {{ .Values.service.ports.app }} +{{- end }} diff --git a/charts/helm3/octopod/templates/ingress-powerapp.yaml b/charts/helm3/octopod/templates/ingress-powerapp.yaml new file mode 100644 index 0000000..91fc0d8 --- /dev/null +++ b/charts/helm3/octopod/templates/ingress-powerapp.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "octopod.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-powerapp + labels: + {{- include "octopod.labels" . | nindent 4 }} + annotations: + kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }} + nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout" + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + {{- with .Values.ingress.powerApp.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.tls }} + tls: + - hosts: + - {{ .Values.ingress.powerApp.host }} + secretName: {{ $fullName }}-powerapp-tls + {{- end }} + rules: + - host: {{ .Values.ingress.powerApp.host | quote }} + http: + paths: + - path: / + backend: + serviceName: {{ $fullName }} + servicePort: {{ .Values.service.ports.powerApp }} +{{- end }} diff --git a/charts/helm3/octopod/templates/ingress-ui.yaml b/charts/helm3/octopod/templates/ingress-ui.yaml new file mode 100644 index 0000000..3562e60 --- /dev/null +++ b/charts/helm3/octopod/templates/ingress-ui.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "octopod.fullname" . -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-ui + labels: + {{- include "octopod.labels" . | nindent 4 }} + annotations: + {{- if .Values.ingress.tls.enabled }} + kubernetes.io/tls-acme: "true" + cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.clusterIssuer | quote }} + {{- end }} + kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }} + nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout" + {{- with .Values.ingress.ui.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.ui.host }} + secretName: {{ $fullName }}-ui-tls + {{- end }} + rules: + - host: {{ .Values.ingress.ui.host | quote }} + http: + paths: + - path: / + backend: + serviceName: {{ $fullName }} + servicePort: {{ .Values.service.ports.ui }} +{{- end }} diff --git a/charts/helm3/octopod/templates/ingress-ws.yaml b/charts/helm3/octopod/templates/ingress-ws.yaml new file mode 100644 index 0000000..8b9ec31 --- /dev/null +++ b/charts/helm3/octopod/templates/ingress-ws.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "octopod.fullname" . -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-ws + labels: + {{- include "octopod.labels" . | nindent 4 }} + annotations: + {{- if .Values.ingress.tls.enabled }} + kubernetes.io/tls-acme: "true" + cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.clusterIssuer | quote }} + {{- end }} + kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }} + nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout" + {{- with .Values.ingress.ws.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.ws.host }} + secretName: {{ $fullName }}-ws-tls + {{- end }} + rules: + - host: {{ .Values.ingress.ws.host | quote }} + http: + paths: + - path: / + backend: + serviceName: {{ $fullName }} + servicePort: {{ .Values.service.ports.ws }} +{{- end }} \ No newline at end of file diff --git a/charts/helm3/octopod/templates/migration-job.yaml b/charts/helm3/octopod/templates/migration-job.yaml new file mode 100644 index 0000000..39fdee9 --- /dev/null +++ b/charts/helm3/octopod/templates/migration-job.yaml @@ -0,0 +1,77 @@ +{{- if .Values.octopod.migrations.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "octopod.fullname" . }}-migrations + labels: + {{- include "octopod.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": hook-succeeded +spec: + activeDeadlineSeconds: 600 + template: + spec: + initContainers: + - name: copy + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + command: + - "bash" + - "-ec" + - | + set -ex + + # copy migrations + cp -av /migrations/* /mymigrations + + # create sqitch.conf + echo '[core]' > /mymigrations/sqitch.conf + echo 'engine = pg' >> /mymigrations/sqitch.conf + echo 'plan_file = sqitch.plan' >> /mymigrations/sqitch.conf + echo 'top_dir = .' >> /mymigrations/sqitch.conf + echo '[engine "pg"]' >> /mymigrations/sqitch.conf + echo ' registry = sqitch' >> /mymigrations/sqitch.conf + echo '[deploy]' >> /mymigrations/sqitch.conf + echo ' verify = true' >> /mymigrations/sqitch.conf + echo '[rebase]' >> /mymigrations/sqitch.conf + echo ' verify = true' >> /mymigrations/sqitch.conf + echo '[target "octopod"]' >> /mymigrations/sqitch.conf + echo 'uri = db:pg://{{ .Values.postgresql.postgresqlUsername }}:$(PG_PASS)@{{ include "postgresqlHost" . }}/{{ .Values.postgresql.postgresqlDatabase }}' >> /mymigrations/sqitch.conf + env: + - name: PG_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresqlSecretName" . }} + key: postgresql-password + volumeMounts: + - name: migrations + mountPath: /mymigrations + containers: + - name: migrations + image: "{{ .Values.sqitch.image.repository }}:{{ .Values.sqitch.image.tag }}" + command: + - "bash" + - "-c" + - | + set -x + echo 'checking connection to postgresql...' + for i in $(seq 1 6); do psql "postgres://{{ .Values.postgresql.postgresqlUsername }}:$(PG_PASS)@{{ include "postgresqlHost" . }}/{{ .Values.postgresql.postgresqlDatabase }}" -c ''; if [ $? -eq 0 ]; then break; fi; sleep 10; done + set -e + echo 'run migrations...' + cd /migrations && /usr/local/bin/sqitch deploy octopod + env: + - name: PG_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresqlSecretName" . }} + key: postgresql-password + volumeMounts: + - name: migrations + mountPath: /migrations + + volumes: + - name: migrations + emptyDir: {} + restartPolicy: Never + backoffLimit: 3 +{{- end }} diff --git a/charts/helm3/octopod/templates/nginx-configmap.yaml b/charts/helm3/octopod/templates/nginx-configmap.yaml new file mode 100644 index 0000000..f4956e2 --- /dev/null +++ b/charts/helm3/octopod/templates/nginx-configmap.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "octopod.fullname" . }}-nginx-config + labels: + {{- include "octopod.labels" . | nindent 4 }} +data: + app.conf: | + server { + listen 80 default_server; + server_name _; + root /www; + index index.html; + error_page 404 =200 /index.html; + } + config.json: | + { + "app_url": "{{ printf "%s://%s" (include "httpScheme" .) .Values.ingress.app.host}}", + "ws_url": "{{ printf "%s://%s" (include "wsScheme" .) .Values.ingress.ws.host}}", + "app_auth": "Basic {{ printf "octopod:%s" (include "octopodAppAuthPassword" .) | b64enc }}", + + "kubernetes_dashboard_url_template": null + + } diff --git a/charts/helm3/octopod/templates/octopod-basic-auth-secret.yaml b/charts/helm3/octopod/templates/octopod-basic-auth-secret.yaml new file mode 100644 index 0000000..97f02c3 --- /dev/null +++ b/charts/helm3/octopod/templates/octopod-basic-auth-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ include "octopodAppAuthSecretName" . }} + labels: + {{- include "octopod.labels" . | nindent 4 }} +data: + auth: {{ htpasswd "octopod" (include "octopodAppAuthPassword" . ) | b64enc }} + diff --git a/charts/helm3/octopod/templates/octopod-configmap.yaml b/charts/helm3/octopod/templates/octopod-configmap.yaml new file mode 100644 index 0000000..7f87ad4 --- /dev/null +++ b/charts/helm3/octopod/templates/octopod-configmap.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "octopod.fullname" . }} + labels: + {{- include "octopod.labels" . | nindent 4 }} +data: + PROJECT_NAME: {{ .Values.octopod.projectName | quote }} + BASE_DOMAIN: {{ .Values.octopod.baseDomain | quote }} + NAMESPACE: {{ .Values.octopod.deploymentNamespace | quote }} + STATUS_UPDATE_TIMEOUT: {{ .Values.octopod.statusUpdateTimeout | quote }} + ARCHIVE_RETENTION: {{ .Values.octopod.archiveRetention | quote }} + CREATION_COMMAND: {{ printf "%s/create" (include "controlScriptsPath" .) | quote }} + UPDATE_COMMAND: {{ printf "%s/update" (include "controlScriptsPath" .) | quote }} + ARCHIVE_COMMAND: {{ printf "%s/archive" (include "controlScriptsPath" .) | quote }} + CHECKING_COMMAND: {{ printf "%s/check" (include "controlScriptsPath" .) | quote }} + CLEANUP_COMMAND: {{ printf "%s/cleanup" (include "controlScriptsPath" .) | quote }} + ARCHIVE_CHECKING_COMMAND: {{ printf "%s/archive_check" (include "controlScriptsPath" .) | quote }} + TAG_CHECKING_COMMAND: {{ printf "%s/tag_check" (include "controlScriptsPath" .) | quote }} + INFO_COMMAND: {{ printf "%s/info" (include "controlScriptsPath" .) | quote }} diff --git a/charts/helm3/octopod/templates/rbac.yaml b/charts/helm3/octopod/templates/rbac.yaml new file mode 100644 index 0000000..81cd585 --- /dev/null +++ b/charts/helm3/octopod/templates/rbac.yaml @@ -0,0 +1,30 @@ +{{- if and .Values.rbac.create (eq .Values.serviceAccount.create true) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "octopod.fullname" . }} + labels: + {{- include "octopod.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["pods/portforward"] + verbs: ["create"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["list", "get"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "octopod.fullname" . }} + labels: + {{- include "octopod.labels" . | nindent 4 }} +roleRef: + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io + name: {{ include "octopod.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "octopod.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/charts/helm3/octopod/templates/service.yaml b/charts/helm3/octopod/templates/service.yaml new file mode 100644 index 0000000..f60c170 --- /dev/null +++ b/charts/helm3/octopod/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "octopod.fullname" . }} + labels: + {{- include "octopod.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: +{{- range $portName, $portNumber := .Values.service.ports }} + - name: octopod-{{ $portName | lower }} + port: {{ $portNumber }} + targetPort: {{ $portNumber }} +{{- end }} + selector: + {{- include "octopod.selectorLabels" . | nindent 4 }} diff --git a/charts/helm3/octopod/templates/serviceaccount.yaml b/charts/helm3/octopod/templates/serviceaccount.yaml new file mode 100644 index 0000000..d098f6a --- /dev/null +++ b/charts/helm3/octopod/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "octopod.serviceAccountName" . }} + labels: + {{- include "octopod.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/helm3/octopod/values-test.yaml b/charts/helm3/octopod/values-test.yaml new file mode 100644 index 0000000..9f0fd6e --- /dev/null +++ b/charts/helm3/octopod/values-test.yaml @@ -0,0 +1,104 @@ +# Default values for octopod. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: typeable/octopod + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" +rbac: + create: true +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + runAsUser: 1000 + runAsGroup: 1000 + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + +service: + type: ClusterIP + ports: + powerApp: 4443 + ui: 80 + app: 4000 + ws: 4020 + +ingress: + enabled: true + ingressClass: nginx + tls: + enabled: true + clusterIssuer: letsencrypt + powerApp: + host: octopod-powerapp.sizov-test.thebestagent.pro + annotations: {} + ui: + host: octopod.sizov-test.thebestagent.pro + annotations: {} + app: + host: octopod-app.sizov-test.thebestagent.pro + annotations: {} + ws: + host: octopod-ws.sizov-test.thebestagent.pro + annotations: {} + +resources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +octopod: + certsConfigMapName: octopod-certs + projectName: Octopod + deploymentNamespace: octopod-deployment + baseDomain: "sizov-test.thebestagent.pro" + statusUpdateTimeout: 600 + archiveRetention: 1209600 + migrations: + enabled: true +controlScripts: + image: + repository: typeable/octopod-helm-example + pullPolicy: IfNotPresent + tag: 1.1 +sqitch: + image: + repository: typeable/sqitch + pullPolicy: IfNotPresent + tag: v2.0.0 +postgresql: + enabled: true + postgresqlUsername: octopod + postgresqlDatabase: octopod diff --git a/charts/helm3/octopod/values.yaml b/charts/helm3/octopod/values.yaml new file mode 100644 index 0000000..60151ae --- /dev/null +++ b/charts/helm3/octopod/values.yaml @@ -0,0 +1,104 @@ +# Default values for octopod. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: typeable/octopod + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" +rbac: + create: true +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + runAsUser: 1000 + runAsGroup: 1000 + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + +service: + type: ClusterIP + ports: + powerApp: 4443 + ui: 80 + app: 4000 + ws: 4020 + +ingress: + enabled: true + ingressClass: nginx + tls: + enabled: true + clusterIssuer: letsencrypt + powerApp: + host: octopod-powerapp.example.com + annotations: {} + ui: + host: octopod.example.com + annotations: {} + app: + host: octopod-app.example.com + annotations: {} + ws: + host: octopod-ws.example.com + annotations: {} + +resources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +octopod: + certsConfigMapName: octopod-certs + projectName: Octopod + deploymentNamespace: octopod-deployment + baseDomain: "" + statusUpdateTimeout: 600 + archiveRetention: 1209600 + migrations: + enabled: true +controlScripts: + image: + repository: typeable/octopod-helm-example + pullPolicy: IfNotPresent + tag: 1.1 +sqitch: + image: + repository: typeable/sqitch + pullPolicy: IfNotPresent + tag: v2.0.0 +postgresql: + enabled: true + postgresqlUsername: octopod + postgresqlDatabase: octopod diff --git a/docs/en/Octopod_deployment_guide.md b/docs/en/Octopod_deployment_guide.md index d5665cd..1f3937d 100644 --- a/docs/en/Octopod_deployment_guide.md +++ b/docs/en/Octopod_deployment_guide.md @@ -422,3 +422,7 @@ helm upgrade --install octopod ./octopod \ [kubedog]: https://github.com/werf/kubedog [lets-encrypt]: https://letsencrypt.org [lets-encrypt-rate-limits]: https://letsencrypt.org/docs/rate-limits + +## Helm 3 chart +You can use a [Helm 3](../../charts/helm3/octopod) chart (beta!) to install octopod. + diff --git a/docs/ru/Octopod_deployment_with_K8S.md b/docs/ru/Octopod_deployment_with_K8S.md index b584208..70facdc 100644 --- a/docs/ru/Octopod_deployment_with_K8S.md +++ b/docs/ru/Octopod_deployment_with_K8S.md @@ -280,3 +280,6 @@ [minikube]: https://kubernetes.io/ru/docs/tasks/tools/install-minikube [tiller]: https://v2.helm.sh/docs/install [kubedog]: https://github.com/werf/kubedog + +## Helm 3 +Для установки Octopod вы также можете использовать чарт [Helm 3](../../charts/helm3/octopod) (бета версия!).