44 Commits

Author SHA1 Message Date
Ben Vincent fc7716a0a2 Install openbao-plugin-secrets-rancher on vault nodes
ci/woodpecker/pr/puppet-lint Pipeline was successful
ci/woodpecker/pr/bolt-validate Pipeline was successful
ci/woodpecker/pr/yamllint Pipeline was successful
ci/woodpecker/pr/erb-validate Pipeline was successful
ci/woodpecker/pr/ruby-validate Pipeline was successful
ci/woodpecker/pr/epp-validate Pipeline was successful
ci/woodpecker/pr/ruby-check Pipeline was successful
ci/woodpecker/pr/puppet-validate Pipeline was successful
Lays down the rancher secrets-engine plugin binary in the OpenBao plugin
directory (/opt/openbao-plugins/vault-plugin-secrets-rancher) so terraform-vault
can register and mount it. Package comes from the rpm-internal repo.

- Add openbao-plugin-secrets-rancher to profiles::packages::include on the vault
  storage role.
2026-07-17 23:40:08 +10:00
unkinben d71e221049 dns: deploy dns-updater daemon in place of the shell nsupdate script [HOLD: needs dns-updater RPM published] (#482)
ci/woodpecker/pr/ruby-check Pipeline was canceled
ci/woodpecker/pr/puppet-validate Pipeline was canceled
ci/woodpecker/pr/ruby-validate Pipeline was successful
ci/woodpecker/pr/puppet-lint Pipeline was successful
ci/woodpecker/pr/yamllint Pipeline was successful
ci/woodpecker/pr/erb-validate Pipeline was successful
ci/woodpecker/pr/bolt-validate Pipeline was successful
ci/woodpecker/pr/epp-validate Pipeline was successful
## Why
Replace the `profiles::dns::updater` shell mechanism (`dns-update.sh` + `dns-update.path`/`.service` + the in-run `exec`) with the packaged **dns-updater** daemon. The daemon watches the records file (inotify) and network interfaces and pushes TSIG-signed RFC2136 updates to BIND natively — with structured per-zone RCODEs and a status API/facter fact, so failures like the recent `invalid owner name: empty label` / NOTZONE surface directly instead of as opaque nsupdate stderr.

## Changes
- Install the `dns-updater` package; manage `/etc/dns-updater/env`.
- Run the packaged `dns-updater.service`, restarting **only** on env/key change — records-file edits are picked up by the daemon`s own inotify watch, so no service churn on record changes.
- Keep the `concat` records file and the TSIG key file unchanged (same paths/format).
- Ensure the old `/usr/local/bin/dns-update` + `dns-update.path`/`.service` units are absent.
- Drop the now-dead `dns-update.{sh,service,path}.epp` templates.

## Sequencing — HOLD
Do not merge until the `dns-updater` RPM is published to artifactapi `rpm-internal` (needs terraform-git#33 to create the repo, then the daemon code pushed + tagged so Woodpecker builds the RPM). Merging before the package exists makes `package { dns-updater }` fail on every host.

Supersedes the interim shell fix in #481 (which stays valid until this rolls out). Keeps the file as the desired-state interface (puppet owns desired records; the daemon reconciles + reports).

Reviewed-on: #482
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-07-17 23:35:00 +10:00
unkinben 0de3ac2a0b dns: fix dns-update fqdn() double-appending zone to FQDN records (#481)
## Why
6 hosts (ausyd1nxvm2069-2073, 2098) ended up with a reverse PTR in bind-authoritative but **no forward A record**, and the `unkin.net` service records (git/grafana/auth/fafflix, all published by the halb host 2069) never landed at all.

VictoriaLogs (`dns-update-apply` on 2069 & 2070) shows the cause:
```
dns-update: nsupdate to 198.18.200.9 failed
invalid owner name: empty label
syntax error
```
`profiles::dns::record` publishes some records whose name is already fully-qualified (trailing dot) — e.g. `au-syd1-pve.main.unkin.net.`, `cobbler.main.unkin.net.`, `dashboard.ceph.unkin.net.`, and the halb CNAMEs. The `dns-update` script `fqdn()` unconditionally appended the zone, producing `…net..main.unkin.net.` — the `..` is an empty label, which nsupdate rejects, failing the entire per-zone `send`. The reverse-PTR send is sorted first and its name is always relative, so it still applied — hence "PTR but no A".

## Change
`fqdn()` now handles three cases:
- `@`/empty → zone apex (unchanged)
- name ending in `.` → already FQDN, used verbatim (**the fix**)
- otherwise → relative, append `.zone.` (unchanged)

Verified against all record shapes (relative host, apex, FQDN CNAME, reverse label) — no more `..`.

## After merge
Once puppet re-runs on the affected hosts their `main.unkin.net`/`unkin.net` updates succeed, filling in the missing A records and the `unkin.net` service zone. Pairs with argocd-apps#260 (adds the `ceph.unkin.net` zone so `dashboard.ceph.unkin.net` does not then hit NOTZONE).

Reviewed-on: #481
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-07-17 22:50:28 +10:00
unkinben 0702676da6 Install openbao-plugin-secrets-gpg on vault nodes (#480)
Deploy the GPG/OpenPGP secrets engine to the OpenBao (vault-role) cluster by installing its plugin RPM into `/opt/openbao-plugins`, mirroring the existing `openbao-plugin-secrets-litellm` deployment (#479).

- Add `openbao-plugin-secrets-gpg` to `profiles::packages::include` in the vault role hiera. The RPM ships from artifactapi `rpm-internal` (built on the [vault-plugin-secrets-gpg](https://git.unkin.net/unkin/vault-plugin-secrets-gpg) v0.1.0 tag) and lands the plugin binary in the node's configured `plugin_directory`.

Registering + enabling the secrets backend (`plugin register` / `secrets enable`) is a follow-up terraform-vault change, matching how litellm is wired.

Reviewed-on: #480
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-07-16 22:48:08 +10:00
unkinben 88fcb97ad1 dns: nsupdate host records to the authoritative server (#475)
Replaces the exported-resources → puppet DNS master zone-file flow with per-host RFC2136 dynamic updates against the k8s **bind-authoritative** write endpoint (198.18.200.9). The master no longer manages zone files.

## Design
Each node assembles its DNS records into a local concat file; a systemd `.path` unit watches it and runs `dns-update` (nsupdate) on change — exactly the watch-a-file model requested.

## Changes
- **profiles::dns::updater** (new): concat records file + TSIG key file + `dns-update` script + `dns-update.service` (oneshot) + `dns-update.path` (watcher). The script sends only the delta since last run and deletes removed records, grouped per zone.
- **profiles::dns::record**: writes a local concat fragment (`zone|name|type|ttl|value`) instead of exporting `@@concat::fragment` to the master.
- **profiles::dns::base**: includes `profiles::dns::updater` (all nodes).
- **hiera**: `profiles::dns::updater` server/key_name/algorithm in common.yaml.

## Inert until keyed
The updater does nothing until `profiles::dns::updater::key_secret` (TSIG) is set in eyaml — records are assembled but not applied, so nodes are safe before the key exists.

## Prerequisites (k8s side, separate)
1. The `bind-authoritative` zones must set `dynamicUpdate: true` + an `updateKeyRef` (a client-update BindTSIGKey) so they accept these updates.
2. The TSIG key must be shared: the operator-generated key value goes into eyaml here (or the planned Vault-sync feature bridges it).

## Validated
puppet parser/epp validate, puppet-lint, and a functional test of the generated per-zone nsupdate message (replace + delete-removed).

Reviewed-on: #475
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-07-12 22:23:18 +10:00
benvin 69781df412 chore: change to openbao-plugin-secrets-litellm (#479)
change to openbao litellm plugin as it installs to the correct directory

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #479
2026-07-06 23:26:21 +10:00
benvin 2ae215daf7 feat: install vault-plugin-secrets-litellm (#477)
ensure the litellm plugin for vault is installed

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #477
2026-07-06 23:02:12 +10:00
benvin cd1c3e6ae2 chore: add rpm-internal repo (#476)
enable installing locally packaged rpms with no specific linux release

- add the rpm-internal repo from artifactapi

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #476
2026-07-06 23:02:02 +10:00
benvin 00a8088aed chore: reduce requsts for all jobs (#478)
- found jobs stalling

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #478
2026-07-06 22:22:51 +10:00
unkinben aeae26711f Convert RKE2 registries to template, disable default endpoints (#474)
## Summary
- Replace static `registries.yaml` with EPP template driven by `rke2::registries` hash
- Add `disable-default-registry-endpoint: true` to all mirrors — RKE2 will only use artifactapi and never fall back to upstream registries
- Registry configuration now fully managed via hiera data (`roles/infra/k8s.yaml`)

Reviewed-on: #474
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-06-29 22:30:48 +10:00
benvin 7b53be7f8c chore: enable rke2 registries (#473)
- re-enable registries for rke2 machines

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #473
2026-06-27 22:27:33 +10:00
benvin 97d21c81c5 feat: make rke2 registries.yaml conditional on manage_registries (#472)
Add/Remove the registries.yaml file based on the manage_registries
boolean. We are leaving it on default=false now as the artifactapi
server was broken.

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #472
2026-06-27 07:50:31 +10:00
unkinben e140b300bb chore: bump almalinux9 image tags (#471)
Bump almalinux9 image tags to 20260606

Reviewed-on: #471
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-06-07 00:31:30 +10:00
benvin 57c844b7e8 feat: upgrade grafana from default to 13.0.2 (#470)
Pin grafana package version to 13.0.2 via a new version parameter on
profiles::metrics::grafana, wired through to the puppet-grafana class.

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #470
2026-06-06 23:46:16 +10:00
benvin 757de20682 feat: upgrade gitea from 1.22.0 to 1.26.2 (#469)
- update release to install to 1.26.2
- change base_url to artifactapi
- update releases/checksums

---------

Co-authored-by: Ben Vincent <ben@unkin.net>
Reviewed-on: #469
2026-06-06 20:23:25 +10:00
unkinben 6ef1b20abd feat: add switch to change to almalinux-vault (#468)
- move old almalinux versions to query the almalinux-vault
- default to the almalinux remote

Reviewed-on: #468
2026-06-06 17:35:04 +10:00
unkinben b754d947d5 feat: add auth.unkin.net proxying to Kubernetes Traefik ingress (#467)
Add static haproxy2 backends for syd1 Kubernetes Traefik ingress
(external 198.18.199.0, internal 198.18.200.4) and route
auth.unkin.net to the internal backend with Let's Encrypt cert.

Reviewed-on: #467
2026-06-02 22:50:10 +10:00
unkinben ba35c8907c chore: increase inotify limits on rke2 nodes to fix fsnotify watcher errors (#466)
Reviewed-on: #466
2026-05-26 23:50:25 +10:00
unkinben ceacfc85ae feat: restart rke2 when registries.yaml is deployed (#465)
- ensure we restart rke2 to pickup registries.yaml changes
- add a comment to registries.yaml to force a restart

Reviewed-on: #465
2026-05-06 23:11:20 +10:00
unkinben 7e45e0d2e5 chore: expand puppet-validate to two cpus (#464)
puppet validate takes 5 mins on one core. doubling to two cores should
bring it down to 2.5mins

Reviewed-on: #464
2026-05-06 22:29:39 +10:00
unkinben 682f65e046 chore: setup proper resource requirements for puppet ci jobs (#463)
currently, all woodpecker jobs jam onto one host, and have no resource
limits resulting in one kubernetes host suddenly maxing its cpu

- ensure we allocate resources for each woodpecker job

Reviewed-on: #463
2026-05-06 22:24:30 +10:00
unkinben 0d412aebdb chore: deploy rke2 registries.yaml (#462)
ensure all new docker pulls are actioned through artifactapi

Reviewed-on: #462
2026-05-06 22:17:59 +10:00
unkinben 4b9b28ddb7 chore: disable rp_filter on k8s nodes (#461)
- k8s control/compute are multihomed, must disable rp_filter

Reviewed-on: #461
2026-04-11 21:51:42 +10:00
unkinben 0451894b48 feat: add ceph service management profiles and facts (#459)
## Summary

- Adds `Unkin::Ceph::Utils` facter module detecting ceph service instances via `systemctl list-units`, exposing `is_ceph_mon`, `is_ceph_mgr`, `is_ceph_mds`, `is_ceph_osd` booleans and a `ceph_services` hash of unit names
- Adds `profiles::ceph::mon`, `mgr`, `mds`, `osd` — each with `Boolean $ensure_running` that iterates discovered service instances and manages them as running and enabled
- Works across incus nodes (mon/mgr/mds/osd) and k8s compute/control nodes (osd only); verified on prodnxsr0001 which correctly reports `is_ceph_osd: true` and `ceph_services: {osd: [ceph-osd@5]}`

## Test plan

- [x] Noop deploy against prodnxsr0001.main.unkin.net passed cleanly
- [x] `ceph_services` fact returns correct service map
- [x] `is_ceph_osd` returns `True`, `is_ceph_mon` returns `False` as expected
- [x] Test on an incus/ceph node with mon/mgr/mds services

Reviewed-on: #459
2026-04-07 19:02:17 +10:00
unkinben 3714691240 chore: enable access to dns (#460)
rebuilding router, taking the chance to not mess up ip ranges. I did
have 198.18.21.0/24 and 198.18.21.160/27 and 198.18.21.192/27 all on
differnt interfaces.

- update IP's that can reach bind view for main.unkin.net
- keep both for intermediate period

Reviewed-on: #460
2026-04-06 22:46:40 +10:00
unkinben dbe04a91e3 chore: change to ceph-public loopback (#458)
- use ceph public loopback port 9443 for dashboard

Reviewed-on: #458
2026-04-05 22:35:39 +10:00
unkinben 476c8115c5 fix: replace puppetdbquery with native PQL queries (#457)
Replace deprecated dalen-puppetdbquery module with native puppetdb_query
function using PQL syntax to resolve URI.escape compatibility issues.
This is required to migrated to Puppet 8 (and kubernetes).

Changes:
- Remove dalen-puppetdbquery dependency from Puppetfile
- Replace query_nodes() calls with puppetdb_query() using PQL syntax
- Update 27 function calls across 18 Puppet manifests
- Maintain equivalent functionality with improved compatibility

Reviewed-on: #457
2026-03-21 22:35:42 +11:00
unkinben 1d41d07b2d fix: allow transfer for external-dns (#456)
external-dns required axfr support to remove old records. add the
capability for the externaldns tsig key.

Reviewed-on: #456
2026-03-18 20:00:22 +11:00
unkinben 029c998797 feat: improve ci performance (#455)
split all pre-commit checks into individual workflows, so that
woodpecker spawns a container/job for each. this vastly improves the
time it takes for CI to complete checks for puppet

- create per-pre-commit-check pre-commit config files
- create per-pre-commit-check woodpecker workflows

Reviewed-on: #455
2026-03-17 17:38:22 +11:00
unkinben 0c0d4a3f61 chore: update r10k repo path (#454)
- change to use letsencrypt ssl path for simpler tls trust management

Reviewed-on: #454
2026-03-17 17:36:58 +11:00
unkinben 1e707b8b9a feat: puppetboard 7 python (#453)
auto-upgraded to puppetboard 7, which requires 3.10 python. upgrade
puppetboard venv from 3.9 (system python) -> 3.12

Reviewed-on: #453
2026-03-16 23:53:52 +11:00
unkinben 416c5ce7d9 chore: update puppet-bind repo url (#452)
changing this to `git.unkin.net` as that certificate is publicly
trusted, requiring no certificate changes for r10k docker container

Reviewed-on: #452
2026-03-08 19:01:55 +11:00
unkinben 0377c40a07 chore: cleanup gitea actions workflows (#451)
- migrated workflows to woodpeckerci

Reviewed-on: #451
2026-02-28 17:50:41 +11:00
unkinben 8bb40dadce feat: add woodpecker ci jobs (#450)
- pre-commit job to run pre-commit against

Reviewed-on: #450
2026-02-28 17:30:23 +11:00
unkinben bc769aa1df feat: add ldap groups for kubernetes/vault (#449)
need to separate the permissions inside vault into different groups, one
per-permission.

- add group for each kubernetes role in vault

Reviewed-on: #449
2026-02-14 19:22:26 +11:00
unkinben 4e652ccbe6 chore: add alt-names to consul (#448)
- ensure consul datacenter is added to altnames

Reviewed-on: #448
2026-02-09 01:03:20 +11:00
unkinben 8c24c6582f feat: manage vault version (#446)
- add params for version and package name
- add param to cleanup openbao
- add version lock (if not latest)

Reviewed-on: #446
2026-02-08 22:26:22 +11:00
unkinben 6bfc63ca31 feat: enable plugins for vault/openbao (#447)
- install openbao-plugins
- add plugin_directory

Reviewed-on: #447
2026-02-08 19:19:33 +11:00
unkinben 69dc9e8f66 docs: add docs for cephfs (#445)
- specifically related to managing csi volumes for kubernetes

Reviewed-on: #445
2026-02-03 19:56:14 +11:00
unkinben c4d28d52bc chore: remove helm deploys from puppet (#444)
- migrate helm deployments to terraform

Reviewed-on: #444
2026-01-30 20:52:51 +11:00
unkinben 6219855fb1 chore: add additional user (#443)
- as per request

Reviewed-on: #443
2026-01-26 20:21:10 +11:00
unkinben 7215a6f534 chore: terraform state too large for body (#442)
- update consul/nginx max body size to 512MB

Reviewed-on: #442
2026-01-18 17:15:08 +11:00
unkinben 88efdbcdd3 chore: reduce synced repos (#441)
- remove repos now available via artifactapi

Reviewed-on: #441
2026-01-17 17:12:44 +11:00
unkinben 3c114371e0 chore: docs for ceph (#440)
- add maintenance mode, how to bootstrap an osd, remove an osd

Reviewed-on: #440
2026-01-17 13:26:44 +11:00
75 changed files with 1204 additions and 508 deletions
-24
View File
@@ -1,24 +0,0 @@
name: Build
on:
pull_request:
jobs:
precommit:
runs-on: almalinux-8
container:
image: git.unkin.net/unkin/almalinux9-actionsdind:latest
options: --privileged
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install requirements
run: |
dnf groupinstall -y "Development Tools" -y
dnf install rubygems ruby-devel gcc make redhat-rpm-config glibc-headers glibc-devel -y
- name: Pre-Commit All Files
run: |
uvx pre-commit run --all-files
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: bolt-validate
image: git.unkin.net/unkin/almalinux9-puppet-pr-validator:20260317
commands:
- uvx pre-commit run --all-files --config ci/bolt-validate.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: epp-validate
image: git.unkin.net/unkin/almalinux9-puppet-pr-validator:20260317
commands:
- uvx pre-commit run --all-files --config ci/epp-validate.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: erb-validate
image: git.unkin.net/unkin/almalinux9-puppet-pr-validator:20260317
commands:
- uvx pre-commit run --all-files --config ci/erb-validate.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: puppet-lint
image: git.unkin.net/unkin/almalinux9-puppet-pr-validator:20260317
commands:
- uvx pre-commit run --all-files --config ci/puppet-lint.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: puppet-validate
image: git.unkin.net/unkin/almalinux9-puppet-pr-validator:20260317
commands:
- uvx pre-commit run --all-files --config ci/puppet-validate.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 1
limits:
memory: 2Gi
cpu: 2
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: ruby-check
image: git.unkin.net/unkin/almalinux9-puppet-pr-validator:20260317
commands:
- uvx pre-commit run --all-files --config ci/ruby-check.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: ruby-validate
image: git.unkin.net/unkin/almalinux9-puppet-pr-validator:20260317
commands:
- uvx pre-commit run --all-files --config ci/ruby-validate.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: yamllint
image: git.unkin.net/unkin/almalinux9-base:20260606
commands:
- uvx pre-commit run --all-files --config ci/yamllint.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: 1
+1 -2
View File
@@ -53,7 +53,6 @@ mod 'saz-ssh', '13.1.0'
mod 'saz-limits', '5.0.0'
mod 'ghoneycutt-timezone', '4.0.0'
mod 'ghoneycutt-puppet', '3.3.0'
mod 'dalen-puppetdbquery', '3.0.1'
mod 'markt-galera', '3.1.0'
mod 'kogitoapp-minio', '1.1.4'
mod 'broadinstitute-certs', '3.0.1'
@@ -66,5 +65,5 @@ mod 'thias-sysctl', '1.0.8'
mod 'cirrax-dovecot', '1.3.3'
mod 'bind',
:git => 'https://git.service.au-syd1.consul/unkinben/puppet-bind.git',
:git => 'https://git.unkin.net/unkinben/puppet-bind.git',
:tag => '1.0'
+5
View File
@@ -0,0 +1,5 @@
repos:
- repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git'
rev: v2.2.0
hooks:
- id: bolt-validate
+5
View File
@@ -0,0 +1,5 @@
repos:
- repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git'
rev: v2.2.0
hooks:
- id: epp-validate
+5
View File
@@ -0,0 +1,5 @@
repos:
- repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git'
rev: v2.2.0
hooks:
- id: erb-validate
+10
View File
@@ -0,0 +1,10 @@
repos:
- repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git'
rev: v2.2.0
hooks:
- id: puppet-lint
args:
- --no-80chars-check
- --no-documentation-check
- --no-puppet_url_without_modules-check
- --fail-on-warnings
+5
View File
@@ -0,0 +1,5 @@
repos:
- repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git'
rev: v2.2.0
hooks:
- id: puppet-validate
+10
View File
@@ -0,0 +1,10 @@
repos:
- repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git'
rev: v2.2.0
hooks:
- id: ruby-validate
- repo: 'https://github.com/jumanjihouse/pre-commit-hooks'
rev: 3.0.0
hooks:
- id: reek
- id: rubocop
+5
View File
@@ -0,0 +1,5 @@
repos:
- repo: 'https://github.com/chriskuehl/puppet-pre-commit-hooks.git'
rev: v2.2.0
hooks:
- id: ruby-validate
+10
View File
@@ -0,0 +1,10 @@
repos:
- repo: 'https://github.com/adrienverge/yamllint'
rev: v1.32.0
hooks:
- id: 'yamllint'
args:
[
"-d {extends: relaxed, rules: {line-length: disable}, ignore: chart}",
"-s",
]
+167
View File
@@ -28,6 +28,98 @@ Always refer back to the official documentation at https://docs.ceph.com/en/late
sudo ceph fs set mediafs max_mds 2
```
## managing cephfs with subvolumes
Create erasure code profiles. The K and M values are equivalent to the number of data disks (K) and parity disks (M) in RAID5, RAID6, etc.
sudo ceph osd erasure-code-profile set ec_6_2 k=6 m=2
sudo ceph osd erasure-code-profile set ec_4_1 k=4 m=1
Create data pools using the erasure-code-profile, set some required options
sudo ceph osd pool create cephfs_data_ssd_ec_6_2 erasure ec_6_2
sudo ceph osd pool set cephfs_data_ssd_ec_6_2 allow_ec_overwrites true
sudo ceph osd pool set cephfs_data_ssd_ec_6_2 bulk true
sudo ceph osd pool create cephfs_data_ssd_ec_4_1 erasure ec_4_1
sudo ceph osd pool set cephfs_data_ssd_ec_4_1 allow_ec_overwrites true
sudo ceph osd pool set cephfs_data_ssd_ec_4_1 bulk true
Add the pool to the fs `cephfs`
sudo ceph fs add_data_pool cephfs cephfs_data_ssd_ec_6_2
sudo ceph fs add_data_pool cephfs cephfs_data_ssd_ec_4_1
Create a subvolumegroup using the new data pool
sudo ceph fs subvolumegroup create cephfs csi_ssd_ec_6_2 --pool_layout cephfs_data_ssd_ec_6_2
sudo ceph fs subvolumegroup create cephfs csi_ssd_ec_4_1 --pool_layout cephfs_data_ssd_ec_4_1
All together:
sudo ceph osd erasure-code-profile set ec_6_2 k=6 m=2
sudo ceph osd pool create cephfs_data_ssd_ec_6_2 erasure ec_6_2
sudo ceph osd pool set cephfs_data_ssd_ec_6_2 allow_ec_overwrites true
sudo ceph osd pool set cephfs_data_ssd_ec_6_2 bulk true
sudo ceph fs add_data_pool cephfs cephfs_data_ssd_ec_6_2
sudo ceph fs subvolumegroup create cephfs csi_ssd_ec_6_2 --pool_layout cephfs_data_ssd_ec_6_2
sudo ceph osd erasure-code-profile set ec_4_1 k=4 m=1
sudo ceph osd pool create cephfs_data_ssd_ec_4_1 erasure ec_4_1
sudo ceph osd pool set cephfs_data_ssd_ec_4_1 allow_ec_overwrites true
sudo ceph osd pool set cephfs_data_ssd_ec_4_1 bulk true
sudo ceph fs add_data_pool cephfs cephfs_data_ssd_ec_4_1
sudo ceph fs subvolumegroup create cephfs csi_ssd_ec_4_1 --pool_layout cephfs_data_ssd_ec_4_1
Create a key with access to the new subvolume groups. Check if the user already exists first:
sudo ceph auth get client.kubernetes-cephfs
If it doesnt:
sudo ceph auth get-or-create client.kubernetes-cephfs \
mgr 'allow rw' \
osd 'allow rw tag cephfs metadata=cephfs, allow rw tag cephfs data=cephfs' \
mds 'allow r fsname=cephfs path=/volumes, allow rws fsname=cephfs path=/volumes/csi_ssd_ec_6_2, allow rws fsname=cephfs path=/volumes/csi_ssd_ec_4_1' \
mon 'allow r fsname=cephfs'
If it does, use `sudo ceph auth caps client.kubernetes-cephfs ...` instead to update existing capabilities.
## removing a cephfs subvolumegroup from cephfs
This will cleanup the subvolumegroup, and subvolumes if they exist, then remove the pool.
Check for subvolumegroups first, then for subvolumes in it
sudo ceph fs subvolumegroup ls cephfs
sudo ceph fs subvolume ls cephfs --group_name csi_raid6
If subvolumes exist, remove each one-by-one:
sudo ceph fs subvolume rm cephfs <subvol_name> --group_name csi_raid6
If you have snapshots, remove snapshots first:
sudo ceph fs subvolume snapshot ls cephfs <subvol_name> --group_name csi_raid6
sudo ceph fs subvolume snapshot rm cephfs <subvol_name> <snap_name> --group_name csi_raid6
Once the group is empty, remove it:
sudo ceph fs subvolumegroup rm cephfs csi_raid6
If it complains its not empty, go back as theres still a subvolume or snapshot.
If you added it with `ceph fs add_data_pool`. Undo with `rm_data_pool`:
sudo ceph fs rm_data_pool cephfs cephfs_data_csi_raid6
After its detached from CephFS, you can delete it.
sudo ceph osd pool rm cephfs_data_csi_raid6 cephfs_data_csi_raid6 --yes-i-really-really-mean-it
## creating authentication tokens
- this will create a client keyring named media
@@ -58,3 +150,78 @@ this will overwrite the current capabilities of a given client.user
mon 'allow r' \
mds 'allow rw path=/' \
osd 'allow rw pool=media_data'
## adding a new osd on new node
create the ceph conf (automate this?)
cat <<EOF | sudo tee /etc/ceph/ceph.conf
[global]
auth_client_required = cephx
auth_cluster_required = cephx
auth_service_required = cephx
fsid = de96a98f-3d23-465a-a899-86d3d67edab8
mon_allow_pool_delete = true
mon_initial_members = prodnxsr0009,prodnxsr0010,prodnxsr0011,prodnxsr0012,prodnxsr0013
mon_host = 198.18.23.9,198.18.23.10,198.18.23.11,198.18.23.12,198.18.23.13
ms_bind_ipv4 = true
ms_bind_ipv6 = false
osd_crush_chooseleaf_type = 1
osd_pool_default_min_size = 2
osd_pool_default_size = 3
osd_pool_default_pg_num = 128
public_network = 198.18.23.1/32,198.18.23.2/32,198.18.23.3/32,198.18.23.4/32,198.18.23.5/32,198.18.23.6/32,198.18.23.7/32,198.18.23.8/32,198.18.23.9/32,198.18.23.10/32,198.18.23.11/32,198.18.23.12/32,198.18.23.13/32
EOF
ssh to one of the monitor hosts, then transfer the keys required
sudo cat /etc/ceph/ceph.client.admin.keyring | ssh prodnxsr0003 'sudo tee /etc/ceph/ceph.client.admin.keyring'
sudo cat /var/lib/ceph/bootstrap-osd/ceph.keyring | ssh prodnxsr0003 'sudo tee /var/lib/ceph/bootstrap-osd/ceph.keyring'
assuming we are adding /dev/sda to the cluster, first zap the disk to remove partitions/lvm/metadata
sudo ceph-volume lvm zap /dev/sda --destroy
then add it to the cluster
sudo ceph-volume lvm create --data /dev/sda
## removing an osd
check what OSD IDs were on this host (if you know it)
sudo ceph osd tree
or check for any DOWN osds
sudo ceph osd stat
sudo ceph health detail
once you identify the old OSD ID, remove it with these steps, replace X with the actual OSD ID:
sudo ceph osd out osd.X
sudo ceph osd down osd.X
sudo ceph osd crush remove osd.X
sudo ceph auth del osd.X
sudo ceph osd rm osd.X
## maintenance mode for the cluster
from one node in the cluster disable recovery
sudo ceph osd set noout
sudo ceph osd set nobackfill
sudo ceph osd set norecover
sudo ceph osd set norebalance
sudo ceph osd set nodown
sudo ceph osd set pause
to undo the change, use unset
sudo ceph osd unset noout
sudo ceph osd unset nobackfill
sudo ceph osd unset norecover
sudo ceph osd unset norebalance
sudo ceph osd unset nodown
sudo ceph osd unset pause
+1
View File
@@ -30,6 +30,7 @@ hierarchy:
- "roles/%{::enc_role_tier1}.eyaml"
- "roles/%{::enc_role_tier1}.yaml"
- "virtual/%{facts.virtual}.yaml"
- "os/%{facts.os.name}/%{facts.os.name}%{facts.os.release.major}.%{facts.os.release.minor}.yaml"
- "os/%{facts.os.name}/%{facts.os.name}%{facts.os.release.major}.yaml"
- "os/%{facts.os.name}/all_releases.yaml"
- "common.eyaml"
+1
View File
@@ -6,3 +6,4 @@ profiles::consul::token::node_editor::secret_id: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDo
profiles::consul::server::acl_tokens_initial_management: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAi1UH7AZirJ1PdxWy+KEgS5ufm0wbn2xy9rkg14hKYpcVjBa4pOZpSLMGMiiUpBIqBytDMZM4ezYa/luktpkBImJbM/TE16beGtsacQGA+9eZk2Tihs9GR2qbAQiu5lLITiDlwNnf0GeWdqHM8CTeD68DczQF320d9U14/k6pG/7z+w/MGLcjsQoSuOFTm42JVn1BI46t1CYSCHMXQc/9Tfs+FzI+vumohI8DxAYBIuyzU5HBX/MntAsvD/yixMJS1pZL9WwgqZJC/wK34rVRB39DpxWf/WROrI+WLuSJwr7WBjaeF9Ju+89WKCgsI53EWhFTj8GgDZm/jqPoE478NjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAoACRzJdQKNYXZv6cghFIIgDAzB81DMcuY815nb8POtZpiA06jT/068AoZmSctHoFK/zW9tY229N5r1Tb+WHElqLk=]
profiles::consul::server::acl_tokens_default: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAh4Ag95xgkIZHL0gP9OLnZauih0dB1/2l9Jzw8mP3OiIv7fw23otHYONlS3Emtj7oxW8MKcZGKDCzwCT6T2p+V5wx1n15wr2J+FmL24VbclJwrMPQ4AdgP359B9h21uoyo7Zdy7RuuvLfkU1fWXbs3SeWbi2HJs1Ed1/oI1jzr3OgwMbVtbyzd1VuAXeZ9bHQG3IA8z+w/k5m61th0HTyHjw7eldQulbohDuwv545z9axHEoHKCRT2a3ZwBufV2ST6Dm3g9GERzXE9Adp9DQC5adqM74wfsujOMLK2QFJSSIOj2uCs1CpEnrNrQ8zjP3fudM2z3l7KdSHZazEamCSxTBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBY/Tn9tzEKYc5dxnzP2rP7gDBWKgVP3lf2T4Q0WPQt3ns0E6RUSO6OtBegb/5qDyohY2nsDeJTnMKOYzYt/J1PhnY=]
profiles::consul::server::acl_tokens_replication: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAEzTIxbaAR/TZYnC671aBhiahsfwf3ieyeSHpD5hQm40sMEF/fXlEDijq9i2ykPikm94074j1Uo4HNzv/V9GTf0NSC/64t61jJ/Ya3QKa5f/36+DcRj3lcETsSIyhWwmU+E+zkY8I2r68MtXAuvSoMSMZdpgWSkPx/3FFgZlrsg//bzDu69jS9cx4UK582N3A6QN4Uy/qwYtJcm+2iTQlqqgGRWGqnSgTirxhegxPbJGWTDoAEpAL4/DyF5/hqcUn6mgoSfAsHF3loPHOqN30lG+9o0THWJ9B8Gf4W/1X2UWA/avmUnqBnumGoz0p7AYdNgpW+qLl2rk4lyGYa4kvQjBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBD9KSLH3Pn/1EIzgVJM+8VOgDDpKWzHfSVsfUMyTD0XIRPGclTdmxqCnsdhKNqmUfSjkYIf2nI9rQtSK6n42TYuO4k=]
profiles::dns::updater::key_secret: ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAJ4GrN3W4zGfVygfji1MeGyAlmlFN45TVP5st6b66jSKeDYNg9BwdnXahUzkmKvFIYdPWyvXqJdvuyUNz7lWr1dw/pTNHrvqUKSvI0C5TOwmtrTwXtTvucDGs7c7FZDfgUxvLs/Vrp0ZdW3C81QXWNBI8vBfVZyiegPNq+5mX7mtcrFE7jZj1g1qwpg/30lrlCguPyXqnmdtBa7VAyU2Al1UZwkrKIYSAOb9GTnvM6bk5L26pW/NXGj+ffacwf58b4AiKCak5lhoCIInVnlogPuThxULN4RF+MYAVIlgwk159CR1abjWjioxvmP7XgjQUwUuTlgoLh9fDZa0amDeFZTBcBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBEb1BTjhuTN9wGrxc2rdQVgDCctNdt72UR/Hj4wteK7XIX6fF43+7FYKBZnPtyWIWalwDniH//H3gfsJ+ULqSb82w=]
+16
View File
@@ -146,6 +146,8 @@ lookup_options:
strategy: deep
profiles::etcd::node::initial_cluster_token:
convert_to: Sensitive
profiles::dns::updater::key_secret:
convert_to: Sensitive
sysctl::base::values:
merge:
strategy: deep
@@ -208,6 +210,20 @@ vault::disable_mlock: false
profiles::dns::base::nameservers:
- 198.18.19.16
profiles::dns::master::basedir: '/var/named/sources'
# dns record publishing. During the k8s cutover both methods run; set
# manage_export false once k8s is authoritative.
# - export: legacy exported-resources -> puppet DNS master
# - nsupdate: RFC2136 to the k8s bind-authoritative write endpoint (.9),
# inert until the TSIG key is set in eyaml:
# profiles::dns::updater::key_secret: ENC[...]
# (must match the key the bind-authoritative zones allow-update
# with; algorithm hmac-sha256)
profiles::dns::updater::manage_export: true
profiles::dns::updater::manage_nsupdate: true
profiles::dns::updater::server: '198.18.200.9'
profiles::dns::updater::key_name: 'client-update'
profiles::dns::updater::key_algorithm: 'hmac-sha256'
#profiles::dns::base::ns_role: 'roles::infra::dns::resolver'
#profiles::dns::base::use_ns: 'region'
profiles::consul::server::members_role: roles::infra::storage::consul
@@ -1,4 +1,7 @@
---
haproxy_server_k8s_syd1_traefik_internal: 'k8s-traefik-internal 198.18.200.4:443 ssl verify none check inter 2s rise 3 fall 2'
haproxy_server_k8s_syd1_traefik_external: 'k8s-traefik-external 198.18.199.0:443 ssl verify none check inter 2s rise 3 fall 2'
profiles::haproxy::dns::ipaddr: "%{hiera('anycast_ip')}"
profiles::haproxy::dns::vrrp_cnames:
- sonarr.main.unkin.net
@@ -16,6 +19,7 @@ profiles::haproxy::dns::vrrp_cnames:
- mail.main.unkin.net
- autoconfig.main.unkin.net
- autodiscover.main.unkin.net
- auth.unkin.net
profiles::haproxy::mappings:
fe_http:
@@ -37,6 +41,7 @@ profiles::haproxy::mappings:
- 'mail-webadmin.main.unkin.net be_stalwart_webadmin'
- 'autoconfig.main.unkin.net be_stalwart_webadmin'
- 'autodiscovery.main.unkin.net be_stalwart_webadmin'
- 'auth.unkin.net be_k8s_kanidm'
fe_https:
ensure: present
mappings:
@@ -56,6 +61,7 @@ profiles::haproxy::mappings:
- 'mail-webadmin.main.unkin.net be_stalwart_webadmin'
- 'autoconfig.main.unkin.net be_stalwart_webadmin'
- 'autodiscovery.main.unkin.net be_stalwart_webadmin'
- 'auth.unkin.net be_k8s_kanidm'
profiles::haproxy::frontends:
fe_http:
@@ -80,6 +86,7 @@ profiles::haproxy::frontends:
- 'acl_stalwart_webadmin req.hdr(host) -i mail-webadmin.main.unkin.net'
- 'acl_stalwart_webadmin req.hdr(host) -i autoconfig.main.unkin.net'
- 'acl_stalwart_webadmin req.hdr(host) -i autodiscovery.main.unkin.net'
- 'acl_kanidm req.hdr(host) -i auth.unkin.net'
- 'acl_internalsubnets src 198.18.0.0/16 10.10.12.0/24'
use_backend:
- "%[req.hdr(host),lower,map(/etc/haproxy/fe_https.map,be_default)]"
@@ -99,6 +106,7 @@ profiles::haproxy::frontends:
- 'set-header X-Frame-Options DENY if acl_grafana'
- 'set-header X-Frame-Options DENY if acl_ceph_dashboard'
- 'set-header X-Frame-Options DENY if acl_stalwart_webadmin'
- 'set-header X-Frame-Options DENY if acl_kanidm'
- 'set-header X-Content-Type-Options nosniff'
- 'set-header X-XSS-Protection 1;mode=block'
@@ -320,6 +328,26 @@ profiles::haproxy::backends:
- add-header X-Forwarded-Proto https if { dst_port 9443 }
redirect: 'scheme https if !{ ssl_fc }'
stick-table: 'type ip size 200k expire 30m'
be_k8s_kanidm:
description: Backend for Kanidm (auth.unkin.net via Kubernetes internal Traefik)
collect_exported: false
options:
balance: roundrobin
option:
- httpchk
- forwardfor
- http-keep-alive
- prefer-last-server
http-check:
- 'connect ssl sni auth.unkin.net'
- 'send meth GET uri /status ver HTTP/1.1 hdr Host auth.unkin.net'
- 'expect status 200'
http-reuse: always
http-request:
- set-header X-Forwarded-Port %[dst_port]
- add-header X-Forwarded-Proto https if { dst_port 443 }
redirect: 'scheme https if !{ ssl_fc }'
server: "%{lookup('haproxy_server_k8s_syd1_traefik_internal')} sni str(auth.unkin.net)"
be_stalwart_imap:
description: Backend for Stalwart IMAP (STARTTLS)
collect_exported: false
@@ -393,6 +421,7 @@ profiles::haproxy::certlist::certificates:
- /etc/pki/tls/letsencrypt/git.unkin.net/fullchain_combined.pem
- /etc/pki/tls/letsencrypt/grafana.unkin.net/fullchain_combined.pem
- /etc/pki/tls/letsencrypt/dashboard.ceph.unkin.net/fullchain_combined.pem
- /etc/pki/tls/letsencrypt/auth.unkin.net/fullchain_combined.pem
- /etc/pki/tls/vault/certificate.pem
# additional altnames
@@ -422,3 +451,4 @@ certbot::client::domains:
- git.unkin.net
- grafana.unkin.net
- dashboard.ceph.unkin.net
- auth.unkin.net
+1 -1
View File
@@ -1,7 +1,7 @@
# hieradata/os/AlmaLinux/AlmaLinux8.yaml
---
crypto_policies::policy: 'DEFAULT'
almalinux-base-repo: almalinux
profiles::packages::include:
network-scripts: {}
+2
View File
@@ -0,0 +1,2 @@
---
almalinux-base-repo: almalinux-vault
+1 -1
View File
@@ -1,7 +1,7 @@
# hieradata/os/AlmaLinux/AlmaLinux9.yaml
---
crypto_policies::policy: 'DEFAULT:SHA1'
almalinux-base-repo: almalinux
profiles::yum::global::repos:
crb:
ensure: present
+19 -12
View File
@@ -23,45 +23,45 @@ profiles::yum::global::repos:
name: baseos
descr: baseos repository
target: /etc/yum.repos.d/baseos.repo
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/BaseOS/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/BaseOS/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/BaseOS/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/BaseOS/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
mirrorlist: absent
extras:
name: extras
descr: extras repository
target: /etc/yum.repos.d/extras.repo
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/extras/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/extras/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/extras/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/extras/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
mirrorlist: absent
appstream:
name: appstream
descr: appstream repository
target: /etc/yum.repos.d/appstream.repo
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/AppStream/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/AppStream/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/AppStream/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/AppStream/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
mirrorlist: absent
highavailability:
name: highavailability
descr: highavailability repository
target: /etc/yum.repos.d/highavailability.repo
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/HighAvailability/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/HighAvailability/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/HighAvailability/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/HighAvailability/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
mirrorlist: absent
crb:
ensure: absent
name: crb
descr: crb repository
target: /etc/yum.repos.d/crb.repo
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/CRB/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/CRB/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/CRB/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/CRB/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
mirrorlist: absent
powertools:
ensure: absent
name: powertools
descr: powertools repository
target: /etc/yum.repos.d/powertools.repo
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/PowerTools/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/%{facts.os.release.full}/PowerTools/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/PowerTools/%{facts.os.architecture}/os/
gpgkey: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/%{lookup('almalinux-base-repo')}/%{facts.os.release.full}/PowerTools/%{facts.os.architecture}/os/RPM-GPG-KEY-AlmaLinux-%{facts.os.release.major}
mirrorlist: absent
epel:
name: epel
@@ -78,6 +78,13 @@ profiles::yum::global::repos:
gpgkey: https://git.query.consul/api/packages/unkinben/rpm/repository.key
gpgcheck: false
mirrorlist: absent
rpm-internal:
name: rpm-internal
descr: rpm-internal repository
target: /etc/yum.repos.d/rpm-internal.repo
baseurl: https://artifactapi.k8s.syd1.au.unkin.net/api/v1/local/rpm-internal/
gpgcheck: false
mirrorlist: absent
# Additional repositories - default to absent, roles can override with ensure: present
# FRRouting repositories
+30
View File
@@ -66,6 +66,9 @@ glauth::users:
- 20025 # jupyterhub_admin
- 20026 # jupyterhub_user
- 20027 # grafana_user
- 20028 # k8s/au/syd1 operator
- 20029 # k8s/au/syd1 admin
- 20030 # k8s/au/syd1 root
loginshell: '/bin/bash'
homedir: '/home/benvin'
passsha256: 'd2434f6b4764ef75d5b7b96a876a32deedbd6aa726a109c3f32e823ca66f604a'
@@ -223,6 +226,24 @@ glauth::users:
loginshell: '/bin/bash'
homedir: '/home/debvin'
passsha256: 'cdac05ddb02e665d4ea65a974995f38a10236bc158731d92d78f6cde89b294a1'
jassol:
user_name: 'jassol'
givenname: 'Jason'
sn: 'Solomon'
mail: 'jassol@users.main.unkin.net'
uidnumber: 20010
primarygroup: 20000
othergroups:
- 20010 # jelly
- 20011 # sonarr
- 20012 # radarr
- 20013 # lidarr
- 20014 # readarr
- 20016 # nzbget
- 20027 # grafana user
loginshell: '/bin/bash'
homedir: '/home/jassol'
passsha256: 'd8e215d3c94b954e1318c9c7243ce72713f2fb1d006037724fe857c1fb7e88e9'
glauth::services:
svc_jellyfin:
@@ -367,3 +388,12 @@ glauth::groups:
grafana_user:
group_name: 'grafana_user'
gidnumber: 20027
kubernetes_au_syd1_cluster_operator:
group_name: 'kubernetes_au_syd1_cluster_operator'
gidnumber: 20028
kubernetes_au_syd1_cluster_admin:
group_name: 'kubernetes_au_syd1_cluster_admin'
gidnumber: 20029
kubernetes_au_syd1_cluster_root:
group_name: 'kubernetes_au_syd1_cluster_root'
gidnumber: 20030
+3 -1
View File
@@ -6,8 +6,10 @@ hiera_include:
profiles::dns::resolver::acls:
acl-main.unkin.net:
addresses:
- 10.10.8.1/32
- 198.18.1.10/32
- 198.18.2.160/27
- 198.18.21.160/27
- 198.18.2.192/27
- 198.18.21.192/27
- 198.18.13.0/24
- 198.18.14.0/24
+8 -2
View File
@@ -82,8 +82,14 @@ profiles::sql::postgresdb::dbname: gitea
profiles::sql::postgresdb::dbuser: gitea
# deploy gitea
gitea::ensure: '1.22.4'
gitea::checksum: 'd549104f55067e6fb156e7ba060c9af488f36e12d5e747db7563fcc99eaf8532'
gitea::base_url: 'https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/gitea-dl/gitea'
gitea::install::checksums:
1.26.2:
linux:
amd64: 5b37937b625de69196748f7293eee1a7363f8637ae6e3da3c359bb380bd61a6a
gitea::ensure: '1.26.2'
gitea::checksum: '5b37937b625de69196748f7293eee1a7363f8637ae6e3da3c359bb380bd61a6a'
gitea::manage_user: false
gitea::manage_group: false
gitea::manage_home: false
+5 -1
View File
@@ -5,6 +5,10 @@ hiera_include:
- incus
- zfs
- profiles::ceph::node
- profiles::ceph::mon
- profiles::ceph::mgr
- profiles::ceph::mds
- profiles::ceph::osd
- profiles::ceph::client
- profiles::ceph::dashboard
- profiles::storage::cephfsvols
@@ -99,7 +103,7 @@ profiles::yum::global::repos:
profiles::dns::base::primary_interface: loopback0
# dashboard/haproxy
profiles::ceph::dashboard::ipaddress: "%{hiera('networking_loopback0_ip')}"
profiles::ceph::dashboard::ipaddress: "%{hiera('networking_loopback2_ip')}"
# networking
systemd::manage_networkd: true
+68
View File
@@ -2,6 +2,7 @@
hiera_include:
- profiles::selinux::setenforce
- profiles::ceph::node
- profiles::ceph::osd
- profiles::ceph::client
- exporters::frr_exporter
- frrouting
@@ -10,6 +11,62 @@ hiera_include:
# manage rke2
rke2::bootstrap_node: prodnxsr0001.main.unkin.net
rke2::join_url: https://join-k8s.service.consul:9345
rke2::manage_registries: true
rke2::registries:
docker.io:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "dockerhub/$1"
disable-default-registry-endpoint: true
ghcr.io:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "ghcr/$1"
disable-default-registry-endpoint: true
quay.io:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "quay/$1"
disable-default-registry-endpoint: true
registry.k8s.io:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "k8s-registry/$1"
disable-default-registry-endpoint: true
registry.gitlab.com:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "gitlab/$1"
disable-default-registry-endpoint: true
docker.elastic.co:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "elastic/$1"
disable-default-registry-endpoint: true
gcr.io:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "gcr/$1"
disable-default-registry-endpoint: true
docker.litellm.ai:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "litellm/$1"
disable-default-registry-endpoint: true
public.ecr.aws:
endpoint:
- "https://artifactapi.k8s.syd1.au.unkin.net"
rewrite:
"^(.*)$": "ecr-public/$1"
disable-default-registry-endpoint: true
rke2::config_hash:
bind-address: "%{hiera('networking_loopback0_ip')}"
node-ip: "%{hiera('networking_loopback0_ip')}"
@@ -125,6 +182,17 @@ frrouting::ospf_exclude_k8s_enable: true
frrouting::k8s_cluster_cidr: '10.42.0.0/16' # RKE2 cluster-cidr (pods)
frrouting::k8s_service_cidr: '10.43.0.0/16' # RKE2 service-cidr
# sysctl recommendations
sysctl::base::values:
net.ipv4.conf.default.rp_filter:
value: '0'
net.ipv4.conf.all.rp_filter:
value: '0'
fs.inotify.max_user_watches:
value: '524288'
fs.inotify.max_user_instances:
value: '512'
# add loopback interfaces to ssh list
ssh::server::options:
ListenAddress:
-3
View File
@@ -3,9 +3,6 @@
rke2::node_type: server
rke2::helm_install: true
rke2::helm_repos:
rancher-stable: https://releases.rancher.com/server-charts/stable
purelb: https://gitlab.com/api/v4/projects/20400619/packages/helm/stable
jetstack: https://charts.jetstack.io
harbor: https://helm.goharbor.io
traefik: https://traefik.github.io/charts
hashicorp: https://helm.releases.hashicorp.com
@@ -11,6 +11,7 @@ profiles::metrics::grafana::db_name: "%{hiera('profiles::sql::postgresdb::dbname
profiles::metrics::grafana::db_user: "%{hiera('profiles::sql::postgresdb::dbuser')}"
profiles::metrics::grafana::db_pass: "%{hiera('profiles::sql::postgresdb::dbpass')}"
profiles::metrics::grafana::pgsql_backend: true
profiles::metrics::grafana::version: '13.0.2'
profiles::metrics::grafana::plugins:
victoriametrics-logs-datasource:
ensure: present
+1
View File
@@ -16,3 +16,4 @@ certbot::domains:
- git.unkin.net
- grafana.unkin.net
- dashboard.ceph.unkin.net
- auth.unkin.net
+1 -1
View File
@@ -26,7 +26,7 @@ profiles::puppet::cobbler_enc::packages:
- 'requests'
- 'PyYAML'
profiles::puppet::enc::repo: https://git.service.au-syd1.consul/unkinben/puppet-enc.git
profiles::puppet::r10k::r10k_repo: https://git.service.au-syd1.consul/unkin/puppet-r10k.git
profiles::puppet::r10k::r10k_repo: https://git.unkin.net/unkin/puppet-r10k.git
profiles::puppet::g10k::bin_path: '/usr/bin/g10k'
profiles::puppet::g10k::cfg_path: '/etc/puppetlabs/r10k/r10k.yaml'
profiles::puppet::g10k::environments_path: '/etc/puppetlabs/code/environments'
-273
View File
@@ -3,125 +3,6 @@ profiles::packages::include:
createrepo: {}
profiles::reposync::repos_list:
almalinux_9.7_baseos:
repository: 'baseos'
description: 'AlmaLinux 9.7 BaseOS'
osname: 'almalinux'
release: '9.7'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.7/baseos'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.7_appstream:
repository: 'appstream'
description: 'AlmaLinux 9.7 AppStream'
osname: 'almalinux'
release: '9.7'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.7/appstream'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.7_crb:
repository: 'crb'
description: 'AlmaLinux 9.7 CRB'
osname: 'almalinux'
release: '9.7'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.7/crb'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.7_ha:
repository: 'ha'
description: 'AlmaLinux 9.7 HighAvailability'
osname: 'almalinux'
release: '9.7'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.7/highavailability'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.7_extras:
repository: 'extras'
description: 'AlmaLinux 9.7 extras'
osname: 'almalinux'
release: '9.7'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.7/extras'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.6_baseos:
repository: 'baseos'
description: 'AlmaLinux 9.6 BaseOS'
osname: 'almalinux'
release: '9.6'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.6/baseos'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.6_appstream:
repository: 'appstream'
description: 'AlmaLinux 9.6 AppStream'
osname: 'almalinux'
release: '9.6'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.6/appstream'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.6_crb:
repository: 'crb'
description: 'AlmaLinux 9.6 CRB'
osname: 'almalinux'
release: '9.6'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.6/crb'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.6_ha:
repository: 'ha'
description: 'AlmaLinux 9.6 HighAvailability'
osname: 'almalinux'
release: '9.6'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.6/highavailability'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9.6_extras:
repository: 'extras'
description: 'AlmaLinux 9.6 extras'
osname: 'almalinux'
release: '9.6'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.6/extras'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9_5_baseos:
repository: 'baseos'
description: 'AlmaLinux 9.5 BaseOS'
osname: 'almalinux'
release: '9.5'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.5/baseos'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9_5_appstream:
repository: 'appstream'
description: 'AlmaLinux 9.5 AppStream'
osname: 'almalinux'
release: '9.5'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.5/appstream'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9_5_crb:
repository: 'crb'
description: 'AlmaLinux 9.5 CRB'
osname: 'almalinux'
release: '9.5'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.5/crb'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9_5_ha:
repository: 'ha'
description: 'AlmaLinux 9.5 HighAvailability'
osname: 'almalinux'
release: '9.5'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.5/highavailability'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
almalinux_9_5_extras:
repository: 'extras'
description: 'AlmaLinux 9.5 extras'
osname: 'almalinux'
release: '9.5'
mirrorlist: 'https://mirrors.almalinux.org/mirrorlist/9.5/extras'
gpgkey: 'http://mirror.aarnet.edu.au/pub/almalinux/RPM-GPG-KEY-AlmaLinux-9'
epel_8:
repository: 'everything'
description: 'EPEL8'
osname: 'epel'
release: '8'
mirrorlist: 'https://mirrors.fedoraproject.org/mirrorlist?repo=epel-8&arch=x86_64'
gpgkey: 'https://epel.mirror.digitalpacific.com.au/RPM-GPG-KEY-EPEL-8'
epel_9:
repository: 'everything'
description: 'EPEL9'
osname: 'epel'
release: '9'
mirrorlist: 'https://mirrors.fedoraproject.org/mirrorlist?repo=epel-9&arch=x86_64'
gpgkey: 'https://epel.mirror.digitalpacific.com.au/RPM-GPG-KEY-EPEL-9'
docker_stable_el8:
repository: 'stable'
description: 'Docker CE Stable EL8'
@@ -136,34 +17,6 @@ profiles::reposync::repos_list:
release: 'el9'
baseurl: 'https://download.docker.com/linux/centos/9/x86_64/stable/'
gpgkey: 'https://download.docker.com/linux/centos/gpg'
frr_stable_el8:
repository: 'stable'
description: 'FRR Stable EL8'
osname: 'frr'
release: 'el8'
baseurl: 'https://rpm.frrouting.org/repo/el8/frr/'
gpgkey: 'https://packagerepo.service.consul/frr/gpg/RPM-GPG-KEY-FRR'
frr_extras_el8:
repository: 'extras'
description: 'FRR Extras EL8'
osname: 'frr'
release: 'el8'
baseurl: 'https://rpm.frrouting.org/repo/el8/extras/'
gpgkey: 'https://packagerepo.service.consul/frr/gpg/RPM-GPG-KEY-FRR'
frr_stable_el9:
repository: 'stable'
description: 'FRR Stable EL9'
osname: 'frr'
release: 'el9'
baseurl: 'https://rpm.frrouting.org/repo/el9/frr/'
gpgkey: 'https://packagerepo.service.consul/frr/gpg/RPM-GPG-KEY-FRR'
frr_extras_el9:
repository: 'extras'
description: 'FRR Extras el9'
osname: 'frr'
release: 'el9'
baseurl: 'https://rpm.frrouting.org/repo/el9/extras/'
gpgkey: 'https://packagerepo.service.consul/frr/gpg/RPM-GPG-KEY-FRR'
k8s_1.32:
repository: '1.32'
description: 'Kubernetes 1.32'
@@ -178,62 +31,6 @@ profiles::reposync::repos_list:
release: '1.33'
baseurl: 'https://pkgs.k8s.io/core:/stable:/v1.33/rpm/'
gpgkey: 'https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key'
mariadb_11_8_el8:
repository: 'el8'
description: 'MariaDB 11.8'
osname: 'mariadb'
release: '11.8'
baseurl: 'http://mariadb.mirror.digitalpacific.com.au/yum/11.8/rhel8-amd64/'
gpgkey: 'https://mariadb.mirror.digitalpacific.com.au/yum/RPM-GPG-KEY-MariaDB'
mariadb_11_8_el9:
repository: 'el9'
description: 'MariaDB 11.8'
osname: 'mariadb'
release: '11.8'
baseurl: 'http://mariadb.mirror.digitalpacific.com.au/yum/11.8/rhel9-amd64/'
gpgkey: 'https://mariadb.mirror.digitalpacific.com.au/yum/RPM-GPG-KEY-MariaDB'
openvox7_el8:
repository: '8'
description: 'openvox 7 EL8'
osname: 'openvox7'
release: 'el'
baseurl: 'https://yum.voxpupuli.org/openvox7/el/8/x86_64/'
gpgkey: 'https://yum.voxpupuli.org/GPG-KEY-openvox.pub'
openvox7_el9:
repository: '9'
description: 'openvox 7 EL9'
osname: 'openvox7'
release: 'el'
baseurl: 'https://yum.voxpupuli.org/openvox7/el/9/x86_64/'
gpgkey: 'https://yum.voxpupuli.org/GPG-KEY-openvox.pub'
openvox7_el10:
repository: '10'
description: 'openvox 7 EL10'
osname: 'openvox7'
release: 'el'
baseurl: 'https://yum.voxpupuli.org/openvox7/el/10/x86_64/'
gpgkey: 'https://yum.voxpupuli.org/GPG-KEY-openvox.pub'
openvox8_el8:
repository: '8'
description: 'openvox 8 EL8'
osname: 'openvox8'
release: 'el'
baseurl: 'https://yum.voxpupuli.org/openvox8/el/8/x86_64/'
gpgkey: 'https://yum.voxpupuli.org/GPG-KEY-openvox.pub'
openvox8_el9:
repository: '9'
description: 'openvox 8 EL9'
osname: 'openvox8'
release: 'el'
baseurl: 'https://yum.voxpupuli.org/openvox8/el/9/x86_64/'
gpgkey: 'https://yum.voxpupuli.org/GPG-KEY-openvox.pub'
openvox8_el10:
repository: '10'
description: 'openvox 8 EL10'
osname: 'openvox8'
release: 'el'
baseurl: 'https://yum.voxpupuli.org/openvox8/el/10/x86_64/'
gpgkey: 'https://yum.voxpupuli.org/GPG-KEY-openvox.pub'
puppet7_el8:
repository: '8'
description: 'Puppet 7 EL8'
@@ -262,76 +59,6 @@ profiles::reposync::repos_list:
release: 'el'
baseurl: 'https://yum.puppet.com/puppet8/el/9/x86_64/'
gpgkey: 'https://yum.puppet.com/RPM-GPG-KEY-puppet-20250406'
postgresql_rhel8_common:
repository: 'common'
description: 'PostgreSQL Common RHEL 8'
osname: 'postgresql'
release: 'rhel8'
baseurl: 'https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-8-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
postgresql_rhel9_common:
repository: 'common'
description: 'PostgreSQL Common RHEL 9'
osname: 'postgresql'
release: 'rhel9'
baseurl: 'https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-9-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
postgresql_rhel8_15:
repository: '15'
description: 'PostgreSQL 15 RHEL 8'
osname: 'postgresql'
release: 'rhel8'
baseurl: 'https://download.postgresql.org/pub/repos/yum/15/redhat/rhel-8-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
postgresql_rhel9_15:
repository: '15'
description: 'PostgreSQL 15 RHEL 9'
osname: 'postgresql'
release: 'rhel9'
baseurl: 'https://download.postgresql.org/pub/repos/yum/15/redhat/rhel-9-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
postgresql_rhel8_16:
repository: '16'
description: 'PostgreSQL 16 RHEL 8'
osname: 'postgresql'
release: 'rhel8'
baseurl: 'https://download.postgresql.org/pub/repos/yum/16/redhat/rhel-8-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
postgresql_rhel9_16:
repository: '16'
description: 'PostgreSQL 16 RHEL 9'
osname: 'postgresql'
release: 'rhel9'
baseurl: 'https://download.postgresql.org/pub/repos/yum/16/redhat/rhel-9-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
postgresql_rhel8_17:
repository: '17'
description: 'PostgreSQL 17 RHEL 8'
osname: 'postgresql'
release: 'rhel8'
baseurl: 'https://download.postgresql.org/pub/repos/yum/17/redhat/rhel-8-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
postgresql_rhel9_17:
repository: '17'
description: 'PostgreSQL 17 RHEL 9'
osname: 'postgresql'
release: 'rhel9'
baseurl: 'https://download.postgresql.org/pub/repos/yum/17/redhat/rhel-9-x86_64/'
gpgkey: 'https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL'
rke2_common_el9:
repository: 'common'
description: 'RKE2 common RHEL 9'
osname: 'rke2'
release: "rhel9"
baseurl: "https://rpm.rancher.io/rke2/latest/common/centos/9/noarch"
gpgkey: "https://rpm.rancher.io/public.key"
rke2_1_33_el9:
repository: '1.33'
description: 'RKE2 1.33 RHEL 9'
osname: 'rke2'
release: "rhel9"
baseurl: "https://rpm.rancher.io/rke2/latest/1.33/centos/9/x86_64"
gpgkey: "https://rpm.rancher.io/public.key"
zfs_dkms_rhel8:
repository: 'dkms'
description: 'ZFS DKMS RHEL 8'
@@ -29,6 +29,7 @@ profiles::consul::server::acl:
profiles::pki::vault::alt_names:
- consul.main.unkin.net
- consul.service.consul
- "consul.service.%{facts.country}-%{facts.region}.consul"
- consul
# manage a simple nginx reverse proxy
@@ -38,6 +39,7 @@ profiles::nginx::simpleproxy::nginx_aliases:
- consul.main.unkin.net
profiles::nginx::simpleproxy::proxy_port: 8500
profiles::nginx::simpleproxy::proxy_path: '/'
nginx::client_max_body_size: 512M
# consul
profiles::consul::client::node_rules:
+10 -2
View File
@@ -2,10 +2,12 @@
profiles::vault::server::members_role: roles::infra::storage::vault
profiles::vault::server::members_lookup: true
profiles::vault::server::data_dir: /data/vault
profiles::vault::server::plugin_dir: /opt/openbao-plugins
profiles::vault::server::manage_storage_dir: true
profiles::vault::server::tls_disable: false
vault::package_name: openbao
vault::package_ensure: latest
profiles::vault::server::package_name: openbao
profiles::vault::server::package_ensure: 2.4.4
profiles::vault::server::disable_openbao: false
# additional altnames
profiles::pki::vault::alt_names:
@@ -23,3 +25,9 @@ profiles::nginx::simpleproxy::proxy_scheme: 'http'
profiles::nginx::simpleproxy::proxy_host: '127.0.0.1'
profiles::nginx::simpleproxy::proxy_port: 8200
profiles::nginx::simpleproxy::proxy_path: '/'
profiles::packages::include:
openbao-plugins: {}
openbao-plugin-secrets-litellm: {}
openbao-plugin-secrets-gpg: {}
openbao-plugin-secrets-rancher: {}
+3 -3
View File
@@ -28,8 +28,8 @@ class externaldns::master inherits externaldns {
dynamic => true,
allow_updates => ['key externaldns-key'],
allow_transfers => empty($slave_ips) ? {
true => [],
false => ['dns-slaves'],
true => ['key externaldns-key'],
false => ['key externaldns-key','dns-slaves'],
},
ns_notify => !empty($slave_ips),
also_notify => $slave_ips,
@@ -42,4 +42,4 @@ class externaldns::master inherits externaldns {
recursion => false,
zones => $externaldns::k8s_zones,
}
}
}
+6 -1
View File
@@ -22,7 +22,12 @@ class incus::cluster (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${members_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
+56
View File
@@ -0,0 +1,56 @@
# frozen_string_literal: true
require 'facter'
# Detects active ceph service instances via systemctl and exposes facts
# for use in ceph service management profiles.
# rubocop:disable Style/ClassAndModuleChildren
module Unkin
module Ceph
# Detects active ceph service instances via systemctl and exposes Facter facts.
module Utils
TYPES = %w[mon mgr mds osd].freeze
def self.services
output = Facter::Core::Execution.execute(
'systemctl list-units "ceph*" --no-legend --plain --all 2>/dev/null',
on_fail: ''
)
parse_units(output)
end
def self.parse_units(output)
result = TYPES.each_with_object({}) { |type, hash| hash[type] = [] }
output.each_line do |line|
unit = line.split.first
next unless unit
match_unit(result, unit)
end
result
end
def self.match_unit(result, unit)
TYPES.each do |type|
match = unit.match(/\Aceph-#{type}@(.+)\.service\z/)
result[type] << "ceph-#{type}@#{match[1]}" if match
end
end
TYPES.each do |type|
define_singleton_method(:"#{type}?") { !services[type].empty? }
end
end
end
end
# rubocop:enable Style/ClassAndModuleChildren
Facter.add('ceph_services') do
setcode { Unkin::Ceph::Utils.services }
end
Unkin::Ceph::Utils::TYPES.each do |type|
Facter.add("is_ceph_#{type}") do
setcode { Unkin::Ceph::Utils.public_send(:"#{type}?") }
end
end
+88
View File
@@ -0,0 +1,88 @@
# frozen_string_literal: true
# lib/facter/dns_records.rb
#
# Reports this host's expected DNS records (assembled by profiles::dns::updater
# into its records file) versus what is currently deployed on the authoritative
# server, so puppet can detect drift and re-apply.
#
# Structured value:
# { server, count, expected => [{zone,fqdn,type,ttl,value}], in_sync,
# drift => [{...,deployed => [...]}] }
# Helpers for the dns_records fact.
module DnsRecordsFact
RECORDS_FILE = '/var/lib/dns-updater/records'
SERVER_FILE = '/var/lib/dns-updater/server'
module_function
# normalise a value for comparison: strip, drop trailing dot, downcase
def norm(value)
value.to_s.strip.chomp('.').downcase
end
def server
File.exist?(SERVER_FILE) ? File.read(SERVER_FILE).strip : nil
end
# a name relative to a zone (or @) as a fully-qualified name
def to_fqdn(name, zone)
return "#{zone}." if name.to_s.empty? || name == '@'
"#{name}.#{zone}."
end
# parse one "zone|name|type|ttl|value" line into a record hash (nil to skip)
def parse_line(line)
line = line.strip
return nil if line.empty? || line.start_with?('#')
zone, name, type, ttl, value = line.split('|', 5)
return nil unless zone && type && value
{ 'zone' => zone, 'fqdn' => to_fqdn(name, zone), 'type' => type, 'ttl' => ttl, 'value' => value }
end
# parse the records file into record hashes
def expected
return [] unless File.exist?(RECORDS_FILE)
File.readlines(RECORDS_FILE).filter_map { |line| parse_line(line) }
end
# the values currently deployed for a record, per the authoritative server
def deployed(record, srv)
cmd = ['dig', '+short', '+time=2', '+tries=1']
cmd << "@#{srv}" if srv && !srv.empty?
cmd += [record['fqdn'], record['type']]
out = Facter::Core::Execution.execute(cmd.join(' '), on_fail: '')
out.to_s.split("\n").map { |line| norm(line) }.reject(&:empty?)
end
def report
srv = server
exp = expected
drift = exp.filter_map do |record|
dep = deployed(record, srv)
record.merge('deployed' => dep) unless dep.include?(norm(record['value']))
end
{ 'server' => srv, 'count' => exp.length, 'expected' => exp, 'in_sync' => drift.empty?, 'drift' => drift }
end
end
Facter.add(:dns_records) do
confine kernel: 'Linux'
setcode do
File.exist?(DnsRecordsFact::RECORDS_FILE) ? DnsRecordsFact.report : nil
end
end
# Convenience boolean for `if $facts['dns_records_insync']` guards.
Facter.add(:dns_records_insync) do
confine kernel: 'Linux'
setcode do
v = Facter.value(:dns_records)
v.nil? ? nil : v['in_sync']
end
end
+6 -1
View File
@@ -20,7 +20,12 @@ class redisha::redis (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${redisha_members_role}' and region='${facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${redisha_members_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
+6 -1
View File
@@ -23,7 +23,12 @@ class redisha::sentinel (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${redisha_members_role}' and region='${facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${redisha_members_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
@@ -1,23 +0,0 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rancher
namespace: cattle-system
annotations:
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts: [rancher.main.unkin.net]
secretName: tls-rancher
rules:
- host: rancher.main.unkin.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rancher
port:
number: 80
-45
View File
@@ -1,45 +0,0 @@
apiVersion: purelb.io/v1
kind: LBNodeAgent
metadata:
name: common
namespace: purelb
spec:
local:
extlbint: kube-lb0
localint: default
sendgarp: false
---
apiVersion: purelb.io/v1
kind: LBNodeAgent
metadata:
name: dmz
namespace: purelb
spec:
local:
extlbint: kube-lb0
localint: default
sendgarp: false
---
apiVersion: purelb.io/v1
kind: ServiceGroup
metadata:
name: dmz
namespace: purelb
spec:
local:
v4pools:
- subnet: 198.18.199.0/24
pool: 198.18.199.0/24
aggregation: /32
---
apiVersion: purelb.io/v1
kind: ServiceGroup
metadata:
name: common
namespace: purelb
spec:
local:
v4pools:
- subnet: 198.18.200.0/24
pool: 198.18.200.0/24
aggregation: /32
+20 -24
View File
@@ -7,6 +7,8 @@ class rke2::config (
Stdlib::Fqdn $bootstrap_node = $rke2::bootstrap_node,
String $node_token = $rke2::node_token,
Array[String[1]] $extra_config_files = $rke2::extra_config_files,
Boolean $manage_registries = $rke2::manage_registries,
Hash $registries = $rke2::registries,
){
# if its not the bootstrap node, add join path to config
@@ -28,6 +30,24 @@ class rke2::config (
$config = $config_hash
}
if $manage_registries {
file { '/etc/rancher/rke2/registries.yaml':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => epp('rke2/registries.yaml.epp', { registries => $registries }),
require => Package["rke2-${node_type}"],
notify => Service["rke2-${node_type}"],
}
}else{
file { '/etc/rancher/rke2/registries.yaml':
ensure => absent,
require => Package["rke2-${node_type}"],
notify => Service["rke2-${node_type}"],
}
}
# create the config file
file { $config_file:
ensure => file,
@@ -68,30 +88,6 @@ class rke2::config (
# on the controller nodes only
if $node_type == 'server' and $facts['k8s_masters'] and $facts['k8s_masters'] > 2 {
# wait for purelb helm to setup namespace
if 'purelb' in $facts['k8s_namespaces'] {
file {'/var/lib/rancher/rke2/server/manifests/purelb-config.yaml':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/rke2/purelb-config.yaml',
require => Service['rke2-server'],
}
}
# wait for rancher helm to setup namespace
if 'cattle-system' in $facts['k8s_namespaces'] {
file {'/var/lib/rancher/rke2/server/manifests/ingress-route-rancher.yaml':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/rke2/ingress-route-rancher.yaml',
require => Service['rke2-server'],
}
}
# manage extra config config (these are not dependent on helm)
$extra_config_files.each |$file| {
-38
View File
@@ -38,44 +38,6 @@ class rke2::helm (
}
}
}
# install specific helm charts to bootstrap environment
$plb_cmd = 'helm install purelb purelb/purelb \
--create-namespace \
--namespace=purelb \
--repository-config /etc/helm/repositories.yaml'
exec { 'install_purelb':
command => $plb_cmd,
path => ['/usr/bin', '/bin'],
environment => ['KUBECONFIG=/etc/rancher/rke2/rke2.yaml'],
unless => 'helm list -n purelb | grep -q ^purelb',
}
$cm_cmd = 'helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set crds.enabled=true \
--repository-config /etc/helm/repositories.yaml'
exec { 'install_cert_manager':
command => $cm_cmd,
path => ['/usr/bin', '/bin'],
environment => ['KUBECONFIG=/etc/rancher/rke2/rke2.yaml'],
unless => 'helm list -n cert-manager | grep -q ^cert-manager',
}
$r_cmd = 'helm install rancher rancher-stable/rancher \
--namespace cattle-system \
--create-namespace \
--set hostname=rancher.main.unkin.net \
--set bootstrapPassword=admin \
--set ingress.tls.source=secret \
--repository-config /etc/helm/repositories.yaml'
exec { 'install_rancher':
command => $r_cmd,
path => ['/usr/bin', '/bin'],
environment => ['KUBECONFIG=/etc/rancher/rke2/rke2.yaml'],
unless => 'helm list -n cattle-system | grep -q ^rancher',
}
}
}
}
+2
View File
@@ -12,6 +12,8 @@ class rke2 (
Hash $helm_repos = $rke2::params::helm_repos,
Array[String[1]] $extra_config_files = $rke2::params::extra_config_files,
Stdlib::HTTPUrl $container_archive_source = $rke2::params::container_archive_source,
Boolean $manage_registries = $rke2::params::manage_registries,
Hash $registries = $rke2::params::registries,
) inherits rke2::params {
include rke2::install
+2
View File
@@ -12,4 +12,6 @@ class rke2::params (
Hash $helm_repos = {},
Array[String[1]] $extra_config_files = [],
Stdlib::HTTPUrl $container_archive_source = 'https://github.com/rancher/rke2/releases/download',
Boolean $manage_registries = false,
Hash $registries = {},
) {}
@@ -0,0 +1,20 @@
<%- | Hash $registries | -%>
---
# DO NOT MODIFY - MANAGED BY PUPPET
mirrors:
<%- $registries.each |$registry, $config| { -%>
<%= $registry %>:
endpoint:
<%- $config['endpoint'].each |$ep| { -%>
- "<%= $ep %>"
<%- } -%>
<%- if $config['rewrite'] { -%>
rewrite:
<%- $config['rewrite'].each |$pattern, $replacement| { -%>
"<%= $pattern %>": "<%= $replacement %>"
<%- } -%>
<%- } -%>
<%- if $config['disable-default-registry-endpoint'] { -%>
disable-default-registry-endpoint: true
<%- } -%>
<%- } -%>
+21 -2
View File
@@ -167,7 +167,13 @@ class stalwart (
# Query cluster members for validation
$cluster_query = "enc_role='${cluster_role}' and country='${facts['country']}' and region='${facts['region']}'"
$cluster_members_raw = query_nodes($cluster_query, 'networking.fqdn')
$cluster_members_raw = puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${cluster_role}' and
certname in facts[certname] { name = 'country' and value = '${facts['country']}' } and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] }
$cluster_members = $cluster_members_raw ? {
undef => [],
default => $cluster_members_raw,
@@ -180,7 +186,20 @@ class stalwart (
# Query HAProxy nodes for proxy trusted networks
$haproxy_query = "enc_role='${haproxy_role}' and country='${facts['country']}' and region='${facts['region']}'"
$haproxy_members_raw = query_nodes($haproxy_query, 'networking.ip')
$haproxy_members_raw = puppetdb_query(
"facts[certname,value] {
name = 'networking' and
certname in facts[certname] {
name = 'enc_role' and value = '${haproxy_role}'
} and
certname in facts[certname] {
name = 'country' and value = '${facts['country']}'
} and
certname in facts[certname] {
name = 'region' and value = '${facts['region']}'
}
}"
).map |$fact| { $fact['value']['ip'] }
$haproxy_ips = $haproxy_members_raw ? {
undef => [],
default => sort($haproxy_members_raw),
+13
View File
@@ -0,0 +1,13 @@
class profiles::ceph::mds (
Boolean $ensure_running = true,
) {
if $ensure_running and $facts['is_ceph_mds'] {
$facts['ceph_services']['mds'].each |String $svc| {
service { $svc:
ensure => running,
enable => true,
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
class profiles::ceph::mgr (
Boolean $ensure_running = true,
) {
if $ensure_running and $facts['is_ceph_mgr'] {
$facts['ceph_services']['mgr'].each |String $svc| {
service { $svc:
ensure => running,
enable => true,
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
class profiles::ceph::mon (
Boolean $ensure_running = true,
) {
if $ensure_running and $facts['is_ceph_mon'] {
$facts['ceph_services']['mon'].each |String $svc| {
service { $svc:
ensure => running,
enable => true,
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
class profiles::ceph::osd (
Boolean $ensure_running = true,
) {
if $ensure_running and $facts['is_ceph_osd'] {
$facts['ceph_services']['osd'].each |String $svc| {
service { $svc:
ensure => running,
enable => true,
}
}
}
}
+6 -1
View File
@@ -28,7 +28,12 @@ class profiles::consul::client (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${members_role}' and
certname in facts[certname] { name = 'region' and value = '${::facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
+12 -2
View File
@@ -65,12 +65,22 @@ class profiles::consul::server (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${members_role}' and
certname in facts[certname] { name = 'region' and value = '${::facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
if $join_remote_regions {
# get all nodes in the members_role for each other region
$region_to_servers = $remote_regions.reduce({}) |$memo, $region| {
$servers = sort(query_nodes("enc_role='${members_role}' and region='${region}'", 'networking.fqdn'))
$servers = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${members_role}' and
certname in facts[certname] { name = 'region' and value = '${region}' }
}"
).map |$fact| { $fact['certname'] })
$memo + { $region => $servers }
}
+26 -4
View File
@@ -11,16 +11,38 @@ class profiles::dns::base (
Optional[String] $ns_role = undef,
){
# install bind_utils
# install bind_utils (provides nsupdate)
include bind::updater
# assemble the host's DNS records and nsupdate them to the authoritative server
include profiles::dns::updater
# if ns_role is set, find all hosts matching that enc_role
$nameserver_array = $ns_role ? {
undef => $nameservers,
default => $use_ns ? {
'all' => query_nodes("enc_role='${ns_role}'", 'networking.ip'),
'region' => query_nodes("enc_role='${ns_role}' and region=${facts['region']}", 'networking.ip'),
'country' => query_nodes("enc_role='${ns_role}' and country=${facts['country']}", 'networking.ip'),
'all' => puppetdb_query(
"facts[certname,value] {
name = 'networking' and
certname in nodes[certname] { facts.enc_role = '${ns_role}' }
}"
).map |$fact| { $fact['value']['ip'] },
'region' => puppetdb_query(
"facts[certname,value] {
name = 'networking' and
certname in nodes[certname] {
facts.enc_role = '${ns_role}' and facts.region = '${facts['region']}'
}
}"
).map |$fact| { $fact['value']['ip'] },
'country' => puppetdb_query(
"facts[certname,value] {
name = 'networking' and
certname in nodes[certname] {
facts.enc_role = '${ns_role}' and facts.country = '${facts['country']}'
}
}"
).map |$fact| { $fact['value']['ip'] },
}
}
+18 -4
View File
@@ -20,9 +20,21 @@ class profiles::dns::master (
$nameservers_array = $ns_role ? {
undef => [$facts['networking']['fqdn']],
default => $use_ns ? {
'all' => sort(query_nodes("enc_role='${ns_role}'", 'networking.fqdn')),
'region' => sort(query_nodes("enc_role='${ns_role}' and region=${facts['region']}", 'networking.fqdn')),
'country' => sort(query_nodes("enc_role='${ns_role}' and country=${facts['country']}", 'networking.fqdn')),
'all' => sort(puppetdb_query(
"facts[certname] { name = 'enc_role' and value = '${ns_role}' }"
).map |$fact| { $fact['certname'] }),
'region' => sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${ns_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] }),
'country' => sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${ns_role}' and
certname in facts[certname] { name = 'country' and value = '${facts['country']}' }
}"
).map |$fact| { $fact['certname'] }),
}
}
@@ -32,7 +44,9 @@ class profiles::dns::master (
$facts['networking']['fqdn'] => $facts['networking']['ip']
},
default => $nameservers_array.reduce({}) |$acc, $fqdn| {
$result = query_nodes("networking.fqdn='${fqdn}'", 'networking.ip')
$result = puppetdb_query(
"facts[certname,value] { name = 'networking' and certname = '${fqdn}' }"
).map |$fact| { $fact['value']['ip'] }
$ip = $result[0]
$acc + { "${fqdn}." => $ip }
}
+27 -6
View File
@@ -1,4 +1,10 @@
# defines the base record that will be exported
# profiles::dns::record
#
# Declares a DNS record for this host. Publishes it via either or both methods,
# controlled by profiles::dns::updater's toggles (both on during cutover):
# - nsupdate: a local concat fragment consumed by profiles::dns::updater,
# which nsupdates it to the authoritative server.
# - export: the legacy @@concat::fragment exported to the puppet DNS master.
define profiles::dns::record (
String $record,
Enum[
@@ -13,11 +19,26 @@ define profiles::dns::record (
String $value,
String $zone,
Integer $order,
Stdlib::AbsolutePath $basedir = lookup('profiles::dns::master::basedir'),
Integer $ttl = 300,
) {
@@concat::fragment { "${zone}_${name}":
target => "${basedir}/${zone}.conf",
content => "${record} IN ${type} ${value}\n",
order => $order,
include profiles::dns::updater
# new: local records file consumed by the nsupdate service
if $profiles::dns::updater::manage_nsupdate {
# zone|name|type|ttl|value (parsed by the dns-update script)
concat::fragment { "dns-record-${name}":
target => $profiles::dns::updater::records_file,
content => "${zone}|${record}|${type}|${ttl}|${value}\n",
order => sprintf('%03d', $order),
}
}
# legacy: export the fragment to the puppet DNS master
if $profiles::dns::updater::manage_export {
@@concat::fragment { "${zone}_${name}":
target => "${profiles::dns::updater::master_basedir}/${zone}.conf",
content => "${record} IN ${type} ${value}\n",
order => $order,
}
}
}
+154
View File
@@ -0,0 +1,154 @@
# profiles::dns::updater
#
# Publishes this host's DNS records. Two methods, independently toggled so both
# can run during the k8s cutover (profiles::dns::record honours the same flags):
#
# - nsupdate ($manage_nsupdate): assemble the records into a local file and
# nsupdate them to the k8s authoritative write endpoint via a systemd .path
# unit that watches the file. Inert until $key_secret (TSIG) is set.
# - export ($manage_export): the legacy exported-resources flow to the puppet
# DNS master. Kept during cutover; disable once k8s is authoritative.
#
# nsupdate comes from bind-utils (installed via bind::updater in
# profiles::dns::base).
class profiles::dns::updater (
Boolean $manage_nsupdate = true,
Boolean $manage_export = true,
String $server = '198.18.200.9',
String $key_name = 'client-update',
String $key_algorithm = 'hmac-sha256',
Optional[Sensitive[String]] $key_secret = undef,
Integer $default_ttl = 300,
Stdlib::AbsolutePath $records_file = '/var/lib/dns-updater/records',
Stdlib::AbsolutePath $state_dir = '/var/lib/dns-updater',
Stdlib::AbsolutePath $config_dir = '/etc/dns-updater',
Stdlib::AbsolutePath $master_basedir = lookup('profiles::dns::master::basedir'),
# dns-updater daemon (replaces the dns-update shell script).
String $package_ensure = 'installed',
Stdlib::AbsolutePath $api_socket = '/run/dns-updater/api.sock',
String $resync = '10m',
Enum['debug', 'info', 'warn', 'error'] $log_level = 'info',
Boolean $watch_interfaces = true,
) {
$state_file = "${state_dir}/applied"
$server_file = "${state_dir}/server"
$key_file = "${config_dir}/key"
if $manage_nsupdate {
file { $state_dir:
ensure => directory,
owner => 'root',
group => 'root',
mode => '0755',
}
# Server address, read by the dns_records fact for drift detection.
file { $server_file:
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => "${server}\n",
require => File[$state_dir],
}
# Records file, assembled from profiles::dns::record fragments.
concat { $records_file:
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
ensure_newline => true,
warn => false,
require => File[$state_dir],
}
concat::fragment { 'dns-update-header':
target => $records_file,
content => "# Managed by puppet (profiles::dns::record): zone|name|type|ttl|value\n",
order => '00',
}
if $key_secret =~ Undef {
notify { 'dns-updater-inert':
message => 'profiles::dns::updater: key_secret unset; records assembled but not applied.',
loglevel => 'info',
}
} else {
file { $config_dir:
ensure => directory,
owner => 'root',
group => 'root',
mode => '0700',
}
file { $key_file:
ensure => file,
owner => 'root',
group => 'root',
mode => '0600',
show_diff => false,
content => Sensitive(epp('profiles/dns/tsig-key.epp', {
'name' => $key_name,
'algorithm' => $key_algorithm,
'secret' => $key_secret.unwrap,
})),
}
# dns-updater daemon: watches the records file (inotify) and network
# interfaces, pushes TSIG-signed RFC2136 updates to $server natively.
package { 'dns-updater':
ensure => $package_ensure,
}
$env_content = @("ENV")
# Managed by puppet (profiles::dns::updater).
DNS_UPDATER_SERVER=${server}
DNS_UPDATER_KEY_FILE=${key_file}
DNS_UPDATER_RECORDS_FILE=${records_file}
DNS_UPDATER_STATE_FILE=${state_file}
DNS_UPDATER_API=${api_socket}
DNS_UPDATER_RESYNC=${resync}
DNS_UPDATER_WATCH_INTERFACES=${watch_interfaces}
DNS_UPDATER_LOG_LEVEL=${log_level}
| ENV
file { "${config_dir}/env":
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => $env_content,
require => [File[$config_dir], Package['dns-updater']],
}
# Restart only on config/key change; records-file changes are picked up by
# the daemon's own inotify watch, so no service churn on record edits.
service { 'dns-updater':
ensure => running,
enable => true,
subscribe => [File["${config_dir}/env"], File[$key_file]],
require => [Package['dns-updater'], Concat[$records_file], File[$key_file]],
}
# Retire the previous shell-based mechanism.
file { '/usr/local/bin/dns-update':
ensure => absent,
}
systemd::unit_file { 'dns-update.service':
ensure => absent,
active => false,
enable => false,
}
systemd::unit_file { 'dns-update.path':
ensure => absent,
active => false,
enable => false,
}
}
}
}
+7 -2
View File
@@ -18,7 +18,12 @@ class profiles::etcd::node (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${members_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
@@ -31,7 +36,7 @@ class profiles::etcd::node (
$initial_cluster = $servers_array.map |$fqdn| {
# lookup the ip address for the current fqdn
$ip = query_nodes("networking.fqdn='${fqdn}'", 'networking.ip')[0]
$ip = puppetdb_query("facts[certname,value] { name = 'networking' and certname = '${fqdn}' }").map |$fact| { $fact['value']['ip'] }[0]
# construct the string for this server
"${fqdn}=https://${ip}:${peer_port}"
+8 -7
View File
@@ -30,13 +30,14 @@ class profiles::haproxy::dns (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes(
"enc_role='${facts['enc_role']}' and
country='${facts['country']}' and
region='${facts['region']}' and
environment='${facts['environment']}'",
'networking.fqdn'
))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${facts['enc_role']}' and
certname in facts[certname] { name = 'country' and value = '${facts['country']}' } and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' } and
certname in facts[certname] { name = 'environment' and value = '${facts['environment']}' }
}"
).map |$fact| { $fact['certname'] })
# give enough time for a few hosts to be provisioned
if length($servers_array) >= 3 {
@@ -1,6 +1,7 @@
# profiles::metrics::grafana
class profiles::metrics::grafana (
String $ldap_bind_pass,
String $version = 'installed',
Stdlib::Port $http_port = 8080,
String $app_mode = 'production',
Boolean $allow_sign_up = false,
@@ -107,6 +108,7 @@ class profiles::metrics::grafana (
# deploy grafana
class { 'grafana':
version => $version,
cfg => $cfg,
ldap_cfg => $ldap_cfg,
plugins => $plugins,
+9 -2
View File
@@ -98,8 +98,15 @@ class profiles::minio::server (
}
# if it is, find hosts, sort them so they dont cause changes every run
#$servers_array = sort(query_nodes("enc_role='${minio_members_role}'", 'networking.fqdn'))
$servers_array = sort(query_nodes("enc_role='${minio_members_role}' and minio_region='${minio_region}'", 'networking.fqdn'))
#$servers_array = sort(puppetdb_query(
# "facts[certname] { name = 'enc_role' and value = '${minio_members_role}' }"
#).map |$fact| { $fact['certname'] })
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${minio_members_role}' and
certname in facts[certname] { name = 'minio_region' and value = '${minio_region}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
+15 -3
View File
@@ -26,9 +26,21 @@ class profiles::ntp::client (
$ntpserver_array = $ntp_role ? {
undef => $peers,
default => $use_ntp ? {
'all' => query_nodes("enc_role='${ntp_role}'", 'networking.fqdn'),
'region' => query_nodes("enc_role='${ntp_role}' and region=${facts['region']}", 'networking.fqdn'),
'country' => query_nodes("enc_role='${ntp_role}' and country=${facts['country']}", 'networking.fqdn'),
'all' => puppetdb_query(
"facts[certname] { name = 'enc_role' and value = '${ntp_role}' }"
).map |$fact| { $fact['certname'] },
'region' => puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${ntp_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] },
'country' => puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${ntp_role}' and
certname in facts[certname] { name = 'country' and value = '${facts['country']}' }
}"
).map |$fact| { $fact['certname'] },
}
}
@@ -24,10 +24,13 @@ class profiles::proxmox::clusterinit {
}
}
$servers_array = sort(query_nodes(
"enc_role='${membersrole}' and country='${facts['country']}' and region='${facts['region']}'",
'networking.fqdn'
))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${membersrole}' and
certname in facts[certname] { name = 'country' and value = '${facts['country']}' } and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
if ! $profiles::proxmox::params::pve_clusterinit_master {
if !empty($servers_array) {
@@ -11,13 +11,14 @@ class profiles::proxmox::clusterjoin {
$root_password = $profiles::proxmox::params::root_password
# query puppetdb for list of cluster members
$members_array = sort(query_nodes(
"enc_role='${membersrole}' and \
country='${facts['country']}' and \
region='${facts['region']}' and \
pve_cluster.cluster_name='${clustername}'",
'networking.fqdn'
))
$members_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${membersrole}' and
certname in facts[certname] { name = 'country' and value = '${facts['country']}' } and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' } and
certname in facts[certname] { name = 'pve_cluster' and value.cluster_name = '${clustername}' }
}"
).map |$fact| { $fact['certname'] })
# check if the pve kernerl is running
if $facts['kernelrelease'] == $profiles::proxmox::params::pve_kernel_release {
@@ -3,7 +3,7 @@
# This class manages the Puppetboard, a web interface to PuppetDB.
#
class profiles::puppet::puppetboard (
String $python_version = $facts['python3_release'],
String $python_version = '3.12',
Boolean $manage_virtualenv = false,
Integer $reports_count = 40,
Boolean $offline_mode = true,
+6 -1
View File
@@ -48,7 +48,12 @@ class profiles::sql::galera_member (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${galera_members_role}' and region='${facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${galera_members_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
+6 -1
View File
@@ -18,7 +18,12 @@ class profiles::sql::postgresdb (
}
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${members_role}' and
certname in facts[certname] { name = 'region' and value = '${facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
+38 -2
View File
@@ -6,11 +6,15 @@ class profiles::vault::server (
Undef
] $members_role = undef,
Array $vault_servers = [],
String $package_name = 'vault',
String $package_ensure = 'latest',
Boolean $disable_openbao = true,
Boolean $tls_disable = false,
Stdlib::Port $client_port = 8200,
Stdlib::Port $cluster_port = 8201,
Boolean $manage_storage_dir = false,
Stdlib::Absolutepath $data_dir = '/opt/vault',
Stdlib::Absolutepath $plugin_dir = '/opt/vault_plugins',
Stdlib::Absolutepath $bin_dir = '/usr/bin',
Stdlib::Absolutepath $ssl_crt = '/etc/pki/tls/vault/certificate.crt',
Stdlib::Absolutepath $ssl_key = '/etc/pki/tls/vault/private.key',
@@ -25,7 +29,12 @@ class profiles::vault::server (
if $members_lookup and $members_role != undef {
# if it is, find hosts, sort them so they dont cause changes every run
$servers_array = sort(query_nodes("enc_role='${members_role}' and region='${::facts['region']}'", 'networking.fqdn'))
$servers_array = sort(puppetdb_query(
"facts[certname] {
name = 'enc_role' and value = '${members_role}' and
certname in facts[certname] { name = 'region' and value = '${::facts['region']}' }
}"
).map |$fact| { $fact['certname'] })
# else use provided array from params
}else{
@@ -51,7 +60,33 @@ class profiles::vault::server (
}
}
# cleanup openbao?
if $disable_openbao {
package {'openbao':
ensure => absent,
before => Class['vault']
}
package {'openbao-vault-compat':
ensure => absent,
before => [
Class['vault'],
Package['openbao']
]
}
}
# add versionlock for package_name?
if $package_ensure != 'latest' {
yum::versionlock{$package_name:
ensure => present,
version => $package_ensure,
before => Class['vault']
}
}
class { 'vault':
package_name => $package_name,
package_ensure => $package_ensure,
manage_service => false,
manage_storage_dir => $manage_storage_dir,
enable_ui => true,
@@ -64,7 +99,8 @@ class profiles::vault::server (
},
api_addr => "${http_scheme}://${::facts['networking']['fqdn']}:${client_port}",
extra_config => {
cluster_addr => "${http_scheme}://${::facts['networking']['fqdn']}:${cluster_port}",
cluster_addr => "${http_scheme}://${::facts['networking']['fqdn']}:${cluster_port}",
plugin_directory => $plugin_dir,
},
listener => [
{
+5
View File
@@ -0,0 +1,5 @@
<%- | String $name, String $algorithm, String $secret | -%>
key "<%= $name %>" {
algorithm <%= $algorithm %>;
secret "<%= $secret %>";
};