Merge pull request #49537 from windsonsea/netwen

Tweak two network tasks: validate-dual-stack and extend-service-ip-ranges
pull/49540/head
Kubernetes Prow Robot 2025-01-23 05:12:58 -08:00 committed by GitHub
commit abdc457a7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 77 additions and 33 deletions

View File

@ -24,14 +24,15 @@ This document shares how to extend the existing Service IP range assigned to a c
## API ## API
Kubernetes clusters with kube-apiservers that have enabled the `MultiCIDRServiceAllocator` Kubernetes clusters with kube-apiservers that have enabled the `MultiCIDRServiceAllocator`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) and have the `networking.k8s.io/v1beta1` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) and have the
API group active, `networking.k8s.io/v1beta1` API group active, will create a ServiceCIDR object that takes
will create a ServiceCIDR object that takes the well-known name `kubernetes`, and that specifies an IP address range the well-known name `kubernetes`, and that specifies an IP address range
based on the value of the `--service-cluster-ip-range` command line argument to kube-apiserver. based on the value of the `--service-cluster-ip-range` command line argument to kube-apiserver.
```sh ```sh
kubectl get servicecidr kubectl get servicecidr
``` ```
``` ```
NAME CIDRS AGE NAME CIDRS AGE
kubernetes 10.96.0.0/28 17d kubernetes 10.96.0.0/28 17d
@ -44,6 +45,7 @@ cluster IP address.
```sh ```sh
kubectl get service kubernetes kubectl get service kubernetes
``` ```
``` ```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
@ -54,26 +56,32 @@ The default Service, in this case, uses the ClusterIP 10.96.0.1, that has the co
```sh ```sh
kubectl get ipaddress 10.96.0.1 kubectl get ipaddress 10.96.0.1
``` ```
``` ```
NAME PARENTREF NAME PARENTREF
10.96.0.1 services/default/kubernetes 10.96.0.1 services/default/kubernetes
``` ```
The ServiceCIDRs are protected with {{<glossary_tooltip text="finalizers" term_id="finalizer">}}, to avoid leaving Service ClusterIPs orphans; The ServiceCIDRs are protected with {{<glossary_tooltip text="finalizers" term_id="finalizer">}},
the finalizer is only removed if there is another subnet that contains the existing IPAddresses or to avoid leaving Service ClusterIPs orphans; the finalizer is only removed if there is another subnet
there are no IPAddresses belonging to the subnet. that contains the existing IPAddresses or there are no IPAddresses belonging to the subnet.
## Extend the number of available IPs for Services ## Extend the number of available IPs for Services
There are cases that users will need to increase the number addresses available to Services, previously, increasing the Service range was a disruptive operation that could also cause data loss. With this new feature users only need to add a new ServiceCIDR to increase the number of available addresses. There are cases that users will need to increase the number addresses available to Services,
previously, increasing the Service range was a disruptive operation that could also cause data loss.
With this new feature users only need to add a new ServiceCIDR to increase the number of available addresses.
### Adding a new ServiceCIDR ### Adding a new ServiceCIDR
On a cluster with a 10.96.0.0/28 range for Services, there is only 2^(32-28) - 2 = 14 IP addresses available. The `kubernetes.default` Service is always created; for this example, that leaves you with only 13 possible Services. On a cluster with a 10.96.0.0/28 range for Services, there is only 2^(32-28) - 2 = 14
IP addresses available. The `kubernetes.default` Service is always created; for this example,
that leaves you with only 13 possible Services.
```sh ```sh
for i in $(seq 1 13); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done for i in $(seq 1 13); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
``` ```
``` ```
10.96.0.11 10.96.0.11
10.96.0.5 10.96.0.5
@ -104,6 +112,7 @@ spec:
- 10.96.0.0/24 - 10.96.0.0/24
EOF EOF
``` ```
``` ```
servicecidr.networking.k8s.io/newcidr1 created servicecidr.networking.k8s.io/newcidr1 created
``` ```
@ -113,6 +122,7 @@ and this will allow you to create new Services with ClusterIPs that will be pick
```sh ```sh
for i in $(seq 13 16); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done for i in $(seq 13 16); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
``` ```
``` ```
10.96.0.48 10.96.0.48
10.96.0.200 10.96.0.200
@ -127,6 +137,7 @@ You cannot delete a ServiceCIDR if there are IPAddresses that depend on the Serv
```sh ```sh
kubectl delete servicecidr newcidr1 kubectl delete servicecidr newcidr1
``` ```
``` ```
servicecidr.networking.k8s.io "newcidr1" deleted servicecidr.networking.k8s.io "newcidr1" deleted
``` ```
@ -136,7 +147,8 @@ Kubernetes uses a finalizer on the ServiceCIDR to track this dependent relations
```sh ```sh
kubectl get servicecidr newcidr1 -o yaml kubectl get servicecidr newcidr1 -o yaml
``` ```
```
```yaml
apiVersion: networking.k8s.io/v1beta1 apiVersion: networking.k8s.io/v1beta1
kind: ServiceCIDR kind: ServiceCIDR
metadata: metadata:
@ -161,12 +173,12 @@ status:
type: Ready type: Ready
``` ```
By removing the Services containing the IP addresses that are blocking the deletion of the ServiceCIDR By removing the Services containing the IP addresses that are blocking the deletion of the ServiceCIDR
```sh ```sh
for i in $(seq 13 16); do kubectl delete service "test-$i" ; done for i in $(seq 13 16); do kubectl delete service "test-$i" ; done
``` ```
``` ```
service "test-13" deleted service "test-13" deleted
service "test-14" deleted service "test-14" deleted
@ -180,6 +192,7 @@ so that the ServiceCIDR that was pending deletion will actually be removed.
```sh ```sh
kubectl get servicecidr newcidr1 kubectl get servicecidr newcidr1
``` ```
``` ```
Error from server (NotFound): servicecidrs.networking.k8s.io "newcidr1" not found Error from server (NotFound): servicecidrs.networking.k8s.io "newcidr1" not found
``` ```

