Skip to main content

Overview

CPLN Advisor watches the workloads in the org it runs in, tracks CPU, memory, replica counts, error rates and billed cost, and turns what it finds into concrete tuning suggestions generated by an LLM: memory limits, autoscaling thresholds, replica counts. Suggestions appear in a dashboard, and Autopilot can apply the qualifying ones for you, each with a one-click revert. The template brings up the dashboard, an API, a worker, a scheduler, a Redis broker and a bundled Postgres database in one install. It creates no secret and takes no credential as a value: it reads two dictionary secrets you create first, and the advisor’s own Control Plane token is entered in the dashboard after install.
This template deploys into an existing GVC you already have. It does not create, own or delete a GVC. The GVC must have exactly one location: every workload runs in every location of its GVC, so a second location would give you a second scheduler firing every scan twice and a second, independent database. Nothing checks this for you.

What Gets Created

What the chart can access. The two policies are the template’s entire grant. Each targets kind secret, grants only the reveal permission, and lists exactly one secret by name: Neither identity can read workloads, metrics, logs or usage, and neither can change anything in your org. The advisor reads and tunes your org with the service account token you enter in the dashboard, so its reach is exactly the permissions you give that service account (see Prerequisites).

Prerequisites

You need an existing GVC with exactly one location, two dictionary secrets created before you install, and a service account whose token you paste into the dashboard after you install. Secret names are org-wide, so give each release its own pair.
1

Choose the database password

Use the same password in both secrets. The URL in the advisor secret must match the database credentials secret, and nothing cross-checks them.
2

Create the database credentials secret

The bundled Postgres reads exactly three keys: username, password and database.
Set postgres.config.credentialsSecretName to this name.
3

Create the advisor credentials secret

The keys are the application’s own environment variable names. Replace RELEASE_NAME and GVC_NAME in DATABASE_URL with the release name and GVC you will install into.
Set auth.secretName to this name.
4

Create a service account for the advisor

Create a service account and a key for it. You paste the key into the dashboard after install (see First Run); it is not a value and not in either secret. Grant it at minimum:
If either secret is missing at install time, the deployment waits silently: cpln logs returns nothing because no container starts. Read status.versions[].message from cpln workload get-deployments RELEASE_NAME-api --gvc GVC_NAME -o yaml; it names the missing secret. See Troubleshooting.

Installation

Create both prerequisite secrets first, then install:

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Configuration

Advisor Credentials

The login name and password are keys in this secret, not values. The login is verified by the API, and there is one account for everyone, so the dashboard’s activity history attributes every change to a single user.

Images

The API, worker and scheduler run the same backend image with different commands, so keep them on one tag. Both images are public and need no pull secret. :latest resolves when a workload is deployed, so two installs a week apart can differ; every build also publishes a :sha-<commit> tag you can pin.

Dashboard URL

