Nomad Lens v1.15.0

Nomad Lens — User guide

HashiCorp Nomad operations inside VS Code: browse clusters/jobs/allocations/tasks, follow logs as a stream, diff the spec in your repo against the running job before deploying, see what the last deploy changed and roll it back, find out why a job will not schedule, export an incident bundle in one click and generate a cluster snapshot.

Zero runtime dependencies: it talks to the Nomad HTTP API through Node's native fetch. ACL tokens are read from environment variables only and are never stored or displayed.


1. Installation

After installing, the Nomad icon appears in the Activity Bar (side bar).

Requirements: VS Code 1.85 or newer. Nothing else — no CLI, no SDK. Network access from your machine to the Nomad HTTP API (:4646 by default) is enough.

2. Configuring clusters

Settings live in settings.json (user or workspace), under nomadLens.clusters:

"nomadLens.clusters": [
  { "name": "dev",  "address": "http://nomad-dev.example:4646" },
  {
    "name": "prod",
    "address": "https://nomad.example:4646",
    "namespace": "default",
    "tokenEnv": "NOMAD_TOKEN_PROD"   // the NAME of the env var, not the token
  }
]
FieldRequiredNotes
nameLabel shown in the status bar and in the picker.
addresshttp(s)://host:4646.
namespaceNomad namespace; appended as a query param to every call.
tokenEnvName of the environment variable holding the ACL token.

The first cluster in the list is the one selected at startup. Switch with Select Cluster (also from the status bar item $(rocket) nomad: <cluster>).

ACL tokens — the security rule

The token is never put in the settings. In tokenEnv you name an env var; the extension reads the token from it at runtime and sends it as the X-Nomad-Token header. The token is never stored, logged or displayed.

Make sure VS Code can see that env var (export it in the shell profile you launch code from, or use the .env/launcher of your setup):

export NOMAD_TOKEN_PROD="…"   # in your ~/.zshrc, read before starting VS Code

If a cluster uses a token over plain http:// towards a non-local host, Nomad Lens warns you once per cluster: the token would travel in cleartext.

3. The cluster explorer

Open the Nomad panel. You will see three sections:

Allocations carry their own warnings: an allocation killed by OOM or stuck in a restart loop (≥3 restarts) shows a ⚠ with the reason, derived from the task events already present in the list — no extra API call.

Filtering the list

On a cluster with hundreds of jobs, the list is only useful if you can cut it down:

The two criteria are ANDed. While a filter is active the list starts with an entry like filter: 2/24 · "web" · problems only; click it to clear. The filter is always shown on purpose — a shortened list must never look like an empty cluster.

4. Plan diff: repo vs running

The heart of the "know what you are changing before deploying" workflow.

  1. Open a .nomad or .hcl job spec.
  2. Right-click in the editor → Plan Current Job File (diff vs running) (or use the Command Palette).
  3. The extension sends the spec to POST /v1/jobs/parse (HCL→JSON, Canonicalize: true), then plans it against the running job and opens the diff beside your editor.

How to read it:

If the diff contains more than you expected, you find out before applying.

To apply the reviewed file, choose Apply Current Job File (plan, confirm, register) from the editor context menu or Command Palette. Nomad Lens shows the same plan diff first, then asks you to type the parsed job id. Only an exact id match registers the job with Nomad.

5. Job version history and revert

Nomad keeps every registered version of a job. Right-click a job → Job Version History (diff between versions): pick a version and Nomad Lens opens a report with the full history table (version, submit time, stable flag, which one is current) and the diff of the version you picked against the immediately older one — the answer to "what did the last deploy actually change?".

To roll back, right-click the job → Revert Job to a Previous Version:

  1. Pick one of the older versions (the current one is not offered).
  2. Nomad Lens plans that old spec against what is running and opens the diff beside your editor: you see exactly what the revert would change before deciding. If the preview cannot be produced the revert is not blocked — you get a warning and the confirmation still asks.
  3. Confirm by typing the job id, like Stop Job. Reverting replaces the running spec, so it gets the strongest confirmation the extension has.

Nomad implements the revert by re-registering the old spec as a new version: nothing is deleted from the history, and reverting a revert is just another revert.

