Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoadBalancer IPAM #1788

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions calico/networking/configuring/advertise-service-ips.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -199,28 +199,30 @@

For help see, [BGP configuration resource](../../reference/resources/bgpconfig.mdx).

Service LoadBalancer address allocation is outside the current scope of $[prodname], but can be implemented with an external controller.
You can build your own, or use a third-party implementation like the MetalLB project.
$[prodname] IPAM can manage address allocation for Service LoadBalancer with LoadBalancerController. To enable $[prodname] IPAM to start managing addresses to Service LoadBalancer set up an IPPool for LoadBalancer.

Check failure on line 202 in calico/networking/configuring/advertise-service-ips.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/configuring/advertise-service-ips.mdx", "range": {"start": {"line": 202, "column": 3}}}, "severity": "ERROR"}

Check failure on line 202 in calico/networking/configuring/advertise-service-ips.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/configuring/advertise-service-ips.mdx", "range": {"start": {"line": 202, "column": 114}}}, "severity": "ERROR"}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Service LoadBalancer: change to LoadBalancer services. Everywhere.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is there a nuance here that I'm missing?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether this section (Advertise service load balancer IP addresses) should have a prerequisite that covers everything in your main doc for creating a loadbalancer? What do you think?


To install the MetalLB controller for allocating addresses, perform the following steps.

