diff --git a/deploy/k8s/Chart.yaml b/deploy/k8s/Chart.yaml new file mode 100644 index 0000000..0d87381 --- /dev/null +++ b/deploy/k8s/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: backoffice-api +description: A Helm chart for Kubernetes +version: 0.0.0 diff --git a/deploy/k8s/templates/NOTES.txt b/deploy/k8s/templates/NOTES.txt new file mode 100644 index 0000000..571fe88 --- /dev/null +++ b/deploy/k8s/templates/NOTES.txt @@ -0,0 +1,3 @@ +{{- if .Values.ingress.enabled }} +URL: https://{{ .Values.ingress.host }} +{{- end }} diff --git a/deploy/k8s/templates/config.yaml b/deploy/k8s/templates/config.yaml new file mode 100644 index 0000000..faefdb5 --- /dev/null +++ b/deploy/k8s/templates/config.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }} +data: + APP_ENV: "production" + APP_PORT: {{ .Values.config.port | quote }} + DATABASE_URL_FILE: "/etc/backoffice-api/secrets/database_url" diff --git a/deploy/k8s/templates/deployment.yaml b/deploy/k8s/templates/deployment.yaml new file mode 100644 index 0000000..64e511a --- /dev/null +++ b/deploy/k8s/templates/deployment.yaml @@ -0,0 +1,65 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" +spec: + replicas: {{ .Values.replicas }} + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/config.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" + spec: + automountServiceAccountToken: false + {{- with .Values.image.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: api + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: Always + ports: + - name: {{ .Values.service.port.name }} + containerPort: {{ .Values.config.port }} + protocol: TCP + # livenessProbe: + # httpGet: + # path: /livez + # port: {{ .Values.service.port.name }} + # readinessProbe: + # httpGet: + # path: /readyz + # port: {{ .Values.service.port.name }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + envFrom: + - configMapRef: + name: {{ .Release.Name }} + volumeMounts: + - mountPath: /etc/backoffice-api/secrets + name: secrets + readOnly: true + volumes: + - name: secrets + secret: + secretName: {{ .Release.Name }} + diff --git a/deploy/k8s/templates/ingress.yaml b/deploy/k8s/templates/ingress.yaml new file mode 100644 index 0000000..726c001 --- /dev/null +++ b/deploy/k8s/templates/ingress.yaml @@ -0,0 +1,27 @@ +{{- if .Values.api.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }} + annotations: + {{- if .Values.ingress.annotations }} + {{- toYaml .Values.ingress.annotations | nindent 8 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.className }} + tls: + - hosts: + - {{ .Values.ingress.host | quote }} + secretName: {{ .Release.Name }}-ingress-tls + rules: + - host: {{ .Values.ingress.host | quote }} + http: + paths: + - path: {{ .Values.ingress.path }} + pathType: {{ .Values.ingress.pathType }} + backend: + service: + name: {{ .Release.Name }} + port: + name: {{ .Values.service.port.name }} +{{- end -}} diff --git a/deploy/k8s/templates/migration-job.yaml b/deploy/k8s/templates/migration-job.yaml new file mode 100644 index 0000000..86c841c --- /dev/null +++ b/deploy/k8s/templates/migration-job.yaml @@ -0,0 +1,46 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-migrations-{{ now | unixEpoch }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "database-migrations" + batch.kubernetes.io/job-name: {{ .Release.Name }}-migrations-{{ now | unixEpoch }} +spec: + ttlSecondsAfterFinished: 604800 # 1 week in seconds + template: + metadata: + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "database-migrations" + batch.kubernetes.io/job-name: {{ .Release.Name }}-migrations-{{ now | unixEpoch }} + spec: + automountServiceAccountToken: false + {{- with .Values.migrations.image.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: migrations + image: "{{ .Values.migrations.image.repository }}:{{ .Values.migrations.image.tag }}" + command: ["/bin/ash"] + args: + - -c + - | + migrate -path /srv/migrations -database $(cat /etc/backoffice-api/secrets/database_url) up + {{- with .Values.migrations.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - mountPath: /etc/backoffice-api/secrets + name: secrets + readOnly: true + volumes: + - name: secrets + secret: + secretName: {{ .Release.Name }}-migrations + restartPolicy: Never + backoffLimit: 0 diff --git a/deploy/k8s/templates/migration-secrets.yaml b/deploy/k8s/templates/migration-secrets.yaml new file mode 100644 index 0000000..df39e57 --- /dev/null +++ b/deploy/k8s/templates/migration-secrets.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-migrations +stringData: + database_url: | + {{ .Values.migrations.config.databaseURL }} diff --git a/deploy/k8s/templates/poddisruptionbudget.yaml b/deploy/k8s/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..bc5280d --- /dev/null +++ b/deploy/k8s/templates/poddisruptionbudget.yaml @@ -0,0 +1,13 @@ +{{- if gt (.Values.replicas | int) 1 -}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ .Release.Name }} +spec: + minAvailable: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" +{{- end -}} diff --git a/deploy/k8s/templates/secrets.yaml b/deploy/k8s/templates/secrets.yaml new file mode 100644 index 0000000..ae67e74 --- /dev/null +++ b/deploy/k8s/templates/secrets.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }} +stringData: + database_url: | + {{ .Values.config.databaseURL }} diff --git a/deploy/k8s/templates/service.yaml b/deploy/k8s/templates/service.yaml new file mode 100644 index 0000000..b03eec7 --- /dev/null +++ b/deploy/k8s/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port.number }} + targetPort: {{ .Values.service.port.name }} + protocol: TCP + name: {{ .Values.service.port.name }} + selector: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" diff --git a/deploy/k8s/values.staging.yaml b/deploy/k8s/values.staging.yaml new file mode 100644 index 0000000..33d391d --- /dev/null +++ b/deploy/k8s/values.staging.yaml @@ -0,0 +1,6 @@ +api: + ingress: + enabled: true + host: staging.backoffice-api.vmdevel.cz + path: / + className: nginx diff --git a/deploy/k8s/values.test.yaml b/deploy/k8s/values.test.yaml new file mode 100644 index 0000000..0cd380d --- /dev/null +++ b/deploy/k8s/values.test.yaml @@ -0,0 +1,9 @@ +ingress: + enabled: true + host: backoffice-api.example.com + annotations: + cert-manager.io/cluster-issuer: letsencrypt-staging + +config: + database: + url: postgres://user:pass@127.0.0.1:5432/db?sslmode=disable diff --git a/deploy/k8s/values.yaml b/deploy/k8s/values.yaml new file mode 100644 index 0000000..f340ac0 --- /dev/null +++ b/deploy/k8s/values.yaml @@ -0,0 +1,51 @@ +image: + pullSecrets: [] + pullPolicy: IfNotPresent + repository: registry.mareshq.com/hq/backoffice/backoffice-api/api + tag: latest + +replicas: 2 + +ingress: + enabled: false + host: example.com + className: nginx + path: / + pathType: Prefix + annotations: {} + +service: + type: ClusterIP + port: + name: http + number: 80 + +resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 200m + memory: 256Mi + +config: + port: 8080 + databaseURL: "" + +migrations: + image: + pullSecrets: [] + pullPolicy: IfNotPresent + repository: registry.mareshq.com/hq/backoffice/backoffice-api/migrations + tag: latest + + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + + config: + databaseURL: ""