View File

@ -11,12 +11,12 @@ content_type: task
<!-- overview --> <!-- overview -->
This document shares how to validate IPv4/IPv6 dual-stack enabled Kubernetes clusters. This document shares how to validate IPv4/IPv6 dual-stack enabled Kubernetes clusters.
## {{% heading "prerequisites" %}} ## {{% heading "prerequisites" %}}
* Provider support for dual-stack networking (Cloud provider or otherwise must be able to
* Provider support for dual-stack networking (Cloud provider or otherwise must be able to provide Kubernetes nodes with routable IPv4/IPv6 network interfaces) provide Kubernetes nodes with routable IPv4/IPv6 network interfaces)
* A [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) that supports dual-stack networking. * A [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
that supports dual-stack networking.
* [Dual-stack enabled](/docs/concepts/services-networking/dual-stack/) cluster * [Dual-stack enabled](/docs/concepts/services-networking/dual-stack/) cluster
{{< version-check >}} {{< version-check >}}
@ -25,29 +25,36 @@ This document shares how to validate IPv4/IPv6 dual-stack enabled Kubernetes clu
While you can validate with an earlier version, the feature is only GA and officially supported since v1.23. While you can validate with an earlier version, the feature is only GA and officially supported since v1.23.
{{< /note >}} {{< /note >}}
<!-- steps --> <!-- steps -->
## Validate addressing ## Validate addressing
### Validate node addressing ### Validate node addressing
Each dual-stack Node should have a single IPv4 block and a single IPv6 block allocated. Validate that IPv4/IPv6 Pod address ranges are configured by running the following command. Replace the sample node name with a valid dual-stack Node from your cluster. In this example, the Node's name is `k8s-linuxpool1-34450317-0`: Each dual-stack Node should have a single IPv4 block and a single IPv6 block allocated.
Validate that IPv4/IPv6 Pod address ranges are configured by running the following command.
Replace the sample node name with a valid dual-stack Node from your cluster. In this example,
the Node's name is `k8s-linuxpool1-34450317-0`:
```shell ```shell
kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .spec.podCIDRs}}{{printf "%s\n" .}}{{end}}' kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .spec.podCIDRs}}{{printf "%s\n" .}}{{end}}'
``` ```
``` ```
10.244.1.0/24 10.244.1.0/24
2001:db8::/64 2001:db8::/64
``` ```
There should be one IPv4 block and one IPv6 block allocated. There should be one IPv4 block and one IPv6 block allocated.
Validate that the node has an IPv4 and IPv6 interface detected. Replace node name with a valid node from the cluster. In this example the node name is `k8s-linuxpool1-34450317-0`: Validate that the node has an IPv4 and IPv6 interface detected.
Replace node name with a valid node from the cluster.
In this example the node name is `k8s-linuxpool1-34450317-0`:
```shell ```shell
kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .status.addresses}}{{printf "%s: %s\n" .type .address}}{{end}}' kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .status.addresses}}{{printf "%s: %s\n" .type .address}}{{end}}'
``` ```
``` ```
Hostname: k8s-linuxpool1-34450317-0 Hostname: k8s-linuxpool1-34450317-0
InternalIP: 10.0.0.5 InternalIP: 10.0.0.5
@ -56,19 +63,23 @@ InternalIP: 2001:db8:10::5
### Validate Pod addressing ### Validate Pod addressing
Validate that a Pod has an IPv4 and IPv6 address assigned. Replace the Pod name with a valid Pod in your cluster. In this example the Pod name is `pod01`: Validate that a Pod has an IPv4 and IPv6 address assigned. Replace the Pod name with
a valid Pod in your cluster. In this example the Pod name is `pod01`:
```shell ```shell
kubectl get pods pod01 -o go-template --template='{{range .status.podIPs}}{{printf "%s\n" .ip}}{{end}}' kubectl get pods pod01 -o go-template --template='{{range .status.podIPs}}{{printf "%s\n" .ip}}{{end}}'
``` ```
``` ```
10.244.1.4 10.244.1.4
2001:db8::4 2001:db8::4
``` ```
You can also validate Pod IPs using the Downward API via the `status.podIPs` fieldPath. The following snippet demonstrates how you can expose the Pod IPs via an environment variable called `MY_POD_IPS` within a container. You can also validate Pod IPs using the Downward API via the `status.podIPs` fieldPath.
The following snippet demonstrates how you can expose the Pod IPs via an environment variable
called `MY_POD_IPS` within a container.
``` ```yaml
env: env:
- name: MY_POD_IPS - name: MY_POD_IPS
valueFrom: valueFrom:
@ -76,20 +87,26 @@ You can also validate Pod IPs using the Downward API via the `status.podIPs` fie
fieldPath: status.podIPs fieldPath: status.podIPs
``` ```
The following command prints the value of the `MY_POD_IPS` environment variable from within a container. The value is a comma separated list that corresponds to the Pod's IPv4 and IPv6 addresses. The following command prints the value of the `MY_POD_IPS` environment variable from
within a container. The value is a comma separated list that corresponds to the
Pod's IPv4 and IPv6 addresses.
```shell ```shell
kubectl exec -it pod01 -- set | grep MY_POD_IPS kubectl exec -it pod01 -- set | grep MY_POD_IPS
``` ```
``` ```
MY_POD_IPS=10.244.1.4,2001:db8::4 MY_POD_IPS=10.244.1.4,2001:db8::4
``` ```
The Pod's IP addresses will also be written to `/etc/hosts` within a container. The following command executes a cat on `/etc/hosts` on a dual stack Pod. From the output you can verify both the IPv4 and IPv6 IP address for the Pod. The Pod's IP addresses will also be written to `/etc/hosts` within a container.
The following command executes a cat on `/etc/hosts` on a dual stack Pod.
From the output you can verify both the IPv4 and IPv6 IP address for the Pod.
```shell ```shell
kubectl exec -it pod01 -- cat /etc/hosts kubectl exec -it pod01 -- cat /etc/hosts
``` ```
``` ```
# Kubernetes-managed hosts file. # Kubernetes-managed hosts file.
127.0.0.1 localhost 127.0.0.1 localhost
@ -104,7 +121,9 @@ fe00::2 ip6-allrouters
## Validate Services ## Validate Services
Create the following Service that does not explicitly define `.spec.ipFamilyPolicy`. Kubernetes will assign a cluster IP for the Service from the first configured `service-cluster-ip-range` and set the `.spec.ipFamilyPolicy` to `SingleStack`. Create the following Service that does not explicitly define `.spec.ipFamilyPolicy`.
Kubernetes will assign a cluster IP for the Service from the first configured
`service-cluster-ip-range` and set the `.spec.ipFamilyPolicy` to `SingleStack`.
{{% code_sample file="service/networking/dual-stack-default-svc.yaml" %}} {{% code_sample file="service/networking/dual-stack-default-svc.yaml" %}}
@ -114,7 +133,9 @@ Use `kubectl` to view the YAML for the Service.
kubectl get svc my-service -o yaml kubectl get svc my-service -o yaml
``` ```
The Service has `.spec.ipFamilyPolicy` set to `SingleStack` and `.spec.clusterIP` set to an IPv4 address from the first configured range set via `--service-cluster-ip-range` flag on kube-controller-manager. The Service has `.spec.ipFamilyPolicy` set to `SingleStack` and `.spec.clusterIP` set
to an IPv4 address from the first configured range set via `--service-cluster-ip-range`
flag on kube-controller-manager.
```yaml ```yaml
apiVersion: v1 apiVersion: v1
@ -141,7 +162,9 @@ status:
loadBalancer: {} loadBalancer: {}
``` ```
Create the following Service that explicitly defines `IPv6` as the first array element in `.spec.ipFamilies`. Kubernetes will assign a cluster IP for the Service from the IPv6 range configured `service-cluster-ip-range` and set the `.spec.ipFamilyPolicy` to `SingleStack`. Create the following Service that explicitly defines `IPv6` as the first array element in
`.spec.ipFamilies`. Kubernetes will assign a cluster IP for the Service from the IPv6 range
configured `service-cluster-ip-range` and set the `.spec.ipFamilyPolicy` to `SingleStack`.
{{% code_sample file="service/networking/dual-stack-ipfamilies-ipv6.yaml" %}} {{% code_sample file="service/networking/dual-stack-ipfamilies-ipv6.yaml" %}}
@ -151,7 +174,8 @@ Use `kubectl` to view the YAML for the Service.
kubectl get svc my-service -o yaml kubectl get svc my-service -o yaml
``` ```
The Service has `.spec.ipFamilyPolicy` set to `SingleStack` and `.spec.clusterIP` set to an IPv6 address from the IPv6 range set via `--service-cluster-ip-range` flag on kube-controller-manager. The Service has `.spec.ipFamilyPolicy` set to `SingleStack` and `.spec.clusterIP` set to
an IPv6 address from the IPv6 range set via `--service-cluster-ip-range` flag on kube-controller-manager.
```yaml ```yaml
apiVersion: v1 apiVersion: v1
@ -179,7 +203,10 @@ status:
loadBalancer: {} loadBalancer: {}
``` ```
Create the following Service that explicitly defines `PreferDualStack` in `.spec.ipFamilyPolicy`. Kubernetes will assign both IPv4 and IPv6 addresses (as this cluster has dual-stack enabled) and select the `.spec.ClusterIP` from the list of `.spec.ClusterIPs` based on the address family of the first element in the `.spec.ipFamilies` array. Create the following Service that explicitly defines `PreferDualStack` in `.spec.ipFamilyPolicy`.
Kubernetes will assign both IPv4 and IPv6 addresses (as this cluster has dual-stack enabled) and
select the `.spec.ClusterIP` from the list of `.spec.ClusterIPs` based on the address family of
the first element in the `.spec.ipFamilies` array.
{{% code_sample file="service/networking/dual-stack-preferred-svc.yaml" %}} {{% code_sample file="service/networking/dual-stack-preferred-svc.yaml" %}}
@ -188,13 +215,16 @@ The `kubectl get svc` command will only show the primary IP in the `CLUSTER-IP`
```shell ```shell
kubectl get svc -l app.kubernetes.io/name=MyApp kubectl get svc -l app.kubernetes.io/name=MyApp
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service ClusterIP 10.0.216.242 <none> 80/TCP 5s my-service ClusterIP 10.0.216.242 <none> 80/TCP 5s
``` ```
{{< /note >}} {{< /note >}}
Validate that the Service gets cluster IPs from the IPv4 and IPv6 address blocks using `kubectl describe`. You may then validate access to the service via the IPs and ports. Validate that the Service gets cluster IPs from the IPv4 and IPv6 address blocks using
`kubectl describe`. You may then validate access to the service via the IPs and ports.
```shell ```shell
kubectl describe svc -l app.kubernetes.io/name=MyApp kubectl describe svc -l app.kubernetes.io/name=MyApp
@ -220,7 +250,9 @@ Events: <none>
### Create a dual-stack load balanced Service ### Create a dual-stack load balanced Service
If the cloud provider supports the provisioning of IPv6 enabled external load balancers, create the following Service with `PreferDualStack` in `.spec.ipFamilyPolicy`, `IPv6` as the first element of the `.spec.ipFamilies` array and the `type` field set to `LoadBalancer`. If the cloud provider supports the provisioning of IPv6 enabled external load balancers,
create the following Service with `PreferDualStack` in `.spec.ipFamilyPolicy`, `IPv6` as
the first element of the `.spec.ipFamilies` array and the `type` field set to `LoadBalancer`.
{{% code_sample file="service/networking/dual-stack-prefer-ipv6-lb-svc.yaml" %}} {{% code_sample file="service/networking/dual-stack-prefer-ipv6-lb-svc.yaml" %}}
@ -230,11 +262,10 @@ Check the Service:
kubectl get svc -l app.kubernetes.io/name=MyApp kubectl get svc -l app.kubernetes.io/name=MyApp
``` ```
Validate that the Service receives a `CLUSTER-IP` address from the IPv6 address block along with an `EXTERNAL-IP`. You may then validate access to the service via the IP and port. Validate that the Service receives a `CLUSTER-IP` address from the IPv6 address block
along with an `EXTERNAL-IP`. You may then validate access to the service via the IP and port.
```shell ```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service LoadBalancer 2001:db8:fd00::7ebc 2603:1030:805::5 80:30790/TCP 35s my-service LoadBalancer 2001:db8:fd00::7ebc 2603:1030:805::5 80:30790/TCP 35s
``` ```