Skip to main content

Node Agent on Kubernetes

The Proxima node agent can run as a Kubernetes DaemonSet to collect per-node kubelet metrics (CPU, memory, network, filesystem) and cAdvisor metrics (throttling, OOM, disk I/O).

Architecture

When deployed as a DaemonSet, the agent enrolls as agent_type=k8s-node-monitor and only collects Kubernetes-specific metrics:

  • Kubelet /stats/summary — node, pod, and container CPU/memory/network/filesystem metrics
  • Kubelet /metrics/cadvisor — CPU throttling, OOM events, and disk I/O metrics

It does not collect gopsutil system metrics, inventory, processes, file changes, or provide terminal/runbook access. Those are handled by the standalone host agent if installed.

Three-Agent Architecture

On a Kubernetes cluster, up to three agents work together:

AgentDeploymentagent_typePurpose
Node agent (DaemonSet)Every nodek8s-node-monitorKubelet metrics only
Cluster agent (StatefulSet)1+ replicas (leader-elected)collectorK8s API inventory (what exists)
Host agent (systemd, optional)Per nodehostFull host monitoring (inventory, metrics, terminal, runbooks)

Each agent enrolls independently with its own agent_id. Enrollment is idempotent by (environment_id, agent_type, name).

Dual-Agent Setup (DaemonSet + Host Agent)

The DaemonSet and host agent can run on the same node without conflict:

  • No enrollment collision — different agent_type values create separate agent records
  • No duplicate metrics — DaemonSet collects kubelet data only, host agent collects gopsutil data only
  • Shared host record — the host agent owns the host record (agent_id set), DaemonSet metrics resolve by hostname
  • Independent stale detection — each agent has its own liveness tracking
SetupKubelet MetricsSystem MetricsInventoryTerminalRunbooks
DaemonSet onlyYesNoMinimal (hostname)NoNo
Host agent onlyNoYesFullYesYes
BothYes (DaemonSet)Yes (host agent)Full (host agent)Yes (host agent)Yes (host agent)
Data directory

The DaemonSet uses /var/lib/proxima-agent (hostPath). If you install a host agent alongside it, give it a different data directory so it does not load the DaemonSet's state.json and adopt its k8s-node-monitor identity. Pass --data-dir /var/lib/proxima-agent-host to the installer (or set PROXIMA_AGENT_DATA_DIR directly):

curl -sL https://install.prxm.uz/agent.sh | bash -s -- \
--backend-url https://api-console.prxm.uz \
--install-token <token> \
--data-dir /var/lib/proxima-agent-host

Collected Metrics

From /stats/summary (every 30s)

MetricLevelTypeDescription
node_cpu_usage_ratioNodegaugeCPU utilization (cores)
node_memory_used_bytesNodegaugeMemory usage
node_memory_available_bytesNodegaugeMemory available
node_memory_rss_bytesNodegaugeResident set size
node_fs_used_bytesNodegaugeRoot filesystem used
node_fs_available_bytesNodegaugeRoot filesystem available
node_network_receive_bytes_totalNodecounterNetwork received
node_network_transmit_bytes_totalNodecounterNetwork transmitted
pod_cpu_usage_ratioPodgaugePod CPU utilization
pod_memory_used_bytesPodgaugePod memory usage
pod_memory_rss_bytesPodgaugePod RSS
pod_memory_working_set_bytesPodgaugePod working set
pod_network_receive_bytes_totalPodcounterPod network received
pod_network_transmit_bytes_totalPodcounterPod network transmitted
container_cpu_usage_ratioContainergaugeContainer CPU utilization
container_memory_used_bytesContainergaugeContainer memory usage
container_memory_working_set_bytesContainergaugeContainer working set
container_memory_rss_bytesContainergaugeContainer RSS
container_rootfs_used_bytesContainergaugeContainer rootfs usage
container_logs_used_bytesContainergaugeContainer log disk usage

From /metrics/cadvisor (every 30s)

MetricLevelTypeDescription
container_cpu_throttled_ratioContainergaugeCPU throttle ratio (0-1)
container_oom_events_totalContainercounterOOM kill count
container_fs_reads_bytes_totalContainercounterDisk read bytes (delta)
container_fs_writes_bytes_totalContainercounterDisk write bytes (delta)

Log Enrichment

Logs tailed from /var/log/pods/ are automatically enriched with:

  • k8s_namespace — pod namespace
  • k8s_pod — pod name
  • k8s_container — container name
  • k8s_pod_uid — pod UID

Queryable in VictoriaLogs: k8s_namespace:app AND k8s_pod:nginx*

Deployment

Recommended: Use the Helm Chart

The easiest way to deploy both the node agent and cluster agent is via the Proxima Helm chart. The manual steps below are for environments where Helm is not available.

Prerequisites

  • Kubernetes cluster with kubelet API access
  • Proxima Console backend running
  • NATS server accessible from cluster
  • Install token from Proxima Console
  • The cluster agent should also be deployed for inventory data

1. Create RBAC