1. Follow [the MetalLB documentation](https://metallb.universe.tf/installation/#installation-by-manifest) to install the `metallb-system/controller` resources.

However, do not install the `metallb-system/speaker` component. The speaker component also attempts to establish BGP sessions on the node, and will conflict with Calico.
```bash
kubectl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: loadBalancerIPPool
spec:
cidr: 192.210.0.0/20
blockSize: 24
natOutgoing: true
disabled: false
assignmentMode: Automatic
allowedUses:
- LoadBalancer
EOF
```

1. Configure MetalLB to provision addresses by creating the following IPAddressPool, replacing `x.x.x.x/16` with the CIDR given to $[prodname] in the steps above. Please note IPAddressPool requires Metallb `0.13+`.
For more information see, [LoadBalancer IP address management](../ipam/service-loadbalancer.mdx)

```bash
kubectl create -f - <<EOF
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- x.x.x.x/16
EOF
```
:::note
If you have previously used MetalLB for Service LoadBalancer address management and wish to continue using it, do not create Calico IPPool for LoadBalancer.
:::
Comment on lines +223 to +225
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be more generic? I know we documented MetalLB, but surely this applies to any other load balancers?

Do we need to describe a migration path for MetalLB users or for other LB configurations?


### Exclude certain nodes from advertisement

Expand Down
1 change: 1 addition & 0 deletions calico/networking/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The $[prodname] network plugins provide a range of networking options to fit you
<DocCardLink docId='networking/ipam/migrate-pools' />
<DocCardLink docId='networking/ipam/change-block-size' />
<DocCardLink docId='networking/ipam/legacy-firewalls' />
<DocCardLink docId='networking/ipam/service-loadbalancer' />
</DocCardLinkLayout>


Expand Down
209 changes: 209 additions & 0 deletions calico/networking/ipam/service-loadbalancer.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
description: Create LoadBalancer
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# LoadBalancer IP address management
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got questions for this page in a separate doc. Will follow up with you directly.


## Understanding $[prodname] LoadBalancer IP address management

Check failure on line 10 in calico/networking/ipam/service-loadbalancer.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/ipam/service-loadbalancer.mdx", "range": {"start": {"line": 10, "column": 20}}}, "severity": "ERROR"}

You might want to utilize Service LoadBalancer in your cluster to provide stable long-lasting IP address to access your deployed application.
$[prodname] can help you with providing and managing IP addresses to your Service LoadBalancers in your cluster. $[prodname] comes with LoadBalancer IPAM deployed as part of $[prodname] Kube-controllers.

Check failure on line 13 in calico/networking/ipam/service-loadbalancer.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/ipam/service-loadbalancer.mdx", "range": {"start": {"line": 13, "column": 3}}}, "severity": "ERROR"}

Check failure on line 13 in calico/networking/ipam/service-loadbalancer.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/ipam/service-loadbalancer.mdx", "range": {"start": {"line": 13, "column": 116}}}, "severity": "ERROR"}

Check failure on line 13 in calico/networking/ipam/service-loadbalancer.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/ipam/service-loadbalancer.mdx", "range": {"start": {"line": 13, "column": 177}}}, "severity": "ERROR"}

## Configure $[prodname] IP address management for Service LoadBalancer

Check failure on line 15 in calico/networking/ipam/service-loadbalancer.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/ipam/service-loadbalancer.mdx", "range": {"start": {"line": 15, "column": 16}}}, "severity": "ERROR"}

### Before you begin...

Ensure that you have a cluster with $[prodname] installed, enabled bgp, external node configured as bgp peer and $[prodname] kube-controllers configured.

Check failure on line 19 in calico/networking/ipam/service-loadbalancer.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'prodname'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'prodname'?", "location": {"path": "calico/networking/ipam/service-loadbalancer.mdx", "range": {"start": {"line": 19, "column": 39}}}, "severity": "ERROR"}

Check failure on line 19 in calico/networking/ipam/service-loadbalancer.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'BGP' instead of 'bgp'. Raw Output: {"message": "[Vale.Terms] Use 'BGP' instead of 'bgp'.", "location": {"path": "calico/networking/ipam/service-loadbalancer.mdx", "range": {"start": {"line": 19, "column": 68}}}, "severity": "ERROR"}

For this example we will use LoadBalancer kube-controller assignIPs set to AllServices. To verify your LoadBalancer kube-controller settings you can check the output of the following command.

```bash
kubectl get kubecontrollersconfiguration default -o "jsonpath={.spec.controllers.loadBalancer}"
```

If the output is not ```{"assignIPs":"AllServices"}``` you can patch your LoadBalancer kube-controller configuration by running the following command.

```bash
kubectl patch kubecontrollersconfiguration default --patch '{"spec": {"controllers":{"loadBalancer":{"AssignIPs": "AllService"}}}}'
```

In this example we will use nginx deployment to connect our Service LoadBalancer to. If you wish to follow along you can create the deployment with the following configuration.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 4
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
```

### Adding IP Pool for Service LoadBalancer

For $[prodname] to be able to manage Service LoadBalancer IP addresses we need to create an IP Pool specifically to be used by LoadBalancer kube-controller. $[prodname] will then use that IP Pool to assign addresses from.

Bellow is example IP Pool

```yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: loadbalancerIPPool
spec:
cidr: 192.210.0.0/20
blockSize: 24
natOutgoing: true
disabled: false
assignmentMode: Automatic
allowedUses:
- LoadBalancer
```

:::note

You can create multiple IP Pools with allowedUses LoadBalancer as long as there are no CIDR conflicts. By setting assignmentMode to Manual you can reserve the IP Pool for manual assignments only. Explore more about [manual assignment](#loadbalancer-ip-address-assignment)

:::

### Creating Service LoadBalancer

We will create a Service LoadBalancer that connects to our nginx deployment. Calico IPAM will automatically detect that a new Service LoadBalancer has been created and assign an IP address from available IP Pool.

```yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-loadbalancer
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
name: default
type: LoadBalancer
```

After creating the Service LoadBalancer you can verify that IP address has been assigned. To do this you can run

```bash
kubectl describe service nginx-loadbalancer
```

In the output you can see that LoadBalancer Ingress IP address has been assigned, take a note of this IP address.

```bash
Name: nginx-loadbalancer
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.99.228.103
IPs: 10.99.228.103
LoadBalancer Ingress: 192.210.10.1 (VIP)
Port: default 80/TCP
TargetPort: 80/TCP
NodePort: default 32002/TCP
Endpoints: 192.168.165.134:80,192.168.21.198:80,192.168.238.133:80 + 1 more...
Session Affinity: None
External Traffic Policy: Cluster
Internal Traffic Policy: Cluster
Events: <none>
```

### Advertise Service LoadBalancer IP address

In order to be able to reach our application via the Service LoadBalancer Ingress IP address we have to advertise the LoadBalancer CIDR. You can find out more information at [Advertising Kubernetes service IP addresses](../../networking/configuring/advertise-service-ips.mdx)

You can patch the bgp configuration to advertise the IP Pool CIDR

```bash
calicoctl patch bgpconfig default --patch '{"spec": {"serviceLoadBalancerIPs": [{"cidr": "192.210.0.0/20"}]}}'
```

We should now be able to access our application behind the Service LoadBalancer by the IP address assigned by $[prodname] from our external bgp peer.

Run the following command to check that our nginx deployment is reachable:

```bash
curl 192.210.10.1
```

If your output contains the following, you have successfully set up Service LoadBalancer with $[prodname]

```
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.
```

## LoadBalancer IP address assignment

There are cases where you would like to be more specific about what IP address $[prodname] assigns to your LoadBalancer. With annotations, you can specify how IP address should be assigned to that Service. The annotations can be added and removed as needed during the lifetime of the Service. When you remove an annotation $[prodname] will check if the assigned IP is still valid and potentially assign a new one.

### Specify IP Pool

#### IPv4 Pool

Annotate the Service with projectcalico.org/ipv4pools to assign IP address from the selected IP Pools. You can specify multiple IP Pools in this annotation, $[prodname] will pick an available IP address to assign.

```
"projectcalico.org/ipv4pools": '["loadBalancerIPv4Pool"]'
```

#### IPv6 Pool

Annotate the Service with projectcalico.org/ipv6pools to assign IP address from the selected IP Pools. You can specify multiple IP Pools in this annotation, $[prodname] will pick an available IP address to assign.

```
"projectcalico.org/ipv6pools": '["loadBalancerIPv6Pool"]'
```

:::note

In dual-stack environment you don't have to specify both annotations. If IP Pool was not specified for IP family, $[prodname] will automatically assign available IP address from available IP Pool

:::

### Specifying IP address

Annotate the Service with projectcalico.org/loadBalancerIPs to assign specific IP address. The address must be available otherwise $[prodname] will not be able to assign the address. Currently you can only specify one IPv4 and one IPv6 address at the same time.

```
"projectcalico.org/loadBalancerIPs": '["x.x.x.x"]'
```

:::note

If Service contains "projectcalico.org/loadBalancerIPs" annotation and either "projectcalico.org/ipv6pools" or "projectcalico.org/ipv4pools" are present, $[prodname] will favour projectcalico.org/loadBalancerIPs annotation and try to assign that IP address. There is no fall back to an IP Pool if the specified address is not available.

:::

### Manage LoadBalancer kube-controller assignment mode

In certain cases you might not wish for $[prodname] to automatically assign IP addresses to your Service LoadBalancers. This can be useful in case you have multiple Service IPAM solutions in your cluster.
LoadBalancer kube-controller is able to operate in two distinct modes ```Automatic``` in which $[prodname] assigns IP address to each Service LoadBalancer in your cluster and ```RequestedServicesOnly``` in which $[prodname] only assigns IP addresses to Service LoadBalancer with annotations mentioned above.
You can change the mode at any point, but note that when switching to ```RequestedServicesOnly``` will unassign any addresses from Services that do not contain the above annotations.

```bash
kubectl patch kubecontrollersconfiguration default --patch '{"spec": {"controllers":{"loadBalancer":{"AssignIPs": "RequestedServicesOnly"}}}}'
```
21 changes: 14 additions & 7 deletions calico/reference/calicoctl/ipam/check.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,25 @@ Usage:
calicoctl ipam check [--config=<CONFIG>] [--show-all-ips] [--show-problem-ips] [-o <FILE>]

Options:
-h --help Show this screen.
-o --output=<FILE> Path to output report file.
--show-all-ips Print all IPs that are checked.
--show-problem-ips Print all IPs that are leaked or not allocated properly.
-c --config=<CONFIG> Path to the file containing connection configuration in
YAML or JSON format.
[default: /etc/calico/calicoctl.cfg]
-h --help Show this screen.
-o --output=<FILE> Path to output report file.
--show-all-ips Print all IPs that are checked.
--show-problem-ips Print all IPs that are leaked or not allocated properly.
-c --config=<CONFIG> Path to the file containing connection configuration in
YAML or JSON format.
[default: /etc/calico/calicoctl.cfg]
--kubeconfig=<KUBECONFIG> Path to Kubeconfig file

Description:
The ipam check command checks the integrity of the IPAM datastructures against Kubernetes.
```

:::note

When using calicoctl in etcd mode, Kubeconfig path is required. It can be specified either as env KUBECONFIG variable or by using the --kubeconfig parameter.

:::
Comment on lines +33 to +37
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note seems a bit out of place. Is there an error message for this situation? I think that would be sufficient, probably the ideal place for this information.

If that's not possible, then we'd want to explain a little better what's happening here. Specifically:
Sounds like it's calicoctl, rather than Calico, that is in etcd mode. Is that right?

For the second sentence, I'd try something like:

To specify the path to your kubeconfig file, you can:
* Add the path to your `KUBECONFIG` environment variable.
* Define the path by using the `--kubeconfig` flag.


### Examples

Example workflow for checking consistency and releasing leaked addresses.
Expand Down
Loading
Loading