Leave it empty unless you serve the dashboard on a custom domain. The app derives its own public URL for this release’s dashboard workload, and uses it for Slack “View in Advisor” links and as the CORS allowlist. When set, it must be a full URL including the scheme (for example https://advisor.example.com), and it must never be *; the chart refuses to render either mistake.

Sessions and Logging

session.hours is the idle timeout and session.rememberDays the idle timeout with “Keep me signed in”. Both slide forward while you work.

Workload Resources

maxCpu/maxMemory are the container limits. minCpu/minMemory are the floor Capacity AI scales from, and are set only on the dashboard, API and scheduler, which run with Capacity AI on. The chart refuses to render when maxCpu is 4 or more times minCpu, when maxMemory is more than 4 times minMemory, or when a value looks like a unit typo (512Gi for 512Mi). Raising a maxCpu or maxMemory on web, api or scheduler usually means raising the matching minimum too.

Database

Values under postgres are passed to the bundled Postgres template. internalAccess.type: same-gvc lets every workload in your GVC reach port 5432. If the GVC is shared, narrow it at install time with the real workload links:
Add RELEASE_NAME-postgres-backup to that list if you turn backups on.

Backup

Backups are off by default and you should turn them on. See Backing Up.

Access

There is no access knob on the advisor’s own workloads. The firewall is fixed by the chart: The dashboard login is the boundary. To narrow the dashboard to an office or VPN range, edit inboundAllowCIDR on the RELEASE_NAME-web workload after installing; a firewall change can take a few minutes to take effect.

Connecting

The advisor’s output (suggestions, scores, Autopilot changes and activity) lives in the dashboard, plus the Slack digest if you configure one. Read the dashboard address from the workload:
To check the API directly from your machine without opening anything up, forward its port (it answers /health without a token):
To read your credentials back:

First Run

1

Sign in

Open the dashboard and sign in with ADVISOR_USERNAME and ADVISOR_PASSWORD from your advisor secret.
2

Connect Control Plane

Go to Configuration → Control Plane, paste the service account key, and press Test connection. The key is stored encrypted in the database.
3

Add an AI provider and optionally Slack

Add an Anthropic or OpenAI key on the same page, and a Slack bot token if you want digests. These are encrypted with ADVISOR_SECRET_KEY.
4

Enroll workloads and scan

Enable Scan on the workloads you want watched, then press Scan now.
5

Confirm the scheduler is running

Scheduled scans depend on RELEASE_NAME-scheduler. Its logs should show it firing run_scan:

Operations

Backing Up

All advisor state (scans, scores, settings and Autopilot history) lives in the bundled Postgres. Turn on postgres.backup.enabled and fill in the postgres.backup block shown in Backup. It needs a bucket and a cloud account you create first; the bucket, cloud account and IAM policy steps are the same as for the Postgres template. provider: minio also needs a prerequisite dictionary secret holding accessKey and secretKey, named by postgres.backup.minio.credentialsSecretName. Keep postgres.backup.image matched to postgres.image: tag 18.1.0 backs up Postgres 18 and 17.1.0 backs up Postgres 17. Each run writes one gzipped pg_dumpall file, postgres-TIMESTAMP.sql.gz, under BUCKET/PREFIX/ in your bucket. It is a whole-cluster SQL script, including CREATE ROLE and CREATE DATABASE statements.

Restoring a Backup

This restore path has not been verified end to end for this template. Test it on a scratch install before you rely on it.
1

Stop the writers

Scale RELEASE_NAME-api, RELEASE_NAME-worker and RELEASE_NAME-scheduler to zero so nothing writes during the restore.
2

Download the dump

Copy postgres-TIMESTAMP.sql.gz from your bucket with your own cloud tooling.
3

Open a tunnel to the database

4

Load the dump

Use psql 18 or newer, which understands the meta-commands a PostgreSQL 18 pg_dumpall writes. Use the username and password from your database credentials secret.
The bundled server already has the role and database from your credentials secret, so already exists errors for those are expected. Treat any other error as a failed restore.

Rotating Credentials

Running workloads keep the old value of a rotated secret until they are redeployed. Export the advisor secret, edit only the key you are rotating, re-apply it, then force a redeployment of every workload that reads it:
Repeat the last command for RELEASE_NAME-web, RELEASE_NAME-worker and RELEASE_NAME-scheduler. Never change ADVISOR_SECRET_KEY: it would make every credential stored in the dashboard unreadable. The database password is read only when the database first initializes, so changing it in the secret does not change it in Postgres; change it in Postgres too and update DATABASE_URL to match.

Scaling and Availability

The API, worker and scheduler each run one replica, and the GVC must have one location.
  • Dashboard scales between web.replicas.min and web.replicas.max; min: 0 scales to zero when idle at the cost of a cold start.
  • API runs the database migration at startup, so two replicas would race on it.
  • Worker scans are limited by upstream rate limits, so a second worker mostly adds rate-limit errors.
  • Scheduler must stay at one replica: two would fire every scan twice.

Troubleshooting

Cause: a prerequisite secret does not exist, so no container starts.Fix: read status.versions[].message, which names the missing secret:
Create the secret. The deployment recovers on its own after a few minutes, or force it:
Cause: the username, password or database name in DATABASE_URL does not match the database credentials secret, or its host does not use your real release name and GVC.Fix: compare the two secrets with cpln secret reveal ADVISOR_SECRET_NAME -o yaml and cpln secret reveal DB_CREDENTIALS_SECRET_NAME -o yaml, correct DATABASE_URL, re-apply the secret and force a redeployment as in Rotating Credentials.
Cause: the scheduler is not running, or the GVC has more than one location.Fix: check the RELEASE_NAME-scheduler logs as in First Run, and confirm the GVC has exactly one location with cpln gvc get GVC_NAME -o yaml (spec.staticPlacement.locationLinks).
Cause: your values file still carries a gvc block. The chart installs into the GVC you select with --gvc and does not read one.Fix: remove the gvc block from your values file.
Cause: ADVISOR_SECRET_KEY changed since they were entered, so they can no longer be decrypted.Fix: restore the original ADVISOR_SECRET_KEY if you still have it; otherwise re-enter the credentials in Configuration.

Important Notes

  • Create both prerequisite secrets before installing, and make DATABASE_URL agree with the database credentials secret.
  • Install into a GVC that already exists and has exactly one location.
  • Keep ADVISOR_SECRET_KEY somewhere durable; losing it loses every credential entered in the dashboard.
  • Turn on postgres.backup.enabled: a volume is not a backup.
  • The dashboard is public; narrow inboundAllowCIDR on RELEASE_NAME-web if you want it tighter.
  • Narrow postgres.internalAccess if the GVC is shared with other workloads.
  • Grant the service account workload: edit only if you want Autopilot and one-click apply; each applied suggestion redeploys a live workload.
  • Do not widen Redis access: it is unauthenticated and its firewall is its only protection.
  • Uninstalling deletes the database volume set and all scan history; it leaves the GVC and both prerequisite secrets in place.

External References

CPLN Advisor Template

View the source files, default values, and chart definition

Create a Service Account

Issue the token the advisor uses to read and tune your org

Capacity AI

How resource floors and automatic sizing work on Control Plane

Workload Firewall

Internal and external access controls used by every workload here