diff --git a/apps/garm/configmap.yaml b/apps/garm/configmap.yaml new file mode 100644 index 0000000..7b80fb9 --- /dev/null +++ b/apps/garm/configmap.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: garm-provider-k8s-config + namespace: garm +data: + provider-config.yaml: | + kubeConfigPath: "" + runnerNamespace: "garm-runners" + podTemplate: + spec: + restartPolicy: Never + flavors: + default: + requests: + cpu: 100m + memory: 512Mi + limits: + memory: 2Gi diff --git a/apps/garm/deployment.yaml b/apps/garm/deployment.yaml new file mode 100644 index 0000000..3231874 --- /dev/null +++ b/apps/garm/deployment.yaml @@ -0,0 +1,122 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: garm + namespace: garm +spec: + replicas: 1 + selector: + matchLabels: + app: garm + template: + metadata: + labels: + app: garm + spec: + serviceAccountName: garm + initContainers: + - name: install-garm-provider-k8s + image: alpine:3.21 + command: + - /bin/sh + - -ec + - | + wget -qO /tmp/garm-provider-k8s.tar.gz "https://github.com/mercedes-benz/garm-provider-k8s/releases/download/v0.3.2/garm-provider-k8s_Linux_x86_64.tar.gz" + tar -xzf /tmp/garm-provider-k8s.tar.gz -C /opt/garm/providers.d + chmod 0755 /opt/garm/providers.d/garm-provider-k8s + volumeMounts: + - name: provider-dir + mountPath: /opt/garm/providers.d + - name: render-garm-config + image: alpine:3.21 + env: + - name: JWT_AUTH_SECRET + valueFrom: + secretKeyRef: + name: garm-config + key: jwt_auth_secret + - name: DATABASE_PASSPHRASE + valueFrom: + secretKeyRef: + name: garm-config + key: database_passphrase + command: + - /bin/sh + - -ec + - | + cat < /etc/garm/config.toml + [default] + enable_webhook_management = true + + [logging] + enable_log_streamer = true + log_format = "text" + log_level = "info" + log_source = false + + [metrics] + enable = true + disable_auth = false + + [jwt_auth] + secret = "${JWT_AUTH_SECRET}" + time_to_live = "8760h" + + [apiserver] + bind = "0.0.0.0" + port = 9997 + use_tls = false + [apiserver.webui] + enable = true + + [database] + backend = "sqlite3" + passphrase = "${DATABASE_PASSPHRASE}" + [database.sqlite3] + db_file = "/data/garm.db" + busy_timeout_seconds = 5 + + [[provider]] + name = "kubernetes_external" + description = "Kubernetes provider" + provider_type = "external" + [provider.external] + config_file = "/etc/garm/provider-config.yaml" + provider_executable = "/opt/garm/providers.d/garm-provider-k8s" + environment_variables = ["KUBERNETES_"] + EOF + volumeMounts: + - name: config-dir + mountPath: /etc/garm + containers: + - name: garm + image: ghcr.io/cloudbase/garm:v0.1.7 + imagePullPolicy: IfNotPresent + command: + - /bin/garm + - --config + - /etc/garm/config.toml + ports: + - name: http + containerPort: 9997 + volumeMounts: + - name: data + mountPath: /data + - name: config-dir + mountPath: /etc/garm + - name: provider-dir + mountPath: /opt/garm/providers.d + - name: provider-config + mountPath: /etc/garm/provider-config.yaml + subPath: provider-config.yaml + volumes: + - name: data + persistentVolumeClaim: + claimName: garm-lvmhdd + - name: config-dir + emptyDir: {} + - name: provider-dir + emptyDir: {} + - name: provider-config + configMap: + name: garm-provider-k8s-config diff --git a/apps/garm/kustomization.yaml b/apps/garm/kustomization.yaml new file mode 100644 index 0000000..3b59249 --- /dev/null +++ b/apps/garm/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - pvc.yaml + - configmap.yaml + - service.yaml + - rbac.yaml + - secret.yaml + - deployment.yaml diff --git a/apps/garm/namespace.yaml b/apps/garm/namespace.yaml new file mode 100644 index 0000000..d3e29ef --- /dev/null +++ b/apps/garm/namespace.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: garm +--- +apiVersion: v1 +kind: Namespace +metadata: + name: garm-runners diff --git a/apps/garm/pvc.yaml b/apps/garm/pvc.yaml new file mode 100644 index 0000000..6da9b22 --- /dev/null +++ b/apps/garm/pvc.yaml @@ -0,0 +1,46 @@ +--- +apiVersion: local.openebs.io/v1alpha1 +kind: LVMVolume +metadata: + labels: + kubernetes.io/nodename: anapistula-delrosalae + name: garm-lvmhdd + namespace: openebs +spec: + capacity: 5Gi + ownerNodeID: anapistula-delrosalae + shared: "yes" + thinProvision: "no" + vgPattern: ^openebs-hdd$ + volGroup: openebs-hdd +--- +kind: PersistentVolume +apiVersion: v1 +metadata: + name: garm-lvmhdd +spec: + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + storageClassName: hdd-lvmpv + volumeMode: Filesystem + csi: + driver: local.csi.openebs.io + fsType: btrfs + volumeHandle: garm-lvmhdd +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: garm-lvmhdd + namespace: garm +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: hdd-lvmpv + volumeName: garm-lvmhdd diff --git a/apps/garm/rbac.yaml b/apps/garm/rbac.yaml new file mode 100644 index 0000000..fc93ab8 --- /dev/null +++ b/apps/garm/rbac.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: garm + namespace: garm +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: garm-provider-k8s + namespace: garm-runners +rules: + - apiGroups: [""] + resources: ["pods", "pods/log", "configmaps", "secrets", "events"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: garm-provider-k8s + namespace: garm-runners +subjects: + - kind: ServiceAccount + name: garm + namespace: garm +roleRef: + kind: Role + name: garm-provider-k8s + apiGroup: rbac.authorization.k8s.io diff --git a/apps/garm/secret.yaml b/apps/garm/secret.yaml new file mode 100644 index 0000000..ebc47bb --- /dev/null +++ b/apps/garm/secret.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultAuth +metadata: + name: garm + namespace: garm +spec: + method: kubernetes + mount: kubernetes + kubernetes: + role: garm + serviceAccount: garm +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret +metadata: + name: garm-config + namespace: garm +spec: + type: kv-v2 + + mount: secret + path: garm + + destination: + create: true + name: garm-config + type: Opaque + transformation: + excludeRaw: true + + vaultAuthRef: garm diff --git a/apps/garm/service.yaml b/apps/garm/service.yaml new file mode 100644 index 0000000..1fad383 --- /dev/null +++ b/apps/garm/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: garm + namespace: garm +spec: + type: ClusterIP + selector: + app: garm + ports: + - name: http + port: 9997 + targetPort: 9997 + protocol: TCP diff --git a/apps/gitea/release.yaml b/apps/gitea/release.yaml index 89efcc2..6424d4c 100644 --- a/apps/gitea/release.yaml +++ b/apps/gitea/release.yaml @@ -72,6 +72,8 @@ spec: indexer: ISSUE_INDEXER_TYPE: bleve REPO_INDEXER_ENABLED: true + webhook: + ALLOWED_HOST_LIST: garm.garm.svc.cluster.local admin: username: GiteaAdmin email: gi@tea.com diff --git a/apps/kustomization.yaml b/apps/kustomization.yaml index e339d19..a92f5b0 100644 --- a/apps/kustomization.yaml +++ b/apps/kustomization.yaml @@ -11,3 +11,4 @@ resources: - searxng - ispeak3 - openwebui + - garm diff --git a/vault/kubernetes-roles/garm.yaml b/vault/kubernetes-roles/garm.yaml new file mode 100644 index 0000000..615f841 --- /dev/null +++ b/vault/kubernetes-roles/garm.yaml @@ -0,0 +1,6 @@ +bound_service_account_names: + - garm +bound_service_account_namespaces: + - garm +token_policies: + - garm diff --git a/vault/policy/garm.hcl b/vault/policy/garm.hcl new file mode 100644 index 0000000..35d5005 --- /dev/null +++ b/vault/policy/garm.hcl @@ -0,0 +1,7 @@ +path "secret/data/garm" { + capabilities = ["read"] +} + +path "secret/data/backblaze" { + capabilities = ["read"] +}