From 5fdfec0306a481adc14b50f7f9e76f204c735a92 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Thu, 24 Oct 2024 11:00:12 +0200 Subject: [PATCH] helm tuto part #1 --- deployment/helm/Chart.lock | 6 - deployment/helm/charts/eoapi-0.4.17.tgz | Bin 27990 -> 0 bytes deployment/helm/debug.yaml | 106 +++++++++++++++ deployment/helm/templates/Webapp.yml | 39 ------ deployment/helm/values.yaml | 19 --- deployment/helm/webapp-polder/.helmignore | 23 ++++ .../helm/{ => webapp-polder}/Chart.yaml | 23 ++-- .../helm/webapp-polder/templates/NOTES.txt | 22 ++++ .../helm/webapp-polder/templates/_helpers.tpl | 62 +++++++++ .../webapp-polder/templates/deployment.yaml | 68 ++++++++++ .../helm/webapp-polder/templates/hpa.yaml | 32 +++++ .../helm/webapp-polder/templates/ingress.yaml | 43 ++++++ .../helm/webapp-polder/templates/service.yaml | 15 +++ .../templates/serviceaccount.yaml | 13 ++ .../templates/tests/test-connection.yaml | 15 +++ deployment/helm/webapp-polder/values.yaml | 123 ++++++++++++++++++ deployment/k8s/deploy.yaml | 105 +++++++++++++++ webapp/Dockerfile | 2 +- 18 files changed, 641 insertions(+), 75 deletions(-) delete mode 100644 deployment/helm/Chart.lock delete mode 100644 deployment/helm/charts/eoapi-0.4.17.tgz create mode 100644 deployment/helm/debug.yaml delete mode 100644 deployment/helm/templates/Webapp.yml delete mode 100644 deployment/helm/values.yaml create mode 100644 deployment/helm/webapp-polder/.helmignore rename deployment/helm/{ => webapp-polder}/Chart.yaml (50%) create mode 100644 deployment/helm/webapp-polder/templates/NOTES.txt create mode 100644 deployment/helm/webapp-polder/templates/_helpers.tpl create mode 100644 deployment/helm/webapp-polder/templates/deployment.yaml create mode 100644 deployment/helm/webapp-polder/templates/hpa.yaml create mode 100644 deployment/helm/webapp-polder/templates/ingress.yaml create mode 100644 deployment/helm/webapp-polder/templates/service.yaml create mode 100644 deployment/helm/webapp-polder/templates/serviceaccount.yaml create mode 100644 deployment/helm/webapp-polder/templates/tests/test-connection.yaml create mode 100644 deployment/helm/webapp-polder/values.yaml create mode 100644 deployment/k8s/deploy.yaml diff --git a/deployment/helm/Chart.lock b/deployment/helm/Chart.lock deleted file mode 100644 index 53c759d..0000000 --- a/deployment/helm/Chart.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: eoapi - repository: https://devseed.com/eoapi-k8s/ - version: 0.4.17 -digest: sha256:adbb8a0db399bf32efbf12ffafafbf07c6d4f676f78b2bf2aa6befdc5f1a4f51 -generated: "2024-10-16T11:33:15.655622351+02:00" diff --git a/deployment/helm/charts/eoapi-0.4.17.tgz b/deployment/helm/charts/eoapi-0.4.17.tgz deleted file mode 100644 index 3838039971e47476d9bf57b07ecb475f0223024a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27990 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 H7V7^2^#Krh diff --git a/deployment/helm/debug.yaml b/deployment/helm/debug.yaml new file mode 100644 index 0000000..3c7bd9c --- /dev/null +++ b/deployment/helm/debug.yaml @@ -0,0 +1,106 @@ +--- +# Source: webapp-polder/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: test-webapp-polder + labels: + helm.sh/chart: webapp-polder-0.1.0 + app.kubernetes.io/name: webapp-polder + app.kubernetes.io/instance: test + app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/managed-by: Helm +automountServiceAccountToken: true +--- +# Source: webapp-polder/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: test-webapp-polder + labels: + helm.sh/chart: webapp-polder-0.1.0 + app.kubernetes.io/name: webapp-polder + app.kubernetes.io/instance: test + app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/managed-by: Helm +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: webapp-polder + app.kubernetes.io/instance: test +--- +# Source: webapp-polder/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-webapp-polder + labels: + helm.sh/chart: webapp-polder-0.1.0 + app.kubernetes.io/name: webapp-polder + app.kubernetes.io/instance: test + app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: webapp-polder + app.kubernetes.io/instance: test + template: + metadata: + labels: + helm.sh/chart: webapp-polder-0.1.0 + app.kubernetes.io/name: webapp-polder + app.kubernetes.io/instance: test + app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/managed-by: Helm + spec: + serviceAccountName: test-webapp-polder + securityContext: + {} + containers: + - name: webapp-polder + securityContext: + {} + image: "nginx:0.1.0" + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 80 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + {} +--- +# Source: webapp-polder/templates/tests/test-connection.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "test-webapp-polder-test-connection" + labels: + helm.sh/chart: webapp-polder-0.1.0 + app.kubernetes.io/name: webapp-polder + app.kubernetes.io/instance: test + app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['test-webapp-polder:80'] + restartPolicy: Never diff --git a/deployment/helm/templates/Webapp.yml b/deployment/helm/templates/Webapp.yml deleted file mode 100644 index 480e61b..0000000 --- a/deployment/helm/templates/Webapp.yml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.service.name }} - labels: - app: {{ .Values.service.name }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ .Values.service.name }} - template: - metadata: - labels: - app: {{ .Values.service.name }} - spec: - containers: - - name: nginx - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - ports: - - containerPort: 80 - resources: - {{- toYaml .Values.resources | nindent 12 }} - ---- - -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.service.name }} - labels: - app: {{ .Values.service.name }} -spec: - type: {{ .Values.service.type }} - ports: - - port: 8081 - targetPort: 80 - selector: - app: {{ .Values.service.name }} diff --git a/deployment/helm/values.yaml b/deployment/helm/values.yaml deleted file mode 100644 index 20b397f..0000000 --- a/deployment/helm/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -replicaCount: 1 - -image: - repository: nginx - pullPolicy: IfNotPresent - tag: "1.27.2" - -service: - enabled: true - name: polder-webapp - type: NodePort - ports: - - port: 8081 - targetPort: 80 - nodePort: 30001 - selector: - app: polder-webapp - -resources: {} diff --git a/deployment/helm/webapp-polder/.helmignore b/deployment/helm/webapp-polder/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/deployment/helm/webapp-polder/.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/deployment/helm/Chart.yaml b/deployment/helm/webapp-polder/Chart.yaml similarity index 50% rename from deployment/helm/Chart.yaml rename to deployment/helm/webapp-polder/Chart.yaml index 1d25638..e398a3e 100644 --- a/deployment/helm/Chart.yaml +++ b/deployment/helm/webapp-polder/Chart.yaml @@ -1,21 +1,24 @@ apiVersion: v2 -name: polder -description: Create a polder - Web AOI viewer - instance. +name: webapp-polder +description: A Helm chart for Polder Web Application + +# 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 -kubeVersion: ">=1.23.0-0" # 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. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: "0.0.1" +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.0.1" - -dependencies: - - name: eoapi - version: 0.4.17 - repository: "https://devseed.com/eoapi-k8s/" +appVersion: "0.2.0" diff --git a/deployment/helm/webapp-polder/templates/NOTES.txt b/deployment/helm/webapp-polder/templates/NOTES.txt new file mode 100644 index 0000000..5c1ca9f --- /dev/null +++ b/deployment/helm/webapp-polder/templates/NOTES.txt @@ -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.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "webapp-polder.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "webapp-polder.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "webapp-polder.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "webapp-polder.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 }} diff --git a/deployment/helm/webapp-polder/templates/_helpers.tpl b/deployment/helm/webapp-polder/templates/_helpers.tpl new file mode 100644 index 0000000..9d8b79e --- /dev/null +++ b/deployment/helm/webapp-polder/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "webapp-polder.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 "webapp-polder.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 "webapp-polder.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "webapp-polder.labels" -}} +helm.sh/chart: {{ include "webapp-polder.chart" . }} +{{ include "webapp-polder.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "webapp-polder.selectorLabels" -}} +app.kubernetes.io/name: {{ include "webapp-polder.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "webapp-polder.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "webapp-polder.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deployment/helm/webapp-polder/templates/deployment.yaml b/deployment/helm/webapp-polder/templates/deployment.yaml new file mode 100644 index 0000000..ccf0400 --- /dev/null +++ b/deployment/helm/webapp-polder/templates/deployment.yaml @@ -0,0 +1,68 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "webapp-polder.fullname" . }} + labels: + {{- include "webapp-polder.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "webapp-polder.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "webapp-polder.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "webapp-polder.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + 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.port }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | 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 }} diff --git a/deployment/helm/webapp-polder/templates/hpa.yaml b/deployment/helm/webapp-polder/templates/hpa.yaml new file mode 100644 index 0000000..109749e --- /dev/null +++ b/deployment/helm/webapp-polder/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "webapp-polder.fullname" . }} + labels: + {{- include "webapp-polder.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "webapp-polder.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 }} diff --git a/deployment/helm/webapp-polder/templates/ingress.yaml b/deployment/helm/webapp-polder/templates/ingress.yaml new file mode 100644 index 0000000..ec44f6a --- /dev/null +++ b/deployment/helm/webapp-polder/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "webapp-polder.fullname" . }} + labels: + {{- include "webapp-polder.labels" . | nindent 4 }} + {{- 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 "webapp-polder.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deployment/helm/webapp-polder/templates/service.yaml b/deployment/helm/webapp-polder/templates/service.yaml new file mode 100644 index 0000000..c5461b7 --- /dev/null +++ b/deployment/helm/webapp-polder/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "webapp-polder.fullname" . }} + labels: + {{- include "webapp-polder.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "webapp-polder.selectorLabels" . | nindent 4 }} diff --git a/deployment/helm/webapp-polder/templates/serviceaccount.yaml b/deployment/helm/webapp-polder/templates/serviceaccount.yaml new file mode 100644 index 0000000..10e945e --- /dev/null +++ b/deployment/helm/webapp-polder/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "webapp-polder.serviceAccountName" . }} + labels: + {{- include "webapp-polder.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/deployment/helm/webapp-polder/templates/tests/test-connection.yaml b/deployment/helm/webapp-polder/templates/tests/test-connection.yaml new file mode 100644 index 0000000..90588bf --- /dev/null +++ b/deployment/helm/webapp-polder/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "webapp-polder.fullname" . }}-test-connection" + labels: + {{- include "webapp-polder.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "webapp-polder.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/deployment/helm/webapp-polder/values.yaml b/deployment/helm/webapp-polder/values.yaml new file mode 100644 index 0000000..ea97a29 --- /dev/null +++ b/deployment/helm/webapp-polder/values.yaml @@ -0,0 +1,123 @@ +# Default values for webapp-polder. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ +replicaCount: 1 + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +image: + repository: ghcr.io/developmentseed/polder + # This sets the pull policy for images. + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "dev" + +# This is for the secretes for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# This is to override the chart name. +nameOverride: "" +fullnameOverride: "" + +#This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: 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: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports + port: 80 + +# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +livenessProbe: + httpGet: + path: / + port: http +readinessProbe: + httpGet: + path: / + port: http + +#This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/deployment/k8s/deploy.yaml b/deployment/k8s/deploy.yaml new file mode 100644 index 0000000..ef2f0a8 --- /dev/null +++ b/deployment/k8s/deploy.yaml @@ -0,0 +1,105 @@ +--- +# Extendable account (kind of a user) running the setup +apiVersion: v1 +kind: ServiceAccount +metadata: + name: test-polder + labels: + app.kubernetes.io/name: polder +automountServiceAccountToken: true +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-polder-configmap +data: + app_config.js: | + window.__APP_CONFIG__ = { + MAPBOX_TOKEN: "pk.eyJ1IjoiZGV2c2VlZCIsImEiOiJnUi1mbkVvIn0.018aLhX0Mb0tdtaT2QNe2Q", + STAC_API: "https://rx3hna9pbg.execute-api.eu-central-1.amazonaws.com", + TILER_API: "https://zbrrek3x0i.execute-api.eu-central-1.amazonaws.com", + PIPPO: "PLUTO" + }; +--- +# Public facing proxy +apiVersion: v1 +kind: Service +metadata: + name: test-polder + labels: + app.kubernetes.io/name: polder +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: polder +--- +# Magic sauce. Defines the what in the template wrapped into a deployment manager +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-polder + labels: + app.kubernetes.io/name: polder +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: polder + template: + metadata: + labels: + app.kubernetes.io/name: polder + spec: + serviceAccountName: test-polder + securityContext: + {} + containers: + - name: polder + securityContext: + {} + image: "ghcr.io/developmentseed/polder:dev" + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 80 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + {} + volumeMounts: + - name: test-polder-config + mountPath: /usr/share/nginx/html/app_config.js + subPath: app_config.js + volumes: + - name: test-polder-config + configMap: + name: test-polder-configmap +--- +# Simple pod to test whether the deployment is working successfully +apiVersion: v1 +kind: Pod +metadata: + name: "test-polder-test-connection" + labels: + helm.sh/chart: polder-0.1.0 + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['test-polder:80'] + restartPolicy: Never diff --git a/webapp/Dockerfile b/webapp/Dockerfile index 2189b0f..bb39a4a 100644 --- a/webapp/Dockerfile +++ b/webapp/Dockerfile @@ -8,4 +8,4 @@ RUN ls -la . FROM nginx:alpine COPY --from=build /src/dist /usr/share/nginx/html -EXPOSE 8080 +EXPOSE 80