DEMO/Infrastructure

← Back to dashboard

Deploying an agent into a cloud

Audience: operator · Profile: both · Read this when: you want the dashboard to build an agent inside a VPC or VNet for Config Management, or to have one exist only around a change window.

Part of Remote Agents. Building the agent's host for you, and deciding when that host exists.

What the dashboard builds

Cloud VMs can be configured from an agent inside their VPC or VNet instead of from the remote worker. Building that agent by hand means a host, Docker, a policy file, an enrolment code and a route. On Remote Agents → Agents → Deploy an agent, the dashboard does all of it, in AWS, Azure or Google Cloud, the way it builds Gateways, Rancher and Portainer hosts.

A deployed agent is an ordinary agent. It appears in the Agents list above the Deployed agents list, enrols or attests, leases its jobs and is routed to exactly like an agent you built yourself. It differs in three ways, all deliberate:

The host

Cloud Image Default size
AWS ECS-optimised Amazon Linux t3.medium
Azure Ubuntu, with docker.io installed by cloud-init Standard_B2s
Google Cloud Container-Optimized OS e2-medium

The default sizes allow about 1 GiB for each run plus the agent, which covers the default of 2 runs at once. Allow about 1 GiB more for each extra run, up to 8.

The host goes into the region's VM subnet (the network dashboard-deployed VMs use) unless you name another subnet. It has no public address and no inbound rule: the agent only dials out. On AWS and Google Cloud it reaches the dashboard through the same on-demand NAT that VMs use, and that NAT is not reclaimed while a deployed agent is up. On Azure it gets the same on-demand NAT gateway and NSG allow as a VM when azure_vm_nat_enabled is on and the subnet has no way out; with it off, the subnet must already reach the internet. A host that can't reach it never installs Docker, and the start fails after 15 minutes. See On-demand VM egress on Azure.

At first boot a script pulls the agent and Ansible runner images and starts the agent with the Docker socket, as examples/remote-agent/docker-compose.sibling.yml does. When attesting, it also starts the SPIRE agent and SPIFFE helper, as docker-compose.spire.yml does.

Before you deploy

The form reads the subnet the host will go into and offers its range and its VPC's or VNet's (Google Cloud has none: a VPC there is global) under Ranges it may configure. An empty box gets the subnet's range; click another to add it. Nothing is filled over a range you typed. If the subnet can't be read, the form says why and you type the ranges.

Identity

Every start mints a new identity for that one host. Which kind depends on the settings:

In both SPIRE modes: - The node key is on disk. The SPIRE agent keeps it at /var/lib/dashboard-agent-host/spire/data, readable only by the SPIRE agent. - Every one of these node attestors attests a node once. A join token is single-use, and the three cloud attestors are trust-on-first-use. - So the key on disk is what lets the host come back after a reboot. - It rotates with every node SVID renewal. - Each start is a new VM, so each start is a first attestation. - The agent's own signing key stays in memory.

See Attesting an agent through SPIRE.

Turning on a cloud's instance identity

Two steps, in this order. Enable the plugin on the SPIRE server first (examples/spire-server/server.conf, or examples/cloud-spire/server.conf on a managed runtime), restart the server, and then tick the cloud. The dashboard can't see the server's plugins, so a cloud ticked without its plugin deploys hosts that never come online. The start then fails after 15 minutes, naming the attestor to check.

Cloud Server NodeAttestor Access the SPIRE server needs Setting
AWS aws_iid with skip_block_device = true and disable_instance_profile_selectors = true Its own read-only identity allowed ec2:DescribeInstances, from environment variables or an instance role. Never the dashboard's keys. Tick AWS.
Google Cloud gcp_iit with projectid_allow_list = ["<project>"] None: the identity token itself carries the project, zone and name that are checked. Tick Google Cloud.
Azure azure_imds with a tenants map keyed by the tenant domain, with restrict_to_subscriptions An app registration with Reader on the subscription (secret_auth), or a managed identity (the default credential chain). Tick Azure and set Azure tenant domain to the same key.

On the host, the SPIRE agent shares the host's network, because it has to reach the instance metadata service. Under IMDSv2's default hop limit of 1, a container on the Docker bridge can't. It listens on nothing: its API is a unix socket.

