# Configure the agent

> Chart values for the LevelFour agent, and how to read Prometheus history, send through a proxy, pull from a private registry and verify the release signatures.

Source: https://docs.levelfour.ai/connectors/kubernetes/configuration


Helm installs and GitOps installs take the same chart values. With GitOps, add them to [your values](/connectors/kubernetes/gitops#point-your-gitops-tool-at-the-chart). With Helm, apply a values file over the install you have:

```bash
helm upgrade levelfour-agent oci://public.ecr.aws/levelfour/charts/levelfour-agent \
  --version 0.1.0 \
  --namespace levelfour --reuse-values -f values.yaml
```

Set `--version` to the chart version you run. Without it, Helm pulls the newest chart and upgrades the agent as well.

## Chart values

The chart validates its values and refuses to install when `clusterName` breaks the naming rule, when neither `token` nor `existingSecret.name` is set, or when both are.

| Value                           | Default                                                                      | What it sets                                                                                                                                                                         |
| ------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `clusterName`                   | none                                                                         | The cluster's name in LevelFour. Required. Lowercase letters, digits and hyphens, at most 63 characters, starting and ending with a letter or digit. Unique across your organization |
| `token`                         | none                                                                         | A cluster token (`l4k_...`) or an install key (`l4ki_...`). Set `token` or `existingSecret.name`, not both                                                                           |
| `existingSecret.name`           | none                                                                         | A Secret in the release namespace that holds the token or install key                                                                                                                |
| `existingSecret.key`            | `token`                                                                      | The key inside that Secret                                                                                                                                                           |
| `apiUrl`                        | `https://api.levelfour.ai`                                                   | Where the agent sends data. Keep the default                                                                                                                                         |
| `prometheus.url`                | none                                                                         | An in-cluster Prometheus to read usage and history from. See [Read history from Prometheus](#read-history-from-prometheus)                                                           |
| `kubelet.insecureSkipTLSVerify` | `false`                                                                      | Skips kubelet certificate checks, for local kind clusters only. On a real cluster it sends the agent's service account token to kubelets the agent cannot verify                     |
| `image.repository`              | `public.ecr.aws/levelfour/k8s-agent`                                         | The agent image. Point it at your [mirror](#private-registry-mirror)                                                                                                                 |
| `image.tag`                     | The chart's version                                                          | Leave it unset so the image moves with the chart                                                                                                                                     |
| `image.digest`                  | none                                                                         | Pulls the image by digest (`sha256:...`) instead of by tag                                                                                                                           |
| `image.pullPolicy`              | `IfNotPresent`                                                               | `IfNotPresent`, `Always` or `Never`                                                                                                                                                  |
| `imagePullSecrets`              | `[]`                                                                         | Pull Secrets for a private registry                                                                                                                                                  |
| `nameOverride`                  | none                                                                         | Replaces the chart name in object names and in the `app.kubernetes.io/name` label                                                                                                    |
| `fullnameOverride`              | none                                                                         | Replaces the whole object name. A release named `levelfour-agent` names its objects `levelfour-agent`                                                                                |
| `serviceAccount.create`         | `true`                                                                       | Whether the chart creates the agent's service account                                                                                                                                |
| `serviceAccount.name`           | The object name                                                              | The service account the agent runs as. With `create: false`, name one that exists                                                                                                    |
| `serviceAccount.annotations`    | `{}`                                                                         | Annotations on the service account the chart creates                                                                                                                                 |
| `commonLabels`                  | `{}`                                                                         | Labels added to every object the chart creates                                                                                                                                       |
| `podAnnotations`                | `{}`                                                                         | Annotations on the agent pod                                                                                                                                                         |
| `podLabels`                     | `{}`                                                                         | Labels on the agent pod, added to the chart's own                                                                                                                                    |
| `priorityClassName`             | none                                                                         | The PriorityClass of the agent pod                                                                                                                                                   |
| `podSecurityContext`            | Non-root user and group `65532`, `RuntimeDefault` seccomp                    | The pod security context                                                                                                                                                             |
| `containerSecurityContext`      | No privilege escalation, read-only root filesystem, every capability dropped | The container security context                                                                                                                                                       |
| `resources`                     | See [Footprint](/connectors/kubernetes/agent-permissions-and-data#footprint) | CPU and memory requests and limits                                                                                                                                                   |
| `metrics.port`                  | `9090`                                                                       | The port that serves `/metrics` and `/healthz`                                                                                                                                       |
| `extraEnv`                      | `[]`                                                                         | Extra environment variables for the agent, such as a [proxy](#behind-a-proxy)                                                                                                        |
| `nodeSelector`                  | `kubernetes.io/os: linux`                                                    | Node selector for the agent pod                                                                                                                                                      |
| `tolerations`                   | `[]`                                                                         | Tolerations for the agent pod                                                                                                                                                        |
| `affinity`                      | `{}`                                                                         | Affinity rules for the agent pod                                                                                                                                                     |

## Read history from Prometheus

The agent measures usage from the kubelet on each node, so it needs no Prometheus. If the cluster already runs one, such as kube-prometheus-stack, point the agent at it. At its first start the agent reads up to 14 days of history from Prometheus, so the first recommendations can come sooner than 7 days after install.

```yaml title="values.yaml"
prometheus:
  url: http://prometheus-operated.monitoring.svc:9090
```

With Helm, set it on the command line:

```bash
helm upgrade levelfour-agent oci://public.ecr.aws/levelfour/charts/levelfour-agent \
  --version 0.1.0 \
  --namespace levelfour --reuse-values \
  --set prometheus.url=http://prometheus-operated.monitoring.svc:9090
```

The agent queries Prometheus from inside the cluster. LevelFour never connects to it, and nothing is exposed outside the cluster.

## Behind a proxy

The agent sends data to `api.levelfour.ai` on port 443. If the cluster reaches the internet through a proxy, set `HTTPS_PROXY` for the agent with `extraEnv`. Set `NO_PROXY` to your in-cluster addresses so the agent still reaches the kubelets and the API server directly: `.svc`, `.cluster.local`, the service CIDR, and the pod and node CIDRs.

```yaml title="values.yaml"
extraEnv:
  - name: HTTPS_PROXY
    value: http://proxy.example.com:3128
  - name: NO_PROXY
    value: .svc,.cluster.local,172.20.0.0/16,10.0.0.0/16
```

Replace the CIDRs with your cluster's. The API server's in-cluster address sits in the service CIDR. On Amazon EKS, read it with:

```bash
aws eks describe-cluster --name YOUR_EKS_CLUSTER \
  --query cluster.kubernetesNetworkConfig.serviceIpv4Cidr --output text
```

## Private registry mirror

To pull the agent from your own registry, copy the image there and point the chart at it. Copy both architectures (`linux/amd64` and `linux/arm64`) and keep the tag, because the chart pulls the tag that matches its version. `crane copy` copies every architecture by default; with `skopeo copy`, pass `--all`.

```bash
crane copy public.ecr.aws/levelfour/k8s-agent:0.1.0 registry.example.com/levelfour/k8s-agent:0.1.0
```

```yaml title="values.yaml"
image:
  repository: registry.example.com/levelfour/k8s-agent
imagePullSecrets:
  - name: registry-credentials
```

`registry-credentials` is a `kubernetes.io/dockerconfigjson` Secret in the `levelfour` namespace. To pin the exact image you [verified](#verify-the-signatures-and-sbom), set `image.digest` to the digest `crane digest public.ecr.aws/levelfour/k8s-agent:0.1.0` prints. `crane copy` keeps that digest.

To mirror the chart as well, pull it and push it to your registry, then install from `oci://registry.example.com/levelfour/charts/levelfour-agent`:

```bash
helm pull oci://public.ecr.aws/levelfour/charts/levelfour-agent --version 0.1.0
helm push levelfour-agent-0.1.0.tgz oci://registry.example.com/levelfour/charts
```

Verify the signatures on the public copies before you mirror them.

## Verify the signatures and SBOM

LevelFour signs every agent image and chart with cosign, and attaches an SPDX SBOM to each image as a signed attestation. The signing key stays in AWS KMS. Check a release with the LevelFour public key and cosign 3 or later.

Download the public key:

```bash
curl -sSfLO https://docs.levelfour.ai/keys/levelfour-k8s-agent.pub
```

Verify the image and the chart:

```bash
cosign verify --key levelfour-k8s-agent.pub public.ecr.aws/levelfour/k8s-agent:0.1.0
cosign verify --key levelfour-k8s-agent.pub public.ecr.aws/levelfour/charts/levelfour-agent:0.1.0
```

Verify the SBOM attestation:

```bash
cosign verify-attestation --key levelfour-k8s-agent.pub --type spdxjson public.ecr.aws/levelfour/k8s-agent:0.1.0
```

To save the SBOM itself, pipe that command's output through `jq -r .payload | base64 -d | jq .predicate > levelfour-agent-0.1.0.spdx.json`.

Each command exits with an error when the signature is missing or a different key made it.

### Verify the chart in Flux

Flux 2.8 and later verify cosign 3 signatures, so Flux can check the chart on every pull. Put the public key in a Secret next to the OCIRepository. Flux reads every key in that Secret whose name ends in `.pub`, and the file name gives the key that name:

```bash
kubectl -n levelfour create secret generic levelfour-cosign-key \
  --from-file=levelfour-k8s-agent.pub
```

Then add `verify` to the OCIRepository from [Install with GitOps](/connectors/kubernetes/gitops#point-your-gitops-tool-at-the-chart). Flux refuses a chart that the LevelFour key did not sign:

```yaml title="levelfour-agent.yaml"
spec:
  verify:
    provider: cosign
    secretRef:
      name: levelfour-cosign-key
```