Nomad reports submit times in nanoseconds; the report shows them as ISO dates.

6. Why is my job not scheduling?

A job stuck in pending with no allocations is a scheduling problem, not a task problem, and Nomad records the reason in the evaluation rather than in any log. Right-click the job → Explain Placement Failures: Nomad Lens reads the evaluations and renders the scheduler's counters as sentences, for example:

Jobs in that state are also marked in the tree with ⚠ cannot place, with the first reason in the tooltip — so you notice before you go looking. Only jobs that already look stuck are checked (one extra API call each, four at a time), and if the check fails the tree keeps working normally.

If there are no placement failures the report says so and points you at the allocations instead: the scheduler did its job and the tasks are the ones failing to start.

7. Streaming logs

8. Cross-allocation grep

Right-click a job → Grep Logs Across Allocations: type a string and Nomad Lens searches (case-insensitive) the stdout+stderr logs of all the job's allocations, in parallel (eight at a time). The result is a markdown report grouped by allocation, with a task/type:line position for every match.

This is the answer to "which instance logged that error?" on a job with many allocations, without opening ten log streams by hand.

9. Incident bundle in one click

On a problematic allocation (right-click → Export Incident Bundle for Allocation):

The report opens right away: your incident write-up is already half done.

Requires a folder open in VS Code (a workspace folder): that is where the bundle is saved.

10. Mutating actions on jobs

From the tree context menu, actions that change the cluster — always behind an explicit confirmation, never a default button:

ActionConfirmation
Restart AllocationDouble modal confirmation.
Stop Job — deregisters the jobType the job id.
Start Job — re-reads the spec, clears Stop, re-registersSingle confirmation.
Revert Job — see §5Type the job id, after the diff preview.

None of these has a default button: Enter does not trigger them.

11. Node drain and eligibility

Nodes have their own context menu:

While a node drains, the tree shows how many allocations are still to be evicted (ready · draining (3 allocs left)). A draining node is ineligible by definition, so the label does not repeat both.

Ineligible and draining nodes also appear in the cluster snapshot problems section: a node that accepts no new allocations is exactly what you want to notice at the morning check, even if it never went down.

12. Deployment watch

While a deployment is active, the status bar shows live progress — $(sync~spin) deploy <job> healthy/desired · canary N — and you get a notification when:

Turn it off with nomadLens.deploymentWatch if you do not want the polling.

Promote canaries

When a deployment has healthy canaries and you are ready to continue the rollout:

  1. Expand Deployments and select the deployment, or open its job panel.
  2. Choose Promote Deployment Canaries. The command is shown only for running or paused deployments that still have canaries.
  3. Confirm the deployment and job shown in the modal. Nomad Lens sends All: true to Nomad, promoting every canary in that deployment.
  4. The tree, deployment watch and open live panels refresh after success. A failed request leaves the deployment unchanged and shows the API error.

Other deployment controls are available from the deployment tree or Command Palette. Select a deployment explicitly, then Pause Deployment, Resume Deployment, Fail Deployment or Cancel Deployment. Pause/resume use the deployment pause endpoint; fail and cancel require typing the displayed job/deployment target.

13. Resource usage vs requested

Right-click a job → Resource Usage vs Requested: for every running allocation Nomad Lens reads the live stats from the client node and puts them next to what the spec asks for, per task:

TaskAllocCPU used/reqMem used/req
appa1b2c3d4480/500 MHz (96%)250/256 MiB (98%)⚠ near the limit
idlee5f6a7b85/500 MHz (1%)10/256 MiB (4%)💤 oversized

Two things get called out: tasks at ≥90% of their memory request (the OOM kill that is about to happen — raise memory) and tasks at ≤20% (a reservation the cluster is holding for nobody). Tasks with no request in the spec, and tasks that have not started yet, are left unflagged rather than guessed at.

Stats come from the client node that runs the allocation, so an unreachable node removes those rows from the report instead of failing it.

14. Compare a job across clusters (drift)

Right-click a job → Compare Job Across Clusters: pick two clusters and Nomad Lens compares the same job, producing a diff table of count, image, cpu, memory and env (differing rows are marked ). Useful for spotting the drift between dev and prod that nobody wrote down.

