Connecting Agents¶
The operator manages the server side. Agents are ordinary Puppet agents: they are not Kubernetes resources, and nothing in the operator creates or tracks them. This page covers what they need from a stack deployed by the operator.
What an agent needs¶
Three things, and they are the usual ones:
| A reachable server address | the Service of a Pool the server joins, on port 8140 |
| A certname | the identity the certificate is issued for |
| A signed certificate | either autosigned by a SigningPolicy or signed by hand |
Without a SigningPolicy nothing is signed
The operator points autosign at its own binary as soon as a
CertificateAuthority exists, and that binary denies every CSR no policy
matches. An empty policy list is deny-all, not off. Agents then sit in
--waitforcert while the servers look perfectly healthy.
Where to point the agent¶
Agents talk to the Service of a Pool. With the default layout the CA server
joins both pools (poolRefs: [ca, server]), so one address serves catalog
requests and the CA:
If you separate the roles - the CA in the ca pool only, compilers in
server - the agent needs both addresses, because catalog and CA no longer
share one:
From inside the cluster¶
Any Puppet agent works. This project also builds openvox-agent-<major>, but
be aware of what it is: a test artifact. It is built by CI and not by the
release workflow, so it carries only the develop tag - no latest, no
version. For anything but a throwaway check, use your own agent image and pin
it.
The shape below is what the e2e suite runs:
apiVersion: batch/v1
kind: Job
metadata:
name: puppet-agent
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: puppet-agent
image: ghcr.io/slauger/openvox-agent-9:develop # test artifact, see above
command: ["sh", "-c"]
args:
- |
puppet agent --test \
--server <release>-server \
--certname agent-01 \
--waitforcert 30
# 0 = no changes, 2 = changes applied; both are success
EXIT=$?
if [ $EXIT -eq 0 ] || [ $EXIT -eq 2 ]; then exit 0; else exit $EXIT; fi
The exit code check matters: puppet agent --test returns 2 when it
applied changes, which is a success and not a failure.
From outside the cluster¶
A Pool Service defaults to ClusterIP, which is unreachable from outside.
Choose one:
| Option | How |
|---|---|
| LoadBalancer | pools[].service.type: LoadBalancer |
| NodePort | pools[].service.type: NodePort, optionally nodePort |
| Gateway API | pools[].route, see Gateway API |
Whichever you pick, the name agents connect through must be in the server
certificate. The chart derives the Service names of every Pool a server joins
into dnsAltNames automatically; an external name such as a load balancer
address has to be added explicitly:
A missing name shows up as a TLS error on the agent, not as an operator problem:
Signing by hand¶
Without a matching policy the CSR waits. List and sign on the CA pod:
kubectl exec -n <namespace> deploy/<ca-server> -- \
puppetserver ca list --all
kubectl exec -n <namespace> deploy/<ca-server> -- \
puppetserver ca sign --certname web01.example.com
Removing an agent¶
Revoking is a CA operation, and the operator does not do it for you - it only manages the certificates that belong to its own resources:
kubectl exec -n <namespace> deploy/<ca-server> -- \
puppetserver ca clean --certname web01.example.com
The revocation reaches agents with the next CRL refresh, which runs on
spec.crlRefreshInterval (default 5m). Until then the revoked certificate is
still accepted.
Verifying it worked¶
The agent reports success itself, but two things are worth checking on the server side.
Did the catalog compile?
Did the facts reach PuppetDB? Only when a Database is wired up:
kubectl exec -n <namespace> deploy/<database> -- \
curl -sf "http://127.0.0.1:8080/pdb/query/v4/nodes"
An empty result with a healthy agent run usually means routes.yaml is not
routing the facts terminus to PuppetDB - see
Database.