github.com/cilium/cilium@v1.16.2/Documentation/network/lb-ipam.rst (about) 1 .. only:: not (epub or latex or html) 2 3 WARNING: You are looking at unreleased Cilium documentation. 4 Please use the official rendered version released here: 5 https://docs.cilium.io 6 7 .. _lb_ipam: 8 9 ******************************************** 10 LoadBalancer IP Address Management (LB IPAM) 11 ******************************************** 12 13 LB IPAM is a feature that allows Cilium to assign IP addresses to Services of 14 type ``LoadBalancer``. This functionality is usually left up to a cloud provider, 15 however, when deploying in a private cloud environment, these facilities are not 16 always available. 17 18 LB IPAM works in conjunction with features such as :ref:`bgp_control_plane` and :ref:`l2_announcements`. Where 19 LB IPAM is responsible for allocation and assigning of IPs to Service objects and 20 other features are responsible for load balancing and/or advertisement of these 21 IPs. 22 23 Use :ref:`bgp_control_plane` to advertise the IP addresses assigned by LB IPAM over BGP and :ref:`l2_announcements` to advertise them locally. 24 25 LB IPAM is always enabled but dormant. The controller is awoken when the first 26 IP Pool is added to the cluster. 27 28 .. _lb_ipam_pools: 29 30 Pools 31 ##### 32 33 LB IPAM has the notion of IP Pools which the administrator can create to tell 34 Cilium which IP ranges can be used to allocate IPs from. 35 36 A basic IP Pools with both an IPv4 and IPv6 range looks like this: 37 38 .. code-block:: yaml 39 40 apiVersion: "cilium.io/v2alpha1" 41 kind: CiliumLoadBalancerIPPool 42 metadata: 43 name: "blue-pool" 44 spec: 45 blocks: 46 - cidr: "10.0.10.0/24" 47 - cidr: "2004::0/64" 48 - start: "20.0.20.100" 49 stop: "20.0.20.200" 50 - start: "1.2.3.4" 51 52 After adding the pool to the cluster, it appears like so. 53 54 .. code-block:: shell-session 55 56 $ kubectl get ippools 57 NAME DISABLED CONFLICTING IPS AVAILABLE AGE 58 blue-pool false False 65788 2s 59 60 CIDRs, Ranges and reserved IPs 61 ------------------------------ 62 63 An IP pool can have multiple blocks of IPs. A block can be specified with CIDR 64 notation (<prefix>/<bits>) or a range notation with a start and stop IP. As 65 pictured in :ref:`lb_ipam_pools`. 66 67 When CIDRs are used to specify routable IP ranges, you might not want to allocate 68 the first and the last IP of a CIDR. Typically the first IP is the 69 "network address" and the last IP is the "broadcast address". In some networks 70 these IPs are not usable and they do not always play well with all network 71 equipment. By default, LB-IPAM uses all IPs in a given CIDR. 72 73 If you wish to reserve the first and last IPs of CIDRs, you can set the 74 ``.spec.allowFirstLastIPs`` field to ``No``. 75 76 This option is ignored for /32 and /31 IPv4 CIDRs and /128 and /127 IPv6 CIDRs 77 since these only have 1 or 2 IPs respectively. 78 79 This setting only applies to blocks specified with ``.spec.blocks[].cidr`` and not to 80 blocks specified with ``.spec.blocks[].start`` and ``.spec.blocks[].stop``. 81 82 .. warning:: 83 84 In v1.15, ``.spec.allowFirstLastIPs`` defaults to ``No``. This has changed to 85 ``Yes`` in v1.16. Please set this field explicitly if you rely on the field 86 being set to ``No``. 87 88 Service Selectors 89 ----------------- 90 91 IP Pools have an optional ``.spec.serviceSelector`` field which allows administrators 92 to limit which services can get IPs from which pools using a `label selector <https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/>`__. 93 The pool will allocate to any service if no service selector is specified. 94 95 .. code-block:: yaml 96 97 apiVersion: "cilium.io/v2alpha1" 98 kind: CiliumLoadBalancerIPPool 99 metadata: 100 name: "blue-pool" 101 spec: 102 blocks: 103 - cidr: "20.0.10.0/24" 104 serviceSelector: 105 matchExpressions: 106 - {key: color, operator: In, values: [blue, cyan]} 107 --- 108 apiVersion: "cilium.io/v2alpha1" 109 kind: CiliumLoadBalancerIPPool 110 metadata: 111 name: "red-pool" 112 spec: 113 blocks: 114 - cidr: "20.0.10.0/24" 115 serviceSelector: 116 matchLabels: 117 color: red 118 119 There are a few special purpose selector fields which don't match on labels but 120 instead on other metadata like ``.meta.name`` or ``.meta.namespace``. 121 122 =============================== =================== 123 Selector Field 124 ------------------------------- ------------------- 125 io.kubernetes.service.namespace ``.meta.namespace`` 126 io.kubernetes.service.name ``.meta.name`` 127 =============================== =================== 128 129 For example: 130 131 .. code-block:: yaml 132 133 apiVersion: "cilium.io/v2alpha1" 134 kind: CiliumLoadBalancerIPPool 135 metadata: 136 name: "blue-pool" 137 spec: 138 blocks: 139 - cidr: "20.0.10.0/24" 140 serviceSelector: 141 matchLabels: 142 "io.kubernetes.service.namespace": "tenant-a" 143 144 Conflicts 145 --------- 146 147 IP Pools are not allowed to have overlapping CIDRs. When an administrator does 148 create pools which overlap, a soft error is caused. The last added pool will be 149 marked as ``Conflicting`` and no further allocation will happen from that pool. 150 Therefore, administrators should always check the status of all pools after making 151 modifications. 152 153 For example, if we add 2 pools (``blue-pool`` and ``red-pool``) both with the same 154 CIDR, we will see the following: 155 156 .. code-block:: shell-session 157 158 $ kubectl get ippools 159 NAME DISABLED CONFLICTING IPS AVAILABLE AGE 160 blue-pool false False 254 25m 161 red-pool false True 254 11s 162 163 The reason for the conflict is stated in the status and can be accessed like so 164 165 .. code-block:: shell-session 166 167 $ kubectl get ippools/red-pool -o jsonpath='{.status.conditions[?(@.type=="cilium.io/PoolConflict")].message}' 168 Pool conflicts since CIDR '20.0.10.0/24' overlaps CIDR '20.0.10.0/24' from IP Pool 'blue-pool' 169 170 or 171 172 .. code-block:: shell-session 173 174 $ kubectl describe ippools/red-pool 175 Name: red-pool 176 #[...] 177 Status: 178 Conditions: 179 #[...] 180 Last Transition Time: 2022-10-25T14:09:05Z 181 Message: Pool conflicts since CIDR '20.0.10.0/24' overlaps CIDR '20.0.10.0/24' from IP Pool 'blue-pool' 182 Observed Generation: 1 183 Reason: cidr_overlap 184 Status: True 185 Type: cilium.io/PoolConflict 186 #[...] 187 188 Disabling a Pool 189 ----------------- 190 191 IP Pools can be disabled. Disabling a pool will stop LB IPAM from allocating 192 new IPs from the pool, but doesn't remove existing allocations. This allows 193 an administrator to slowly drain pool or reserve a pool for future use. 194 195 .. code-block:: yaml 196 197 apiVersion: "cilium.io/v2alpha1" 198 kind: CiliumLoadBalancerIPPool 199 metadata: 200 name: "blue-pool" 201 spec: 202 blocks: 203 - cidr: "20.0.10.0/24" 204 disabled: true 205 206 .. code-block:: shell-session 207 208 $ kubectl get ippools 209 NAME DISABLED CONFLICTING IPS AVAILABLE AGE 210 blue-pool true False 254 41m 211 212 Status 213 ------ 214 215 The IP Pool's status contains additional counts which can be used to monitor 216 the amount of used and available IPs. A machine parsable output can be obtained like so. 217 218 .. code-block:: shell-session 219 220 $ kubectl get ippools -o jsonpath='{.items[*].status.conditions[?(@.type!="cilium.io/PoolConflict")]}' | jq 221 { 222 "lastTransitionTime": "2022-10-25T14:08:55Z", 223 "message": "254", 224 "observedGeneration": 1, 225 "reason": "noreason", 226 "status": "Unknown", 227 "type": "cilium.io/IPsTotal" 228 } 229 { 230 "lastTransitionTime": "2022-10-25T14:08:55Z", 231 "message": "254", 232 "observedGeneration": 1, 233 "reason": "noreason", 234 "status": "Unknown", 235 "type": "cilium.io/IPsAvailable" 236 } 237 { 238 "lastTransitionTime": "2022-10-25T14:08:55Z", 239 "message": "0", 240 "observedGeneration": 1, 241 "reason": "noreason", 242 "status": "Unknown", 243 "type": "cilium.io/IPsUsed" 244 } 245 246 Or human readable output like so 247 248 .. code-block:: shell-session 249 250 $ kubectl describe ippools/blue-pool 251 Name: blue-pool 252 Namespace: 253 Labels: <none> 254 Annotations: <none> 255 API Version: cilium.io/v2alpha1 256 Kind: CiliumLoadBalancerIPPool 257 #[...] 258 Status: 259 Conditions: 260 #[...] 261 Last Transition Time: 2022-10-25T14:08:55Z 262 Message: 254 263 Observed Generation: 1 264 Reason: noreason 265 Status: Unknown 266 Type: cilium.io/IPsTotal 267 Last Transition Time: 2022-10-25T14:08:55Z 268 Message: 254 269 Observed Generation: 1 270 Reason: noreason 271 Status: Unknown 272 Type: cilium.io/IPsAvailable 273 Last Transition Time: 2022-10-25T14:08:55Z 274 Message: 0 275 Observed Generation: 1 276 Reason: noreason 277 Status: Unknown 278 Type: cilium.io/IPsUsed 279 280 Services 281 ######## 282 283 Any service with ``.spec.type=LoadBalancer`` can get IPs from any pool as long 284 as the IP Pool's service selector matches the service. 285 286 Lets say we add a simple service. 287 288 .. code-block:: yaml 289 290 apiVersion: v1 291 kind: Service 292 metadata: 293 name: service-red 294 namespace: example 295 labels: 296 color: red 297 spec: 298 type: LoadBalancer 299 ports: 300 - port: 1234 301 302 This service will appear like so. 303 304 .. code-block:: shell-session 305 306 $ kubectl -n example get svc 307 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 308 service-red LoadBalancer 10.96.192.212 <pending> 1234:30628/TCP 24s 309 310 The ExternalIP field has a value of ``<pending>`` which means no LB IPs have been assigned. 311 When LB IPAM is unable to allocate or assign IPs for the service, it will update the service 312 conditions in the status. 313 314 The service conditions can be checked like so: 315 316 .. code-block:: shell-session 317 318 $ kubectl -n example get svc/service-red -o jsonpath='{.status.conditions}' | jq 319 [ 320 { 321 "lastTransitionTime": "2022-10-06T13:40:48Z", 322 "message": "There are no enabled CiliumLoadBalancerIPPools that match this service", 323 "reason": "no_pool", 324 "status": "False", 325 "type": "io.cilium/lb-ipam-request-satisfied" 326 } 327 ] 328 329 After updating the service labels to match our ``blue-pool`` from before we see: 330 331 .. code-block:: shell-session 332 333 $ kubectl -n example get svc 334 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 335 service-red LoadBalancer 10.96.192.212 20.0.10.163 1234:30628/TCP 12m 336 337 $ kubectl -n example get svc/service-red -o jsonpath='{.status.conditions}' | jq 338 [ 339 { 340 "lastTransitionTime": "2022-10-06T13:40:48Z", 341 "message": "There are no enabled CiliumLoadBalancerIPPools that match this service", 342 "reason": "no_pool", 343 "status": "False", 344 "type": "io.cilium/lb-ipam-request-satisfied" 345 }, 346 { 347 "lastTransitionTime": "2022-10-06T13:52:55Z", 348 "message": "", 349 "reason": "satisfied", 350 "status": "True", 351 "type": "io.cilium/lb-ipam-request-satisfied" 352 } 353 ] 354 355 IPv4 / IPv6 families + policy 356 ----------------------------- 357 358 LB IPAM supports IPv4 and/or IPv6 in SingleStack or `DualStack <https://kubernetes.io/docs/concepts/services-networking/dual-stack/>`__ mode. 359 Services can use the ``.spec.ipFamilyPolicy`` and ``.spec.ipFamilies`` fields to change 360 the requested IPs. 361 362 If ``.spec.ipFamilyPolicy`` isn't specified, ``SingleStack`` mode is assumed. 363 If both IPv4 and IPv6 are enabled in ``SingleStack`` mode, an IPv4 address is allocated. 364 365 If ``.spec.ipFamilyPolicy`` is set to ``PreferDualStack``, LB IPAM will attempt to allocate 366 both an IPv4 and IPv6 address if both are enabled on the cluster. If only IPv4 or only IPv6 is 367 enabled on the cluster, the service is still considered "satisfied". 368 369 If ``.spec.ipFamilyPolicy`` is set to ``RequireDualStack`` LB IPAM will attempt to allocate 370 both an IPv4 and IPv6 address. The service is considered "unsatisfied" If IPv4 371 or IPv6 is disabled on the cluster. 372 373 The order of ``.spec.ipFamilies`` has no effect on LB IPAM but is significant for cluster IP 374 allocation which isn't handled by LB IPAM. 375 376 LoadBalancerClass 377 ----------------- 378 379 Kubernetes >= v1.24 supports `multiple load balancers <https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class>`_ 380 in the same cluster. Picking between load balancers is done with the ``.spec.loadBalancerClass`` field. 381 When LB IPAM is enabled it allocates and assigns IPs for services with 382 no load balancer class set. 383 384 LB IPAM only does IP allocation and doesn't provide load balancing services by itself. Therefore, 385 users should pick one of the following Cilium load balancer classes, all of which use LB IPAM 386 for allocation (if the feature is enabled): 387 388 =============================== ======================== 389 loadBalancerClass Feature 390 ------------------------------- ------------------------ 391 ``io.cilium/bgp-control-plane`` :ref:`bgp_control_plane` 392 ------------------------------- ------------------------ 393 ``io.cilium/l2-announcer`` :ref:`l2_announcements` 394 =============================== ======================== 395 396 If the ``.spec.loadBalancerClass`` is set to a class which isn't handled by Cilium's LB IPAM, 397 then Cilium's LB IPAM will ignore the service entirely, not even setting a condition in the status. 398 399 Requesting IPs 400 -------------- 401 402 Services can request specific IPs. The legacy way of doing so is via ``.spec.loadBalancerIP`` 403 which takes a single IP address. This method has been deprecated in k8s v1.24 but is supported 404 until its future removal. 405 406 The new way of requesting specific IPs is to use annotations, ``lbipam.cilium.io/ips`` in the case 407 of Cilium LB IPAM. This annotation takes a comma-separated list of IP addresses, allowing for 408 multiple IPs to be requested at once. 409 410 The service selector of the IP Pool still applies, requested IPs will not be allocated or assigned 411 if the services don't match the pool's selector. 412 413 Don't configure the annotation to request the first or last IP of an IP pool. They are reserved 414 for the network and broadcast addresses respectively. 415 416 .. code-block:: yaml 417 418 apiVersion: v1 419 kind: Service 420 metadata: 421 name: service-blue 422 namespace: example 423 labels: 424 color: blue 425 annotations: 426 "lbipam.cilium.io/ips": "20.0.10.100,20.0.10.200" 427 spec: 428 type: LoadBalancer 429 ports: 430 - port: 1234 431 432 .. code-block:: shell-session 433 434 $ kubectl -n example get svc 435 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 436 service-blue LoadBalancer 10.96.26.105 20.0.10.100,20.0.10.200 1234:30363/TCP 43s 437 438 Sharing Keys 439 ------------ 440 441 Services can share the same IP or set of IPs with other services. This is done by setting the ``lbipam.cilium.io/sharing-key`` annotation on the service. 442 Services that have the same sharing key annotation will share the same IP or set of IPs. The sharing key is a string that can be any value. 443 444 .. code-block:: yaml 445 446 apiVersion: v1 447 kind: Service 448 metadata: 449 name: service-blue 450 namespace: example 451 labels: 452 color: blue 453 annotations: 454 "lbipam.cilium.io/sharing-key": "1234" 455 spec: 456 type: LoadBalancer 457 ports: 458 - port: 1234 459 --- 460 apiVersion: v1 461 kind: Service 462 metadata: 463 name: service-red 464 namespace: example 465 labels: 466 color: red 467 annotations: 468 "lbipam.cilium.io/sharing-key": "1234" 469 spec: 470 type: LoadBalancer 471 ports: 472 - port: 2345 473 474 .. code-block:: shell-session 475 476 $ kubectl -n example get svc 477 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 478 service-blue LoadBalancer 10.96.26.105 20.0.10.100 1234:30363/TCP 43s 479 service-red LoadBalancer 10.96.26.106 20.0.10.100 2345:30131/TCP 43s 480 481 As long as the services do not have conflicting ports, they will be allocated the same IP. If the services have conflicting ports, they will be allocated different IPs, which will be added to the set of IPs belonging to the sharing key. 482 If a service has a sharing key and also requests a specific IP, the service will be allocated the requested IP and it will be added to the set of IPs belonging to that sharing key. 483 484 By default, sharing IPs across namespaces is not allowed. To allow sharing across a namespace, set the ``lbipam.cilium.io/sharing-cross-namespace`` annotation to the namespaces the service can be shared with. The value must be a comma-separated list of namespaces. The annotation must be present on both services. You can allow all namespaces with ``*``.