Navin Cluster Agent
The Navin Cluster Agent (module navin-manager/cluster-agent, Go) runs inside a Kubernetes cluster managed by
navin-manager. It reports the cluster inventory and applies the ManagedComponent changes asked by the manager, after
verifying the signature of every command. Reference: CONTRACT.md section 7.14.
Import of a cluster without SSH
A cluster is imported through its API only. Fetch the least privilege RBAC of the import identity:
GET /api/v1/clusters/{cluster_id}/kubernetes/import-rbac?namespace=navin-platform
Apply the returned yaml with an administrator account, then register the cluster with a kubeconfig holding the
token of the navin-import ServiceAccount (kubectl -n navin-platform create token navin-import). That identity may
read nodes, namespaces, CRDs, storage classes and ingress classes, read the CoreDNS Deployment, and write only the
platform.navin.ai resources of the managed namespace. Secrets, workloads, RBAC objects and every other namespace
are refused.
Install
- Issue the identity of the agent of this cluster (one per cluster; a new one revokes the previous one):
POST /api/v1/clusters/{cluster_id}/kubernetes/agent {"gateway_url": "https://manager.example:8462"}. The answer holds the client certificate and its private key (returned once, never stored), the manager CA, the manager public key and the signed configuration. - Create the Secret
navin-cluster-agent-identityin the managed namespace with the filesconfig.json(theconfigobject),manager.pem,tls.crt,tls.keyandca.crt. - Apply the manifests of
GET /api/v1/clusters/{cluster_id}/kubernetes/agent/manifests?image=<image@sha256:...>: ServiceAccount, RBAC and a Deployment of 2 replicas (pod anti affinity, non root, read only file system).
RBAC of the agent
- cluster scope, read only: nodes, namespaces, CRDs, storage classes, ingress classes,
/version,/api,/apis; - managed namespace: the Lease
navin-cluster-agent(get, create, update), the ConfigMapnavin-cluster-agent-state(create, get and update of that name only), events, and theplatform.navin.airesources. No Secret, no workload.
The Kubernetes identity is the ServiceAccount token of the pod: it is valid on this cluster only. The manager identity is the client certificate: the gateway serves to it the commands of this cluster only and refuses (403, audited) a receipt for the command of another cluster.
Outbound connection
The agent opens every connection: HTTPS (TLS 1.2 or newer) to the manager gateway with its client certificate,
the manager CA as the only trusted issuer, proxies of the environment ignored. No Service, no inbound port. It long
polls GET /v1/cluster-agent/commands (up to 30 s), posts the inventory to /v1/cluster-agent/report and every
result to /v1/cluster-agent/receipts. The manager starts the gateway with
python -m navin_manager.kubernetes.agent_gateway --host <address> --port <port> --tls-dir <dir> --server-name <name>.
High availability
Only the replica holding the Lease acts. When it disappears, another replica takes the Lease after its expiry
(lease_duration_s, 15 s by default) and continues with the same nonces, receipts and desired state, kept in the
ConfigMap navin-cluster-agent-state. A command delivered to the lost leader without receipt is delivered again by
the gateway after 15 s; if it had already run, the new leader refuses it as nonce_replayed with the original
result, and the manager keeps the original status.
Commands
Every command is a signed envelope (Ed25519, canonical JSON, same envelope as the Node Agent). It is refused on an
invalid signature, an unknown key, another target or tenant, an expired or future validity window, or a nonce
already used. Operations: managedcomponent.apply {name, spec}, managedcomponent.delete {name} (sensitive) and
inventory.report (read only).
Offline behaviour
The configuration is signed: a modified configuration is refused at start. When the manager cannot be reached for
offline_after_s, the agent is offline:
- it keeps re-applying the last approved desired state (a component modified or deleted by hand is restored); a desired state whose signature no longer verifies is not applied;
- it refuses every new sensitive operation with
manager_unreachable, also a validly signed command dropped in the break glass directory--inbox(each<name>.jsonis answered in<name>.receipt.json); - read only operations still run. Receipts are sent again when the manager is back.