From 1001e8f8c639c15348d67f3a315d451bb91f2b45 Mon Sep 17 00:00:00 2001 From: LeNei Date: Sun, 5 Nov 2023 21:27:36 +0100 Subject: [PATCH] First commit --- .gitignore | 125 +++++++++++++++++++++++++++++ .helmignore | 23 ++++++ Chart.lock | 9 +++ Chart.yaml | 32 ++++++++ README.md | 39 +++++++++ templates/api-deployment.yaml | 48 +++++++++++ templates/api-ingress.yaml | 23 ++++++ templates/api-service.yaml | 11 +++ templates/cluster-issuer.yaml | 15 ++++ templates/frontend-deployment.yaml | 26 ++++++ templates/frontend-ingres.yaml | 23 ++++++ templates/frontend-service.yaml | 11 +++ templates/traefik-middleware.yaml | 8 ++ values.yaml | 21 +++++ 14 files changed, 414 insertions(+) create mode 100644 .gitignore create mode 100644 .helmignore create mode 100644 Chart.lock create mode 100644 Chart.yaml create mode 100644 README.md create mode 100644 templates/api-deployment.yaml create mode 100644 templates/api-ingress.yaml create mode 100644 templates/api-service.yaml create mode 100644 templates/cluster-issuer.yaml create mode 100644 templates/frontend-deployment.yaml create mode 100644 templates/frontend-ingres.yaml create mode 100644 templates/frontend-service.yaml create mode 100644 templates/traefik-middleware.yaml create mode 100644 values.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc3f518 --- /dev/null +++ b/.gitignore @@ -0,0 +1,125 @@ + +# Created by https://www.gitignore.io/api/helm,macos,jetbrains+all +# Edit at https://www.gitignore.io/?templates=helm,macos,jetbrains+all + +### Helm ### +# Chart dependencies +**/charts/*.tgz + +### JetBrains+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### JetBrains+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# End of https://www.gitignore.io/api/helm,macos,jetbrains+all + +temp/ diff --git a/.helmignore b/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/.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/Chart.lock b/Chart.lock new file mode 100644 index 0000000..06c8576 --- /dev/null +++ b/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 13.0.0 +- name: cert-manager + repository: https://charts.jetstack.io + version: v1.13.1 +digest: sha256:91c595353bdbd2750e7ddf4b2ede43cc89fe16135dcf7c33ed8ce80d89c3a998 +generated: "2023-10-01T11:42:35.931074+02:00" diff --git a/Chart.yaml b/Chart.yaml new file mode 100644 index 0000000..bcff1ce --- /dev/null +++ b/Chart.yaml @@ -0,0 +1,32 @@ +apiVersion: v2 +name: backend +description: A Helm chart for Kubernetes + +# 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. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +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: "1.16.0" + +dependencies: + - name: postgresql + version: 13.0.0 + repository: https://charts.bitnami.com/bitnami + - name: cert-manager + version: 1.13.1 + repository: https://charts.jetstack.io diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec70fe6 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# api-helm-chart +## Hetzner Setup +Setup cloud instance and firewall with the following ports 22, 80 and 443. +
+
+After that connect to the instance over ssh and in update + upgrade everything: +
+`apt update -y && apt upgrade -y` +
+
+To install k3s run the following command: +
+`curl -sfL https://get.k3s.io | sh -` +
+
+To get the kube config execute the following command: +
+`scp root@remoteHost:/etc/rancher/k3s/k3s.yaml ~/.kube/k3s-config` + +## Accessing The Cluster +To get acces to the cluster make a safety copy of your current `~/.kube/config` and rename the copied config from your setup. +After that you have to forward the kubernetes API-Port from your server to your local machine: +
+`ssh -L 6443:remoteHost:6443 root@remoteHost` +
+Now you should be able to run `kubectl` commands on your cluster. + +## cert-manager Setup +Since cert-manager is part of our helm chart we have to make sure the crd is installed beforehand so we have access to all resources. We do that with the following command: +
+`kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.1.1/cert-manager.crds.yaml` + +## Starting the chart +If we want to run the chart in its own namespace we can do so by creating one and switching to it. Here we create the namespace `prod`: +
+`kubectl create namespace prod && kubectl config set-context --current --namespace=prod` +
+We should also make sure that our DNS is pointing to the correct IP so cert-manager can fetch the certificate without a problem. +Now we can just run our chart and we should be good to go :) diff --git a/templates/api-deployment.yaml b/templates/api-deployment.yaml new file mode 100644 index 0000000..8faa2c5 --- /dev/null +++ b/templates/api-deployment.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.api.appName }} # Name of the deployment + labels: + app: {{ .Values.api.appName }} # Name of your application +spec: + selector: + matchLabels: + app: {{ .Values.api.appName }} # Name of your application + replicas: {{ .Values.api.replicas }} # Number of replicas + template: + metadata: + labels: + app: {{ .Values.api.appName }} # Name of your application + spec: + containers: + # Containers are the individual pieces of your application that you want + # to run. + - name: {{ .Values.api.appName }} # Name of the container + image: {{ .Values.api.image }} + ports: + # Ports are the ports that your application uses. + - containerPort: {{ .Values.api.containerPort }} # The port that your application uses + env: + - name: APP_ENVIRONMENT + value: "production" + - name: APP_APPLICATION__PORT + value: "{{ .Values.api.containerPort }}" + - name: APP_DATABASE__HOST + value: "{{ .Release.Name }}-postgresql" + - name: APP_DATABASE__USERNAME + value: "postgres" + - name: APP_DATABASE__PASSWORD + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-postgresql" + key: postgres-password + - name: APP_DATABASE__DATABASE_NAME + value: "{{ .Values.postgresql.auth.database }}" + - name: APP_DATABASE__REQUIRE_SSL + value: "false" + - name: APP_AUTH__JWKS_URL + value: "{{ .Values.api.jwksUrl }}" + - name: CARGO_MANIFEST_DIR + value: "/app" + imagePullSecrets: + - name: docker-regcred diff --git a/templates/api-ingress.yaml b/templates/api-ingress.yaml new file mode 100644 index 0000000..7322486 --- /dev/null +++ b/templates/api-ingress.yaml @@ -0,0 +1,23 @@ +kind: Ingress +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ .Values.api.appName }} + annotations: + cert-manager.io/cluster-issuer: letsencrypt + traefik.ingress.kubernetes.io/router.middlewares: "{{ .Release.Namespace }}-redirect-https@kubernetescrd" +spec: + rules: + - host: {{ .Values.api.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Values.api.appName }} + port: + number: 80 + tls: + - hosts: + - {{ .Values.api.host }} + secretName: {{ .Values.api.host | replace "." "-" }} diff --git a/templates/api-service.yaml b/templates/api-service.yaml new file mode 100644 index 0000000..a7680a0 --- /dev/null +++ b/templates/api-service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.api.appName }} +spec: + selector: + app: {{ .Values.api.appName }} + type: ClusterIP + ports: + - name: http + port: 80 diff --git a/templates/cluster-issuer.yaml b/templates/cluster-issuer.yaml new file mode 100644 index 0000000..c871e47 --- /dev/null +++ b/templates/cluster-issuer.yaml @@ -0,0 +1,15 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: {{ .Values.email }} + privateKeySecretRef: + name: letsencrypt + solvers: + - selector: {} + http01: + ingress: + class: traefik diff --git a/templates/frontend-deployment.yaml b/templates/frontend-deployment.yaml new file mode 100644 index 0000000..24cf07e --- /dev/null +++ b/templates/frontend-deployment.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.nextjs.appName }} # Name of the deployment + labels: + app: {{ .Values.nextjs.appName }} # Name of your application +spec: + selector: + matchLabels: + app: {{ .Values.nextjs.appName }} # Name of your application + replicas: {{ .Values.nextjs.replicas }} # Number of replicas + template: + metadata: + labels: + app: {{ .Values.nextjs.appName }} # Name of your application + spec: + containers: + # Containers are the individual pieces of your application that you want + # to run. + - name: {{ .Values.nextjs.appName }} # Name of the container + image: {{ .Values.nextjs.image }} + ports: + # Ports are the ports that your application uses. + - containerPort: {{ .Values.nextjs.containerPort }} # The port that your application uses + imagePullSecrets: + - name: docker-regcred diff --git a/templates/frontend-ingres.yaml b/templates/frontend-ingres.yaml new file mode 100644 index 0000000..b432906 --- /dev/null +++ b/templates/frontend-ingres.yaml @@ -0,0 +1,23 @@ +kind: Ingress +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ .Values.nextjs.appName }} + annotations: + cert-manager.io/cluster-issuer: letsencrypt + traefik.ingress.kubernetes.io/router.middlewares: "{{ .Release.Namespace }}-redirect-https@kubernetescrd" +spec: + rules: + - host: {{ .Values.nextjs.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Values.nextjs.appName }} + port: + number: 80 + tls: + - hosts: + - {{ .Values.nextjs.host }} + secretName: {{ .Values.nextjs.host | replace "." "-" }} diff --git a/templates/frontend-service.yaml b/templates/frontend-service.yaml new file mode 100644 index 0000000..74258ae --- /dev/null +++ b/templates/frontend-service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.frontend.appName }} +spec: + selector: + app: {{ .Values.frontend.appName }} + type: ClusterIP + ports: + - name: http + port: 80 diff --git a/templates/traefik-middleware.yaml b/templates/traefik-middleware.yaml new file mode 100644 index 0000000..a84b60b --- /dev/null +++ b/templates/traefik-middleware.yaml @@ -0,0 +1,8 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: redirect-https +spec: + redirectScheme: + scheme: https + permanent: true diff --git a/values.yaml b/values.yaml new file mode 100644 index 0000000..3638f4d --- /dev/null +++ b/values.yaml @@ -0,0 +1,21 @@ +email: your-mail@web.com + +api: + appName: nice-name + host: public-url + replicas: 1 + image: image-name + containerPort: 80 + jwksUrl: required-for-jwks + +frontend: + appName: nice-name + host: public-url + replicas: 1 + image: image-name + +postgresql: + auth: + database: database-name + enablePostgresUser: true + postgresPassword: very-secret-password