[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: Definition von Env-Vars im Deployment:
AUTHTOKEN - muss konfigurierbar sein AUTHTOKEN - muss konfigurierbar sein
REPOZIPURL - 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 ## Getting started

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

@ -7,10 +7,14 @@
(defn k8s-objects [config] (defn k8s-objects [config]
(cm/concat-vec (cm/concat-vec
(map yaml/to-string (map yaml/to-string
[(website/generate-nginx-deployment) [(website/generate-nginx-deployment config)
(website/generate-nginx-configmap config) (website/generate-nginx-configmap config)
(website/generate-nginx-service) (website/generate-nginx-service config)
(website/generate-website-content-volume config) (website/generate-website-content-volume config)
(website/generate-ingress config) (website/generate-ingress config)
(website/generate-certificate 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] #?(:clj [clojure.edn :as edn]
:cljs [cljs.reader :as edn]) :cljs [cljs.reader :as edn])
[dda.c4k-common.yaml :as yaml] [dda.c4k-common.yaml :as yaml]
[dda.c4k-common.common :as cm] [dda.c4k-common.common :as cm]
[dda.c4k-common.predicate :as pred])) [dda.c4k-common.predicate :as pred]))
(defn domain-list? (defn domain-list?
@ -27,15 +27,29 @@
(def config? (s/keys :req-un [::fqdn] (def config? (s/keys :req-un [::fqdn]
:opt-un [::issuer])) :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 (def vol? (s/keys :req-un [::volume-total-storage-size
::number-of-websites])) ::number-of-websites]))
(defn data-storage-by-volume-size (defn volume-size-by-total-available-space
[total number-of-websites-on-node] [total number-of-websites-on-node]
(m/floor (/ total number-of-websites-on-node))) ; ToDo: This might be a terrible idea (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 #?(:cljs
(defmethod yaml/load-resource :website [resource-name] (defmethod yaml/load-resource :website [resource-name]
(case resource-name (case resource-name
@ -45,6 +59,9 @@
"website/nginx-deployment.yaml" (rc/inline "website/nginx-deployment.yaml") "website/nginx-deployment.yaml" (rc/inline "website/nginx-deployment.yaml")
"website/nginx-service.yaml" (rc/inline "website/nginx-service.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-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!"))))) (throw (js/Error. "Undefined Resource!")))))
#?(:cljs #?(:cljs
@ -59,6 +76,7 @@
(-> (->
(yaml/load-as-edn "website/certificate.yaml") (yaml/load-as-edn "website/certificate.yaml")
(assoc-in [:spec :issuerRef :name] letsencrypt-issuer) (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)))) (cm/replace-all-matching-values-by-new-value "FQDN" fqdn))))
(defn-spec generate-ingress pred/map-or-seq? (defn-spec generate-ingress pred/map-or-seq?
@ -66,30 +84,60 @@
(let [{:keys [fqdn]} config] (let [{:keys [fqdn]} config]
(-> (->
(yaml/load-as-edn "website/ingress.yaml") (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)))) (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?] [config config?]
(let [{:keys [fqdn]} config (let [{:keys [fqdn]} config
configmap (yaml/load-as-edn "website/nginx-configmap.yaml")] configmap (yaml/load-as-edn "website/nginx-configmap.yaml")]
(-> (->
configmap configmap
(assoc-in [:data :website.conf] (st/replace (-> configmap :data :website.conf) #"FQDN" (str fqdn ";"))) (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? (defn-spec generate-nginx-deployment pred/map-or-seq?
[] [config config?]
(yaml/load-as-edn "website/nginx-deployment.yaml")) (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? (defn-spec generate-nginx-service pred/map-or-seq?
[] [config config?]
(yaml/load-as-edn "website/nginx-service.yaml")) (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? (defn-spec generate-website-content-volume pred/map-or-seq?
[config vol?] [config vol?]
(let [{:keys [volume-total-storage-size number-of-websites]} config (let [{:keys [volume-total-storage-size number-of-websites fqdn]} config
data-storage-size (data-storage-by-volume-size volume-total-storage-size number-of-websites)] 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") (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"))))) (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 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: website-cert name: NAME-cert
namespace: default namespace: default
spec: spec:
secretName: website-cert secretName: NAME-cert
commonName: FQDN commonName: FQDN
duration: 2160h # 90d duration: 2160h # 90d
renewBefore: 360h # 15d renewBefore: 360h # 15d

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

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

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

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

@ -1,7 +1,7 @@
apiVersion: batch/v1beta1 apiVersion: batch/v1beta1
kind: CronJob kind: CronJob
metadata: metadata:
name: website-builder name: NAME-build-cron
labels: labels:
app.kubernetes.part-of: website # correct name? app.kubernetes.part-of: website # correct name?
spec: spec:
@ -13,35 +13,18 @@ spec:
template: template:
spec: spec:
containers: containers:
- name: backup-app - image: domaindrivenarchitecture/c4k-website-build
image: domaindrivenarchitecture/c4k-gitea-backup name: NAME-build-app
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: ["/entrypoint.sh"] command: ["/entrypoint.sh"]
env: envFrom:
- name: AWS_DEFAULT_REGION - secretRef:
value: eu-central-1 name: NAME-secret
- 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
volumeMounts: volumeMounts:
- name: gitea-data-volume - name: content-volume
mountPath: /var/backups mountPath: /var/www/html/website
- name: backup-secret-volume
mountPath: /var/run/secrets/backup-secrets
readOnly: true
volumes: volumes:
- name: gitea-data-volume - name: content-volume
persistentVolumeClaim: persistentVolumeClaim:
claimName: gitea-data-pvc claimName: NAME-content-pvc
- name: backup-secret-volume
secret:
secretName: backup-secret
restartPolicy: OnFailure restartPolicy: OnFailure

@ -1,73 +1,33 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: backup-restore name: NAME-build-deployment
spec: spec:
replicas: 0 replicas: 0
selector: selector:
matchLabels: matchLabels:
app: backup-restore app: NAME-builder
strategy: strategy:
type: Recreate type: Recreate
template: template:
metadata: metadata:
labels: labels:
app: backup-restore app: NAME-builder
app.kubernetes.io/name: backup-restore app.kubernetes.io/name: NAME-builder
app.kubernetes.io/part-of: gitea app.kubernetes.io/part-of: website
spec: spec:
containers: containers:
- image: domaindrivenarchitecture/c4k-gitea-backup - image: domaindrivenarchitecture/c4k-website-build
name: backup-app name: NAME-build-app
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: ["/entrypoint-start-and-wait.sh"] command: ["/entrypoint.sh"]
env: envFrom:
- name: POSTGRES_USER - secretRef:
valueFrom: name: NAME-secret
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: ""
volumeMounts: volumeMounts:
- name: gitea-data-volume - name: content-volume
mountPath: /var/backups mountPath: /var/www/html/website
- name: backup-secret-volume
mountPath: /var/run/secrets/backup-secrets
readOnly: true
volumes: volumes:
- name: gitea-data-volume - name: content-volume
persistentVolumeClaim: persistentVolumeClaim:
claimName: gitea-data-pvc claimName: NAME-content-pvc
- name: backup-secret-volume
secret:
secretName: backup-secret

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

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