diff --git a/.go-version b/.go-version index 0e0c284d88ab0..4fd1625308000 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.25.9 +1.25.11 diff --git a/CHANGELOG/CHANGELOG-1.35.md b/CHANGELOG/CHANGELOG-1.35.md index 6b38da9b9bc4a..0c39070f26ada 100644 --- a/CHANGELOG/CHANGELOG-1.35.md +++ b/CHANGELOG/CHANGELOG-1.35.md @@ -1,192 +1,298 @@ -- [v1.35.4](#v1354) - - [Downloads for v1.35.4](#downloads-for-v1354) +- [v1.35.5](#v1355) + - [Downloads for v1.35.5](#downloads-for-v1355) - [Source Code](#source-code) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - [Container Images](#container-images) - - [Changelog since v1.35.3](#changelog-since-v1353) + - [Changelog since v1.35.4](#changelog-since-v1354) - [Changes by Kind](#changes-by-kind) - - [Feature](#feature) - [Bug or Regression](#bug-or-regression) - [Dependencies](#dependencies) - [Added](#added) - [Changed](#changed) - [Removed](#removed) -- [v1.35.3](#v1353) - - [Downloads for v1.35.3](#downloads-for-v1353) +- [v1.35.4](#v1354) + - [Downloads for v1.35.4](#downloads-for-v1354) - [Source Code](#source-code-1) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - [Container Images](#container-images-1) - - [Changelog since v1.35.2](#changelog-since-v1352) + - [Changelog since v1.35.3](#changelog-since-v1353) - [Changes by Kind](#changes-by-kind-1) + - [Feature](#feature) - [Bug or Regression](#bug-or-regression-1) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake) - [Dependencies](#dependencies-1) - [Added](#added-1) - [Changed](#changed-1) - [Removed](#removed-1) -- [v1.35.2](#v1352) - - [Downloads for v1.35.2](#downloads-for-v1352) +- [v1.35.3](#v1353) + - [Downloads for v1.35.3](#downloads-for-v1353) - [Source Code](#source-code-2) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - [Container Images](#container-images-2) - - [Changelog since v1.35.1](#changelog-since-v1351) + - [Changelog since v1.35.2](#changelog-since-v1352) - [Changes by Kind](#changes-by-kind-2) - - [Feature](#feature-1) + - [Bug or Regression](#bug-or-regression-2) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake) - [Dependencies](#dependencies-2) - [Added](#added-2) - [Changed](#changed-2) - [Removed](#removed-2) -- [v1.35.1](#v1351) - - [Downloads for v1.35.1](#downloads-for-v1351) +- [v1.35.2](#v1352) + - [Downloads for v1.35.2](#downloads-for-v1352) - [Source Code](#source-code-3) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) - [Container Images](#container-images-3) - - [Changelog since v1.35.0](#changelog-since-v1350) + - [Changelog since v1.35.1](#changelog-since-v1351) - [Changes by Kind](#changes-by-kind-3) - - [Feature](#feature-2) - - [Bug or Regression](#bug-or-regression-2) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-1) + - [Feature](#feature-1) - [Dependencies](#dependencies-3) - [Added](#added-3) - [Changed](#changed-3) - [Removed](#removed-3) -- [v1.35.0](#v1350) - - [Downloads for v1.35.0](#downloads-for-v1350) +- [v1.35.1](#v1351) + - [Downloads for v1.35.1](#downloads-for-v1351) - [Source Code](#source-code-4) - [Client Binaries](#client-binaries-4) - [Server Binaries](#server-binaries-4) - [Node Binaries](#node-binaries-4) - [Container Images](#container-images-4) - - [Changelog since v1.34.0](#changelog-since-v1340) - - [Urgent Upgrade Notes](#urgent-upgrade-notes) - - [(No, really, you MUST read this before you upgrade)](#no-really-you-must-read-this-before-you-upgrade) + - [Changelog since v1.35.0](#changelog-since-v1350) - [Changes by Kind](#changes-by-kind-4) - - [Deprecation](#deprecation) - - [API Change](#api-change) - - [Feature](#feature-3) - - [Documentation](#documentation) + - [Feature](#feature-2) - [Bug or Regression](#bug-or-regression-3) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-2) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-1) - [Dependencies](#dependencies-4) - [Added](#added-4) - [Changed](#changed-4) - [Removed](#removed-4) -- [v1.35.0-rc.1](#v1350-rc1) - - [Downloads for v1.35.0-rc.1](#downloads-for-v1350-rc1) +- [v1.35.0](#v1350) + - [Downloads for v1.35.0](#downloads-for-v1350) - [Source Code](#source-code-5) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) - [Container Images](#container-images-5) - - [Changelog since v1.35.0-rc.0](#changelog-since-v1350-rc0) + - [Changelog since v1.34.0](#changelog-since-v1340) + - [Urgent Upgrade Notes](#urgent-upgrade-notes) + - [(No, really, you MUST read this before you upgrade)](#no-really-you-must-read-this-before-you-upgrade) - [Changes by Kind](#changes-by-kind-5) - - [Feature](#feature-4) + - [Deprecation](#deprecation) + - [API Change](#api-change) + - [Feature](#feature-3) + - [Documentation](#documentation) - [Bug or Regression](#bug-or-regression-4) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-3) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-2) - [Dependencies](#dependencies-5) - [Added](#added-5) - [Changed](#changed-5) - [Removed](#removed-5) -- [v1.35.0-rc.0](#v1350-rc0) - - [Downloads for v1.35.0-rc.0](#downloads-for-v1350-rc0) +- [v1.35.0-rc.1](#v1350-rc1) + - [Downloads for v1.35.0-rc.1](#downloads-for-v1350-rc1) - [Source Code](#source-code-6) - [Client Binaries](#client-binaries-6) - [Server Binaries](#server-binaries-6) - [Node Binaries](#node-binaries-6) - [Container Images](#container-images-6) - - [Changelog since v1.35.0-beta.0](#changelog-since-v1350-beta0) + - [Changelog since v1.35.0-rc.0](#changelog-since-v1350-rc0) - [Changes by Kind](#changes-by-kind-6) - - [Feature](#feature-5) + - [Feature](#feature-4) - [Bug or Regression](#bug-or-regression-5) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-3) - [Dependencies](#dependencies-6) - [Added](#added-6) - [Changed](#changed-6) - [Removed](#removed-6) -- [v1.35.0-beta.0](#v1350-beta0) - - [Downloads for v1.35.0-beta.0](#downloads-for-v1350-beta0) +- [v1.35.0-rc.0](#v1350-rc0) + - [Downloads for v1.35.0-rc.0](#downloads-for-v1350-rc0) - [Source Code](#source-code-7) - [Client Binaries](#client-binaries-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - [Container Images](#container-images-7) - - [Changelog since v1.35.0-alpha.3](#changelog-since-v1350-alpha3) + - [Changelog since v1.35.0-beta.0](#changelog-since-v1350-beta0) - [Changes by Kind](#changes-by-kind-7) - - [API Change](#api-change-1) - - [Feature](#feature-6) + - [Feature](#feature-5) - [Bug or Regression](#bug-or-regression-6) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-4) - [Dependencies](#dependencies-7) - [Added](#added-7) - [Changed](#changed-7) - [Removed](#removed-7) -- [v1.35.0-alpha.3](#v1350-alpha3) - - [Downloads for v1.35.0-alpha.3](#downloads-for-v1350-alpha3) +- [v1.35.0-beta.0](#v1350-beta0) + - [Downloads for v1.35.0-beta.0](#downloads-for-v1350-beta0) - [Source Code](#source-code-8) - [Client Binaries](#client-binaries-8) - [Server Binaries](#server-binaries-8) - [Node Binaries](#node-binaries-8) - [Container Images](#container-images-8) - - [Changelog since v1.35.0-alpha.2](#changelog-since-v1350-alpha2) - - [Urgent Upgrade Notes](#urgent-upgrade-notes-1) - - [(No, really, you MUST read this before you upgrade)](#no-really-you-must-read-this-before-you-upgrade-1) + - [Changelog since v1.35.0-alpha.3](#changelog-since-v1350-alpha3) - [Changes by Kind](#changes-by-kind-8) - - [API Change](#api-change-2) - - [Feature](#feature-7) + - [API Change](#api-change-1) + - [Feature](#feature-6) - [Bug or Regression](#bug-or-regression-7) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-5) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-4) - [Dependencies](#dependencies-8) - [Added](#added-8) - [Changed](#changed-8) - [Removed](#removed-8) -- [v1.35.0-alpha.2](#v1350-alpha2) - - [Downloads for v1.35.0-alpha.2](#downloads-for-v1350-alpha2) +- [v1.35.0-alpha.3](#v1350-alpha3) + - [Downloads for v1.35.0-alpha.3](#downloads-for-v1350-alpha3) - [Source Code](#source-code-9) - [Client Binaries](#client-binaries-9) - [Server Binaries](#server-binaries-9) - [Node Binaries](#node-binaries-9) - [Container Images](#container-images-9) - - [Changelog since v1.35.0-alpha.1](#changelog-since-v1350-alpha1) + - [Changelog since v1.35.0-alpha.2](#changelog-since-v1350-alpha2) + - [Urgent Upgrade Notes](#urgent-upgrade-notes-1) + - [(No, really, you MUST read this before you upgrade)](#no-really-you-must-read-this-before-you-upgrade-1) - [Changes by Kind](#changes-by-kind-9) - - [Deprecation](#deprecation-1) - - [API Change](#api-change-3) - - [Feature](#feature-8) - - [Documentation](#documentation-1) + - [API Change](#api-change-2) + - [Feature](#feature-7) - [Bug or Regression](#bug-or-regression-8) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-6) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-5) - [Dependencies](#dependencies-9) - [Added](#added-9) - [Changed](#changed-9) - [Removed](#removed-9) -- [v1.35.0-alpha.1](#v1350-alpha1) - - [Downloads for v1.35.0-alpha.1](#downloads-for-v1350-alpha1) +- [v1.35.0-alpha.2](#v1350-alpha2) + - [Downloads for v1.35.0-alpha.2](#downloads-for-v1350-alpha2) - [Source Code](#source-code-10) - [Client Binaries](#client-binaries-10) - [Server Binaries](#server-binaries-10) - [Node Binaries](#node-binaries-10) - [Container Images](#container-images-10) - - [Changelog since v1.34.0](#changelog-since-v1340-1) + - [Changelog since v1.35.0-alpha.1](#changelog-since-v1350-alpha1) - [Changes by Kind](#changes-by-kind-10) - - [API Change](#api-change-4) - - [Feature](#feature-9) + - [Deprecation](#deprecation-1) + - [API Change](#api-change-3) + - [Feature](#feature-8) + - [Documentation](#documentation-1) - [Bug or Regression](#bug-or-regression-9) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-7) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-6) - [Dependencies](#dependencies-10) - [Added](#added-10) - [Changed](#changed-10) - [Removed](#removed-10) +- [v1.35.0-alpha.1](#v1350-alpha1) + - [Downloads for v1.35.0-alpha.1](#downloads-for-v1350-alpha1) + - [Source Code](#source-code-11) + - [Client Binaries](#client-binaries-11) + - [Server Binaries](#server-binaries-11) + - [Node Binaries](#node-binaries-11) + - [Container Images](#container-images-11) + - [Changelog since v1.34.0](#changelog-since-v1340-1) + - [Changes by Kind](#changes-by-kind-11) + - [API Change](#api-change-4) + - [Feature](#feature-9) + - [Bug or Regression](#bug-or-regression-10) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-7) + - [Dependencies](#dependencies-11) + - [Added](#added-11) + - [Changed](#changed-11) + - [Removed](#removed-11) +# v1.35.5 + + +## Downloads for v1.35.5 + + + +### Source Code + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes.tar.gz) | 9fae066bbdbcf68be964271a00be186c6fd8dbfa9d29ab66d060e11a23d2e472cff701014dfbcca4e5bd690a6767a32c4cc7d4f994975173a5f9ae84e4fe5b2c +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-src.tar.gz) | 7d375a8c59ba80288db208c12b8dd016f9c2e1b1d5dafc8de5c6716c101279e048a0d4ff867eff044c4a6be5e6cda028a842def73ff99372fed973d9a78f875f + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-darwin-amd64.tar.gz) | ddddb5c6aa59ad9dfbf16f98091cb62ac76680ff30d557d8b4aaf1be2ce26acd41f48025aad3cb9fe5a67cdbe9c3fedeed817c9dcacc72f31a4a886bd1038cbd +[kubernetes-client-darwin-arm64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-darwin-arm64.tar.gz) | a2595425c1de84f60c20cf381c57e81878b67ba459c5d425c224fabaff2f975ceb8bdcc6c37711e6f432e4c960801d1efec996da98ffe826afcb4901b4c4e6e5 +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-linux-386.tar.gz) | 909775fd9d3de94a1ff3e63db77061f6586532ba940a5bbc353c26b0a09cbd83c8066f87c5d2fe817882b6019957ad4542682939ae3dad39345c4c140f720cb1 +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-linux-amd64.tar.gz) | 5fc5b3e63884f18a5ac8856a4cb87a505826ff706a555baa30c1ce7eee1e7123c4f4a3a87f09a48924c15b50de82cf0bac37b859a92024eb9106a948f1ea9ab5 +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-linux-arm.tar.gz) | 503d58934d62d55e099c9c236557b3d3fe295af4741984e6e2b68ab800e4b0bbe8ccc372172781dddae268260fc5eae337f30b8610adffdd53de3a8a0dbaaa9f +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-linux-arm64.tar.gz) | d981d71c41eb351e977ec39e5b7d1832c6cfed7d5fd951d4cff14f5e4b371ebf7941a27fe73024e503a7662c824a60b71f6a9db036f48c77dbb1c326695e74cf +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-linux-ppc64le.tar.gz) | 5060414b36f3363789e165c7ed51f3ae42ee0fa31d0a47151e6e27da7eabc4e33ce005dfe96d7c1db8f64ab21df612e9c654241f32ad5a79f03dbd9080f5ca89 +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-linux-s390x.tar.gz) | 515e8ebda9d7152fc1c37c97a3629a477c5edb78b9cd8e752d4766e7c3c4d5dd2f1cca046aa8fd21290b1fe3aa5055df1659c12b12655c886f68573b3443b6ba +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-windows-386.tar.gz) | 6fc51b19b2975c119f4f2ed85fd5e951d0197df8583a972aa5e1c7122fe0ec97f367d22c216d7db4e04ddc16e8769e5ccdb8d96efa581bb1bb7c756dec369109 +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-windows-amd64.tar.gz) | 14fb6490b22582f68c280b38023798f25d26d74d43f81f9913612643b3ec0d64db0f124a136e166a68ed926f8452bfd243cd450c2604c772a8be2d327a7843ea +[kubernetes-client-windows-arm64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-client-windows-arm64.tar.gz) | cc999fc58d65e37df49b0d5512a465299af91267e3dfb3a510cffd85afc58ab6f98593e0dac939e803f408345242bf31a6c268a62048f4575bb32e082acba7c4 + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-server-linux-amd64.tar.gz) | e8c85142436316eb790ff7ca077f09051d6203b49601ddd56dc93770d32c6304f423d227469d7bdf603f56eb11e88e3d2d1ef6db2e443e10406ba768d0fffa74 +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-server-linux-arm64.tar.gz) | 8024efc9285c116d28924b80957783da9214d821bfe15a4d73c5be3764a6836f470847062f9ac1ae939379e590dd8f62d0f7b531034e478aca94182d954ac18c +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-server-linux-ppc64le.tar.gz) | e2e29fcee38dc7dca1ff205ea723240da65149ac2c0bf8bf60f60f8c91c63384a6b145d59464a3b3509f9b0d9e5c840c6bd8a56cfddfbe1a9e02e2f171883738 +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-server-linux-s390x.tar.gz) | 9e07b5fd04bf43e4a9ac1b44d17a0959841ffe9827d8984c0a9b997cc60f8860445ff628404eb3519165f233de9586dd3855dfb715935f35b7e4a0c26855c264 + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-node-linux-amd64.tar.gz) | b9bd503bb0ece05c4f34cb6611ceb8d1a9716f5cf4a5663898112e2e5a6c1e4e4a52206f62f900dfb24a8f9f799f7a7c20891ece8cdae521e7cd755b6fdbc844 +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-node-linux-arm64.tar.gz) | 7d804f2ef7fa5c5efcce7776ff784a22f09a6cdd1bd662c9b65f2feb793617e1693c478f0d2e3bb9764ce6c8f0eed1071eb596bd9f15eba0e7e43d99aa5f8b34 +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-node-linux-ppc64le.tar.gz) | f1b4a9174229ef68336de4eae91f13ac7bf5b9e59b62564a6f3c98cbb167ea61ad636b9be3800b3edccc05989570c5c0235363395a94244836c1e3308faa1e4e +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-node-linux-s390x.tar.gz) | c0f54407576ebec53aaba95a48da4bb3c8d46bb89fac00276f979ed8055b7a1ca838ff88efc85cbf9f5bdd2e6464b74db13a2bfc8deca0cc02935dd91a4b280c +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.35.5/kubernetes-node-windows-amd64.tar.gz) | 92e45a91666c7e13d79bb3dae7ad889c1f9b1d809c73b24fd2db493fd7887605f1d3d6d1fb243ebc42b99dc262eb9ac9a842ab792183807f5b97c490364ca0c6 + +### Container Images + +All container images are available as manifest lists and support the described +architectures. It is also possible to pull a specific architecture directly by +adding the "-$ARCH" suffix to the container image name. + +name | architectures +---- | ------------- +[registry.k8s.io/conformance:v1.35.5](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-s390x) +[registry.k8s.io/kube-apiserver:v1.35.5](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-s390x) +[registry.k8s.io/kube-controller-manager:v1.35.5](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-s390x) +[registry.k8s.io/kube-proxy:v1.35.5](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-s390x) +[registry.k8s.io/kube-scheduler:v1.35.5](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-s390x) +[registry.k8s.io/kubectl:v1.35.5](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-s390x) + +## Changelog since v1.35.4 + +## Changes by Kind + +### Bug or Regression + +- Fixed a scheduler bug where replacing a Pod with the same name during a failed scheduling attempt could leave stale in-flight queue state and unbounded growth of in-flight event tracking. The scheduler now clears in-flight state using the UID from the scheduling attempt, not only the UID on the refreshed Pod object. ([#138434](https://github.com/kubernetes/kubernetes/pull/138434), [@Argh4k](https://github.com/Argh4k)) [SIG Scheduling] +- Fixed stale remote HNS endpoint cleanup on Windows when a pod IP is reused across nodes in L2Bridge networks, preventing DNS timeouts caused by traffic being routed to the wrong node. ([#138602](https://github.com/kubernetes/kubernetes/pull/138602), [@princepereira](https://github.com/princepereira)) [SIG Network and Windows] +- Kube-proxy does not perform full-sync operations when operation in large cluster mode (more than 1000 endpoints) ([#138636](https://github.com/kubernetes/kubernetes/pull/138636), [@aojea](https://github.com/aojea)) [SIG Network] +- Kubeadm: during 'kubeadm init', if the default 'admin.conf' and 'super-admin.conf' paths are used, load the files, but construct in memory kubeconfigs that point to the InitConfiguration.localAPIEndpoint instead of the ClusterConfiguration.controlPlaneEndpoint. This would resolve issues with delayed load balancers which are provisioned only after the first kube-apiserver instance starts. ([#138683](https://github.com/kubernetes/kubernetes/pull/138683), [@neolit123](https://github.com/neolit123)) [SIG Cluster Lifecycle] +- Kubeadm: skip LocalAPIEndpoint defaulting on 'kubeadm join' for worker nodes. ([#138803](https://github.com/kubernetes/kubernetes/pull/138803), [@neolit123](https://github.com/neolit123)) [SIG Cluster Lifecycle] +- Kubeadm: use a dedicated ClusterRole 'system:kubelet-api-admin' for the kube-apiserver kubelet client. ([#138959](https://github.com/kubernetes/kubernetes/pull/138959), [@neolit123](https://github.com/neolit123)) [SIG Cluster Lifecycle] +- Kubeadm: when checking the etcd cluster status use a quorum approach, instead of considering the health of all members. This would allow the check to not fail if there are sufficient healthy voting members. ([#138539](https://github.com/kubernetes/kubernetes/pull/138539), [@ahrtr](https://github.com/ahrtr)) [SIG Cluster Lifecycle] +- Kubelet_pod_start_sli_duration_seconds_bucket metric now matches pod startup latency SLI/SLO documentation. ([#138153](https://github.com/kubernetes/kubernetes/pull/138153), [@alimaazamat](https://github.com/alimaazamat)) [SIG Node] + +## Dependencies + +### Added +_Nothing has changed._ + +### Changed +_Nothing has changed._ + +### Removed +_Nothing has changed._ + + + # v1.35.4 diff --git a/build/build-image/cross/VERSION b/build/build-image/cross/VERSION index 53dd3d6c1b53a..5338637c768f8 100644 --- a/build/build-image/cross/VERSION +++ b/build/build-image/cross/VERSION @@ -1 +1 @@ -v1.35.0-go1.25.9-bullseye.0 \ No newline at end of file +v1.35.0-go1.25.11-bullseye.0 \ No newline at end of file diff --git a/build/common.sh b/build/common.sh index e9c0268a37990..d8342d7319291 100755 --- a/build/common.sh +++ b/build/common.sh @@ -80,8 +80,8 @@ readonly REMOTE_OUTPUT_BINPATH="${REMOTE_OUTPUT_SUBPATH}/bin" readonly REMOTE_OUTPUT_GOPATH="${REMOTE_OUTPUT_SUBPATH}/go" # These are the default versions (image tags) for their respective base images. -readonly __default_distroless_iptables_version=v0.8.9 -readonly __default_go_runner_version=v2.4.0-go1.25.9-bookworm.0 +readonly __default_distroless_iptables_version=v0.8.11 +readonly __default_go_runner_version=v2.4.0-go1.25.11-bookworm.0 readonly __default_setcap_version=bookworm-v1.0.6 # The default image for all binaries which are dynamically linked. diff --git a/build/dependencies.yaml b/build/dependencies.yaml index dd422524fc298..14820fb091222 100644 --- a/build/dependencies.yaml +++ b/build/dependencies.yaml @@ -122,7 +122,7 @@ dependencies: # should also be updated, but go-runner is much harder to exploit and has # far less relevancy to go updates for Kubernetes more generally. - name: "registry.k8s.io/kube-cross: dependents" - version: v1.35.0-go1.25.9-bullseye.0 + version: v1.35.0-go1.25.11-bullseye.0 refPaths: - path: build/build-image/cross/VERSION @@ -170,7 +170,7 @@ dependencies: match: registry\.k8s\.io\/build-image\/debian-base:[a-zA-Z]+\-v((([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?) - name: "registry.k8s.io/distroless-iptables: dependents" - version: v0.8.9 + version: v0.8.11 refPaths: - path: build/common.sh match: __default_distroless_iptables_version= @@ -178,7 +178,7 @@ dependencies: match: configs\[DistrolessIptables\] = Config{list\.BuildImageRegistry, "distroless-iptables", "v([0-9]+)\.([0-9]+)\.([0-9]+)"} - name: "registry.k8s.io/go-runner: dependents" - version: v2.4.0-go1.25.9-bookworm.0 + version: v2.4.0-go1.25.11-bookworm.0 refPaths: - path: build/common.sh match: __default_go_runner_version= diff --git a/cmd/kubeadm/app/cmd/phases/init/certs.go b/cmd/kubeadm/app/cmd/phases/init/certs.go index 5d1df7453f09d..84280e52d9e83 100644 --- a/cmd/kubeadm/app/cmd/phases/init/certs.go +++ b/cmd/kubeadm/app/cmd/phases/init/certs.go @@ -18,6 +18,7 @@ package phases import ( "fmt" + "os" "path/filepath" "strings" @@ -216,20 +217,25 @@ func runCAPhase(ca *certsphase.KubeadmCert) func(c workflow.RunData) error { if cert, err := pkiutil.TryLoadCertFromDisk(data.CertificateDir(), ca.BaseName); err == nil { certsphase.CheckCertificatePeriodValidity(ca.BaseName, cert) + srcCertPath, srcKeyPath := pkiutil.PathsForCertAndKey(data.CertificateDir(), ca.BaseName) + dryRunCertPath, dryRunKeyPath := pkiutil.PathsForCertAndKey(data.CertificateWriteDir(), ca.BaseName) // If CA Cert existed while dryrun, copy CA Cert to dryrun dir for later use if data.DryRun() { - err := kubeadmutil.CopyFile(filepath.Join(data.CertificateDir(), kubeadmconstants.CACertName), filepath.Join(data.CertificateWriteDir(), kubeadmconstants.CACertName)) + if err := os.MkdirAll(filepath.Dir(dryRunCertPath), os.FileMode(0700)); err != nil { + return errors.Wrapf(err, "failed to create directory %s", filepath.Dir(dryRunCertPath)) + } + err := kubeadmutil.CopyFile(srcCertPath, dryRunCertPath) if err != nil { - return errors.Wrapf(err, "could not copy %s to dry run directory %s", kubeadmconstants.CACertName, data.CertificateWriteDir()) + return errors.Wrapf(err, "could not copy %s to dry run directory %s", fmt.Sprintf("%s.crt", ca.BaseName), data.CertificateWriteDir()) } } if _, err := pkiutil.TryLoadKeyFromDisk(data.CertificateDir(), ca.BaseName); err == nil { // If CA Key existed while dryrun, copy CA Key to dryrun dir for later use if data.DryRun() { - err := kubeadmutil.CopyFile(filepath.Join(data.CertificateDir(), kubeadmconstants.CAKeyName), filepath.Join(data.CertificateWriteDir(), kubeadmconstants.CAKeyName)) + err := kubeadmutil.CopyFile(srcKeyPath, dryRunKeyPath) if err != nil { - return errors.Wrapf(err, "could not copy %s to dry run directory %s", kubeadmconstants.CAKeyName, data.CertificateWriteDir()) + return errors.Wrapf(err, "could not copy %s to dry run directory %s", fmt.Sprintf("%s.key", ca.BaseName), data.CertificateWriteDir()) } } fmt.Printf("[certs] Using existing %s certificate authority\n", ca.BaseName) diff --git a/cmd/kubeadm/app/cmd/phases/init/certs_test.go b/cmd/kubeadm/app/cmd/phases/init/certs_test.go index 7ee76b6459c1a..fb8d3a97dc7ed 100644 --- a/cmd/kubeadm/app/cmd/phases/init/certs_test.go +++ b/cmd/kubeadm/app/cmd/phases/init/certs_test.go @@ -17,13 +17,17 @@ limitations under the License. package phases import ( + "os" + "path/filepath" "testing" "github.com/spf13/cobra" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" + certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" + "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" pkiutiltesting "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil/testing" testutil "k8s.io/kubernetes/cmd/kubeadm/test" ) @@ -33,10 +37,19 @@ type testCertsData struct { cfg *kubeadmapi.InitConfiguration } +type testDryRunCertsData struct { + testCertsData + certificateDir string + certificateWriteDir string +} + func (t *testCertsData) Cfg() *kubeadmapi.InitConfiguration { return t.cfg } func (t *testCertsData) ExternalCA() bool { return false } func (t *testCertsData) CertificateDir() string { return t.cfg.CertificatesDir } func (t *testCertsData) CertificateWriteDir() string { return t.cfg.CertificatesDir } +func (t *testDryRunCertsData) DryRun() bool { return true } +func (t *testDryRunCertsData) CertificateDir() string { return t.certificateDir } +func (t *testDryRunCertsData) CertificateWriteDir() string { return t.certificateWriteDir } func TestCreateSparseCerts(t *testing.T) { for _, test := range certstestutil.GetSparseCertTestCases(t) { @@ -63,3 +76,45 @@ func TestCreateSparseCerts(t *testing.T) { }) } } + +func TestRunCAPhaseCopiesExistingCAFilesToDryRunDir(t *testing.T) { + for _, ca := range []*certsphase.KubeadmCert{ + certsphase.KubeadmCertRootCA(), + certsphase.KubeadmCertFrontProxyCA(), + certsphase.KubeadmCertEtcdCA(), + } { + t.Run(ca.Name, func(t *testing.T) { + pkiutiltesting.Reset() + + sourceDir := t.TempDir() + writeDir := t.TempDir() + caCert, caKey := certstestutil.SetupCertificateAuthority(t) + certPath, _ := pkiutil.PathsForCertAndKey(sourceDir, ca.BaseName) + if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0700)); err != nil { + t.Fatalf("failed to create source directory for %s: %v", ca.BaseName, err) + } + if err := pkiutil.WriteCertAndKey(sourceDir, ca.BaseName, caCert, caKey); err != nil { + t.Fatalf("failed to write source CA files for %s: %v", ca.BaseName, err) + } + + cfg := testutil.GetDefaultInternalConfig(t) + cfg.CertificatesDir = sourceDir + data := &testDryRunCertsData{ + testCertsData: testCertsData{cfg: cfg}, + certificateDir: sourceDir, + certificateWriteDir: writeDir, + } + + if err := runCAPhase(ca)(data); err != nil { + t.Fatalf("runCAPhase(%s) returned error: %v", ca.Name, err) + } + + if _, err := pkiutil.TryLoadCertFromDisk(writeDir, ca.BaseName); err != nil { + t.Fatalf("expected copied cert for %s in dry-run dir: %v", ca.BaseName, err) + } + if _, err := pkiutil.TryLoadKeyFromDisk(writeDir, ca.BaseName); err != nil { + t.Fatalf("expected copied key for %s in dry-run dir: %v", ca.BaseName, err) + } + }) + } +} diff --git a/openshift-hack/images/hyperkube/Dockerfile.rhel b/openshift-hack/images/hyperkube/Dockerfile.rhel index 5c8de9a5feecd..a3817ddbb1ab2 100644 --- a/openshift-hack/images/hyperkube/Dockerfile.rhel +++ b/openshift-hack/images/hyperkube/Dockerfile.rhel @@ -15,4 +15,4 @@ COPY --from=builder /tmp/build/* /usr/bin/ LABEL io.k8s.display-name="OpenShift Kubernetes Server Commands" \ io.k8s.description="OpenShift is a platform for developing, building, and deploying containerized applications." \ io.openshift.tags="openshift,hyperkube" \ - io.openshift.build.versions="kubernetes=1.35.5" + io.openshift.build.versions="kubernetes=1.35.6" diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index fbb62132d630d..038eac5cfae7c 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -176,7 +176,7 @@ func ValidateQualifiedName(value string, fldPath *field.Path) field.ErrorList { func ValidateDNS1123SubdomainWithUnderScore(value string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, msg := range validation.IsDNS1123SubdomainWithUnderscore(value) { - allErrs = append(allErrs, field.Invalid(fldPath, value, msg)).WithOrigin("format=k8s-dns-subdomain-with-underscore") + allErrs = append(allErrs, field.Invalid(fldPath, value, msg).WithOrigin("format=k8s-dns-subdomain-with-underscore")) } return allErrs } @@ -185,7 +185,7 @@ func ValidateDNS1123SubdomainWithUnderScore(value string, fldPath *field.Path) f func ValidateDNS1123Subdomain(value string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, msg := range validation.IsDNS1123Subdomain(value) { - allErrs = append(allErrs, field.Invalid(fldPath, value, msg)).WithOrigin("format=k8s-long-name") + allErrs = append(allErrs, field.Invalid(fldPath, value, msg).WithOrigin("format=k8s-long-name")) } return allErrs } @@ -4977,7 +4977,7 @@ func ValidateNodeSelectorRequirement(rq core.NodeSelectorRequirement, allowInval path := fldPath.Child("values") for valueIndex, value := range rq.Values { for _, msg := range validation.IsValidLabelValue(value) { - allErrs = append(allErrs, field.Invalid(path.Index(valueIndex), value, msg)).WithOrigin("format=k8s-label-value") + allErrs = append(allErrs, field.Invalid(path.Index(valueIndex), value, msg).WithOrigin("format=k8s-label-value")) } } } diff --git a/pkg/apis/resource/validation/validation.go b/pkg/apis/resource/validation/validation.go index ef2b4cfe82603..a3ec8f899ec29 100644 --- a/pkg/apis/resource/validation/validation.go +++ b/pkg/apis/resource/validation/validation.go @@ -773,7 +773,7 @@ func validateCounterSet(counterSet resource.CounterSet, fldPath *field.Path) fie if counterSet.Name == "" { allErrs = append(allErrs, field.Required(fldPath.Child("name"), "").MarkCoveredByDeclarative()) } else { - allErrs = append(allErrs, validateCounterName(counterSet.Name, fldPath.Child("name"))...).MarkCoveredByDeclarative() + allErrs = append(allErrs, validateCounterName(counterSet.Name, fldPath.Child("name")).MarkCoveredByDeclarative()...) } if len(counterSet.Counters) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("counters"), "")) @@ -874,7 +874,7 @@ func validateDeviceCounterConsumption(deviceCounterConsumption resource.DeviceCo if len(deviceCounterConsumption.CounterSet) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("counterSet"), "").MarkCoveredByDeclarative()) } else { - allErrs = append(allErrs, validateCounterName(deviceCounterConsumption.CounterSet, fldPath.Child("counterSet"))...).MarkCoveredByDeclarative() + allErrs = append(allErrs, validateCounterName(deviceCounterConsumption.CounterSet, fldPath.Child("counterSet")).MarkCoveredByDeclarative()...) } if len(deviceCounterConsumption.Counters) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("counters"), "")) diff --git a/pkg/apis/storage/validation/validation.go b/pkg/apis/storage/validation/validation.go index e103b613aae58..6b0d8c4ea54d7 100644 --- a/pkg/apis/storage/validation/validation.go +++ b/pkg/apis/storage/validation/validation.go @@ -88,7 +88,7 @@ func ValidateStorageClassUpdate(storageClass, oldStorageClass *storage.StorageCl func validateProvisioner(provisioner string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(provisioner) == 0 { - allErrs = append(allErrs, field.Required(fldPath, provisioner)).MarkCoveredByDeclarative() + allErrs = append(allErrs, field.Required(fldPath, provisioner).MarkCoveredByDeclarative()) } if len(provisioner) > 0 { allErrs = append(allErrs, apivalidation.ValidateQualifiedName(strings.ToLower(provisioner), fldPath)...) diff --git a/pkg/controller/endpoint/endpoints_controller.go b/pkg/controller/endpoint/endpoints_controller.go index fe1c5f40832c7..6b52f860a2f7a 100644 --- a/pkg/controller/endpoint/endpoints_controller.go +++ b/pkg/controller/endpoint/endpoints_controller.go @@ -220,8 +220,22 @@ func (e *Controller) Run(ctx context.Context, workers int) { func podToEndpointAddressForService(svc *v1.Service, pod *v1.Pod) (*v1.EndpointAddress, error) { var endpointIP string - - wantIPv6 := svc.Spec.IPFamilies[0] == v1.IPv6Protocol + ipFamily := v1.IPv4Protocol + + // IPFamilies is expected to be populated by apiserver defaulting, but + // some services may reach this controller with an empty IPFamilies via + // watch events. Infer the family from ClusterIP or + // pod IP so we never panic on IPFamilies[0]. + if len(svc.Spec.IPFamilies) > 0 { + ipFamily = svc.Spec.IPFamilies[0] + } else if len(svc.Spec.ClusterIP) > 0 && svc.Spec.ClusterIP != v1.ClusterIPNone { + if utilnet.IsIPv6String(svc.Spec.ClusterIP) { + ipFamily = v1.IPv6Protocol + } + } else if utilnet.IsIPv6String(pod.Status.PodIP) { + ipFamily = v1.IPv6Protocol + } + wantIPv6 := ipFamily == v1.IPv6Protocol // Find an IP that matches the family. We parse and restringify the IP in case the // value on the Pod is in an irregular format. diff --git a/pkg/controller/endpoint/endpoints_controller_test.go b/pkg/controller/endpoint/endpoints_controller_test.go index bead9c2f6494a..c12fb83a9fa10 100644 --- a/pkg/controller/endpoint/endpoints_controller_test.go +++ b/pkg/controller/endpoint/endpoints_controller_test.go @@ -3224,3 +3224,83 @@ func TestSyncEndpointsAddDeletePorts(t *testing.T) { t.Fatalf("incorrect endpoints after deleting first port:\n%s", diff) } } + +func TestPodToEndpointAddressForServiceEmptyIPFamilies(t *testing.T) { + testCases := []struct { + name string + clusterIP string + podIPs []v1.PodIP + podIP string + wantErr bool + wantFamily v1.IPFamily + }{ + { + name: "headful IPv4, IPv4 pod", + clusterIP: "10.0.0.1", + podIPs: []v1.PodIP{{IP: "10.244.0.1"}}, + wantFamily: v1.IPv4Protocol, + }, + { + name: "headful IPv6, IPv6 pod", + clusterIP: "fd00::1", + podIPs: []v1.PodIP{{IP: "fd00::10"}}, + wantFamily: v1.IPv6Protocol, + }, + { + name: "headful IPv4, no matching pod IP", + clusterIP: "10.0.0.1", + podIPs: []v1.PodIP{{IP: "fd00::10"}}, + wantErr: true, + }, + { + name: "headless, IPv4 pod", + clusterIP: v1.ClusterIPNone, + podIPs: []v1.PodIP{{IP: "10.244.0.1"}}, + podIP: "10.244.0.1", + wantFamily: v1.IPv4Protocol, + }, + { + name: "headless, IPv6 pod", + clusterIP: v1.ClusterIPNone, + podIPs: []v1.PodIP{{IP: "fd00::10"}}, + podIP: "fd00::10", + wantFamily: v1.IPv6Protocol, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + svc := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, + Spec: v1.ServiceSpec{ + // Intentionally leave IPFamilies empty. + ClusterIP: tc.clusterIP, + }, + } + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "foo-pod", Namespace: "bar", UID: "uid-1"}, + Spec: v1.PodSpec{NodeName: "node-1"}, + Status: v1.PodStatus{PodIP: tc.podIP, PodIPs: tc.podIPs}, + } + + addr, err := podToEndpointAddressForService(svc, pod) + if tc.wantErr { + if err == nil { + t.Fatalf("expected error but got addr=%v", addr) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if addr == nil { + t.Fatal("expected an address but got nil") + } + isV6 := utilnet.IsIPv6String(addr.IP) + wantV6 := tc.wantFamily == v1.IPv6Protocol + if isV6 != wantV6 { + t.Errorf("got IP %q (IPv6=%v), want family %v", addr.IP, isV6, tc.wantFamily) + } + }) + } +} diff --git a/pkg/kubelet/container/runtime.go b/pkg/kubelet/container/runtime.go index 46deb9da07b80..8823f866f5240 100644 --- a/pkg/kubelet/container/runtime.go +++ b/pkg/kubelet/container/runtime.go @@ -462,7 +462,7 @@ type Image struct { // EnvVar represents the environment variable. type EnvVar struct { Name string - Value string + Value string // TODO: switch to []byte } // Annotation represents an annotation. diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 4df460a08805e..2c8d0c07f0d6f 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -766,7 +766,7 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container var ( configMaps = make(map[string]*v1.ConfigMap) secrets = make(map[string]*v1.Secret) - tmpEnv = make(map[string]string) + tmpEnv = make(map[string]string) // TODO: switch to map[string][]byte ) // Env will override EnvFrom variables. @@ -798,6 +798,7 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container k = envFrom.Prefix + k } + // TODO: validate no NUL bytes tmpEnv[k] = v } case envFrom.SecretRef != nil: @@ -825,6 +826,7 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container k = envFrom.Prefix + k } + // TODO: validate no NUL bytes tmpEnv[k] = string(v) } } @@ -918,6 +920,7 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container } return result, fmt.Errorf("couldn't find key %v in Secret %v/%v", key, pod.Namespace, name) } + // TODO: validate no NUL bytes runtimeVal = string(runtimeValBytes) case utilfeature.DefaultFeatureGate.Enabled(features.EnvFiles) && envVar.ValueFrom.FileKeyRef != nil: f := envVar.ValueFrom.FileKeyRef diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container.go b/pkg/kubelet/kuberuntime/kuberuntime_container.go index 88b34a14ea67a..e4763b8613016 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -34,6 +34,7 @@ import ( "time" codes "google.golang.org/grpc/codes" + crierror "k8s.io/cri-api/pkg/errors" "github.com/opencontainers/selinux/go-selinux" @@ -400,7 +401,7 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(ctx context.Context, e := opts.Envs[idx] envs[idx] = &runtimeapi.KeyValue{ Key: e.Name, - Value: e.Value, + Value: []byte(e.Value), } } config.Envs = envs diff --git a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources.go b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources.go index 75551dc98055d..c737882fa0e91 100644 --- a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources.go +++ b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources.go @@ -830,7 +830,7 @@ func (pl *DynamicResources) PostFilter(ctx context.Context, cs fwk.CycleState, p } func (pl *DynamicResources) Score(ctx context.Context, cs fwk.CycleState, pod *v1.Pod, nodeInfo fwk.NodeInfo) (int64, *fwk.Status) { - if !pl.enabled { + if !pl.enabled || !pl.fts.EnableDRAPrioritizedList { return 0, nil } logger := klog.FromContext(ctx) @@ -859,13 +859,29 @@ func (pl *DynamicResources) Score(ctx context.Context, cs fwk.CycleState, pod *v func computeScore(iterator iter.Seq2[int, *resourceapi.ResourceClaim], allocations nodeAllocation) (int64, error) { var score int64 - for i, claim := range iterator { + unallocatedIndex := 0 + for _, claim := range iterator { // Collect the names for all allocated subrequests. allocatedSubRequests := sets.New[string]() - if i >= len(allocations.allocationResults) { - return 0, fmt.Errorf("number of allocations %d is smaller than number of claims", len(allocations.allocationResults)) + + var allocation *resourceapi.AllocationResult + // The allocation for a claim can be in two places: + // 1. For claims allocated in a previous cycle (e.g. PodGroup claims), the allocation + // is already in claim.Status.Allocation. + // 2. For claims allocated in this cycle (in Filter), the allocation is in + // allocations.allocationResults. + // Since we iterate over all claims, we must check both and maintain a separate index + // for claims that needed allocation in this cycle. + if claim.Status.Allocation != nil { + allocation = claim.Status.Allocation + } else { + if unallocatedIndex >= len(allocations.allocationResults) { + return 0, fmt.Errorf("number of allocations %d is smaller than number of claims needing allocation", len(allocations.allocationResults)) + } + allocation = &allocations.allocationResults[unallocatedIndex] + unallocatedIndex++ } - allocation := allocations.allocationResults[i] + for _, res := range allocation.Devices.Results { request := res.Request if resourceclaim.IsSubRequestRef(request) { diff --git a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go index fc089251eab1c..03d63da6cfe3e 100644 --- a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go +++ b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go @@ -3310,6 +3310,19 @@ func Test_computesScore(t *testing.T) { allocations: nodeAllocation{}, expectErr: true, }, + "mix-of-allocated-and-unallocated-claims": { + claims: []*resourceapi.ResourceClaim{ + allocatedClaim, + pendingClaim2, + }, + allocations: nodeAllocation{ + allocationResults: []resourceapi.AllocationResult{ + *allocationResult2, + }, + }, + expectedScore: 0, + expectErr: false, + }, "single-request-only-subrequest-allocated": { claims: []*resourceapi.ResourceClaim{ st.MakeResourceClaim(). diff --git a/pkg/volume/csi/csi_mounter.go b/pkg/volume/csi/csi_mounter.go index f8760280dcb0e..2674a9afac6ec 100644 --- a/pkg/volume/csi/csi_mounter.go +++ b/pkg/volume/csi/csi_mounter.go @@ -314,7 +314,11 @@ func (c *csiMountMgr) SetUpAt(dir string, mounterArgs volume.MounterArgs) error if csiRPCError != nil { // If operation finished with error then we can remove the mount directory. - if volumetypes.IsOperationFinishedError(csiRPCError) { + // Skip on remount (e.g. CSIDriver.spec.requiresRepublish=true): the volume + // was already published and the pod is observing the existing bind mount, + // so removing the mount dir here would leave the pod with stale contents + // that a subsequent successful republish cannot repair (#121271). + if volumetypes.IsOperationFinishedError(csiRPCError) && !mounterArgs.IsRemount { if removeMountDirErr := removeMountDir(c.plugin, dir); removeMountDirErr != nil { klog.Error(log("mounter.SetupAt failed to remove mount dir after a NodePublish() error [%s]: %v", dir, removeMountDirErr)) } diff --git a/pkg/volume/csi/csi_mounter_test.go b/pkg/volume/csi/csi_mounter_test.go index 62aecb809f0b1..e192eec60265b 100644 --- a/pkg/volume/csi/csi_mounter_test.go +++ b/pkg/volume/csi/csi_mounter_test.go @@ -28,6 +28,8 @@ import ( "time" "github.com/google/go-cmp/cmp" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" authenticationv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" storage "k8s.io/api/storage/v1" @@ -1169,6 +1171,86 @@ func TestMounterSetUpWithFSGroup(t *testing.T) { } } +func TestMounterSetUpFWithNodePublishFinalError(t *testing.T) { + testCases := []struct { + name string + podUID types.UID + options []string + spec func(string, []string) *volume.Spec + isRemount bool + expectDataFileExists bool + }{ + { + // Regression test for https://github.com/kubernetes/kubernetes/issues/121271: + // when NodePublishVolume fails on a remount (e.g. a republish + // triggered by CSIDriver.spec.requiresRepublish=true), the + // mount directory and vol_data.json must be preserved so the + // pod continues to see the previously-published contents and + // a subsequent successful republish can refresh them in place. + name: "setup with remount preserves mount dir on final error", + podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())), + spec: func(fsType string, options []string) *volume.Spec { + pvSrc := makeTestPV("pv1", 20, testDriver, "vol1") + pvSrc.Spec.CSI.FSType = fsType + pvSrc.Spec.MountOptions = options + return volume.NewSpecFromPersistentVolume(pvSrc, false) + }, + isRemount: true, + expectDataFileExists: true, + }, + } + + for _, tc := range testCases { + volumeLifecycleModes := []storage.VolumeLifecycleMode{ + storage.VolumeLifecyclePersistent, + } + driver := getTestCSIDriver(testDriver, nil, nil, volumeLifecycleModes) + fakeClient := fakeclient.NewClientset(driver) + plug, tmpDir := newTestPlugin(t, fakeClient) + defer func() { + _ = os.RemoveAll(tmpDir) + }() + registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t) + t.Run(tc.name, func(t *testing.T) { + mounter, err := plug.NewMounter( + tc.spec("zfs", tc.options), + &corev1.Pod{ObjectMeta: meta.ObjectMeta{UID: tc.podUID, Namespace: testns}}, + ) + if mounter == nil || err != nil { + t.Fatal("failed to create CSI mounter") + } + + csiMounter := mounter.(*csiMountMgr) + csiMounter.csiClient = setupClient(t, true) + + attachID := getAttachmentName(csiMounter.volumeID, string(csiMounter.driverName), string(plug.host.GetNodeName())) + attachment := makeTestAttachment(attachID, "test-node", csiMounter.spec.Name()) + _, err = csiMounter.k8s.StorageV1().VolumeAttachments().Create(context.TODO(), attachment, meta.CreateOptions{}) + if err != nil { + t.Fatalf("failed to setup VolumeAttachment: %v", err) + } + + csiMounter.csiClient.(*fakeCsiDriverClient).nodeClient.SetNextError(status.Errorf(codes.InvalidArgument, "mount failed")) + + // Mounter.SetUp() + if err := csiMounter.SetUp(volume.MounterArgs{ + IsRemount: tc.isRemount, + }); err == nil { + t.Fatalf("mounter.Setup expected err but succeed") + } + + mountPath := csiMounter.GetPath() + volPath := filepath.Dir(mountPath) + dataFile := filepath.Join(volPath, volDataFileName) + _, statErr := os.Stat(dataFile) + exists := statErr == nil + if exists != tc.expectDataFileExists { + t.Errorf("volume file [%s]: exists=%v, want=%v (statErr=%v)", dataFile, exists, tc.expectDataFileExists, statErr) + } + }) + } +} + func TestUnmounterTeardown(t *testing.T) { plug, tmpDir := newTestPlugin(t, nil) defer os.RemoveAll(tmpDir) diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index 9d5c937d95372..790ff5e119dbb 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -586,6 +586,7 @@ func (og *operationGenerator) GenerateMountVolumeFunc( FSGroupChangePolicy: fsGroupChangePolicy, Recorder: og.recorder, SELinuxLabel: volumeToMount.SELinuxLabel, + IsRemount: isRemount, }) // Update actual state of world markOpts := MarkVolumeOpts{ diff --git a/pkg/volume/volume.go b/pkg/volume/volume.go index 4a6fc55e29bb7..fa5c7c6025dd7 100644 --- a/pkg/volume/volume.go +++ b/pkg/volume/volume.go @@ -138,6 +138,16 @@ type MounterArgs struct { // Optional interface that will be used to change the ownership of the volume, if specified. // mainly used by unit tests VolumeOwnershipApplicator VolumeOwnershipChanger + + // IsRemount is true when SetUp is being invoked on a volume that the + // reconciler considers already mounted to the pod, e.g. a periodic + // republish triggered by CSIDriver.spec.requiresRepublish=true. Volume + // plugins should use this to avoid destroying state (e.g. mount + // directories, volume metadata files) that the pod is currently + // observing through an existing bind mount, since teardown on a + // failed remount cannot be repaired by a subsequent successful + // remount and would leave the pod with stale contents. + IsRemount bool } type VolumeOwnershipChanger interface { diff --git a/staging/publishing/rules.yaml b/staging/publishing/rules.yaml index beb93c49fed75..681def6c81651 100644 --- a/staging/publishing/rules.yaml +++ b/staging/publishing/rules.yaml @@ -25,7 +25,7 @@ rules: dirs: - staging/src/k8s.io/apimachinery - name: release-1.35 - go: 1.25.9 + go: 1.25.11 source: branch: release-1.35 dirs: @@ -69,7 +69,7 @@ rules: dirs: - staging/src/k8s.io/api - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -140,7 +140,7 @@ rules: go build -mod=mod ./... go test -mod=mod ./... - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -193,7 +193,7 @@ rules: dirs: - staging/src/k8s.io/code-generator - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -255,7 +255,7 @@ rules: dirs: - staging/src/k8s.io/component-base - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -322,7 +322,7 @@ rules: dirs: - staging/src/k8s.io/component-helpers - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -373,7 +373,7 @@ rules: dirs: - staging/src/k8s.io/kms - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -452,7 +452,7 @@ rules: dirs: - staging/src/k8s.io/apiserver - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -555,7 +555,7 @@ rules: dirs: - staging/src/k8s.io/kube-aggregator - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -681,7 +681,7 @@ rules: # assumes GO111MODULE=on go build -mod=mod . - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -788,7 +788,7 @@ rules: # assumes GO111MODULE=on go build -mod=mod . - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -901,7 +901,7 @@ rules: required-packages: - k8s.io/code-generator - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -985,7 +985,7 @@ rules: dirs: - staging/src/k8s.io/metrics - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -1054,7 +1054,7 @@ rules: dirs: - staging/src/k8s.io/cli-runtime - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -1129,7 +1129,7 @@ rules: dirs: - staging/src/k8s.io/sample-cli-plugin - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -1205,7 +1205,7 @@ rules: dirs: - staging/src/k8s.io/kube-proxy - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -1246,7 +1246,7 @@ rules: dirs: - staging/src/k8s.io/cri-api - name: release-1.35 - go: 1.25.9 + go: 1.25.11 source: branch: release-1.35 dirs: @@ -1322,7 +1322,7 @@ rules: dirs: - staging/src/k8s.io/cri-client - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -1425,7 +1425,7 @@ rules: dirs: - staging/src/k8s.io/kubelet - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -1524,7 +1524,7 @@ rules: dirs: - staging/src/k8s.io/controller-manager - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -1637,7 +1637,7 @@ rules: dirs: - staging/src/k8s.io/cloud-provider - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -1762,7 +1762,7 @@ rules: dirs: - staging/src/k8s.io/kube-controller-manager - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -1833,7 +1833,7 @@ rules: dirs: - staging/src/k8s.io/cluster-bootstrap - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -1890,7 +1890,7 @@ rules: dirs: - staging/src/k8s.io/csi-translation-lib - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -1927,7 +1927,7 @@ rules: dirs: - staging/src/k8s.io/mount-utils - name: release-1.35 - go: 1.25.9 + go: 1.25.11 source: branch: release-1.35 dirs: @@ -2027,7 +2027,7 @@ rules: dirs: - staging/src/k8s.io/kubectl - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -2128,7 +2128,7 @@ rules: dirs: - staging/src/k8s.io/pod-security-admission - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -2249,7 +2249,7 @@ rules: dirs: - staging/src/k8s.io/dynamic-resource-allocation - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -2355,7 +2355,7 @@ rules: dirs: - staging/src/k8s.io/kube-scheduler - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: apimachinery branch: release-1.35 @@ -2442,7 +2442,7 @@ rules: dirs: - staging/src/k8s.io/endpointslice - name: release-1.35 - go: 1.25.9 + go: 1.25.11 dependencies: - repository: api branch: release-1.35 @@ -2482,11 +2482,11 @@ rules: dirs: - staging/src/k8s.io/externaljwt - name: release-1.35 - go: 1.25.9 + go: 1.25.11 source: branch: release-1.35 dirs: - staging/src/k8s.io/externaljwt recursive-delete-patterns: - '*/.gitattributes' -default-go-version: 1.25.9 +default-go-version: 1.25.11 diff --git a/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go b/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go index 839fcbc2c17b0..9a4f378483a6a 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/validation/objectmeta.go @@ -46,7 +46,7 @@ func ValidateAnnotations(annotations map[string]string, fldPath *field.Path) fie for k := range annotations { // The rule is QualifiedName except that case doesn't matter, so convert to lowercase before checking. for _, msg := range validation.IsQualifiedName(strings.ToLower(k)) { - allErrs = append(allErrs, field.Invalid(fldPath, k, msg)).WithOrigin("format=k8s-label-key") + allErrs = append(allErrs, field.Invalid(fldPath, k, msg).WithOrigin("format=k8s-label-key")) } } if err := ValidateAnnotationsSize(annotations); err != nil { diff --git a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go index ab5bda03a6a57..98e3c33e1de4c 100644 --- a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go +++ b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go @@ -4078,7 +4078,7 @@ func (x *ImageSpec) GetRuntimeHandler() string { type KeyValue struct { state protoimpl.MessageState `protogen:"open.v1"` Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4120,11 +4120,11 @@ func (x *KeyValue) GetKey() string { return "" } -func (x *KeyValue) GetValue() string { +func (x *KeyValue) GetValue() []byte { if x != nil { return x.Value } - return "" + return nil } // LinuxContainerResources specifies Linux specific configuration for @@ -11571,7 +11571,7 @@ var file_staging_src_k8s_io_cri_api_pkg_apis_runtime_v1_api_proto_rawDesc = stri 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x32, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x95, 0x04, 0x0a, 0x17, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x70, 0x75, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, diff --git a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto index 9e7b26aa72e41..3649609bfc1e3 100644 --- a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto +++ b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto @@ -839,7 +839,7 @@ message ImageSpec { message KeyValue { string key = 1; - string value = 2; + bytes value = 2; } // LinuxContainerResources specifies Linux specific configuration for diff --git a/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go b/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go index 9a62ae4b98403..46ba0c6cd4efb 100644 --- a/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go +++ b/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go @@ -1223,6 +1223,43 @@ func TestAllocator(t *testing.T, deviceAllocationResult(req0, driverA, pool1, device1, false), )}, }, + "all-devices-with-consumed-counters": { + features: Features{ + PartitionableDevices: true, + }, + claimsToAllocate: objects(claimWithRequests(claim0, nil, resourceapi.DeviceRequest{ + Name: req0, + Exactly: &resourceapi.ExactDeviceRequest{ + AllocationMode: resourceapi.DeviceAllocationModeAll, + DeviceClassName: classA, + }, + })), + classes: objects(class(classA, driverA)), + slices: unwrapResourceSlices( + sliceWithDevices(slice1, node1, resourcePool(pool1, 2), driverA, + device(device1, nil, nil).withDeviceCounterConsumption( + deviceCounterConsumption(counterSet1, + map[string]resource.Quantity{ + "memory": resource.MustParse("4Gi"), + }, + ), + ), + ), + sliceWithCounterSets(slice2, node1, resourcePool(pool1, 2), driverA, + counterSet(counterSet1, + map[string]resource.Quantity{ + "memory": resource.MustParse("8Gi"), + }, + ), + ), + ), + node: node(node1, region1), + + expectResults: []any{allocationResult( + localNodeSelector(node1), + deviceAllocationResult(req0, driverA, pool1, device1, false), + )}, + }, "all-devices-many": { claimsToAllocate: objects(claimWithRequests(claim0, nil, resourceapi.DeviceRequest{ Name: req0, diff --git a/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go b/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go index fd63fff1e8e3f..8b4a077485e34 100644 --- a/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go +++ b/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go @@ -552,6 +552,7 @@ func (alloc *allocator) validateDeviceRequest(request requestAccessor, parentReq id: DeviceID{Driver: slice.Spec.Driver, Pool: slice.Spec.Pool.Name, Device: slice.Spec.Devices[deviceIndex].Name}, Device: &slice.Spec.Devices[deviceIndex], slice: slice, + pool: pool, } if alloc.features.ConsumableCapacity { // Next validate whether resource request over capacity diff --git a/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go b/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go index a051dd9640ca2..ef6c113596b0c 100644 --- a/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go +++ b/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go @@ -471,6 +471,7 @@ func (alloc *allocator) validateDeviceRequest(request requestAccessor, parentReq id: DeviceID{Driver: slice.Spec.Driver, Pool: slice.Spec.Pool.Name, Device: slice.Spec.Devices[deviceIndex].Name}, Device: &slice.Spec.Devices[deviceIndex], slice: slice, + pool: pool, } requestData.allDevices = append(requestData.allDevices, device) } diff --git a/test/utils/image/manifest.go b/test/utils/image/manifest.go index c0c6fd35a6b86..0844af178f43a 100644 --- a/test/utils/image/manifest.go +++ b/test/utils/image/manifest.go @@ -214,7 +214,7 @@ func initImageConfigs(list RegistryList) (map[ImageID]Config, map[ImageID]Config configs[APIServer] = Config{list.PromoterE2eRegistry, "sample-apiserver", "1.29.2"} configs[AppArmorLoader] = Config{list.PromoterE2eRegistry, "apparmor-loader", "1.4"} configs[BusyBox] = Config{list.PromoterE2eRegistry, "busybox", "1.37.0-1"} - configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.8.9"} + configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.8.11"} configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.6.6-0"} configs[InvalidRegistryImage] = Config{list.InvalidRegistry, "alpine", "3.1"} configs[IpcUtils] = Config{list.PromoterE2eRegistry, "ipc-utils", "1.3"}