[skip-ci] Make unique name for each website deploy

Add function for replacing values in the beginning of a string.
Add build secret.
merge-requests/1/merge
erik 2 years ago
parent 76f5b87ec9
commit de88a5d807

@ -40,9 +40,9 @@ https://www.tecmint.com/deploy-nginx-on-a-kubernetes-cluster/
Definition von Env-Vars im Deployment:
AUTHTOKEN - muss konfigurierbar sein
REPOZIPURL - muss konfigurierbar sein
TARGETDIR - wird aus dem FQDN zusammengesetzt
WEBSITEROOT - hardcoded, da containerspezifisch
Ingress, Service, Certificate, Deployment, Configmap und Volume Mount sollen durch eindeutige, auf FQDN basierenden Namen verbunden sein.
Certificate, Ingress, Configmap, Deployment, Service, Volume Claim, Website-deployment sollen durch eindeutige, auf FQDN basierenden Namen verbunden sein.
## Getting started

@ -4,6 +4,7 @@ FROM clojure:temurin-18-jammy
ADD resources /tmp
ENV BUILDDIR="website"
ENV WEBSITEROOT="/var/www/html/website/"
RUN /tmp/install.sh
RUN /tmp/entrypoint.sh

@ -7,10 +7,14 @@
(defn k8s-objects [config]
(cm/concat-vec
(map yaml/to-string
[(website/generate-nginx-deployment)
[(website/generate-nginx-deployment config)
(website/generate-nginx-configmap config)
(website/generate-nginx-service)
(website/generate-nginx-service config)
(website/generate-website-content-volume config)
(website/generate-ingress config)
(website/generate-certificate config)
(website/generate-website-build-cron config)
(website/generate-website-build-deployment config)
(website/generate-website-build-secret config)
])))

@ -9,7 +9,7 @@
#?(:clj [clojure.edn :as edn]
:cljs [cljs.reader :as edn])
[dda.c4k-common.yaml :as yaml]
[dda.c4k-common.common :as cm]
[dda.c4k-common.common :as cm]
[dda.c4k-common.predicate :as pred]))
(defn domain-list?
@ -27,15 +27,29 @@
(def config? (s/keys :req-un [::fqdn]
:opt-un [::issuer]))
(def auth? (s/keys :req-un [::none]))
(def auth? (s/keys :req-un [::token ::url]))
(def vol? (s/keys :req-un [::volume-total-storage-size
::number-of-websites]))
(defn data-storage-by-volume-size
(defn volume-size-by-total-available-space
[total number-of-websites-on-node]
(m/floor (/ total number-of-websites-on-node))) ; ToDo: This might be a terrible idea
(defn unique-name-from-fqdn
[fqdn]
(st/replace fqdn #"\." "-"))
; ToDo: Move to common
(defn-spec replace-all-matching-subvalues-in-string-start pred/map-or-seq?
[col string?
value-to-partly-match string?
value-to-inplace string?]
(clojure.walk/postwalk #(if (and (= (type value-to-partly-match) (type %))
(re-matches (re-pattern (str value-to-partly-match ".*")) %))
(st/replace % value-to-partly-match value-to-inplace) %)
col))
#?(:cljs
(defmethod yaml/load-resource :website [resource-name]
(case resource-name
@ -45,6 +59,9 @@
"website/nginx-deployment.yaml" (rc/inline "website/nginx-deployment.yaml")
"website/nginx-service.yaml" (rc/inline "website/nginx-service.yaml")
"website/website-content-volume.yaml" (rc/inline "website/website-content-volume.yaml")
"website/website-build-cron.yaml" (rc/inline "website/website-build-cron.yaml")
"website/website-build-deployment.yaml" (rc/inline "website/website-build-deployment.yaml")
"website/website-build-secret.yaml" (rc/inline "website/website-build-secret.yaml")
(throw (js/Error. "Undefined Resource!")))))
#?(:cljs
@ -59,6 +76,7 @@
(->
(yaml/load-as-edn "website/certificate.yaml")
(assoc-in [:spec :issuerRef :name] letsencrypt-issuer)
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn))
(cm/replace-all-matching-values-by-new-value "FQDN" fqdn))))
(defn-spec generate-ingress pred/map-or-seq?
@ -66,30 +84,60 @@
(let [{:keys [fqdn]} config]
(->
(yaml/load-as-edn "website/ingress.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn))
(cm/replace-all-matching-values-by-new-value "FQDN" fqdn))))
(defn-spec generate-nginx-configmap pred/map-or-seq?
(defn-spec generate-nginx-configmap pred/map-or-seq?
[config config?]
(let [{:keys [fqdn]} config
configmap (yaml/load-as-edn "website/nginx-configmap.yaml")]
(->
configmap (yaml/load-as-edn "website/nginx-configmap.yaml")]
(->
configmap
(assoc-in [:data :website.conf] (st/replace (-> configmap :data :website.conf) #"FQDN" (str fqdn ";")))
)
))
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn)))))
(defn-spec generate-nginx-deployment pred/map-or-seq?
[]
(yaml/load-as-edn "website/nginx-deployment.yaml"))
[config config?]
(let [{:keys [fqdn]} config]
(->
(yaml/load-as-edn "website/nginx-deployment.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn)))))
(defn-spec generate-nginx-service pred/map-or-seq?
[]
(yaml/load-as-edn "website/nginx-service.yaml"))
[config config?]
(let [{:keys [fqdn]} config]
(->
(yaml/load-as-edn "website/nginx-service.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn)))))
(defn-spec generate-website-content-volume pred/map-or-seq?
[config vol?]
(let [{:keys [volume-total-storage-size number-of-websites]} config
data-storage-size (data-storage-by-volume-size volume-total-storage-size number-of-websites)]
(let [{:keys [volume-total-storage-size number-of-websites fqdn]} config
data-storage-size (volume-size-by-total-available-space volume-total-storage-size number-of-websites)]
(->
(yaml/load-as-edn "website/website-content-volume.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn))
(cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str (str data-storage-size) "Gi")))))
(defn-spec generate-website-build-cron pred/map-or-seq?
[config config?]
(let [{:keys [fqdn]} config]
(->
(yaml/load-as-edn "website/website-build-cron.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn)))))
(defn-spec generate-website-build-deployment pred/map-or-seq?
[config config?]
(let [{:keys [fqdn]} config]
(->
(yaml/load-as-edn "website/website-build-deployment.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn)))))
(defn-spec generate-website-build-secret pred/map-or-seq?
[auth auth?]
(let [{:keys [fqdn token url]} config]
(->
(yaml/load-as-edn "website/website-build-secrets.yaml")
(replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn fqdn))
(cm/replace-all-matching-values-by-new-value "TOKEN" (b64/encode token))
(cm/replace-all-matching-values-by-new-value "URL" (b64/encode url)))))

@ -1,10 +1,10 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: website-cert
name: NAME-cert
namespace: default
spec:
secretName: website-cert
secretName: NAME-cert
commonName: FQDN
duration: 2160h # 90d
renewBefore: 360h # 15d

@ -1,7 +1,7 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-website
name: NAME-ingress
namespace: default
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
@ -10,7 +10,7 @@ spec:
tls:
- hosts:
- FQDN
secretName: website-cert
secretName: NAME-cert
rules:
- host: FQDN
http:
@ -19,6 +19,6 @@ spec:
path: "/"
backend:
service:
name: nginx-service
name: NAME-service
port:
number: 80

@ -1,7 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nginxconf
name: NAME-configmap
namespace: default
data:
nginx.conf: |

@ -1,19 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
name: NAME-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
app: NAME-nginx
template:
metadata:
labels:
app: nginx
app: NAME-nginx
spec:
containers:
- name: nginx
- name: NAME-nginx
image: nginx:latest
imagePullPolicy: "Always"
ports:
@ -21,7 +21,7 @@ spec:
volumeMounts:
- mountPath: /etc/nginx
readOnly: true
name: nginxconfigvol
name: nginx-config-volume
- mountPath: /var/log/nginx
name: log
- mountPath: /var/www/html/website
@ -30,9 +30,9 @@ spec:
name: website-cert
readOnly: true
volumes:
- name: nginxconfigvol
- name: nginx-config-volume
configMap:
name: nginxconf
name: NAME-configmap
items:
- key: nginx.conf
path: nginx.conf
@ -44,10 +44,10 @@ spec:
emptyDir: {}
- name: website-content-volume
persistentVolumeClaim:
claimName: website-content-pvc
claimName: NAME-content-pvc
- name: website-cert
secret:
secretName: website-cert
secretName: NAME-cert
items:
- key: tls.crt
path: tls.crt

@ -1,13 +1,13 @@
kind: Service
apiVersion: v1
metadata:
name: nginx-service
name: NAME-service
labels:
app: nginx
app: NAME-nginx
namespace: default
spec:
selector:
app: nginx
app: NAME-nginx
ports:
- name: nginx-http
port: 80

@ -1,7 +1,7 @@
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: website-builder
name: NAME-build-cron
labels:
app.kubernetes.part-of: website # correct name?
spec:
@ -13,35 +13,18 @@ spec:
template:
spec:
containers:
- name: backup-app
image: domaindrivenarchitecture/c4k-gitea-backup
- image: domaindrivenarchitecture/c4k-website-build
name: NAME-build-app
imagePullPolicy: IfNotPresent
command: ["/entrypoint.sh"]
env:
- name: AWS_DEFAULT_REGION
value: eu-central-1
- name: AWS_ACCESS_KEY_ID_FILE
value: /var/run/secrets/backup-secrets/aws-access-key-id
- name: AWS_SECRET_ACCESS_KEY_FILE
value: /var/run/secrets/backup-secrets/aws-secret-access-key
- name: RESTIC_REPOSITORY
valueFrom:
configMapKeyRef:
name: backup-config
key: restic-repository
- name: RESTIC_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-password
envFrom:
- secretRef:
name: NAME-secret
volumeMounts:
- name: gitea-data-volume
mountPath: /var/backups
- name: backup-secret-volume
mountPath: /var/run/secrets/backup-secrets
readOnly: true
- name: content-volume
mountPath: /var/www/html/website
volumes:
- name: gitea-data-volume
- name: content-volume
persistentVolumeClaim:
claimName: gitea-data-pvc
- name: backup-secret-volume
secret:
secretName: backup-secret
claimName: NAME-content-pvc
restartPolicy: OnFailure

@ -1,73 +1,33 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backup-restore
name: NAME-build-deployment
spec:
replicas: 0
selector:
matchLabels:
app: backup-restore
app: NAME-builder
strategy:
type: Recreate
template:
metadata:
labels:
app: backup-restore
app.kubernetes.io/name: backup-restore
app.kubernetes.io/part-of: gitea
app: NAME-builder
app.kubernetes.io/name: NAME-builder
app.kubernetes.io/part-of: website
spec:
containers:
- image: domaindrivenarchitecture/c4k-gitea-backup
name: backup-app
- image: domaindrivenarchitecture/c4k-website-build
name: NAME-build-app
imagePullPolicy: IfNotPresent
command: ["/entrypoint-start-and-wait.sh"]
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres-user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres-password
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres-db
- name: POSTGRES_HOST
value: "postgresql-service:5432"
- name: POSTGRES_SERVICE
value: "postgresql-service"
- name: POSTGRES_PORT
value: "5432"
- name: AWS_DEFAULT_REGION
value: eu-central-1
- name: AWS_ACCESS_KEY_ID_FILE
value: /var/run/secrets/backup-secrets/aws-access-key-id
- name: AWS_SECRET_ACCESS_KEY_FILE
value: /var/run/secrets/backup-secrets/aws-secret-access-key
- name: RESTIC_REPOSITORY
valueFrom:
configMapKeyRef:
name: backup-config
key: restic-repository
- name: RESTIC_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-password
- name: CERTIFICATE_FILE
value: ""
command: ["/entrypoint.sh"]
envFrom:
- secretRef:
name: NAME-secret
volumeMounts:
- name: gitea-data-volume
mountPath: /var/backups
- name: backup-secret-volume
mountPath: /var/run/secrets/backup-secrets
readOnly: true
- name: content-volume
mountPath: /var/www/html/website
volumes:
- name: gitea-data-volume
- name: content-volume
persistentVolumeClaim:
claimName: gitea-data-pvc
- name: backup-secret-volume
secret:
secretName: backup-secret
claimName: NAME-content-pvc

@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: NAME-secret
data:
AUTHTOKEN: TOKEN
REPOZIPURL: URL

@ -1,14 +1,15 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: website-content-pvc
name: NAME-content-volume
namespace: default
labels:
app: nginx
app: NAME-nginx
spec:
storageClassName: local-path
accessModes:
- ReadWriteOnce
resources:
requests:
storage: WEBSITESTORAGESIZE
storage: WEBSITESTORAGESIZE
Loading…
Cancel
Save