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.What Gets Created
secret, grants only the reveal permission, and lists exactly one secret by name:
Prerequisites
You need an existing GVC with exactly one location, twodictionary 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.
Choose the database password
Create the database credentials secret
username, password and database.postgres.config.credentialsSecretName to this name.Create the advisor credentials secret
RELEASE_NAME and GVC_NAME in DATABASE_URL with the release name and GVC you will install into.auth.secretName to this name.Create a service account for the advisor
Installation
Create both prerequisite secrets first, then install:UI
CLI
Terraform
Pulumi
Configuration
Advisor Credentials
Images
: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
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
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:
RELEASE_NAME-postgres-backup to that list if you turn backups on.
Backup
Access
There is no access knob on the advisor’s own workloads. The firewall is fixed by the chart:inboundAllowCIDR on the RELEASE_NAME-web workload after installing; a firewall change can take a few minutes to take effect.
Connecting
/health without a token):
First Run
Sign in
ADVISOR_USERNAME and ADVISOR_PASSWORD from your advisor secret.Connect Control Plane
Add an AI provider and optionally Slack
ADVISOR_SECRET_KEY.Enroll workloads and scan
Confirm the scheduler is running
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 onpostgres.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
Stop the writers
RELEASE_NAME-api, RELEASE_NAME-worker and RELEASE_NAME-scheduler to zero so nothing writes during the restore.Download the dump
postgres-TIMESTAMP.sql.gz from your bucket with your own cloud tooling.Open a tunnel to the database
Load the dump
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.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: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.minandweb.replicas.max;min: 0scales 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
The install sits waiting and cpln logs shows nothing
The install sits waiting and cpln logs shows nothing
status.versions[].message, which names the missing secret:Everything installs but the API fails to authenticate to the database
Everything installs but the API fails to authenticate to the database
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.Nothing is scanned on a schedule but every workload is healthy
Nothing is scanned on a schedule but every workload is healthy
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).The chart refuses to render and says the gvc values key is no longer used
The chart refuses to render and says the gvc values key is no longer used
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.AI or Slack credentials show as not set
AI or Slack credentials show as not set
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_URLagree with the database credentials secret. - Install into a GVC that already exists and has exactly one location.
- Keep
ADVISOR_SECRET_KEYsomewhere 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
inboundAllowCIDRonRELEASE_NAME-webif you want it tighter. - Narrow
postgres.internalAccessif the GVC is shared with other workloads. - Grant the service account
workload: editonly 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.