The SPIRE server must reach the cloud APIs it calls (AWS and Azure), and every agent host must still reach the SPIRE server, as with join tokens.

A host started with SPIRE attestation also gets the updater container, and an upgrades: block in its policy that accepts only images the project's release workflow signed. The Agents page can then upgrade or restart it like any other attested agent; see Upgrading and restarting agents centrally. A host starts the newest release recorded there, pinned by digest, or chrweav/dashboard-agent:latest when none is recorded. A host started with an enrolment code gets neither.

Stopping the host clears the agent's key and any unused code, so a destroyed host's identity is dead. Revoking a deployed agent on the Agents list also takes its host down.

When it exists

Lifecycle Up Down
Always When deployed, and on Start On Stop or Delete
Until a time When deployed, and on Start At that time; it then stays parked and becomes Always
For a change window Start minutes (default 20) before each occurrence Keep minutes (default 15) after it closes

The schedule is a pass of the existing schedule sweep, so a window-mode agent starts within one sweep interval of its start time. Allow for that in the lead time: 20 minutes covers the sweep, the boot, two image pulls and enrolment.

Stopping waits for running jobs, up to the Keep minutes. A run still going after that is stopped with the host, and the dashboard fails it when its heartbeat goes stale.

Starting a window-mode agent by hand ahead of its window keeps it up until the end of that next window plus Keep. Stopping one by hand during its window keeps it down until the next occurrence.

A failed start leaves the agent in error. The host is removed if it got that far, and nothing is retried on its own, since retrying every sweep would only repeat the failure. Fix the cause, which the row names, and press Start. A window-mode agent in error also needs that press before its next window.

Booking runs into a window

A Config Management run normally refuses an agent that is not online. For a deployed agent that is parked until its window, a run scheduled into that window is accepted: book it with Run at or Change window on the run form, at a time the agent will be up. A run for any other time is refused, and the refusal names when the agent is next up.

Routes

Route cloud VMs in these ranges to it (on by default) adds a Config-Management route for each range, scoped to the agent's cloud and region. That is the step that sends cloud-VM runs to the agent. A range that already has a route in that cloud and region is skipped, and the deploy says so; an on-premises route for the same range is no clash. After the host's first successful start, those routes are also narrowed to the network it runs in (its VPC, VNet or GCP network), since that is the only network the agent can reach. Routes you narrowed or added yourself are left as they are.

Delete takes the host down, then revokes and deletes the agent and its routes. Runs for those ranges then go back to the remote worker.

Kubernetes work

An agent the dashboard deployed can also run a cluster's Kubernetes work, instead of the remote worker: no cold start and no dashboard worker slot. That covers:

Each one hands the agent the cluster's cluster-admin kubeconfig, so only an agent the dashboard owns qualifies. A customer-hosted agent never does, whatever its policy says. All of these must hold:

Work goes to a chosen agent only while it reports that the updater beside it has verified the Kubernetes image's signature (below). Until then, and if the check ever fails, the cluster's work runs on the remote worker. The executor list and the Agents page show the state.

Then, on the Kubernetes page, choose Runs on worker on a cluster and pick the agent. The list shows every deployed agent in the cluster's cloud, with the reason any of them cannot be chosen. An on-premises cluster keeps the dashboard's own runner.

What the host gets. At start, the dashboard writes a k8s: block into the agent's policy and adds agent_k8s to its job types:

How the work runs.

What always stays on the remote worker:

The API

All on /api/agent-hosts, behind the remote agents feature flag. Reading needs agents:read, deploying and changing need agents:write, and deleting needs agents:delete.

Method and path Does
GET /api/agent-hosts Every deployed agent, with its status and next up and down times
GET /api/agent-hosts/options Default sizes, change windows and the identity a deploy would use
POST /api/agent-hosts Deploy one
PATCH /api/agent-hosts/{id} Change the lifecycle now, or the ranges, size and runs at once from the next start
POST /api/agent-hosts/{id}/start, /stop Bring the host up or take it down now
DELETE /api/agent-hosts/{id} Take it down and delete the agent and its routes