---
title: "Configure IP pools"
description: "Calico the hard way — define IP pools that govern which address ranges Calico Open Source assigns to pods and services."
product: "Calico Open Source"
version: "3.32 (latest)"
section: "Installing and upgrading"
canonical_url: "https://docs.tigera.io/calico/latest/getting-started/kubernetes/hardway/configure-ip-pools"
---

# Configure IP pools

A *workload* is a container or VM that Calico handles the virtual networking for. In Kubernetes, workloads are pods. A **workload endpoint** is the virtual network interface a workload uses to connect to the Calico network.

**IP pools** are ranges of IP addresses that Calico uses for **workload endpoints**.

When we stood up the Kubernetes cluster, we set the pod CIDR, which is the range of IP addresses Kubernetes thinks the pods should be in. Many Kubernetes components use this setting to determine if an IP belongs to a pod, so you normally want all IP pools you configure to be subsets of the pod CIDR.

Let's define two IP pools for use in this cluster. You can have a production-ready Calico install with only a single pool, but we define two so that we can show advanced networking later in this guide.

```bash
cat > pool1.yaml <<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: pool1
spec:
  cidr: 192.168.0.0/18
  ipipMode: Never
  natOutgoing: true
  disabled: false
  nodeSelector: all()
EOF
```

The pod CIDR was `192.168.0.0/16`. The `/16` means 16 bits of a 32-bit IPv4 address is the fixed prefix, therefore 16 bits are freely variable within the CIDR, or about 64K addresses. For our first IP pool, we define the prefix `192.168.0.0/18`, leaving only 14 bits free, or about 16K addresses for pods. This is enough for a very large Kubernetes cluster, and it still leaves a lot of room in the pod CIDR if we want to create some more IP pools.

Let's define a second pool right now.

```bash
cat > pool2.yaml <<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: pool2
spec:
  cidr: 192.168.192.0/19
  ipipMode: Never
  natOutgoing: true
  disabled: true
  nodeSelector: all()
EOF
```

In this second pool, we set `disabled` to `true`, meaning that Calico will not create new pods with addresses in the pool but will still recognize pods with these addresses as part of the Calico network. Later, in the [test networking](https://docs.tigera.io/calico/latest/getting-started/kubernetes/hardway/test-networking.md) lab, we will enable this pool and demonstrate how to control which pools your pods are assigned addresses from.

The `nodeSelector` is a label selector which determines which nodes use the pool. They are both set to `all()` meaning all nodes can use the pools.

Add these pools to Calico

```bash
calicoctl create -f pool1.yaml
calicoctl create -f pool2.yaml
```

Verify the pools are created by

```bash
calicoctl get ippools
```

You should see output similar to

```text
NAME    CIDR               SELECTOR
pool1   192.168.0.0/18     all()
pool2   192.168.192.0/19   all()
```

## Next

[Install CNI plugin](https://docs.tigera.io/calico/latest/getting-started/kubernetes/hardway/install-cni-plugin.md)
