> For the complete documentation index, see [llms.txt](https://docs.release.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.release.com/guides-and-examples/advanced-guides/restrict-cluster-api-access.md).

# Restrict cluster API access

Lock down your cluster's Kubernetes API server to a specific list of source IP addresses (allowed hosts) for AWS EKS and GCP GKE clusters, without losing Release's management access.

By default, your cluster's Kubernetes API server (the control plane) accepts connections from any source IP address. **Allowed hosts** lets you restrict that access to an explicit allowlist of source IPs and CIDR ranges — so only you and Release can reach the API server.

Use this when you want a tighter, private-networking or compliance-oriented posture around your cluster's control plane.

## What it does

When you enable allowed hosts, the cluster's Kubernetes API endpoint stops accepting connections from any source that isn't on your list. `kubectl`, `k9s`, CI runners, and any other API clients must connect from an allowed address, or they are denied at the cloud provider's control plane.

## How Release access is preserved

Release's static egress address, **`35.247.5.67/32`**, is **always** merged into your allowlist automatically. You never type it, and it can't be removed. This guarantees Release never loses management access to your cluster, no matter what you enter.

Whatever list you submit is applied as *your entries plus Release's egress*.

## Before you start

* Your cluster must be **AWS (EKS)** or **GCP (GKE)**, **Release-managed**, and in the **running** state.
* Have your own current public IP address ready. You can find it by running:

  ```bash
  curl ifconfig.me
  ```
* Entries must be **IPv4** addresses or CIDR ranges. A bare IP (for example `203.0.113.4`) is treated as a `/32`. IPv6 is not supported.

## How to enable or edit allowed hosts

1. Open your cluster's detail page in the Release dashboard.
2. Open the **Actions** menu (top right).
3. Click **Enable allowed hosts** (or **Edit allowed hosts** if a list is already applied). This opens the **Restrict cluster API access** dialog.
4. Enter one IP address or CIDR range per row:
   * A bare IP such as `203.0.113.4` becomes `203.0.113.4/32`.
   * A range such as `203.0.113.0/24` is used as-is.
   * Use **+ Add another** to add more rows. Invalid entries are flagged inline and you can't apply until every row is valid.
5. Click **Apply allowlist**.

Release's egress (`35.247.5.67/32`) is shown at the top of the dialog and is always included — you don't need to add it.

> The **Actions** menu item is only available on running, managed AWS or GCP clusters. It doesn't appear on imported clusters and is disabled while the cluster is busy with another operation.

## ⚠️ Avoiding lockout

**Every source that isn't on your allowlist is denied — including you.** If you apply a list that doesn't contain your own current public IP, you'll immediately lose direct `kubectl` / API access to the cluster.

Before applying:

1. Find your current public IP: `curl ifconfig.me`
2. Add it to the list (as a `/32`, or as a wider CIDR that covers it).
3. If you connect from behind a NAT, VPN, or corporate gateway, allowlist that egress range instead of your local address.

Release access is always preserved regardless, so Release itself is never locked out — but **your** direct access depends entirely on including your own address.

### The "Release access only" option

If you submit an **empty** list (no entries of your own), the dialog requires you to explicitly check **"Allow Release access only — I understand this may remove my own direct kubectl/API access."**

Only check this if you intend for Release's egress to be the *only* thing that can reach the API server. This is a deliberate choice, not something you can do by accident.

## Recovering from lockout

The allowlist lives at your cloud provider's control plane, so even if you lock yourself out of the Release UI action, you can fix it directly with your cloud CLI (using credentials that don't depend on cluster API access).

**AWS (EKS)** — add your IP to the public-access CIDR list:

```bash
aws eks update-cluster-config \
  --name <CLUSTER_NAME> \
  --region <REGION> \
  --resources-vpc-config \
    endpointPublicAccess=true,publicAccessCidrs=35.247.5.67/32,<YOUR_IP>/32
```

Include **every** address you want to keep — this call replaces the current public-access CIDR list, so list Release's `35.247.5.67/32` alongside your own.

