From 333e638e2468f40335b20721dc74af31df7ede1f Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sun, 5 Jul 2026 17:41:21 +1000 Subject: [PATCH] deploy encapi to au-syd1 (#230) ## Why encapi is the new Postgres-backed Puppet ENC that replaces Cobbler (Go API + encapi-cli + terraform provider). It needs to run somewhere reachable by the puppet masters (`encapi-cli classify`) and every node's `enc_direct_facts` fact. Deploy it in k8s alongside artifactapi, exposed at `encapi.k8s.syd1.au.unkin.net`. ## Changes - add `apps/base/encapi/`: namespace, deployment (`git.unkin.net/unkin/encapi`, port 8000, `/healthz` probes), service, gateway + httproute (`encapi.k8s.syd1.au.unkin.net`, traefik-internal), configmap (DB coordinates), CNPG cluster + pooler (database `encapi`), and VaultAuth + VaultStaticSecrets (`postgres-credentials`, `environment`) - add `apps/overlays/au-syd1/encapi` overlay referencing the base - register `apps/overlays/*/encapi` in the platform ApplicationSet so ArgoCD picks it up ## Notes - Mirrors the artifactapi pattern (VaultAuth role `default`, namespace-scoped VSO paths `kv/kubernetes/namespace/encapi/default/*`). - Before first sync, seed the Vault KV secrets: `environment` must carry `DBPASS` (matching the CNPG owner password) and `ENCAPI_WRITE_TOKEN`; `postgres-credentials` carries the CNPG owner username/password. - `kustomize build apps/overlays/au-syd1/encapi` validates clean (11 resources). --------- Co-authored-by: unkinben Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/230 Co-authored-by: Ben Vincent Co-committed-by: Ben Vincent --- apps/base/encapi/cnpg_cluster.yaml | 91 +++++++++++++++++++ apps/base/encapi/cnpg_pooler.yaml | 33 +++++++ apps/base/encapi/configmap.yaml | 13 +++ apps/base/encapi/deployment.yaml | 64 +++++++++++++ apps/base/encapi/gateway.yaml | 37 ++++++++ apps/base/encapi/httproute.yaml | 49 ++++++++++ apps/base/encapi/kustomization.yaml | 15 +++ apps/base/encapi/namespace.yaml | 5 + apps/base/encapi/service.yaml | 17 ++++ apps/base/encapi/vaultauth.yaml | 18 ++++ apps/base/encapi/vaultstaticsecret.yaml | 34 +++++++ .../au-syd1/encapi/kustomization.yaml | 6 ++ argocd/applicationsets/platform.yaml | 1 + 13 files changed, 383 insertions(+) create mode 100644 apps/base/encapi/cnpg_cluster.yaml create mode 100644 apps/base/encapi/cnpg_pooler.yaml create mode 100644 apps/base/encapi/configmap.yaml create mode 100644 apps/base/encapi/deployment.yaml create mode 100644 apps/base/encapi/gateway.yaml create mode 100644 apps/base/encapi/httproute.yaml create mode 100644 apps/base/encapi/kustomization.yaml create mode 100644 apps/base/encapi/namespace.yaml create mode 100644 apps/base/encapi/service.yaml create mode 100644 apps/base/encapi/vaultauth.yaml create mode 100644 apps/base/encapi/vaultstaticsecret.yaml create mode 100644 apps/overlays/au-syd1/encapi/kustomization.yaml diff --git a/apps/base/encapi/cnpg_cluster.yaml b/apps/base/encapi/cnpg_cluster.yaml new file mode 100644 index 0000000..a3efc2c --- /dev/null +++ b/apps/base/encapi/cnpg_cluster.yaml @@ -0,0 +1,91 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: postgres + namespace: encapi +spec: + affinity: + podAntiAffinityType: preferred + bootstrap: + initdb: + database: encapi + encoding: UTF8 + localeCType: C + localeCollate: C + owner: encapi + secret: + name: postgres-credentials + enablePDB: true + enableSuperuserAccess: false + failoverDelay: 0 + imageName: ghcr.io/cloudnative-pg/postgresql:18.1-system-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/encapi/cnpg_pooler.yaml b/apps/base/encapi/cnpg_pooler.yaml new file mode 100644 index 0000000..0a3ff6c --- /dev/null +++ b/apps/base/encapi/cnpg_pooler.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Pooler +metadata: + name: postgres-pooler + namespace: encapi +spec: + cluster: + name: postgres + instances: 2 + pgbouncer: + parameters: + default_pool_size: "100" + max_client_conn: "400" + 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/encapi/configmap.yaml b/apps/base/encapi/configmap.yaml new file mode 100644 index 0000000..0d000fd --- /dev/null +++ b/apps/base/encapi/configmap.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: encapi-env + namespace: encapi +data: + LISTEN_ADDR: ":8000" + DBHOST: postgres-pooler + DBNAME: encapi + DBPORT: "5432" + DBUSER: encapi + DBSSL: require diff --git a/apps/base/encapi/deployment.yaml b/apps/base/encapi/deployment.yaml new file mode 100644 index 0000000..60f14d8 --- /dev/null +++ b/apps/base/encapi/deployment.yaml @@ -0,0 +1,64 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: encapi + namespace: encapi + annotations: + reloader.stakater.com/auto: "true" +spec: + replicas: 2 + selector: + matchLabels: + app: encapi + strategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app: encapi + spec: + automountServiceAccountToken: true + containers: + - name: encapi + image: git.unkin.net/unkin/encapi:v0.1.1 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8000 + name: http + protocol: TCP + envFrom: + # DBHOST/DBNAME/DBPORT/DBUSER/DBSSL/LISTEN_ADDR + - configMapRef: + name: encapi-env + optional: false + # DBPASS + ENCAPI_WRITE_TOKEN (seeded in Vault, see cutover notes) + - secretRef: + name: environment + optional: false + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 15 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 3 + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 500m + memory: 256Mi + restartPolicy: Always diff --git a/apps/base/encapi/gateway.yaml b/apps/base/encapi/gateway.yaml new file mode 100644 index 0000000..a8c4a1c --- /dev/null +++ b/apps/base/encapi/gateway.yaml @@ -0,0 +1,37 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + labels: + traefik.io/instance: internal + annotations: + cert-manager.io/cluster-issuer: vault-issuer + cert-manager.io/common-name: encapi.k8s.syd1.au.unkin.net + cert-manager.io/private-key-size: "4096" + external-dns.alpha.kubernetes.io/hostname: encapi.k8s.syd1.au.unkin.net + external-dns.alpha.kubernetes.io/target: 198.18.200.4 + name: encapi + namespace: encapi +spec: + gatewayClassName: traefik-internal + listeners: + - allowedRoutes: + namespaces: + from: Same + hostname: encapi.k8s.syd1.au.unkin.net + name: http + port: 80 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + hostname: encapi.k8s.syd1.au.unkin.net + name: https + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: encapi-tls + mode: Terminate diff --git a/apps/base/encapi/httproute.yaml b/apps/base/encapi/httproute.yaml new file mode 100644 index 0000000..c8a26a7 --- /dev/null +++ b/apps/base/encapi/httproute.yaml @@ -0,0 +1,49 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: encapi-http-redirect + namespace: encapi +spec: + hostnames: + - encapi.k8s.syd1.au.unkin.net + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: encapi + sectionName: http + rules: + - filters: + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: encapi + namespace: encapi +spec: + hostnames: + - encapi.k8s.syd1.au.unkin.net + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: encapi + sectionName: https + rules: + - backendRefs: + - group: "" + kind: Service + name: encapi + port: 80 + weight: 1 + matches: + - path: + type: PathPrefix + value: / diff --git a/apps/base/encapi/kustomization.yaml b/apps/base/encapi/kustomization.yaml new file mode 100644 index 0000000..fcbf043 --- /dev/null +++ b/apps/base/encapi/kustomization.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - namespace.yaml + - configmap.yaml + - deployment.yaml + - service.yaml + - gateway.yaml + - httproute.yaml + - cnpg_cluster.yaml + - cnpg_pooler.yaml + - vaultauth.yaml + - vaultstaticsecret.yaml diff --git a/apps/base/encapi/namespace.yaml b/apps/base/encapi/namespace.yaml new file mode 100644 index 0000000..d42f1fd --- /dev/null +++ b/apps/base/encapi/namespace.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: encapi diff --git a/apps/base/encapi/service.yaml b/apps/base/encapi/service.yaml new file mode 100644 index 0000000..8cae6bb --- /dev/null +++ b/apps/base/encapi/service.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: encapi + namespace: encapi +spec: + internalTrafficPolicy: Cluster + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + selector: + app: encapi + sessionAffinity: None + type: ClusterIP diff --git a/apps/base/encapi/vaultauth.yaml b/apps/base/encapi/vaultauth.yaml new file mode 100644 index 0000000..3863f36 --- /dev/null +++ b/apps/base/encapi/vaultauth.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultAuth +metadata: + name: default + namespace: encapi +spec: + allowedNamespaces: + - encapi + kubernetes: + audiences: + - vault + role: default + serviceAccount: default + tokenExpirationSeconds: 600 + method: kubernetes + mount: k8s/au/syd1 + vaultConnectionRef: vso-system/default diff --git a/apps/base/encapi/vaultstaticsecret.yaml b/apps/base/encapi/vaultstaticsecret.yaml new file mode 100644 index 0000000..05d7975 --- /dev/null +++ b/apps/base/encapi/vaultstaticsecret.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret +metadata: + name: postgres-credentials + namespace: encapi +spec: + destination: + create: true + name: postgres-credentials + overwrite: true + hmacSecretData: true + mount: kv + path: kubernetes/namespace/encapi/default/postgres-credentials + refreshAfter: 5m + type: kv-v2 + vaultAuthRef: default +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret +metadata: + name: environment + namespace: encapi +spec: + destination: + create: true + name: environment + overwrite: true + hmacSecretData: true + mount: kv + path: kubernetes/namespace/encapi/default/environment + refreshAfter: 5m + type: kv-v2 + vaultAuthRef: default diff --git a/apps/overlays/au-syd1/encapi/kustomization.yaml b/apps/overlays/au-syd1/encapi/kustomization.yaml new file mode 100644 index 0000000..a476c64 --- /dev/null +++ b/apps/overlays/au-syd1/encapi/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../../../base/encapi diff --git a/argocd/applicationsets/platform.yaml b/argocd/applicationsets/platform.yaml index 101655f..634fcf4 100644 --- a/argocd/applicationsets/platform.yaml +++ b/argocd/applicationsets/platform.yaml @@ -21,6 +21,7 @@ spec: - path: apps/overlays/*/cnpg-system - path: apps/overlays/*/consul - path: apps/overlays/*/elastic-system + - path: apps/overlays/*/encapi - path: apps/overlays/*/externaldns - path: apps/overlays/*/inteldeviceplugins-system - path: apps/overlays/*/jfrog