15. Image inventory

From the Nomad view title → Image Inventory (all clusters): Nomad Lens queries every configured cluster and produces a job × cluster matrix with the docker image per cell; jobs with different images across clusters are marked . The at-a-glance answer to "who is still on the old tag".

16. Cluster snapshot

Cluster Snapshot Report generates a health markdown:

Perfect for the morning check or as a preflight baseline before an intervention.

Saving it to a file — the Save Cluster Snapshot to File command writes the snapshot to nomadLens.snapshotPath. If the path is a folder (or empty → the working folder) the file is nomad-snapshot-<cluster>-<date>.md; if it ends in .md it is the exact file; ~ is supported. Bind the command to a task or an external scheduler to get the report every morning.

17. Recipes

Sequences that combine the commands above into the jobs you actually do.

Before a deploy

  1. Open the spec you are about to apply → Plan Current Job File. Read the diff: is it only what you intended?
  2. Doubtful about the current state? Cluster Snapshot Report first — it is your preflight baseline, and it is worth keeping.
  3. Apply with your usual pipeline, then watch the status bar: the deployment watch tells you when it is healthy, failed or stalled.
  4. If it goes wrong: Job Version History to confirm what changed, then Revert Job with the diff preview in front of you.

Morning check

  1. Cluster Snapshot Report (or the file version, scheduled): problems are on top.
  2. For every degraded job, expand it in the tree — OOM and restart loops are already flagged on the allocations.
  3. For anything pending, Explain Placement Failures: capacity, constraint or datacenter?
  4. Nodes not ready, draining or ineligible are in the snapshot too — a node left ineligible after maintenance is a classic.

An allocation is failing

  1. Follow Task Logs on the task, stderr first.
  2. Many allocations, only some broken? Grep Logs Across Allocations on the job to find which ones logged it.
  3. Suspect memory? Resource Usage vs Requested — at ≥90% of the request it is going to be OOM-killed.
  4. Before touching anything: Export Incident Bundle — event timeline plus log tails, so the evidence survives the restart that erases it.

Node maintenance

  1. Toggle Node Scheduling Eligibility → ineligible: nothing new lands there while you prepare.
  2. Drain Node with a deadline that fits your migration budget, and watch the remaining-allocation count go down.
  3. Do the maintenance. When done, Stop Draining Node and toggle eligibility back.
  4. Check the snapshot: no node should be left ineligible.

Is prod really like dev?

  1. Compare Job Across Clusters on the job you suspect: count, image, cpu, memory, env, side by side.
  2. Image Inventory (all clusters) for the wide view: which jobs run different images where.

18. Command reference

Every command is prefixed with Nomad Lens: in the Command Palette. "Where" says where it is offered besides the palette.

CommandWhereWhat it does
Refreshview titleReloads the tree.
Open Cluster Dashboardview titleCluster health dashboard webview (§23).
Search Jobs Across All Clustersview titleGlobal job QuickPick → switch cluster + open the job panel (§23).
Open Job PaneljobJob detail webview: allocations, gauges, versions, actions (§23).
Open Node PanelnodeNode detail webview: allocations by job, drain/eligibility (§23).
Select Clusterstatus barSwitches the active cluster; stops open log streams.
Filter Jobs by Nameview titleSubstring filter on the job id (§3).
Show Problem Jobs Only (toggle)view titleKeeps only unhealthy jobs (§3).
Clear Job Filterview titleRemoves both filters.
Plan Current Job File (diff vs running)editor context (.nomad/.hcl)Plan diff repo vs running (§4).
Apply Current Job File (plan, confirm, register)editor context / palettePlan, show the diff, then register after typed confirmation (§4).
Job Version History (diff between versions)jobHistory table + diff between versions (§5).
Revert Job to a Previous VersionjobRollback with a plan preview, typed confirmation (§5).
Explain Placement FailuresjobWhy the scheduler cannot place it (§6).
Follow Task LogstaskStreams stdout/stderr (§7).
Open Log ConsoletaskWebview log viewer: level colours, live filter, follow/wrap (§23).
Open Log ConsolejobSelect and follow multiple allocation/task streams in tabs (§7).
Stop Following LogspaletteStops one open stream.
Grep Logs Across AllocationsjobSearches every allocation's logs (§8).
Export Incident Bundle for AllocationallocationIncident folder with report and logs (§9).
Restart AllocationallocationRestarts the allocation's tasks (§10).
Stop JobjobDeregisters the job — type the id (§10).
Start JobjobRe-registers a stopped job (§10).
Promote Deployment Canariesdeployment with canaries, or job panelPromotes every canary in an active deployment after explicit confirmation (§12).
Pause Deploymentdeployment / palettePause a selected active deployment (§12).
Resume Deploymentpaused deployment / paletteResume a selected paused deployment (§12).
Fail Deploymentdeployment / paletteMark a selected active deployment failed; type the target (§12).
Cancel Deploymentdeployment / paletteCancel a selected pending or active deployment; type the target (§12).
Drain NodenodeEvicts every allocation — type the node name (§11).
Stop Draining Nodenode (draining)Cancels the drain (§11).
Toggle Node Scheduling EligibilitynodeEligible ⇄ ineligible (§11).
Resource Usage vs RequestedjobLive usage against the requests (§13).
Compare Job Across ClustersjobDiff of the same job on two clusters (§14).
Image Inventory (all clusters)view titlejob × cluster image matrix (§15).
Cluster Snapshot Reportview titleHealth report in markdown (§16).
Save Cluster Snapshot to FilepaletteWrites the snapshot to snapshotPath (§16).