**GCP (GKE)** — update the master authorized networks:

```bash
gcloud container clusters update <CLUSTER_NAME> \
  --region <REGION> \
  --enable-master-authorized-networks \
  --master-authorized-networks=35.247.5.67/32,<YOUR_IP>/32
```

As with EKS, this replaces the existing list, so include Release's `35.247.5.67/32` along with your own address.

Because Release's egress stays on the list regardless, **Release support can also re-open access** for you if needed.

Once you can reach the cluster again, re-run **Edit allowed hosts** in the Release dashboard so the UI and the cloud provider stay in sync.

## What happens during apply

Applying an allowlist is asynchronous. When you click **Apply allowlist**:

1. The cluster briefly enters a **maintenance** state (typically \~15–30 seconds) while the change is pushed to your cloud provider's control plane.
2. Once the provider confirms the change, the cluster returns to **running** and the new allowlist is shown as applied.

This brief maintenance state is expected — it is not an error. The allowlist only reads as "applied" after the provider confirms it, so a change that hasn't finished (or that failed) never shows as active.

## AWS (EKS): worker nodes and the private endpoint

This section applies only to AWS (EKS) clusters. It explains a behavior Release handles for you automatically so a restrictive allowlist doesn't disconnect your worker nodes.

### Why EKS needs special handling

By default an EKS cluster's Kubernetes API endpoint is **public-only** (`endpointPrivateAccess: false`). In that configuration your worker nodes reach the control plane over the **public** endpoint, using your VPC's NAT/internet gateway egress IP addresses.

The allowed-hosts list (`publicAccessCidrs`) gates that public endpoint — it does not affect the private endpoint. So on a public-only cluster, a restrictive allowlist that doesn't include your node egress IPs would cut the nodes' kubelets off from the control plane, and the nodes would go **NotReady**.

### What Release does automatically

When you apply a restrictive allowlist to a public-only EKS cluster, Release **automatically enables the EKS private endpoint** (`endpointPrivateAccess: true`) in the same update. Node-to-control-plane traffic then routes **inside your VPC**, so the nodes stay connected regardless of the public-access allowlist. This is AWS's recommended durable configuration.

You do **not** need to add your NAT/egress IPs to the allowlist to keep nodes healthy — Release takes care of the private-endpoint side for you. (The modal shows a note reminding you of this whenever you're about to apply a restrictive list on an AWS cluster.)

Some guarantees worth knowing:

* Release **only ever enables** the private endpoint — it never disables a private endpoint you already have on.
* Reverting the allowlist to open (`0.0.0.0/0`) does **not** change the private-endpoint setting; once on, it stays on.
* Release's own egress CIDRs are always merged into the allowlist, so Release retains access either way.

> **Note — custom VPCs:** Enabling the EKS private endpoint requires the cluster's VPC to have `enableDnsHostnames` and `enableDnsSupport` set to `true` (EKS creates a Route 53 private hosted zone for the endpoint). Standard Release-provisioned VPCs already satisfy this. If you run the cluster in a custom VPC, confirm both settings are enabled.

### GKE is different

On GCP (GKE), the cluster's own internal IP ranges are preset access sources for the control-plane endpoint, so restricting authorized networks does **not** sever your nodes. There is no equivalent auto-enable step on GKE, and none is needed.

## The active-restriction banner

Whenever an allowlist is applied, the cluster page shows an **"API access is restricted"** banner listing the currently allowed sources. If you lose direct access, use the banner as a reminder to add your current IP via **Actions → Edit allowed hosts**, or follow the recovery steps above.

## Supported clusters and limits

* **Providers:** AWS (EKS) and GCP (GKE) only. Azure and imported clusters are not supported.
* **Cluster state:** must be Release-managed and running.
* **Address family:** IPv4 only. IPv6 is rejected.
* **GKE limit:** GKE caps authorized networks at **50 entries** total (your entries plus Release's egress).


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.release.com/guides-and-examples/advanced-guides/restrict-cluster-api-access.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
