From a4f9b46fdb98237c5ba581fef3c7a38f6121a112 Mon Sep 17 00:00:00 2001 From: Vojtech Mares Date: Wed, 13 Dec 2023 18:15:03 +0100 Subject: [PATCH] feat: initial commit Signed-off-by: Vojtech Mares --- .editorconfig | 13 + Makefile | 37 +++ docs/converge.sql | 4 + docs/create-postgres-user.md | 14 + helm/values/hccm.yaml | 8 + helm/values/keycloak.yaml | 112 ++++++++ manifests/clusterissuer.yaml | 14 + manifests/hcloud-csi-driver.yaml | 393 ++++++++++++++++++++++++++++ manifests/hcloud-token.yaml | 9 + rke2/config.yaml | 21 ++ rke2/rke2-ingress-nginx-config.yaml | 15 ++ 11 files changed, 640 insertions(+) create mode 100644 .editorconfig create mode 100644 Makefile create mode 100644 docs/converge.sql create mode 100644 docs/create-postgres-user.md create mode 100644 helm/values/hccm.yaml create mode 100644 helm/values/keycloak.yaml create mode 100644 manifests/clusterissuer.yaml create mode 100644 manifests/hcloud-csi-driver.yaml create mode 100644 manifests/hcloud-token.yaml create mode 100644 rke2/config.yaml create mode 100644 rke2/rke2-ingress-nginx-config.yaml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..87a0020 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +max_line_length = null + +[Makefile] +indent_style = tab diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6bf9c27 --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +.PHONY: helm-repos +helm-repos: + helm repo add jetstack https://charts.jetstack.io + helm repo add hcloud https://charts.hetzner.cloud + helm repo update + +.PHONY: install-cert-manager +install-cert-manager: helm-repos + helm upgrade --install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --version v1.12.2 \ + --set installCRDs=true \ + --set ingressShim.defaultIssuerName=letsencrypt-prod \ + --set ingressShim.defaultIssuerKind=ClusterIssuer \ + --set ingressShim.defaultIssuerGroup=cert-manager.io + +.PHONY: install-clusterissuer +install-clusterissuer: + kubectl apply -f ./manifests/clusterissuer.yaml + +.PHONY: install-hccm +install-hccm: + helm upgrade --install hccm hcloud/hcloud-cloud-controller-manager \ + --namespace kube-system \ + -f ./helm/values/hccm.yaml + +.PHONY: install-hcloud-csi-driver +install-hcloud-csi-driver: + kubectl apply -f ./manifests/hcloud-csi-driver.yaml + +.PHONY: install-keycloak +install-keycloak: helm-repos + helm upgrade --install keycloak oci://registry-1.docker.io/bitnamicharts/keycloak \ + --namespace mareshq-keycloak \ + --version 16.1.1 \ + -f ./helm/values/keycloak.yaml diff --git a/docs/converge.sql b/docs/converge.sql new file mode 100644 index 0000000..948dc5c --- /dev/null +++ b/docs/converge.sql @@ -0,0 +1,4 @@ +GRANT CONNECT ON DATABASE converge TO c4core; +GRANT ALL ON SCHEMA public TO c4core; +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO c4core; +GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO c4core; diff --git a/docs/create-postgres-user.md b/docs/create-postgres-user.md new file mode 100644 index 0000000..3d9c77d --- /dev/null +++ b/docs/create-postgres-user.md @@ -0,0 +1,14 @@ +# Create Postgres user + +```sql +CREATE DATABASE ; +\c ; + +CREATE USER WITH ENCRYPTED PASSWORD ''; + +GRANT CONNECT ON DATABASE TO ; +GRANT ALL ON SCHEMA public TO ; +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ; +GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ; +ALTER USER CREATEDB; # Prisma ORM needs this to run migrations +``` diff --git a/helm/values/hccm.yaml b/helm/values/hccm.yaml new file mode 100644 index 0000000..b7d6b76 --- /dev/null +++ b/helm/values/hccm.yaml @@ -0,0 +1,8 @@ +replicaCount: 2 + +env: + HCLOUD_TOKEN: + valueFrom: + secretKeyRef: + name: hcloud-token + key: token diff --git a/helm/values/keycloak.yaml b/helm/values/keycloak.yaml new file mode 100644 index 0000000..5f7eef8 --- /dev/null +++ b/helm/values/keycloak.yaml @@ -0,0 +1,112 @@ +auth: + adminUser: mareshqadmin + adminPassword: mareshqadmin + +global: + storageClass: longhorn + +replicaCount: 2 + +pdb: + create: true + minAvailable: 1 + +autoscaling: + enabled: false + +resources: + limits: + cpu: "1" + memory: 2Gi + requests: + cpu: 500m + memory: 1Gi + +# Pods must be spread across nodes +# See: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_affinities.tpl#L56-L106 +# podAntiAffinityPreset: hard + +updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + +service: + type: ClusterIP + # http: + # enable: false + +ingress: + enabled: true + hostname: sso.mareshq.com + + servicePort: https + + ingressClassName: nginx + + tls: true + + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + # Allow self-signed certificates on the backend + nginx.ingress.kubernetes.io/server-snippet: | + proxy_ssl_verify off; + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/proxy-buffering: "on" + nginx.ingress.kubernetes.io/proxy-buffers-number: "4" + nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" + +tls: + enabled: true + autoGenerated: true + +production: true + +metrics: + enabled: true + + serviceMonitor: + enabled: false + +postgresql: + enabled: false + +externalDatabase: + existingSecret: mareshq-keycloak-database-credentials + existingSecretHostKey: host + existingSecretPortKey: port + existingSecretUserKey: username + existingSecretDatabaseKey: database + existingSecretPasswordKey: password + +startupProbe: + # Keycloak should be ready to serve requests within 15 minutes + enabled: true + initialDelaySeconds: 180 # 3min + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 80 # 12min + successThreshold: 1 + +# Custom theme installation and configuration +initContainers: + - name: theme-installer + image: busybox:latest + command: + - /bin/sh + - "-c" + - | + wget https://vojtechmares.github.io/cdn/keywind.tar.gz -O /tmp/keywind.tar.gz + tar -xzvf /tmp/keywind.tar.gz -C /opt/bitnami/keycloak/themes + + volumeMounts: + - mountPath: /opt/bitnami/keycloak/themes/keywind + name: theme + +extraVolumes: + - name: theme + emptyDir: {} + +extraVolumeMounts: + - name: theme + mountPath: /opt/bitnami/keycloak/themes/keywind diff --git a/manifests/clusterissuer.yaml b/manifests/clusterissuer.yaml new file mode 100644 index 0000000..ea35e62 --- /dev/null +++ b/manifests/clusterissuer.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + email: me+infra@vojtechmares.com + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-prod + solvers: + - http01: + ingress: + class: nginx diff --git a/manifests/hcloud-csi-driver.yaml b/manifests/hcloud-csi-driver.yaml new file mode 100644 index 0000000..de2f5ea --- /dev/null +++ b/manifests/hcloud-csi-driver.yaml @@ -0,0 +1,393 @@ +allowVolumeExpansion: true +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + annotations: + storageclass.kubernetes.io/is-default-class: "true" + name: hcloud-volumes +provisioner: csi.hetzner.cloud +volumeBindingMode: WaitForFirstConsumer +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: hcloud-csi-controller + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: hcloud-csi-controller +rules: + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - update + - patch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - csi.storage.k8s.io + resources: + - csinodeinfos + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - csinodes + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - volumeattachments + verbs: + - get + - list + - watch + - update + - patch + - apiGroups: + - storage.k8s.io + resources: + - volumeattachments/status + verbs: + - patch + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - create + - delete + - patch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + - persistentvolumeclaims/status + verbs: + - get + - list + - watch + - update + - patch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - list + - watch + - create + - update + - patch + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - get + - list + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshotcontents + verbs: + - get + - list + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - get + - list + - watch + - create + - update + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: hcloud-csi-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: hcloud-csi-controller +subjects: + - kind: ServiceAccount + name: hcloud-csi-controller + namespace: kube-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: hcloud-csi-controller + name: hcloud-csi-controller-metrics + namespace: kube-system +spec: + ports: + - name: metrics + port: 9189 + targetPort: metrics + selector: + app: hcloud-csi-controller +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: hcloud-csi + name: hcloud-csi-node-metrics + namespace: kube-system +spec: + ports: + - name: metrics + port: 9189 + targetPort: metrics + selector: + app: hcloud-csi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hcloud-csi-controller + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app: hcloud-csi-controller + template: + metadata: + labels: + app: hcloud-csi-controller + spec: + containers: + - args: + - --default-fstype=ext4 + image: registry.k8s.io/sig-storage/csi-attacher:v4.1.0 + name: csi-attacher + volumeMounts: + - mountPath: /run/csi + name: socket-dir + - image: registry.k8s.io/sig-storage/csi-resizer:v1.7.0 + name: csi-resizer + volumeMounts: + - mountPath: /run/csi + name: socket-dir + - args: + - --feature-gates=Topology=true + - --default-fstype=ext4 + image: registry.k8s.io/sig-storage/csi-provisioner:v3.4.0 + name: csi-provisioner + volumeMounts: + - mountPath: /run/csi + name: socket-dir + - command: + - /bin/hcloud-csi-driver-controller + env: + - name: CSI_ENDPOINT + value: unix:///run/csi/socket + - name: METRICS_ENDPOINT + value: 0.0.0.0:9189 + - name: ENABLE_METRICS + value: "true" + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: HCLOUD_TOKEN + valueFrom: + secretKeyRef: + key: token + name: hcloud-token + image: hetznercloud/hcloud-csi-driver:v2.4.0 # x-release-please-version + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + periodSeconds: 2 + timeoutSeconds: 3 + name: hcloud-csi-driver + ports: + - containerPort: 9189 + name: metrics + - containerPort: 9808 + name: healthz + protocol: TCP + volumeMounts: + - mountPath: /run/csi + name: socket-dir + - image: registry.k8s.io/sig-storage/livenessprobe:v2.9.0 + imagePullPolicy: Always + name: liveness-probe + volumeMounts: + - mountPath: /run/csi + name: socket-dir + serviceAccountName: hcloud-csi-controller + volumes: + - emptyDir: {} + name: socket-dir +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + app: hcloud-csi + name: hcloud-csi-node + namespace: kube-system +spec: + selector: + matchLabels: + app: hcloud-csi + template: + metadata: + labels: + app: hcloud-csi + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: instance.hetzner.cloud/is-root-server + operator: NotIn + values: + - "true" + containers: + - args: + - --kubelet-registration-path=/var/lib/kubelet/plugins/csi.hetzner.cloud/socket + image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.7.0 + name: csi-node-driver-registrar + volumeMounts: + - mountPath: /run/csi + name: plugin-dir + - mountPath: /registration + name: registration-dir + - command: + - /bin/hcloud-csi-driver-node + env: + - name: CSI_ENDPOINT + value: unix:///run/csi/socket + - name: METRICS_ENDPOINT + value: 0.0.0.0:9189 + - name: ENABLE_METRICS + value: "true" + image: hetznercloud/hcloud-csi-driver:v2.4.0 # x-release-please-version + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + periodSeconds: 2 + timeoutSeconds: 3 + name: hcloud-csi-driver + ports: + - containerPort: 9189 + name: metrics + - containerPort: 9808 + name: healthz + protocol: TCP + securityContext: + privileged: true + volumeMounts: + - mountPath: /var/lib/kubelet + mountPropagation: Bidirectional + name: kubelet-dir + - mountPath: /run/csi + name: plugin-dir + - mountPath: /dev + name: device-dir + - image: registry.k8s.io/sig-storage/livenessprobe:v2.9.0 + imagePullPolicy: Always + name: liveness-probe + volumeMounts: + - mountPath: /run/csi + name: plugin-dir + tolerations: + - effect: NoExecute + operator: Exists + - effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + volumes: + - hostPath: + path: /var/lib/kubelet + type: Directory + name: kubelet-dir + - hostPath: + path: /var/lib/kubelet/plugins/csi.hetzner.cloud/ + type: DirectoryOrCreate + name: plugin-dir + - hostPath: + path: /var/lib/kubelet/plugins_registry/ + type: Directory + name: registration-dir + - hostPath: + path: /dev + type: Directory + name: device-dir +--- +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: csi.hetzner.cloud +spec: + attachRequired: true + fsGroupPolicy: File + podInfoOnMount: true + volumeLifecycleModes: + - Persistent diff --git a/manifests/hcloud-token.yaml b/manifests/hcloud-token.yaml new file mode 100644 index 0000000..503981c --- /dev/null +++ b/manifests/hcloud-token.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: hcloud-token + namespace: kube-system +type: Opaque +data: + # n9IOtQfzXjSnsXSxUtGNOmfnr2uWaQVbpbve7wOphQPv0Flm1ssol5SCWYxn8vIs + token: bjlJT3RRZnpYalNuc1hTeFV0R05PbWZucjJ1V2FRVmJwYnZlN3dPcGhRUHYwRmxtMXNzb2w1U0NXWXhuOHZJcw== diff --git a/rke2/config.yaml b/rke2/config.yaml new file mode 100644 index 0000000..68939bc --- /dev/null +++ b/rke2/config.yaml @@ -0,0 +1,21 @@ +write-kubeconfig-mode: "0644" +tls-san: + - "node-0.kiwi.k8s.vxm.cz" + +# profile: "cis-1.5" + +#disable: +# - rke2-canal +# - rke2-kube-proxy + +# disable-kube-proxy: true + +#cni: +# - cilium + +enable-servicelb: false + +# Make a etcd snapshot every 6 hours +etcd-snapshot-schedule-cron: " */6 * * *" +# Keep 56 etcd snapshots (equals to 2 weeks with 6 a day) +etcd-snapshot-retention: 56 diff --git a/rke2/rke2-ingress-nginx-config.yaml b/rke2/rke2-ingress-nginx-config.yaml new file mode 100644 index 0000000..e45c963 --- /dev/null +++ b/rke2/rke2-ingress-nginx-config.yaml @@ -0,0 +1,15 @@ +apiVersion: helm.cattle.io/v1 +kind: HelmChartConfig +metadata: + name: rke2-ingress-nginx + namespace: kube-system +spec: + valuesContent: |- + controller: + config: + allow-snippet-annotations: "true" + metrics: + service: + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "10254"