From 14e3946d4b95b6ba8967709886b84b4731a46a39 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Mon, 9 Mar 2026 01:10:30 +1100 Subject: [PATCH] feat: initial puppet deployment (#25) working towards a larger, redundant, autoscaling and simple puppet implementation in kubernetes. this was originally based on the openvox helm chart with several improvements (not all in this pr) - use of cnpg instead of single bitnamilegacy postgres container - use for g10k instead of r10k - run one instance of g10k per namespace, instead of per-pod - store only keep one copy of the environments/branches (instead of per-pod) - change g10k to native cronjob instead of hacky implementation - use vault secrets part one adds: - cnpg puppetdb pgsql cluster - cnpg puppetdb pgpooler - persistent volume claims for puppet, puppetdb, the code repository, etc Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/25 --- apps/base/puppet/cnpg_cluster.yaml | 94 +++++++++++++++ apps/base/puppet/cnpg_pooler.yaml | 33 ++++++ apps/base/puppet/cronjob_g10k-code.yaml | 106 +++++++++++++++++ apps/base/puppet/kustomization.yaml | 11 ++ apps/base/puppet/namespace.yaml | 5 + apps/base/puppet/persistentvolumeclaims.yaml | 108 ++++++++++++++++++ apps/base/puppet/vaultauth.yaml | 18 +++ apps/base/puppet/vaultstaticsecret.yaml | 34 ++++++ .../au-syd1/puppet/kustomization.yaml | 8 ++ argocd/applicationsets/platform.yaml | 1 + argocd/projects/platform.yaml | 2 + 11 files changed, 420 insertions(+) create mode 100644 apps/base/puppet/cnpg_cluster.yaml create mode 100644 apps/base/puppet/cnpg_pooler.yaml create mode 100644 apps/base/puppet/cronjob_g10k-code.yaml create mode 100644 apps/base/puppet/kustomization.yaml create mode 100644 apps/base/puppet/namespace.yaml create mode 100644 apps/base/puppet/persistentvolumeclaims.yaml create mode 100644 apps/base/puppet/vaultauth.yaml create mode 100644 apps/base/puppet/vaultstaticsecret.yaml create mode 100644 apps/overlays/au-syd1/puppet/kustomization.yaml diff --git a/apps/base/puppet/cnpg_cluster.yaml b/apps/base/puppet/cnpg_cluster.yaml new file mode 100644 index 0000000..7e0984a --- /dev/null +++ b/apps/base/puppet/cnpg_cluster.yaml @@ -0,0 +1,94 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: puppet-postgres + namespace: puppet +spec: + affinity: + podAntiAffinityType: preferred + bootstrap: + initdb: + database: puppetdb + encoding: UTF8 + localeCType: C + localeCollate: C + owner: puppetdb + secret: + name: postgres-credentials + postInitApplicationSQL: + - CREATE EXTENSION IF NOT EXISTS pg_trgm; + - CREATE EXTENSION IF NOT EXISTS pgcrypto; + enablePDB: true + enableSuperuserAccess: false + failoverDelay: 0 + imageName: ghcr.io/cloudnative-pg/postgresql:17-minimal-trixie + instances: 3 + logLevel: info + maxSyncReplicas: 0 + minSyncReplicas: 0 + monitoring: + customQueriesConfigMap: + - key: queries + name: cnpg-default-monitoring + disableDefaultQueries: false + enablePodMonitor: false + postgresql: + parameters: + archive_mode: "on" + archive_timeout: 5min + dynamic_shared_memory_type: posix + effective_cache_size: 256MB + full_page_writes: "on" + log_destination: csvlog + log_directory: /controller/log + log_filename: postgres + log_rotation_age: "0" + log_rotation_size: "0" + log_truncate_on_rotation: "false" + logging_collector: "on" + max_connections: "200" + max_parallel_workers: "16" + max_replication_slots: "16" + max_worker_processes: "16" + shared_buffers: 128MB + shared_memory_type: mmap + ssl_max_protocol_version: TLSv1.3 + ssl_min_protocol_version: TLSv1.3 + wal_keep_size: 256MB + wal_level: logical + wal_log_hints: "on" + wal_receiver_timeout: 5s + wal_sender_timeout: 5s + syncReplicaElectionConstraint: + enabled: false + primaryUpdateMethod: restart + primaryUpdateStrategy: unsupervised + probes: + liveness: + isolationCheck: + connectionTimeout: 1000 + enabled: true + requestTimeout: 1000 + replicationSlots: + highAvailability: + enabled: true + slotPrefix: _cnpg_ + synchronizeReplicas: + enabled: true + updateInterval: 30 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 250m + memory: 256Mi + smartShutdownTimeout: 180 + startDelay: 3600 + stopDelay: 1800 + storage: + resizeInUseVolumes: true + size: 10Gi + storageClass: cephrbd-fast-delete + switchoverDelay: 3600 diff --git a/apps/base/puppet/cnpg_pooler.yaml b/apps/base/puppet/cnpg_pooler.yaml new file mode 100644 index 0000000..e82e660 --- /dev/null +++ b/apps/base/puppet/cnpg_pooler.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Pooler +metadata: + name: puppet-postgres-pooler + namespace: puppet +spec: + cluster: + name: puppet-postgres + instances: 2 + pgbouncer: + parameters: + default_pool_size: "20" + max_client_conn: "100" + paused: false + poolMode: session + template: + metadata: + labels: + app: pooler + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - pooler + topologyKey: kubernetes.io/hostname + containers: [] + type: rw diff --git a/apps/base/puppet/cronjob_g10k-code.yaml b/apps/base/puppet/cronjob_g10k-code.yaml new file mode 100644 index 0000000..52b470d --- /dev/null +++ b/apps/base/puppet/cronjob_g10k-code.yaml @@ -0,0 +1,106 @@ +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + labels: + app.kubernetes.io/component: r10k-code + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: g10k-code + namespace: puppet +spec: + schedule: "*/1 * * * *" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + template: + metadata: + labels: + app.kubernetes.io/component: g10k-code + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + spec: + hostname: g10k-code + imagePullSecrets: null + initContainers: + - name: fetch-config + image: alpine/git:latest + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi + args: + - | + set -e + echo "Cloning r10k config repository..." + git clone https://git.unkin.net/unkin/puppet-r10k.git /tmp/config + cp /tmp/config/r10k.yaml /shared/r10k.yaml + echo "r10k.yaml fetched successfully" + command: + - /bin/sh + - -c + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - all + runAsGroup: 999 + runAsNonRoot: true + runAsUser: 999 + volumeMounts: + - mountPath: /shared + name: shared-config + containers: + - name: g10k-code + image: git.unkin.net/unkin/almalinux9-g10k:20260308 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi + args: + - -config + - /shared/r10k.yaml + command: + - /usr/bin/g10k + envFrom: null + env: [] + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - all + runAsGroup: 999 + runAsNonRoot: true + runAsUser: 999 + volumeMounts: + - mountPath: /etc/puppetlabs/code/ + name: puppet-code-volume + - mountPath: /opt/puppetlabs/cache/ + name: puppet-cache-volume + - mountPath: /shared + name: shared-config + restartPolicy: OnFailure + securityContext: + fsGroup: 999 + volumes: + - name: puppet-code-volume + persistentVolumeClaim: + claimName: puppetserver-code-shared + - name: puppet-cache-volume + persistentVolumeClaim: + claimName: puppetserver-cache + - name: shared-config + persistentVolumeClaim: + claimName: puppetserver-shared-config diff --git a/apps/base/puppet/kustomization.yaml b/apps/base/puppet/kustomization.yaml new file mode 100644 index 0000000..2e3a5be --- /dev/null +++ b/apps/base/puppet/kustomization.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - namespace.yaml + - cnpg_cluster.yaml + - cnpg_pooler.yaml + - cronjob_g10k-code.yaml + - vaultauth.yaml + - vaultstaticsecret.yaml diff --git a/apps/base/puppet/namespace.yaml b/apps/base/puppet/namespace.yaml new file mode 100644 index 0000000..d8b06c5 --- /dev/null +++ b/apps/base/puppet/namespace.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: puppet diff --git a/apps/base/puppet/persistentvolumeclaims.yaml b/apps/base/puppet/persistentvolumeclaims.yaml new file mode 100644 index 0000000..001a433 --- /dev/null +++ b/apps/base/puppet/persistentvolumeclaims.yaml @@ -0,0 +1,108 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/component: puppetserver + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: puppetserver-ca-claim + namespace: puppet +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1G + storageClassName: cephfs-raid6-delete +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/component: r10k-cache + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: puppetserver-cache + namespace: puppet +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: cephrbd-fast-delete +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/component: puppetserver-compilers + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: puppetserver-code-shared + namespace: puppet +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 30G + storageClassName: cephfs-raid6-delete +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/component: puppetserver + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: puppetserver-puppet-claim + namespace: puppet +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1G + storageClassName: cephfs-raid6-delete +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/component: puppetdb + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: puppetserver-puppetdb-claim + namespace: puppet +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: cephfs-raid6-delete +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/component: r10k-shared-config + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: puppetserver-shared-config + namespace: puppet +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: cephrbd-fast-delete diff --git a/apps/base/puppet/vaultauth.yaml b/apps/base/puppet/vaultauth.yaml new file mode 100644 index 0000000..cfeb096 --- /dev/null +++ b/apps/base/puppet/vaultauth.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultAuth +metadata: + name: default + namespace: puppet +spec: + allowedNamespaces: + - puppet + kubernetes: + audiences: + - vault + role: default + serviceAccount: default + tokenExpirationSeconds: 600 + method: kubernetes + mount: k8s/au/syd1 + vaultConnectionRef: vso-system/default diff --git a/apps/base/puppet/vaultstaticsecret.yaml b/apps/base/puppet/vaultstaticsecret.yaml new file mode 100644 index 0000000..002d4d9 --- /dev/null +++ b/apps/base/puppet/vaultstaticsecret.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret +metadata: + name: postgres-credentials + namespace: puppet +spec: + destination: + create: true + name: postgres-credentials + overwrite: true + hmacSecretData: true + mount: kv + path: kubernetes/namespace/puppet/default/postgres-credentials + refreshAfter: 5m + type: kv-v2 + vaultAuthRef: default +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret +metadata: + name: puppetboard-secrets + namespace: puppet +spec: + destination: + create: true + name: puppetboard-secrets + overwrite: true + hmacSecretData: true + mount: kv + path: kubernetes/namespace/puppet/default/puppetboard-secrets + refreshAfter: 5m + type: kv-v2 + vaultAuthRef: default diff --git a/apps/overlays/au-syd1/puppet/kustomization.yaml b/apps/overlays/au-syd1/puppet/kustomization.yaml new file mode 100644 index 0000000..00f0673 --- /dev/null +++ b/apps/overlays/au-syd1/puppet/kustomization.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: puppet + +resources: + - ../../../base/puppet diff --git a/argocd/applicationsets/platform.yaml b/argocd/applicationsets/platform.yaml index 77eec55..6e7115c 100644 --- a/argocd/applicationsets/platform.yaml +++ b/argocd/applicationsets/platform.yaml @@ -14,6 +14,7 @@ spec: - path: apps/overlays/*/reflector-system - path: apps/overlays/*/reloader-system - path: apps/overlays/*/jfrog + - path: apps/overlays/*/puppet - path: apps/overlays/*/woodpecker template: metadata: diff --git a/argocd/projects/platform.yaml b/argocd/projects/platform.yaml index d9928b5..d7941c5 100644 --- a/argocd/projects/platform.yaml +++ b/argocd/projects/platform.yaml @@ -17,6 +17,8 @@ spec: server: https://kubernetes.default.svc - namespace: 'jfrog' server: https://kubernetes.default.svc + - namespace: 'puppet' + server: https://kubernetes.default.svc - namespace: 'woodpecker' server: https://kubernetes.default.svc clusterResourceWhitelist: