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 ``*``.