|
| 1 | +--- |
| 2 | +layout: blog |
| 3 | +title: "Kubernetes 1.24: Avoid Collisions Assigning IP Addresses to Services" |
| 4 | +date: 2022-05-23 |
| 5 | +slug: service-ip-dynamic-and-static-allocation |
| 6 | +--- |
| 7 | + |
| 8 | +**Author:** Antonio Ojea (Red Hat) |
| 9 | + |
| 10 | + |
| 11 | +In Kubernetes, [Services](/docs/concepts/services-networking/service/) are an abstract way to expose |
| 12 | +an application running on a set of Pods. Services |
| 13 | +can have a cluster-scoped virtual IP address (using a Service of `type: ClusterIP`). |
| 14 | +Clients can connect using that virtual IP address, and Kubernetes then load-balances traffic to that |
| 15 | +Service across the different backing Pods. |
| 16 | + |
| 17 | +## How Service ClusterIPs are allocated? |
| 18 | + |
| 19 | +A Service `ClusterIP` can be assigned: |
| 20 | + |
| 21 | +_dynamically_ |
| 22 | +: the cluster's control plane automatically picks a free IP address from within the configured IP range for `type: ClusterIP` Services. |
| 23 | + |
| 24 | +_statically_ |
| 25 | +: you specify an IP address of your choice, from within the configured IP range for Services. |
| 26 | + |
| 27 | +Across your whole cluster, every Service `ClusterIP` must be unique. |
| 28 | +Trying to create a Service with a `ClusterIP` that has already |
| 29 | +been allocated will return an error. |
| 30 | + |
| 31 | +## Why do you need to reserve Service Cluster IPs? |
| 32 | + |
| 33 | +Because you may want to have Services running in well-known IP addresses, so other components and |
| 34 | +users in the cluster can use them. |
| 35 | + |
| 36 | +The best example is the DNS Service for the cluster. Some Kubernetes installers assign the 10th address from |
| 37 | +the Service IP range to the DNS service. Assuming you configured your cluster with Service IP range |
| 38 | +10.96.0.0/16 and you want your DNS Service IP to be 10.96.0.10, you'd have to create a Service like |
| 39 | +this: |
| 40 | + |
| 41 | +```yaml |
| 42 | +apiVersion: v1 |
| 43 | +kind: Service |
| 44 | +metadata: |
| 45 | + labels: |
| 46 | + k8s-app: kube-dns |
| 47 | + kubernetes.io/cluster-service: "true" |
| 48 | + kubernetes.io/name: CoreDNS |
| 49 | + name: kube-dns |
| 50 | + namespace: kube-system |
| 51 | +spec: |
| 52 | + clusterIP: 10.96.0.10 |
| 53 | + ports: |
| 54 | + - name: dns |
| 55 | + port: 53 |
| 56 | + protocol: UDP |
| 57 | + targetPort: 53 |
| 58 | + - name: dns-tcp |
| 59 | + port: 53 |
| 60 | + protocol: TCP |
| 61 | + targetPort: 53 |
| 62 | + selector: |
| 63 | + k8s-app: kube-dns |
| 64 | + type: ClusterIP |
| 65 | +``` |
| 66 | +
|
| 67 | +but as I explained before, the IP address 10.96.0.10 has not been reserved; if other Services are created |
| 68 | +before or in parallel with dynamic allocation, there is a chance they can allocate this IP, hence, |
| 69 | +you will not be able to create the DNS Service because it will fail with a conflict error. |
| 70 | +
|
| 71 | +## How can you avoid Service ClusterIP conflicts? {#avoid-ClusterIP-conflict} |
| 72 | +
|
| 73 | +In Kubernetes 1.24, you can enable a new feature gate `ServiceIPStaticSubrange`. |
| 74 | +Turning this on allows you to use a different IP |
| 75 | +allocation strategy for Services, reducing the risk of collision. |
| 76 | + |
| 77 | +The `ClusterIP` range will be divided, based on the formula `min(max(16, cidrSize / 16), 256)`, |
| 78 | +described as _never less than 16 or more than 256 with a graduated step between them_. |
| 79 | + |
| 80 | +Dynamically IP assignment will use the upper band by default, once this has been exhausted it will |
| 81 | +use the lower range. This will allow users to use static allocations on the lower band with a low |
| 82 | +risk of collision. |
| 83 | + |
| 84 | +Examples: |
| 85 | + |
| 86 | +#### Service IP CIDR block: 10.96.0.0/24 |
| 87 | + |
| 88 | +Range Size: 2<sup>8</sup> - 2 = 254 |
| 89 | +Band Offset: `min(max(16,256/16),256)` = `min(16,256)` = 16 |
| 90 | +Static band start: 10.96.0.1 |
| 91 | +Static band end: 10.96.0.16 |
| 92 | +Range end: 10.96.0.254 |
| 93 | + |
| 94 | +{{< mermaid >}} |
| 95 | +pie showData |
| 96 | + title 10.96.0.0/24 |
| 97 | + "Static" : 16 |
| 98 | + "Dynamic" : 238 |
| 99 | +{{< /mermaid >}} |
| 100 | + |
| 101 | +#### Service IP CIDR block: 10.96.0.0/20 |
| 102 | + |
| 103 | +Range Size: 2<sup>12</sup> - 2 = 4094 |
| 104 | +Band Offset: `min(max(16,256/16),256)` = `min(256,256)` = 256 |
| 105 | +Static band start: 10.96.0.1 |
| 106 | +Static band end: 10.96.1.0 |
| 107 | +Range end: 10.96.15.254 |
| 108 | + |
| 109 | +{{< mermaid >}} |
| 110 | +pie showData |
| 111 | + title 10.96.0.0/20 |
| 112 | + "Static" : 256 |
| 113 | + "Dynamic" : 3838 |
| 114 | +{{< /mermaid >}} |
| 115 | + |
| 116 | +#### Service IP CIDR block: 10.96.0.0/16 |
| 117 | + |
| 118 | +Range Size: 2<sup>16</sup> - 2 = 65534 |
| 119 | +Band Offset: `min(max(16,65536/16),256)` = `min(4096,256)` = 256 |
| 120 | +Static band start: 10.96.0.1 |
| 121 | +Static band ends: 10.96.1.0 |
| 122 | +Range end: 10.96.255.254 |
| 123 | + |
| 124 | +{{< mermaid >}} |
| 125 | +pie showData |
| 126 | + title 10.96.0.0/16 |
| 127 | + "Static" : 256 |
| 128 | + "Dynamic" : 65278 |
| 129 | +{{< /mermaid >}} |
| 130 | + |
| 131 | +## Get involved with SIG Network |
| 132 | + |
| 133 | +The current SIG-Network [KEPs](https://github.com/orgs/kubernetes/projects/10) and [issues](https://github.com/kubernetes/kubernetes/issues?q=is%3Aopen+is%3Aissue+label%3Asig%2Fnetwork) on GitHub illustrate the SIG’s areas of emphasis. |
| 134 | + |
| 135 | +[SIG-Network meetings](https://github.com/kubernetes/community/tree/master/sig-network) are a friendly, welcoming venue for you to connect with the community and share your ideas. |
| 136 | +Looking forward to hearing from you! |
| 137 | + |
0 commit comments