---
title: "Amazon Elastic Kubernetes Service (EKS)"
description: "Add Calico Open Source network policy to an Amazon EKS cluster running the AWS VPC CNI, without replacing the cluster's networking data plane."
product: "Calico Open Source"
version: "3.32 (latest)"
section: "Installing and upgrading"
canonical_url: "https://docs.tigera.io/calico/latest/getting-started/kubernetes/managed-public-cloud/eks"
---

# Amazon Elastic Kubernetes Service (EKS)

## Big picture

Enable Calico in EKS managed Kubernetes service.

## Value

EKS has built-in support for Calico, providing a robust implementation of the full Kubernetes Network Policy API. EKS users wanting to go beyond Kubernetes network policy capabilities can make full use of the Calico Network Policy API.

You can also use Calico for networking on EKS in place of the default AWS VPC networking without the need to use IP addresses from the underlying VPC. This allows you to take advantage of the full set of Calico networking features, including Calico's flexible IP address management capabilities.

## How to

### Install EKS with Amazon VPC networking

The geeky details of what you get:

| Policy | IPAM | CNI | Overlay | Routing    | Datastore  |
| ------ | ---- | --- | ------- | ---------- | ---------- |
| Calico | AWS  | AWS | No      | VPC Native | Kubernetes |

?

> **SECONDARY:** When using the Amazon VPC CNI plugin, Calico does not support enforcement of network policy on IPv6 pods with `ENABLE_V4_EGRESS` set to `true`.

