Compare commits

...

14 Commits

Author SHA1 Message Date
unkinben d9ea57a8e0 chore: enable access to gitea
- add gitea to gitea-dl remote
2026-06-06 19:43:41 +10:00
unkinben 90a18e5ff9 chore: add almalinux-vault repos (#186)
- 9.7 is end of life, ensure that we can still query packages

Reviewed-on: #186
2026-06-06 19:42:59 +10:00
unkinben 4b1fbe1fe1 feat(kanidm): scale down to single replica, remove replication (#185)
Drop from 3 replicas to 1. Remove init container, repl-certs secret,
replication port, podAntiAffinity, server-1/2 configs, and replication
stanza from server-0.toml. Mount configmap directly via subPath.

Reviewed-on: #185
2026-06-02 22:41:28 +10:00
unkinben 666f3d055c feat: add sessionaffinity to kanidm service (#184)
- required as traefik is in passthrough mode

Reviewed-on: #184
2026-06-02 21:17:51 +10:00
unkinben 3dc8801070 fix(kanidm): fix automatic_refresh TOML generation in init container (#182)
## Summary

- The `\n` escape in a shell variable wasn't interpreted as a newline when passed as a `printf %s` argument
- This caused `automatic_refresh = true` to be appended to the `partner_cert` string value on the same line, breaking TOML parsing on kanidm-2
- Fixed by using separate `printf` calls per peer type, with `\n` in the format string (not a variable) where it is correctly interpreted

## Test plan

- [ ] kanidm-2 init container generates valid TOML with `automatic_refresh = true` on its own line under the kanidm-0 peer section
- [ ] kanidm-1 and kanidm-2 start successfully and auto-refresh domain UUID from kanidm-0

Reviewed-on: #182
2026-05-31 00:25:21 +10:00
unkinben 60f1f3130b fix(kanidm): replicate 1/2 from 0 only with automatic_refresh (#181)
kanidm-0 is the authoritative supplier; kanidm-1 and kanidm-2 pull
from kanidm-0 only. automatic_refresh = true on the kanidm-0 peer
entry for kanidm-1/2 so fresh nodes auto-sync domain UUID on restart.

Reviewed-on: #181
2026-05-31 00:20:30 +10:00
unkinben b6f8cb0633 feat: autorestart statefulset (#180)
- ensure kanidm is restarted with vault secrets

Reviewed-on: #180
2026-05-30 23:40:07 +10:00
unkinben f11ec1056d fix(kanidm): remove invalid automatic_refresh from replication config (#179)
Reviewed-on: #179
2026-05-30 23:20:48 +10:00
unkinben ed7feaf19a Update apps/base/kanidm/vaultauth.yaml (#177)
Fix the VaultAuth object

Reviewed-on: #177
2026-05-30 23:11:38 +10:00
unkinben 4d594fbde7 feat(kanidm): vault-managed replication certs with auto-restart (#176)
- Store per-pod replication certs in Vault (kv/kubernetes/namespace/kanidm/default/repl-certs)
- VaultAuth + VaultStaticSecret sync certs to kanidm-repl-certs Secret
- busybox config-init init container injects peer certs from Secret into server.toml at startup
- Remove hardcoded partner_cert entries from per-pod server.toml templates
- Add automatic_refresh = true to all replication configs
- Add reloader.stakater.com/auto annotation to trigger rolling restart on ConfigMap/Secret changes
- Document domain UUID mismatch resolution and cert rotation in README

Reviewed-on: #176
2026-05-30 23:00:46 +10:00
unkinben 1b781e0885 feat(woodpecker): set workflow pod priority class to power (#175)
## Summary
Sets `WOODPECKER_BACKEND_K8S_PRIORITY_CLASS: power` on the Woodpecker agent so all CI pipeline pods are scheduled with the `power` PriorityClass (value 100, preemptionPolicy: Never).

This means pipeline pods can be evicted when the cluster is under pressure but won't preempt other workloads.

## Dependency
Requires the `power` PriorityClass to exist on the cluster — deploy PR #174 (priority-classes app) first.

## Test plan
- Trigger a pipeline run and confirm pods are created with `priorityClassName: power`
- `kubectl get pod -n woodpecker -o jsonpath='{.items[*].spec.priorityClassName}'`

Reviewed-on: #175
2026-05-26 23:58:57 +10:00
unkinben ede25a3858 feat(platform): add priority-classes app with low/power/medium/high classes (#174)
## Summary
- New `apps/base/priority-classes/` app with four `PriorityClass` objects managed via the `platform` ArgoCD project
- Adds `apps/overlays/*/priority-classes` to the platform ApplicationSet generator
- Adds `priority-classes` namespace to platform AppProject destinations (required even for cluster-scoped resources)

| Class | Value | PreemptionPolicy | Intent |
|---|---|---|---|
| `low` | 100 | Never | Background work; evictable, won't preempt others |
| `power` | 100 | Never | Compute-heavy but expendable (e.g. AI/ML workloads) |
| `medium` | 10000 | PreemptLowerPriority | Standard services |
| `high` | 100000 | PreemptLowerPriority | Critical services; preempts lower-priority pods |

`PriorityClass` is already in the platform project's `clusterResourceWhitelist` so no project policy changes were needed.

## Test plan
- ArgoCD syncs `platform-priority-classes` successfully
- `kubectl get priorityclasses low power medium high` shows all four classes

Reviewed-on: #174
2026-05-26 23:41:54 +10:00
unkinben f5f713fe86 feat(artifactapi): add open-webui/open-webui to ghcr immutable patterns (#173)
Part of #155 (prerequisite for open-webui deployment PR #172).

## Summary
- Adds `^open-webui/open-webui` to the `ghcr` remote's `immutable_patterns` in `remote-docker.yaml` so version-pinned open-webui image pulls are cached indefinitely through artifactapi

## Test plan
- artifactapi serves `ghcr.io/open-webui/open-webui:<version>` with `X-Artifact-Source: cache` on second fetch

Reviewed-on: #173
2026-05-26 23:28:27 +10:00
unkinben 3990fbfe06 feat(vault): switch to Kubernetes service registration (#171)
Replaces Consul service registration with the native Kubernetes provider so Vault labels its own pods with active/standby/perf-standby status without requiring a Consul dependency.

## Changes
- `values.yaml`: swap `service_registration "consul"` for `service_registration "kubernetes" {}`, add `VAULT_K8S_NAMESPACE` and `VAULT_K8S_POD_NAME` env vars via downward API
- `role_k8s-service-registration.yaml`: Role + RoleBinding granting the `vault` service account `get`/`update`/`patch` on pods
- `kustomization.yaml`: include new RBAC file

Reviewed-on: #171
2026-05-26 00:06:56 +10:00
21 changed files with 197 additions and 129 deletions
@@ -6,6 +6,7 @@ remotes:
immutable_patterns: immutable_patterns:
- "^cloudnative-pg/cloudnative-pg" - "^cloudnative-pg/cloudnative-pg"
- "^emberstack/helm-charts" - "^emberstack/helm-charts"
- "^open-webui/open-webui"
- "^openvoxproject/" - "^openvoxproject/"
- "^stakater/reloader" - "^stakater/reloader"
- "^stalwartlabs/stalwart" - "^stalwartlabs/stalwart"
@@ -81,6 +81,8 @@ remotes:
description: "Gitea download site" description: "Gitea download site"
immutable_patterns: immutable_patterns:
- "act_runner/.*/act_runner-.*-linux-amd64$" - "act_runner/.*/act_runner-.*-linux-amd64$"
- "gitea/.*/gitea-.*-linux-amd64$"
- "gitea/.*/gitea-.*-linux-amd64.xz$"
- "tea/.*/tea-.*-linux-amd64$" - "tea/.*/tea-.*-linux-amd64$"
cache: cache:
immutable_ttl: 0 immutable_ttl: 0
@@ -17,6 +17,24 @@ remotes:
immutable_ttl: 0 immutable_ttl: 0
mutable_ttl: 7200 mutable_ttl: 7200
almalinux-vault:
base_url: "https://vault.almalinux.org"
package: "rpm"
description: "AlmaLinux Vault RPM package repository"
immutable_patterns:
- ".*/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
- ".*/repodata/.*\\.sqlite.*$"
- ".*/repodata/.*\\.xml.*$"
- ".*/repodata/.*\\.yaml.*$"
- ".*/install.img"
- ".*/squashfs.img"
- ".*/updates.img"
- ".*/RPM-GPG-KEY-.*$"
cache:
immutable_ttl: 0
mutable_ttl: 7200
ceph-reef: ceph-reef:
base_url: "https://download.ceph.com/rpm-reef/" base_url: "https://download.ceph.com/rpm-reef/"
package: "rpm" package: "rpm"
+37 -18
View File
@@ -1,32 +1,51 @@
# kanidm # kanidm
Single-replica kanidm identity server deployment. Three-replica kanidm identity server with Vault-managed replication certificates.
## Architecture
- Per-pod `server-N.toml` in `resources/` — each has its own replication origin hardcoded
- `config-init` busybox init container copies the right config and injects peer certs from the
vault-synced `kanidm-repl-certs` Secret at pod startup
- `reloader.stakater.com/auto: "true"` triggers a rolling restart when the ConfigMap or Secret changes
- Vault path: `kv/kubernetes/namespace/kanidm/default/repl-certs`
- Keys: `kanidm-0`, `kanidm-1`, `kanidm-2` — each holds that pod's replication certificate
## Initial setup ## Initial setup
After the pod starts for the first time, generate the admin and idm_admin credentials: After the first pod starts, generate the admin credentials:
```bash ```bash
kubectl exec -n kanidm kanidm-0 -- /sbin/kanidmd recover-account admin kubectl exec -n kanidm kanidm-0 -- /sbin/kanidmd recover-account -c /config/server.toml admin
kubectl exec -n kanidm kanidm-0 -- /sbin/kanidmd recover-account idm_admin kubectl exec -n kanidm kanidm-0 -- /sbin/kanidmd recover-account -c /config/server.toml idm_admin
``` ```
## Adding replication ## Replication certificate rotation
If replication is needed in the future: When certs need to be renewed, update vault and reloader will roll the StatefulSet:
1. Scale the StatefulSet to 3 replicas and add `podAntiAffinity` to spread across nodes.
2. Add a `[replication]` section to `configmap.yaml` per pod (origin is pod-specific:
`repl://kanidm-N.kanidm-headless.kanidm.svc.cluster.local:8444`).
3. Add the replication port (8444) back to the StatefulSet container ports and headless service.
4. Restore `rbac.yaml` for the cert-publisher sidecar, or exchange certificates manually:
```bash ```bash
# On each pod, get its replication certificate # Get new cert from a pod
kubectl exec -n kanidm kanidm-0 -- /sbin/kanidmd renew-replication-certificate kubectl exec -it -n kanidm kanidm-N -- /sbin/kanidmd renew-replication-certificate -c /config/server.toml
# Add each peer's certificate to the other pods' configs under: # Write updated cert to vault (reloader triggers restart automatically)
# [replication."repl://<peer-fqdn>:8444"] vault kv patch kv/kubernetes/namespace/kanidm/default/repl-certs "kanidm-N=<cert>"
# type = "mutual-pull" ```
# partner_cert = "<cert>"
## Resolving domain UUID mismatch
If pods initialized independently (each with a different domain UUID), replication will fail with
`Consumer Domain UUID does not match`. Fix by resetting kanidm-1 and kanidm-2 to sync from
kanidm-0 (the authoritative node):
```bash
# Scale down to avoid split-brain during reset
kubectl scale statefulset -n kanidm kanidm --replicas=1
# Delete the stale PVCs for the replica pods
kubectl delete pvc -n kanidm data-kanidm-1 data-kanidm-2
# Scale back up — replicas start with empty DBs and automatic_refresh=true
# will trigger a full sync from kanidm-0 once TLS peer certs are verified
kubectl scale statefulset -n kanidm kanidm --replicas=3
``` ```
+2 -2
View File
@@ -5,6 +5,8 @@ kind: Kustomization
resources: resources:
- namespace.yaml - namespace.yaml
- serviceaccount.yaml - serviceaccount.yaml
- vaultauth.yaml
- vaultstaticsecret.yaml
- certificate.yaml - certificate.yaml
- service.yaml - service.yaml
- statefulset.yaml - statefulset.yaml
@@ -23,5 +25,3 @@ configMapGenerator:
app.kubernetes.io/instance: kanidm app.kubernetes.io/instance: kanidm
files: files:
- server-0.toml=resources/server-0.toml - server-0.toml=resources/server-0.toml
- server-1.toml=resources/server-1.toml
- server-2.toml=resources/server-2.toml
-12
View File
@@ -13,15 +13,3 @@ log_level = "info"
path = "/data/backups/" path = "/data/backups/"
schedule = "0 22 * * *" schedule = "0 22 * * *"
versions = 7 versions = 7
[replication]
origin = "repl://kanidm-0.kanidm-headless.kanidm.svc.cluster.local:8444"
bindaddress = "[::]:8444"
[replication."repl://kanidm-1.kanidm-headless.kanidm.svc.cluster.local:8444"]
type = "mutual-pull"
partner_cert = "MIIB-TCCAZ-gAwIBAgIRASqOpORz60wiv7wF_7oBOxQwCgYIKoZIzj0EAwIwTDEtMCsGA1UEAwwkMmE4ZWE0ZTQtNzNlYi00YzIyLWJmYmMtMDVmZmJhMDEzYjE0MRswGQYDVQQKDBJLYW5pZG0gUmVwbGljYXRpb24wHhcNMjYwNTI1MTMyODM5WhcNMzAwNTI1MTMyODM5WjBMMS0wKwYDVQQDDCQyYThlYTRlNC03M2ViLTRjMjItYmZiYy0wNWZmYmEwMTNiMTQxGzAZBgNVBAoMEkthbmlkbSBSZXBsaWNhdGlvbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFQP3zpFRt7TCOhzrUpOJBojn-sC2LmqZUub8P2ymVdIQbmoAyh4Q8Me0hNWJFyuFDnnqO06dt5I2iv0910-X6KjYjBgMCAGA1UdJQEB_wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATA8BgNVHREENTAzgjFrYW5pZG0tMS5rYW5pZG0taGVhZGxlc3Mua2FuaWRtLnN2Yy5jbHVzdGVyLmxvY2FsMAoGCCqGSM49BAMCA0gAMEUCIGjl58U6apcDjMEPIca8Wwg_JMfuMvV-uVcJI49Gl_9GAiEA2tFdb9rnFeBI7mwysScf5UsmY3ZziMD3UVm1vWN2IKs"
[replication."repl://kanidm-2.kanidm-headless.kanidm.svc.cluster.local:8444"]
type = "mutual-pull"
partner_cert = "MIIB-TCCAZ-gAwIBAgIRAeFGUAJbCkJ2vzf_Vv4qjeUwCgYIKoZIzj0EAwIwTDEtMCsGA1UEAwwkZTE0NjUwMDItNWIwYS00Mjc2LWJmMzctZmY1NmZlMmE4ZGU1MRswGQYDVQQKDBJLYW5pZG0gUmVwbGljYXRpb24wHhcNMjYwNTI1MTMyOTEwWhcNMzAwNTI1MTMyOTEwWjBMMS0wKwYDVQQDDCRlMTQ2NTAwMi01YjBhLTQyNzYtYmYzNy1mZjU2ZmUyYThkZTUxGzAZBgNVBAoMEkthbmlkbSBSZXBsaWNhdGlvbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCrncHSbDNSV3_aOSZ14plbVfrvSXQQL9MOqvrDKlf_Q6WbcA8OrTUjs3Jt0Q2beWjC3Z5-5c9fGu8M_k2iVWf-jYjBgMCAGA1UdJQEB_wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATA8BgNVHREENTAzgjFrYW5pZG0tMi5rYW5pZG0taGVhZGxlc3Mua2FuaWRtLnN2Yy5jbHVzdGVyLmxvY2FsMAoGCCqGSM49BAMCA0gAMEUCIQDHY5Yl-bhDTuJaYnHSMSiSAEWPrDcRVzvfmOJukuJ1QQIgSwgyeSG3K0MY87DI1RDYAdZlpP1YOK3Yatj7-YSXPC0"
-27
View File
@@ -1,27 +0,0 @@
version = "2"
domain = "auth.unkin.net"
origin = "https://auth.unkin.net"
bindaddress = "[::]:8443"
db_path = "/data/kanidm.db"
db_arc_size = 2048
tls_chain = "/data/tls/tls.crt"
tls_key = "/data/tls/tls.key"
log_level = "info"
[online_backup]
path = "/data/backups/"
schedule = "0 22 * * *"
versions = 7
[replication]
origin = "repl://kanidm-1.kanidm-headless.kanidm.svc.cluster.local:8444"
bindaddress = "[::]:8444"
[replication."repl://kanidm-0.kanidm-headless.kanidm.svc.cluster.local:8444"]
type = "mutual-pull"
partner_cert = "MIIB-jCCAZ-gAwIBAgIRAVKuoPDpF0IBnvFjCwdK41EwCgYIKoZIzj0EAwIwTDEtMCsGA1UEAwwkNTJhZWEwZjAtZTkxNy00MjAxLTllZjEtNjMwYjA3NGFlMzUxMRswGQYDVQQKDBJLYW5pZG0gUmVwbGljYXRpb24wHhcNMjYwNTI1MTMzNzQ5WhcNMzAwNTI1MTMzNzQ5WjBMMS0wKwYDVQQDDCQ1MmFlYTBmMC1lOTE3LTQyMDEtOWVmMS02MzBiMDc0YWUzNTExGzAZBgNVBAoMEkthbmlkbSBSZXBsaWNhdGlvbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGejqjk0Eet-RILHI236wHYqISdnPlebqnkuUTh4W2mCzkmqKibyjxGIUOs8LBrUeTR2DxVR1VV6H2rYQk2wdROjYjBgMCAGA1UdJQEB_wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATA8BgNVHREENTAzgjFrYW5pZG0tMC5rYW5pZG0taGVhZGxlc3Mua2FuaWRtLnN2Yy5jbHVzdGVyLmxvY2FsMAoGCCqGSM49BAMCA0kAMEYCIQCSkFj2A-KVWv2tKJLFzb18J5eWWKtsvWewZTn-FVnRnQIhAKJbt84IoZ9oXxgfp0VOLyVZiAgUgwMFS6JOfno3D-Nw"
[replication."repl://kanidm-2.kanidm-headless.kanidm.svc.cluster.local:8444"]
type = "mutual-pull"
partner_cert = "MIIB-TCCAZ-gAwIBAgIRAeFGUAJbCkJ2vzf_Vv4qjeUwCgYIKoZIzj0EAwIwTDEtMCsGA1UEAwwkZTE0NjUwMDItNWIwYS00Mjc2LWJmMzctZmY1NmZlMmE4ZGU1MRswGQYDVQQKDBJLYW5pZG0gUmVwbGljYXRpb24wHhcNMjYwNTI1MTMyOTEwWhcNMzAwNTI1MTMyOTEwWjBMMS0wKwYDVQQDDCRlMTQ2NTAwMi01YjBhLTQyNzYtYmYzNy1mZjU2ZmUyYThkZTUxGzAZBgNVBAoMEkthbmlkbSBSZXBsaWNhdGlvbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCrncHSbDNSV3_aOSZ14plbVfrvSXQQL9MOqvrDKlf_Q6WbcA8OrTUjs3Jt0Q2beWjC3Z5-5c9fGu8M_k2iVWf-jYjBgMCAGA1UdJQEB_wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATA8BgNVHREENTAzgjFrYW5pZG0tMi5rYW5pZG0taGVhZGxlc3Mua2FuaWRtLnN2Yy5jbHVzdGVyLmxvY2FsMAoGCCqGSM49BAMCA0gAMEUCIQDHY5Yl-bhDTuJaYnHSMSiSAEWPrDcRVzvfmOJukuJ1QQIgSwgyeSG3K0MY87DI1RDYAdZlpP1YOK3Yatj7-YSXPC0"
-27
View File
@@ -1,27 +0,0 @@
version = "2"
domain = "auth.unkin.net"
origin = "https://auth.unkin.net"
bindaddress = "[::]:8443"
db_path = "/data/kanidm.db"
db_arc_size = 2048
tls_chain = "/data/tls/tls.crt"
tls_key = "/data/tls/tls.key"
log_level = "info"
[online_backup]
path = "/data/backups/"
schedule = "0 22 * * *"
versions = 7
[replication]
origin = "repl://kanidm-2.kanidm-headless.kanidm.svc.cluster.local:8444"
bindaddress = "[::]:8444"
[replication."repl://kanidm-0.kanidm-headless.kanidm.svc.cluster.local:8444"]
type = "mutual-pull"
partner_cert = "MIIB-jCCAZ-gAwIBAgIRAVKuoPDpF0IBnvFjCwdK41EwCgYIKoZIzj0EAwIwTDEtMCsGA1UEAwwkNTJhZWEwZjAtZTkxNy00MjAxLTllZjEtNjMwYjA3NGFlMzUxMRswGQYDVQQKDBJLYW5pZG0gUmVwbGljYXRpb24wHhcNMjYwNTI1MTMzNzQ5WhcNMzAwNTI1MTMzNzQ5WjBMMS0wKwYDVQQDDCQ1MmFlYTBmMC1lOTE3LTQyMDEtOWVmMS02MzBiMDc0YWUzNTExGzAZBgNVBAoMEkthbmlkbSBSZXBsaWNhdGlvbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGejqjk0Eet-RILHI236wHYqISdnPlebqnkuUTh4W2mCzkmqKibyjxGIUOs8LBrUeTR2DxVR1VV6H2rYQk2wdROjYjBgMCAGA1UdJQEB_wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATA8BgNVHREENTAzgjFrYW5pZG0tMC5rYW5pZG0taGVhZGxlc3Mua2FuaWRtLnN2Yy5jbHVzdGVyLmxvY2FsMAoGCCqGSM49BAMCA0kAMEYCIQCSkFj2A-KVWv2tKJLFzb18J5eWWKtsvWewZTn-FVnRnQIhAKJbt84IoZ9oXxgfp0VOLyVZiAgUgwMFS6JOfno3D-Nw"
[replication."repl://kanidm-1.kanidm-headless.kanidm.svc.cluster.local:8444"]
type = "mutual-pull"
partner_cert = "MIIB-TCCAZ-gAwIBAgIRASqOpORz60wiv7wF_7oBOxQwCgYIKoZIzj0EAwIwTDEtMCsGA1UEAwwkMmE4ZWE0ZTQtNzNlYi00YzIyLWJmYmMtMDVmZmJhMDEzYjE0MRswGQYDVQQKDBJLYW5pZG0gUmVwbGljYXRpb24wHhcNMjYwNTI1MTMyODM5WhcNMzAwNTI1MTMyODM5WjBMMS0wKwYDVQQDDCQyYThlYTRlNC03M2ViLTRjMjItYmZiYy0wNWZmYmEwMTNiMTQxGzAZBgNVBAoMEkthbmlkbSBSZXBsaWNhdGlvbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFQP3zpFRt7TCOhzrUpOJBojn-sC2LmqZUub8P2ymVdIQbmoAyh4Q8Me0hNWJFyuFDnnqO06dt5I2iv0910-X6KjYjBgMCAGA1UdJQEB_wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATA8BgNVHREENTAzgjFrYW5pZG0tMS5rYW5pZG0taGVhZGxlc3Mua2FuaWRtLnN2Yy5jbHVzdGVyLmxvY2FsMAoGCCqGSM49BAMCA0gAMEUCIGjl58U6apcDjMEPIca8Wwg_JMfuMvV-uVcJI49Gl_9GAiEA2tFdb9rnFeBI7mwysScf5UsmY3ZziMD3UVm1vWN2IKs"
+4 -4
View File
@@ -9,6 +9,10 @@ metadata:
app.kubernetes.io/instance: kanidm app.kubernetes.io/instance: kanidm
spec: spec:
type: ClusterIP type: ClusterIP
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
ports: ports:
- name: https - name: https
port: 8443 port: 8443
@@ -34,10 +38,6 @@ spec:
port: 8443 port: 8443
targetPort: https targetPort: https
protocol: TCP protocol: TCP
- name: replication
port: 8444
targetPort: replication
protocol: TCP
selector: selector:
app.kubernetes.io/name: kanidm app.kubernetes.io/name: kanidm
app.kubernetes.io/instance: kanidm app.kubernetes.io/instance: kanidm
+6 -36
View File
@@ -4,12 +4,14 @@ kind: StatefulSet
metadata: metadata:
name: kanidm name: kanidm
namespace: kanidm namespace: kanidm
annotations:
reloader.stakater.com/auto: "true"
labels: labels:
app.kubernetes.io/name: kanidm app.kubernetes.io/name: kanidm
app.kubernetes.io/instance: kanidm app.kubernetes.io/instance: kanidm
spec: spec:
serviceName: kanidm-headless serviceName: kanidm-headless
replicas: 3 replicas: 1
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: kanidm app.kubernetes.io/name: kanidm
@@ -21,39 +23,11 @@ spec:
app.kubernetes.io/instance: kanidm app.kubernetes.io/instance: kanidm
spec: spec:
serviceAccountName: kanidm serviceAccountName: kanidm
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: kanidm
app.kubernetes.io/instance: kanidm
topologyKey: kubernetes.io/hostname
securityContext: securityContext:
runAsUser: 1000 runAsUser: 1000
runAsGroup: 1000 runAsGroup: 1000
runAsNonRoot: true runAsNonRoot: true
fsGroup: 1000 fsGroup: 1000
initContainers:
- name: config-init
image: busybox:1.36
command: ["/bin/sh", "-c"]
args:
- cp "/config-template/server-${POD_NAME##*-}.toml" /config/server.toml
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeMounts:
- name: config-template
mountPath: /config-template
readOnly: true
- name: config
mountPath: /config
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
containers: containers:
- name: kanidm - name: kanidm
image: kanidm/server:1.10.3 image: kanidm/server:1.10.3
@@ -63,14 +37,12 @@ spec:
- name: https - name: https
containerPort: 8443 containerPort: 8443
protocol: TCP protocol: TCP
- name: replication
containerPort: 8444
protocol: TCP
volumeMounts: volumeMounts:
- name: data - name: data
mountPath: /data mountPath: /data
- name: config - name: config
mountPath: /config mountPath: /config/server.toml
subPath: server-0.toml
readOnly: true readOnly: true
- name: tls - name: tls
mountPath: /data/tls mountPath: /data/tls
@@ -96,11 +68,9 @@ spec:
initialDelaySeconds: 30 initialDelaySeconds: 30
periodSeconds: 30 periodSeconds: 30
volumes: volumes:
- name: config-template - name: config
configMap: configMap:
name: kanidm-config name: kanidm-config
- name: config
emptyDir: {}
- name: tls - name: tls
secret: secret:
secretName: kanidm-tls secretName: kanidm-tls
+18
View File
@@ -0,0 +1,18 @@
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: default
namespace: kanidm
spec:
allowedNamespaces:
- kanidm
kubernetes:
audiences:
- vault
role: default
serviceAccount: default
tokenExpirationSeconds: 600
method: kubernetes
mount: k8s/au/syd1
vaultConnectionRef: vso-system/default
+23
View File
@@ -0,0 +1,23 @@
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: repl-certs
namespace: kanidm
labels:
app.kubernetes.io/name: kanidm
app.kubernetes.io/instance: kanidm
spec:
vaultAuthRef: default
mount: kv
type: kv-v2
path: kubernetes/namespace/kanidm/default/repl-certs
refreshAfter: 5m
destination:
name: kanidm-repl-certs
create: true
overwrite: true
hmacSecretData: true
rolloutRestartTargets:
- kind: StatefulSet
name: kanidm
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- priorityclasses.yaml
@@ -0,0 +1,36 @@
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low
value: 100
preemptionPolicy: Never
globalDefault: false
description: "Low-importance workloads. Can be evicted under pressure but will not preempt other pods."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: power
value: 100
preemptionPolicy: Never
globalDefault: false
description: "Compute-heavy workloads with low scheduling importance. Evictable under pressure."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: medium
value: 10000
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: "Standard workloads. Will preempt low-priority pods if the cluster is under pressure."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high
value: 100000
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: "High-importance services. Will preempt medium- and low-priority pods if necessary."
+1
View File
@@ -6,3 +6,4 @@ resources:
- namespace.yaml - namespace.yaml
- gateway.yaml - gateway.yaml
- httproute.yaml - httproute.yaml
- role_k8s-service-registration.yaml
@@ -0,0 +1,24 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: vault-k8s-service-registration
namespace: vault
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: vault-k8s-service-registration
namespace: vault
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: vault-k8s-service-registration
subjects:
- kind: ServiceAccount
name: vault
namespace: vault
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base/priority-classes
+9 -3
View File
@@ -40,9 +40,7 @@ server:
} }
} }
service_registration "consul" { service_registration "kubernetes" {}
address = "consul-server.consul.svc.cluster.local:8500"
}
dataStorage: dataStorage:
enabled: true enabled: true
@@ -50,6 +48,14 @@ server:
storageClass: cephrbd-fast-delete storageClass: cephrbd-fast-delete
accessMode: ReadWriteOnce accessMode: ReadWriteOnce
extraEnv:
- name: VAULT_K8S_NAMESPACE
value: vault
- name: VAULT_K8S_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
statefulSet: statefulSet:
securityContext: securityContext:
container: container:
@@ -2,6 +2,7 @@ agent:
replicaCount: 3 replicaCount: 3
env: env:
WOODPECKER_MAX_WORKFLOWS: "8" WOODPECKER_MAX_WORKFLOWS: "8"
WOODPECKER_BACKEND_K8S_PRIORITY_CLASS: power
WOODPECKER_BACKEND_K8S_STORAGE_CLASS: cephrbd-fast-delete WOODPECKER_BACKEND_K8S_STORAGE_CLASS: cephrbd-fast-delete
WOODPECKER_BACKEND_K8S_VOLUME_SIZE: 10G WOODPECKER_BACKEND_K8S_VOLUME_SIZE: 10G
WOODPECKER_BACKEND_K8S_STORAGE_RWX: false WOODPECKER_BACKEND_K8S_STORAGE_RWX: false
+1
View File
@@ -22,6 +22,7 @@ spec:
- path: apps/overlays/*/jfrog - path: apps/overlays/*/jfrog
- path: apps/overlays/*/kanidm - path: apps/overlays/*/kanidm
- path: apps/overlays/*/node-feature-discovery - path: apps/overlays/*/node-feature-discovery
- path: apps/overlays/*/priority-classes
- path: apps/overlays/*/puppet - path: apps/overlays/*/puppet
- path: apps/overlays/*/purelb - path: apps/overlays/*/purelb
- path: apps/overlays/*/reflector-system - path: apps/overlays/*/reflector-system
+2
View File
@@ -31,6 +31,8 @@ spec:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
- namespace: 'node-feature-discovery' - namespace: 'node-feature-discovery'
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
- namespace: 'priority-classes'
server: https://kubernetes.default.svc
- namespace: 'purelb' - namespace: 'purelb'
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
- namespace: 'puppet' - namespace: 'puppet'