Same as the client-server example, but all workloads run as a shared non-root user (demo-svc, UID 1500 / GID 1500). This demonstrates Reaper's securityContext.runAsUser / runAsGroup support and mimics an LDAP environment where UIDs are consistent across all nodes.
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ worker (server) │ │ worker2 (client) │ │ worker3 (client) │
│ │ │ │ │ │
│ socat :9090 │◄────│ socat connects │ │ socat connects │
│ uid=1500 (demo- │◄──────────────────────────────│ uid=1500 (demo- │
│ svc) │ │ uid=1500 (demo- │ │ svc) │
│ │ │ svc) │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
All processes drop privileges from root to demo-svc before executing.
- Creates a 4-node Kind cluster
- Creates the
demo-svcuser (UID 1500, GID 1500) on every worker node with the same IDs — mimicking how LDAP/AD/SSSD provides consistent UIDs across a cluster - Labels nodes (
role=server/role=client) - Installs Reaper and socat on all nodes
- Creates a ConfigMap with the server node's IP
From the repository root:
./examples/client-server-runas/setup.sh- Docker
- kind
- kubectl
- Ansible (
pip install ansible)
# Start the server (drops to uid=1500)
kubectl apply -f examples/client-server-runas/server-daemonset.yaml
# Start the clients (drop to uid=1500)
kubectl apply -f examples/client-server-runas/client-daemonset.yaml
# Watch client logs — note uid=1500 in every line
kubectl logs -l app=demo-client-runas --all-containers --prefix -fExpected output:
[pod/demo-client-runas-abc12/client] Client starting on ...-worker2 as uid=1500 gid=1500 user=demo-svc, server at 172.18.0.3:9090
[pod/demo-client-runas-abc12/client] [...-worker2 uid=1500] 14:32:05 <- Hello from ...-worker as uid=1500 — 14:32:05
[pod/demo-client-runas-xyz34/client] [...-worker3 uid=1500] 14:32:07 <- Hello from ...-worker as uid=1500 — 14:32:07
Server side:
kubectl logs -l app=demo-server-runas -fServer starting on ...-worker as uid=1500 gid=1500 user=demo-svc
setup.shcreates thedemo-svcuser with identical UID/GID on every worker node, just like LDAP or SSSD would in a real cluster.- The pod specs set
securityContext.runAsUser: 1500andrunAsGroup: 1500. - Reaper's runtime calls
setgroups(),setgid(), thensetuid()before executing the command, dropping from root to the target user. - The workload runs with the privileges of
demo-svc— it can only access files owned by or readable to UID 1500 / GID 1500.
kubectl delete -f examples/client-server-runas/
./examples/client-server-runas/setup.sh --cleanup