19. Settings reference

SettingTypeDefaultNotes
nomadLens.clustersarrayone local entryCluster list (§2). Tokens only via tokenEnv.
nomadLens.deploymentWatchbooleantrueWatch active deployments (§12).
nomadLens.deploymentPollSecondsnumber5Deployment polling interval; minimum 2.
nomadLens.deploymentStallSecondsnumber90A running deployment with an unchanged healthy count for this long is reported as stalled; minimum 10.
nomadLens.livePanelsbooleantrueAuto-refresh the dashboard and job panels on each poll tick, in place (§23).
nomadLens.snapshotPathstring""Where Save Cluster Snapshot to File writes (§16). Folder, or an exact .md path; ~ supported.
nomadLens.autoFixGoVulncheckbooleantrueThe Go extension fix in §20.
nomadLens.goVulncheckFixValuestring"Off""Off" or "Imports" (§20).

20. go.diagnostic.vulncheck auto-fix

If you also use the Go extension, its go.diagnostic.vulncheck: "Prompt" default is rejected by gopls (Invalid settings: … invalid option "Prompt"). At startup Nomad Lens detects the case and sets a valid value, with a notification offering Undo and Stop fixing this.

It only steps in when the effective value is exactly "Prompt": an "Off"/"Imports" you already chose is left alone. If the "Prompt" comes from a workspace override it is fixed in that same scope, otherwise globally.

This has nothing to do with Nomad — it is here because it breaks the editor of anyone who writes Go, and the fix is two lines.

21. Troubleshooting

SymptomCause / remedy
"No cluster configured"Add nomadLens.clusters to your settings.
error: … HTTP 403 in the treeMissing or invalid ACL token: check that the env var named in tokenEnv is exported before starting VS Code.
error: … HTTP 404 on a commandNamespace mismatch, or the object no longer exists — refresh.
The tree hangs, then errorsRequests abort after 8 seconds: the cluster address is unreachable from your machine (VPN? firewall?).
HTTP 400 Failed to parse job on planThe HCL spec is not valid for the cluster's Nomad version (e.g. a single-line block with multiple arguments).
Plan says "Open a .nomad/.hcl job spec"The active file does not have a .nomad/.hcl extension.
Logs do not startThe allocation is no longer on the node, or the task has not produced output yet.
Resource usage is emptyNo running allocation, or the client node is unreachable — stats are served by the node, not the server.
The job list looks emptyA filter may be active: look for the filter: … entry at the top of the list and click it to clear.

22. Security in short

Beyond the tree and the markdown reports, Nomad Lens has webview panels — dark-theme, zero-dependency, CSP-locked, and (where relevant) live.

The dashboard and job panels update in place on each deployment-poll tick (a small "live" pulse); turn it off with nomadLens.livePanels.