Security
Architect is a cluster-scoped service, but its permissions are scoped to exactly
what it needs. There is no cluster-admin binding in the default install, and
nothing in Architect can grant itself more access at runtime (it has no verbs on
roles, clusterroles, or their bindings).
Service accounts and permissions
The chart installs three ServiceAccounts in Architect's namespace (default
architect), each bound to narrow ClusterRoles. A fourth, architect-router, is
added only when live-migration buffering is enabled (see below).
architectd-installer-daemon (the per-node daemon)
| Resource | Verbs | Why |
|---|---|---|
node.k8s.io/runtimeclasses | create, update, patch | Installs the runc-architect RuntimeClass on startup. |
pods, pods/resize | get, list, watch, patch | Reads managed-pod status; zeroes and restores CPU/memory requests on hibernate/wake. |
events | create, patch | Emits lifecycle Events (ScaleDownCompleted, CheckpointCreated, and so on). |
apps/deployments | create, deletecollection, get | Installs and uninstalls Architect's bootstrap Deployments. |
apps/replicasets | get | Owner lookups for managed pods. |
architect.loopholelabs.io/checkpoints | create, patch, get, delete, watch | Manages the internal Checkpoint CRD records. |
architect.loopholelabs.io/persistentcheckpoints | get, list, watch, update, delete | Consumes the user-facing PersistentCheckpoint CRD. |
discovery.k8s.io/endpointslices | list | Locates peer daemons for checkpoint transfer. |
When features.liveMigrationBuffering is enabled, this role also gains
architect.loopholelabs.io/networkmigrationstates (full access), services
(get/list/watch), and get on deployments/replicasets/statefulsets/daemonsets
(to tell whether a migrating pod's owner is being torn down).
architect-admission-controller (the admission controller)
| Resource | Verbs | Why |
|---|---|---|
admissionregistration.k8s.io/mutatingwebhookconfigurations | create, update, patch, get | Registers the mutating webhook that injects the health-check-proxy sidecar. |
services, endpoints | get, list, watch, create, update, delete | Manages the webhook's service and the endpoints it injects (health-check-proxy and shadow services). |
pods | get, list, watch, patch | Inspects and patches managed pods. |
architect-control-plane (the control plane)
| Resource | Verbs | Why |
|---|---|---|
pods | list | Observes pods to coordinate migration and checkpoint locking. |
apps/deployments | list, delete | Cleans up Architect's bootstrap Deployments on uninstall. |
architect-router (optional, live-migration buffering)
Installed only when features.liveMigrationBuffering is enabled. The router runs
as a DaemonSet and buffers in-flight traffic while a pod migrates.
| Resource | Verbs | Why |
|---|---|---|
architect.loopholelabs.io/networkmigrationstates | get, list, watch, patch | Reads and updates the migration-buffering state. |
services, pods | get, list, watch | Resolves the pods and services it routes traffic to. |
What Architect cannot do
Across all three roles, Architect has no access to:
secretsorconfigmaps: it cannot read your workloads' secrets or config.roles/clusterroles/bindings: it cannot escalate its own privileges.
It also cannot create or delete your StatefulSets or pods; the daemon only patches
managed pods' status and resources. It does hold cluster-scoped create/delete
on Deployments, which it uses to install and clean up its own bootstrap
Deployments (see the tables above), so that grant is not restricted to the
architect namespace.
Architect reads its own machine token from a mounted Secret (architectd-secrets
by default, or the one you pass via secretRef), not through the Kubernetes API.
Checkpoint data is sensitive
Hibernation and migration use CRIU (Checkpoint/Restore In Userspace), which captures the full memory of the process, including anything held in memory at checkpoint time (cached credentials, decrypted data, in-flight requests). Treat a checkpoint with the same sensitivity as a memory dump.
- At rest (local): checkpoints are written to node-local disk via a hostPath
the daemon mounts, as zstd-compressed tar (
tar.zst) archives. Architect does not encrypt them itself, so rely on node-disk encryption (EBS, GCE PD, or LUKS). - At rest (S3): when persistent checkpoints use S3, enable bucket-level encryption (SSE-S3 or SSE-KMS). Architect uploads over TLS but does not encrypt contents before upload.
- In transit between nodes: daemons stream
tar.zstcheckpoints to each other over plain HTTP on port 1337. Control-plane to daemon traffic is also plain HTTP on 1337. If your pod network is untrusted, add fabric-level encryption (a mesh, or WireGuard via your CNI). - Admission webhook: served over HTTPS with a self-signed CA the installer generates and registers at install time.
Admission webhook behavior
The mutating webhook registers cluster-wide on pod create. The handler
short-circuits any pod whose runtimeClassName is not runc-architect; those
pods pass through untouched. Its failurePolicy is Ignore, so if the admission
controller is down, pod creation proceeds without the Architect mutation and
Architect never blocks cluster operations.
Audit trail
Every hibernate, wake, and migration emits a Kubernetes Event on the affected pod:
kubectl get events --field-selector involvedObject.name=<pod>Expect reasons like ScaleDownCompleted, ScaleUpCompleted, CheckpointCreated,
and CheckpointDownloaded. Events follow the standard one-hour retention, so ship
them to your log backend for longer history. Architect keeps no separate audit
log.
Security review checklist
| Question | Answer |
|---|---|
| Does Architect need cluster-admin? | No. See the ClusterRole tables above. |
| Can it read my Secrets or ConfigMaps? | No. It has no verbs on either. |
| Can it escalate privileges? | No. It has no verbs on roles, clusterroles, or bindings. |
| Does it capture process memory? | Yes. CRIU checkpoints are full memory dumps; treat them as sensitive. |
| Are checkpoints encrypted at rest? | Not by Architect. Use node-disk encryption locally and SSE for S3. |
| Is inter-component traffic encrypted? | Only the admission webhook (HTTPS). Daemon-to-daemon and control-plane-to-daemon are plain HTTP on 1337. |
| Can a non-opted-in workload be affected? | No. The webhook ignores any pod without runtimeClassName: runc-architect. |
For anything not covered here, contact security@loopholelabs.io.