kubectl apply -f infra/k8s/node-agent/serviceaccount.yaml
kubectl apply -f infra/k8s/node-agent/clusterrole.yaml
kubectl apply -f infra/k8s/node-agent/clusterrolebinding.yaml

2. Create install token secret (if not already exists)

kubectl -n proxima-system create secret generic proxima-install-token \
--from-literal=token=YOUR_INSTALL_TOKEN

3. Deploy DaemonSet

Edit infra/k8s/node-agent/daemonset.yaml:

  • Set PROXIMA_BACKEND_URL to your backend URL
  • Adjust resource limits if needed

The DaemonSet requires the following security context to support both kubelet metric collection and interactive terminal access via nsenter:

spec:
hostPID: true # required for nsenter -t 1 (enter host PID namespace)
containers:
- name: proxima-node-agent
securityContext:
allowPrivilegeEscalation: true # required for nsenter to enter namespaces
readOnlyRootFilesystem: true # pod filesystem stays read-only
capabilities:
add:
- SYS_PTRACE # allows ptrace of PID 1 to enter namespaces
- SYS_ADMIN # allows mount namespace operations

Why each field is needed:

FieldWhy
hostPID: trueShares the host PID namespace so nsenter -t 1 can target the host's init process
SYS_PTRACERequired by nsenter to attach to PID 1 and enter its namespaces
SYS_ADMINRequired to enter the host mount namespace (nsenter --mount)
allowPrivilegeEscalation: truensenter raises its effective capabilities when entering namespaces; this must not be blocked
readOnlyRootFilesystem: trueThe agent pod's own filesystem remains read-only — writes go to the host via nsenter
No privileged: truePrivileged mode is not required and is a security audit red flag — targeted capabilities are sufficient
kubectl apply -f infra/k8s/node-agent/daemonset.yaml

4. Verify

# Check pods are running on all nodes
kubectl -n proxima-system get pods -l app.kubernetes.io/name=proxima-node-agent -o wide

# Check logs for kubelet metrics collection
kubectl -n proxima-system logs daemonset/proxima-node-agent | grep "kubelet stats published"

Configuration

Environment VariableDefaultDescription
PROXIMA_AGENT_TYPEhostAgent type for enrollment. Set to k8s-node-monitor for DaemonSet agents (Helm chart sets this automatically).
PROXIMA_K8S_NODE_METRICSfalseEnable kubelet/cAdvisor metrics
PROXIMA_K8S_METRICS_INTERVAL30sKubelet scrape interval
PROXIMA_K8S_NODE_NAME(downward API)Fallback node name for enrollment. The agent prefers /host/etc/hostname (FQDN) when PROXIMA_HOST_ROOT is set.
PROXIMA_INSTALL_TOKEN(required)Enrollment token
PROXIMA_BACKEND_URL(required)Backend API URL
PROXIMA_LOG_LEVELinfoLog verbosity

When PROXIMA_AGENT_TYPE=k8s-node-monitor, the agent only runs kubelet/cAdvisor collection and heartbeats. Inventory, system metrics, processes, file watch, terminal, and runbooks are disabled.

Terminal Access

DaemonSet agents support interactive terminal access to the underlying Kubernetes node via nsenter. When you open a terminal session to a K8s node in the Console UI, the agent runs nsenter -t 1 --pid --mount --uts --ipc --net -- su - <login> to enter the host's full namespace set and drop into a shell on the actual node — not inside the agent pod.

The security context described in the Deploy DaemonSet section above is required for this to work. Without hostPID: true and the SYS_PTRACE/SYS_ADMIN capabilities, nsenter will fail with a permission error.

See Terminal Security — K8s Node Terminal Security for the full security model.

Terminal Access on Minimal Nodes

Minimal K8s distributions (RKE2/SLE Micro, k3s, Talos, Flatcar) don't include user management binaries (useradd, groupadd, passwd). The DaemonSet agent automatically detects this and disables host user creation — terminal sessions are limited to existing users (typically root).

Dual-Agent Setup (Full Features)

For full terminal features (user creation, sudoers, custom shell) on K8s nodes, install the Proxima agent directly on the host alongside the DaemonSet:

ComponentPurpose
DaemonSet agentMetrics, inventory, K8s node monitoring
Host agentTerminal access, user creation, runbooks

Install the host agent on each node using the standard install script:

curl -sL https://install.prxm.uz/agent.sh | bash -s -- \
--backend-url https://api-console.prxm.uz \
--install-token <token>

Both agents enroll independently and coexist without conflict.

Integration-to-Asset Bridge

When the node agent runs with integration collectors enabled (PostgreSQL, Redis, Nginx, Docker), the agent heartbeat includes collector statuses. The backend heartbeat worker automatically creates CMDB assets for each detected integration. For example, a K8s node running PostgreSQL will produce both a host asset (from inventory) and a database asset (from the heartbeat integration bridge).

This works identically whether the agent runs as a DaemonSet on K8s or as a standalone service on a bare-metal host. See Assets & CMDB for details on the asset types and metadata created.