> For the complete documentation index, see [llms.txt](https://docs.heeler.com/mrecEO40m5D6bt7Pq5pE/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.heeler.com/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime/kubernetes-native-setup.md).

# Kubernetes (native) Setup

Connect a native Kubernetes cluster to Heeler with a read-only service account and token.

Heeler harvests Kubernetes resources and models them as services linked to your code. Cloud-hosted clusters (**EKS**, **GKE**) are discovered automatically from your [AWS](/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime/amazon-web-services.md) or [GCP](/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime/google-cloud-platform.md) connection. For a **native** cluster, add it here with a read-only service account and token.

{% hint style="info" %}
**EKS, GKE, and AKS clusters appear under Kubernetes Clusters automatically** once the cloud connection harvests them — you don't add them by hand with the steps below. EKS and AKS clusters do, however, each need a one-time grant so Heeler can reach and read their control plane; see [Cloud-discovered clusters (EKS and AKS)](#cloud-discovered-clusters-eks-and-aks). Use the steps in this section for **native** clusters that aren't reached through a cloud connection.
{% endhint %}

## Three prerequisites

1. **Network access** — the cluster's control plane must accept connections from Heeler's two IPs: `44.221.229.40/32` and `52.73.231.96/32`.
2. **A read-only setup applied** to the cluster (below).
3. **A read-only token** provided to Heeler (below).

## Step 1 — Apply the read-only setup

Download `heeler-readonly.yaml` and replace `<kube-system>` with your namespace in **three** places (the `ServiceAccount`, the `ClusterRoleBinding` subject, and the `Secret`). It creates a `heeler-readonly` ServiceAccount, a ClusterRole granting **`get`/`list`** on all resources, a binding, and a service-account-token Secret:

```yaml
apiVersion: v1
kind: ServiceAccount
metadata: { name: heeler-readonly, namespace: <kube-system> }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: { name: heeler-readonly-role }
rules:
- apiGroups: ['*']
  resources: ['*']
  verbs: [get, list]
- nonResourceURLs: ['*']
  verbs: [get, list]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: { name: heeler-readonly }
roleRef: { apiGroup: rbac.authorization.k8s.io, kind: ClusterRole, name: heeler-readonly-role }
subjects:
- { kind: ServiceAccount, name: heeler-readonly, namespace: <kube-system> }
---
apiVersion: v1
kind: Secret
metadata:
  name: heeler-readonly
  namespace: <kube-system>
  annotations: { kubernetes.io/service-account.name: heeler-readonly }
type: kubernetes.io/service-account-token
```

```bash
kubectl apply -f heeler-readonly.yaml
```

## Step 2 — Get the read-only token

```bash
kubectl -n <kube-system> describe secret heeler-readonly
```

Save the **token** — it goes into the `token` field of the kubeconfig you'll paste into Heeler.

## Step 3 — Add the cluster in Heeler

Go to **Connections → Kubernetes Clusters → Add Cluster** and fill in:

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2Fgit-blob-dec948256c5dcf6fb545396d94fd56fc4a91f2ec%2Fcc-gs-cloud-addcluster.png?alt=media" alt="The Add Kubernetes Cluster modal with Cluster Name, Cluster FQDN, and Configuration (YAML) fields."><figcaption><p>Add a native cluster with its FQDN and a read-only kubeconfig. EKS/GKE/AKS clusters appear here automatically from the cloud connection.</p></figcaption></figure>

<table><thead><tr><th width="200">Field</th><th>Value</th></tr></thead><tbody><tr><td><strong>Cluster Name</strong></td><td>A unique, human-friendly name (needn't match the kubeconfig cluster name).</td></tr><tr><td><strong>Cluster FQDN</strong></td><td>The cluster's fully qualified domain — matches <code>server</code> in the Configuration.</td></tr><tr><td><strong>Configuration</strong></td><td>A kubeconfig-style YAML (below) with the server, certificate-authority-data, and the bearer token.</td></tr></tbody></table>

```yaml
apiVersion: v1
kind: Config
clusters:
- name: <cluster name, e.g. acme-k8s-dev>
  cluster:
    certificate-authority-data: <CA data as one block>
    server: <FQDN/URL, e.g. https://k8s-dev.acme.com:443>
contexts:
- name: heeler-readonly@<cluster name>
  context: { cluster: <cluster name>, user: heeler-readonly }
current-context: heeler-readonly@<cluster name>
users:
- name: heeler-readonly
  user:
    token: <bearer token as one block>
```

Click **Save** — a **healthy** status confirms Heeler can reach and read the cluster.

## You're done when…

* [ ] The cluster shows a **healthy** status under **Connections → Kubernetes Clusters**.
* [ ] Workloads and deployments from the cluster appear in the [Catalog](/mrecEO40m5D6bt7Pq5pE/catalog/deployments.md).
* [ ] Services map from the cluster back to your code — see [Services](/mrecEO40m5D6bt7Pq5pE/catalog/services.md).

## Troubleshooting

<table><thead><tr><th width="300">Symptom</th><th>Fix</th></tr></thead><tbody><tr><td>Status is not <strong>healthy</strong></td><td>Heeler can't reach the control plane or authenticate. Confirm the control plane accepts Heeler's IPs (<code>44.221.229.40/32</code>, <code>52.73.231.96/32</code>), and that the <code>server</code>, <code>certificate-authority-data</code>, and <code>token</code> in the kubeconfig are correct and current.</td></tr><tr><td>No workloads or deployments appear</td><td>The <code>heeler-readonly</code> ClusterRole or binding wasn't applied — or was applied to the wrong namespace — so the token lacks <strong><code>get</code>/<code>list</code></strong>. Re-apply <code>heeler-readonly.yaml</code> and confirm the token belongs to that ServiceAccount.</td></tr></tbody></table>

## Cloud-discovered clusters (EKS and AKS)

EKS (AWS) and AKS (Azure) clusters are discovered from your cloud connection and appear under **Kubernetes Clusters** automatically — don't add them with the steps above. Each one does need a one-time grant so Heeler can reach its API server and read its resources. GKE clusters need no extra step.

### Amazon EKS

Three things must be in place for Heeler to harvest an EKS cluster:

* An [**AWS connection**](/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime/amazon-web-services.md). Its setup deploys the `heeler-member` role, the `Heeler` policy (denies access to your data plane — `s3:GetObject`, `dynamodb:GetItem`, and the like), and an EKS access policy.
* **Network access** — Heeler's two IPs allowed on the cluster's public API server endpoint.
* **EKS API authentication** — already enabled for clusters created after January 1, 2024; legacy clusters may need updating.

The EKS access policy lets Heeler associate `AmazonEKSAdminViewPolicy` with its own access entry on each cluster. That AWS-managed policy is read-only. It also grants read on Kubernetes Secrets, which Heeler does not read.

To grant in-cluster access with a ClusterRole you apply yourself, see [A ClusterRole you manage](/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime/amazon-web-services.md#a-clusterrole-you-manage).

#### Allow Heeler's IPs on the API server endpoint

1. Open the cluster's **Networking** tab → **Manage** → **Endpoint access**.
2. Select the **Public and private** option.
3. Under **Advanced settings**, add Heeler's two IPs to the **Public access source allowlist** (CIDR block): `44.221.229.40/32` and `52.73.231.96/32`.
4. **Save changes**.

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2FaHYUJ1u3wKkgLArQvsEy%2F1%20--%20Manage%20endpoint%20access%20--%20gimp.png?alt=media&amp;token=eadc7e85-7ef2-4e48-95ed-320d5b60b595" alt="The EKS Networking tab with Manage → Endpoint access selected in the AWS console."><figcaption><p>On the cluster's <strong>Networking</strong> tab, choose <strong>Manage → Endpoint access</strong>.</p></figcaption></figure>

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2Fnqxnp6673AJ1oqonK3KW%2F2%20--%20CIDR%20block%20--%20gimp.png?alt=media&amp;token=756abfcf-52fe-4915-8771-d64d3d831391" alt="Public access source allowlist with Heeler&#x27;s two CIDR blocks entered in the AWS console."><figcaption><p>Add Heeler's two IPs to the <strong>Public access source allowlist</strong>.</p></figcaption></figure>

If you manage the cluster with Terraform, set `endpoint_public_access` and `public_access_cidrs` in `vpc_config`:

```hcl
resource "aws_eks_cluster" "this" {
  name = var.cluster_name

  vpc_config {
    subnet_ids         = var.subnet_ids
    security_group_ids = [var.cluster_sg_id]

    # "Public and private" endpoint access
    endpoint_public_access  = true
    endpoint_private_access = true

    # Public access source allowlist includes Heeler's two IPs
    public_access_cidrs = [
      "44.221.229.40/32",
      "52.73.231.96/32",
    ]
  }
}
```

#### Enable EKS API authentication (legacy clusters only)

Clusters created after January 1, 2024 already have the required **Cluster Authentication Mode** — no action needed. For a legacy cluster:

1. Open the cluster's **Access** tab → **Manage**.
2. If the mode is `ConfigMap`, choose **EKS API and ConfigMap**. (Don't choose `EKS API` alone while you still manage access through `ConfigMap`.)
3. **Save changes**.

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2FIctve2LUG6OYFJ7CcSma%2F3%20--%20Manage%20access%20configuration%20--%20gimp.png?alt=media&amp;token=52f08d70-8446-435f-bc81-f89ca4017777" alt="The EKS Access tab with Manage selected in the AWS console."><figcaption><p>On the cluster's <strong>Access</strong> tab, choose <strong>Manage</strong>.</p></figcaption></figure>

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2FPP9SvhyIFoUYzWGIYSjJ%2F4%20--%20EKS%20API%20and%20ConfigMap%20--%20gimp.png?alt=media&amp;token=02d84c5a-3fcc-4d09-8b92-79b863437476" alt="Cluster Authentication Mode set to EKS API and ConfigMap in the AWS console."><figcaption><p>Set the authentication mode to <strong>EKS API and ConfigMap</strong>.</p></figcaption></figure>

With Terraform, confirm `access_config.authentication_mode` is `API_AND_CONFIG_MAP` (or `API`):

```hcl
resource "aws_eks_cluster" "this" {
  name = var.cluster_name

  access_config {
    authentication_mode = "API_AND_CONFIG_MAP" # or "API"
  }
}
```

### Azure AKS

Four things must be in place for Heeler to harvest an AKS cluster:

* An [**Azure connection**](/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime/microsoft-azure.md) that authenticates with a client secret and covers the subscription that hosts the cluster.
* **Network access** — Heeler's two IPs in the cluster's **Authorized IP ranges**.
* The Azure connection's **service principal** granted two cluster role assignments.
* **Microsoft Entra ID authentication with Azure RBAC** enabled on the cluster.

{% hint style="warning" %}
**AKS onboarding requires a client-secret Azure connection.** Heeler builds each AKS cluster's `kubeconfig` with `kubelogin`, which needs a client secret. On an Azure connection that uses federated identity, discovered AKS clusters are listed as inaccessible under the connection's Health badge. Add the cluster with a kubeconfig using the steps at the top of this page, or use a client-secret Azure connection.
{% endhint %}

#### Allow Heeler's IPs on the API server

1. Open the cluster's **Settings → Networking → Resource Settings → Manage**.
2. Set **Authorized IP ranges** to a comma-separated list that includes `44.221.229.40/32,52.73.231.96/32`.
3. **Save**.

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2FVRBPhO3SQmNLVxQeQInl%2F1%20--%20Networking%20--%20gimp.png?alt=media&amp;token=bbd2ca20-5456-4d45-acc9-7163c72f2d43" alt="AKS Networking settings with Heeler&#x27;s IPs in the Authorized IP ranges field in the Azure console."><figcaption><p>Add Heeler's two IPs to the cluster's <strong>Authorized IP ranges</strong>.</p></figcaption></figure>

With Terraform, add Heeler's IPs to `api_server_access_profile.authorized_ip_ranges`:

```hcl
resource "azurerm_kubernetes_cluster" "this" {
  # ...
  api_server_access_profile {
    authorized_ip_ranges = [
      "44.221.229.40/32",
      "52.73.231.96/32",
      "<your other IPs>",
    ]
  }
}
```

#### Assign the two cluster roles to the service principal

Grant the service principal used for the Azure connection **both** roles, scoped to each cluster:

* `Azure Kubernetes Service Cluster User Role`
* `Azure Kubernetes Service RBAC Cluster Admin`

On each cluster, open **Access control (IAM) → Add → Add role assignment**. Select a role and **Next**; under **Members**, confirm **Assign access to** is *User, group, or service principal*, click **+ Select members**, search for the service principal **by name**, **Select** it, then **Review + assign**. Repeat for the second role.

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2FsdcHMyLnhQS5Mv1mhm16%2F2%20--%20Add%20role%20assignment%20--%20gimp.png?alt=media&amp;token=8fd98f0a-7b10-47c6-8e25-a966a532692a" alt="AKS Access control (IAM) with Add → Add role assignment in the Azure console."><figcaption><p>On the cluster, open <strong>Access control (IAM) → Add → Add role assignment</strong>.</p></figcaption></figure>

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2FxDm37FMWrSTAsOZipTKf%2F3%20--%20Select%20role%20--%20gimp.png?alt=media&amp;token=4bdbb839-23c9-4113-9b8d-efdbb4407f61" alt="Selecting an Azure Kubernetes Service role in the role-assignment dialog in the Azure console."><figcaption><p>Search for and select each role in turn.</p></figcaption></figure>

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2FkFDuinDJWVk8Jdz6cjJk%2F4%20--%20Select%20service%20principal%20--%20gimp.png?alt=media&amp;token=ce60ebe7-2a27-4dd8-b776-718816445916" alt="Selecting the App Registration service principal as the member in the Azure console."><figcaption><p>Add the connection's service principal as the member, then <strong>Review + assign</strong>.</p></figcaption></figure>

With Terraform, add two `azurerm_role_assignment` resources scoped to the cluster:

```hcl
data "azuread_service_principal" "aks_service_principal" {
  client_id = var.client_id
}

resource "azurerm_role_assignment" "aks_cluster_user_role" {
  scope                = azurerm_kubernetes_cluster.aks.id
  role_definition_name = "Azure Kubernetes Service Cluster User Role"
  principal_id         = data.azuread_service_principal.aks_service_principal.object_id
}

resource "azurerm_role_assignment" "aks_rbac_cluster_admin" {
  scope                = azurerm_kubernetes_cluster.aks.id
  role_definition_name = "Azure Kubernetes Service RBAC Cluster Admin"
  principal_id         = data.azuread_service_principal.aks_service_principal.object_id
}
```

#### Enable Entra ID authentication with Azure RBAC

1. Open the cluster's **Settings → Security Configuration → Authentication and Authorization**.
2. Select **Microsoft Entra ID authentication with Azure RBAC**.
3. **Apply**.

<figure><img src="https://414480750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXP3dp2kecwKA2KvYkntz%2Fuploads%2Fd3lg6fgfdm8A9ksPIT0Y%2F8%20--%20Entra%20--%20gimp.png?alt=media&amp;token=972a1ecf-0b99-4d3b-af74-b614b6639f96" alt="AKS Authentication and Authorization set to Microsoft Entra ID authentication with Azure RBAC in the Azure console."><figcaption><p>Set <strong>Authentication and Authorization</strong> to <strong>Microsoft Entra ID authentication with Azure RBAC</strong>.</p></figcaption></figure>

With Terraform, the relevant settings are `azure_rbac_enabled = true` (under `azure_active_directory_role_based_access_control`) and `local_account_disabled = true`.

Once the settings propagate, Heeler harvests the cluster and relates it to the other resources in your cloud environment.

## Related

* [Connect Your Cloud and Runtime](/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime.md) — the spine; EKS/GKE are discovered from the cloud connection.
* [On-Premises Broker](/mrecEO40m5D6bt7Pq5pE/get-started/registries-and-artifacts/on-premises-broker.md) — for cluster inventory collected by an in-cluster sidecar.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.heeler.com/mrecEO40m5D6bt7Pq5pE/get-started/cloud-and-runtime/kubernetes-native-setup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