1. First, create an Amazon EKS cluster.

   ```bash
   eksctl create cluster --name  <my-calico-cluster>
   ```

   Do **not** enable [network policy for the AWS VPC CNI](https://docs.aws.amazon.com/eks/latest/userguide/network-policy-disable.html); it conflicts with Calico.

2. Configure AWS VPC CNI to [annotate Pods with their IPs](https://github.com/aws/amazon-vpc-cni-k8s?tab=readme-ov-file#annotate_pod_ip-v193). Note the requirement to grant the "patch" permission to the `aws-node` daemon set to avoid permission errors. This setting ensures that pod IPs propagate quickly from AWS VPC CNI to Calico.

   ```bash
   cat << EOF > append.yaml
   - apiGroups:
     - ""
     resources:
     - pods
     verbs:
     - patch
   EOF
   kubectl apply -f <(cat <(kubectl get clusterrole aws-node -o yaml) append.yaml)
   kubectl set env  -n kube-system daemonset/aws-node ANNOTATE_POD_IP=true
   ```

3. Install the Tigera Operator and custom resource definitions.

   ```bash
   kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/v1_crd_projectcalico_org.yaml
   kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/tigera-operator.yaml
   ```

4. Configure the Calico installation.

   ```bash
   kubectl create -f - <<EOF
   apiVersion: operator.tigera.io/v1
   kind: Installation
   metadata:
     name: default
   spec:
     kubernetesProvider: EKS
     cni:
       type: AmazonVPC
     calicoNetwork:
       bgp: Disabled
   ---

   # This section configures the Calico API server.
   # For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.APIServer
   apiVersion: operator.tigera.io/v1
   kind: APIServer
   metadata:
     name: default
   spec: {}

   ---

   # Configures the Calico Goldmane flow aggregator.
   apiVersion: operator.tigera.io/v1
   kind: Goldmane
   metadata:
     name: default

   ---

   # Configures the Calico Whisker observability UI.
   apiVersion: operator.tigera.io/v1
   kind: Whisker
   metadata:
     name: default
   EOF
   ```

5. Confirm installation by checking the `STATUS`, your cluster nodes should have a `Ready` status.

   ```text
   kubectl get nodes -o wide
   ```

   It should return something like the following.

   ```text
   NAME              STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME
   <your-hostname>   Ready    master   52m   v1.12.2   10.128.0.28   <none>        Ubuntu 18.04.1 LTS   4.15.0-1023-gcp   docker://18.6.1
   ```

### Install EKS with Calico networking

The geeky details of what you get:

| Policy | IPAM   | CNI    | Overlay | Routing | Datastore  |
| ------ | ------ | ------ | ------- | ------- | ---------- |
| Calico | Calico | Calico | VXLAN   | Calico  | Kubernetes |

?

> **SECONDARY:** Calico networking cannot currently be installed on the EKS control plane nodes. As a result the control plane nodes will not be able to initiate network connections to Calico pods. (This is a general limitation of EKS's custom networking support, not specific to Calico.) As a workaround, trusted pods that require control plane nodes to connect to them, such as those implementing admission controller webhooks, can include `hostNetwork:true` in their pod spec. See the Kubernetes API [pod spec](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec) definition for more information on this setting.

For these instructions, we will use `eksctl` to provision the cluster. However, you can use any of the methods in [Getting Started with Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html)

Before you get started, make sure you have downloaded and configured the [necessary prerequisites](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html#eksctl-prereqs)

1. First, create an Amazon EKS cluster without any nodes.

   ```bash
   eksctl create cluster --name my-calico-cluster --without-nodegroup
   ```

2. Since this cluster will use Calico for networking, you must delete the `aws-node` daemon set to disable AWS VPC networking for pods.

   ```bash
   kubectl delete daemonset -n kube-system aws-node
   ```

3. Now that you have a cluster configured, you can install Calico.

<!-- tabs -->

**Tab: Operator**

1. Install the Tigera Operator and custom resource definitions.

   ```bash
   kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/v1_crd_projectcalico_org.yaml
   kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/tigera-operator.yaml
   ```

2. Configure the Calico installation.

   ```bash
   kubectl create -f - <<EOF
   apiVersion: operator.tigera.io/v1
   kind: Installation
   metadata:
     name: default
   spec:
     kubernetesProvider: EKS
     cni:
       type: Calico
     calicoNetwork:
       bgp: Disabled
   ---

   # This section configures the Calico API server.
   # For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.APIServer
   apiVersion: operator.tigera.io/v1
   kind: APIServer
   metadata:
     name: default
   spec: {}

   ---

   # Configures the Calico Goldmane flow aggregator.
   apiVersion: operator.tigera.io/v1
   kind: Goldmane
   metadata:
     name: default

   ---

   # Configures the Calico Whisker observability UI.
   apiVersion: operator.tigera.io/v1
   kind: Whisker
   metadata:
     name: default
   EOF
   ```

3. Finally, add nodes to the cluster.

   ```batch
   eksctl create nodegroup --cluster <my-calico-cluster> --node-type t3.medium --max-pods-per-node 100
   ```

**Tab: Manifest**

1. Install the Calico manifest.

   ```bash
   kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico-vxlan.yaml
   ```

2. Configure Calico to disable AWS src/dst checks.

   ```bash
   kubectl -n kube-system set env daemonset/calico-node FELIX_AWSSRCDSTCHECK=Disable
   ```

3. Finally, add nodes to the cluster.

   ```bash
   eksctl create nodegroup --cluster my-calico-cluster --node-type t3.medium --max-pods-per-node 100
   ```

**Tab: Helm**

1. Add Calico into your Helm repository.

   ```batch
   helm repo add projectcalico https://docs.tigera.io/calico/charts
   ```

2. If Calico is already added, update it to get the latest released version.

   ```batch
   helm repo update
   ```

3. Create the `tigera-operator` namespace.

   ```bash
   kubectl create namespace tigera-operator
   ```

4. Install version v3.32.1 of the Calico operator and custom resource definitions.

   ```batch
   helm install calico projectcalico/tigera-operator --version v3.32.1 --namespace tigera-operator
   ```

5. Patch the CNI type with value `Calico`.

   ```batch
   kubectl patch installation default --type='json' -p='[{"op": "replace", "path": "/spec/cni", "value": {"type":"Calico"} }]'
   ```

6. Finally, add nodes to the cluster.

   ```batch
   eksctl create nodegroup --cluster my-calico-cluster --node-type t3.medium --max-pods-per-node 100
   ```

<!-- /tabs -->

> **SUCCESS:** Without the `--max-pods-per-node` option above, EKS will limit the [number of pods based on node-type](https://github.com/awslabs/amazon-eks-ami/blob/main/nodeadm/internal/kubelet/eni-max-pods.txt). See `eksctl create nodegroup --help` for the full set of node group options.

## Next steps

**Required**

- [Install calicoctl command line tool](https://docs.tigera.io/calico/latest/operations/calicoctl/install.md)

**Recommended**

- [Get started with Kubernetes network policy](https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy.md)
- [Get started with Calico network policy](https://docs.tigera.io/calico/latest/network-policy/get-started/calico-policy/calico-network-policy.md)
- [Enable default deny for Kubernetes pods](https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-default-deny.md)
