Skip to main content
Version: 3.28 (latest)

Multiple regions

If you use a multiple region deployment

of OpenStack, you can use Calico to facilitate defining security policy between VMs in different regions.


The way this works is that all of the regions share the same Calico etcd datastore, but each region uses a different Calico namespace. For example, when the Neutron server for region "xyz-east" generates Calico WorkloadEndpoint and NetworkPolicy data automatically from OpenStack VMs and security groups, it writes that into the Calico datastore in the namespace "openstack-region-xyz-east".

Because all the information is in the same Calico datastore, you can then define Calico policy for communication between VMs in different regions.


There isn't currently any simple way to define policy between different regions using only the OpenStack API. When a security group specifies a set of remote peers (i.e. that are allowed to send or prevented from sending a kind of traffic) it can do that either as an IP prefix or as a 'remote' security group ID, meaning the VMs that belong to that security group. But a 'remote' security group ID has to be in the same region as where the overall security group is being defined, and can only identify VMs within that same region.


To install a multi-region OpenStack deployment with Calico, proceed region-by-region and follow the normal procedure for adding Calico to an OpenStack region , except for these points:

  1. Only install a single etcd database (instead of one per region) and configure all of the regions to use that as their Calico datastore.

  2. In /etc/calico/felix.cfg on each compute host, add

    OpenStackRegion = <region>

    where <region> is the name of the region that that compute host belongs to.

  3. In /etc/neutron/neutron.conf on each controller and compute node, add

    openstack_region = <region>

    where <region> is the name of the region that that node belongs to.


the value specified for OpenStackRegion and openstack_region must be a string of lower case alphanumeric characters or '-', starting and ending with an alphanumeric character.


If the Felix and Neutron values here do not match, OpenStack will not be able to launch any VMs in that region, because the Neutron server for the region will think that there are no working compute nodes.

Configuring OpenStack

You should now create networks in your OpenStack regions as normal. e.g.

 neutron net-create --shared calico
neutron subnet-create --gateway --enable-dhcp --ip-version 4 --name calico-v4 calico

that Calico networking provides a flat L3 network, so subnets across all regions must not overlap. For example, having in one region and in another would be fine, but and would not.

Configuring cross-region policy

Suppose that:

  • you have two regions

  • you have a set of VMs in one region belonging to security group a7734e61-b545-452d-a3cd-0189cbd9747a

  • you have a set of VMs in another region belonging to security group 85cc3048-abc3-43cc-89b3-377341426ac5

  • you want to allow the second set of VMs to connect to port 80 of the first set.

You need to have calicoctl installed and configured for your cluster . Once that is in place, you could achieve the desired connectivity by using calicoctl to configure this Calico policy:

calicoctl apply -f - <<EOF
kind: GlobalNetworkPolicy
name: allow-tcp-80
selector: "has("
- Ingress
- action: Allow
protocol: TCP
selector: "has("
- 80

In words, this says that connections to port 80 of the VMs with the label for the a7734e61... security group are allowed from VMs (in any region) with the label for the 85cc3048... security group.

In the selector fields, you can use any of the labels that Calico adds to OpenStack VM endpoints, to identify the set of VMs that the policy should apply to, and the set of allowed (or denied) clients. Here are some more examples of selectors to get you started:

  • To select all VMs in a region named "one": == 'openstack-region-one'.

  • To select all VMs that are in a security group named "production", in any region: has(

You can also use nets or notNets instead of the selector field under source or destination, to identify clients by IP address.