Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
00ab044
Mark API server errors as transient in csi raw block driver
eltrufas Aug 18, 2025
aeeda7b
mark device manager as haelthy before it started for the first time
SergeyKanzhelev Nov 5, 2025
7247ba3
Update CHANGELOG/CHANGELOG-1.32.md for v1.32.10
k8s-release-robot Nov 11, 2025
91fb130
Merge pull request #135066 from eltrufas/automated-cherry-pick-of-#13…
k8s-ci-robot Nov 20, 2025
9af05b6
Fallback to live ns lookup on admission if lister cannot find namespace
liggitt Nov 19, 2025
8ffde8c
Bump dependencies, images and versions used to Go 1.24.10 and distrol…
cpanato Nov 29, 2025
36c9103
Merge pull request #135508 from cpanato/update-go132
k8s-ci-robot Dec 1, 2025
72cc34d
Merge pull request #135444 from lalitc375/automated-cherry-pick-of-#1…
k8s-ci-robot Dec 1, 2025
fff934e
fix docker IP address detection for rsync
BenTheElder Dec 3, 2025
edca070
Merge pull request #135578 from BenTheElder/fix-rsync-1.32
k8s-ci-robot Dec 4, 2025
0ee9937
Merge pull request #135209 from SergeyKanzhelev/automated-cherry-pick…
k8s-ci-robot Dec 4, 2025
1fb4fe1
Bump dependencies, images and versions used to Go 1.24.11 and distrol…
cpanato Dec 5, 2025
ed76e14
Merge pull request #135614 from cpanato/update-rel-132
k8s-ci-robot Dec 5, 2025
cabe97a
upgrade to cos 121
upodroid Oct 2, 2025
8377087
Merge pull request #135700 from xmudrii/automated-cherry-pick-of-#134…
k8s-ci-robot Dec 10, 2025
2195eae
Release commit for Kubernetes v1.32.11
k8s-release-robot Dec 16, 2025
f5fe7e5
Merge tag 'v1.32.11' into release-4.19
dusk125 Dec 17, 2025
9e5eb74
UPSTREAM: <drop>: hack/update-vendor.sh, make update and update image
dusk125 Dec 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .go-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.24.9
1.24.11
300 changes: 211 additions & 89 deletions CHANGELOG/CHANGELOG-1.32.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/build-image/cross/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1.32.0-go1.24.9-bullseye.0
v1.32.0-go1.24.11-bullseye.0
6 changes: 3 additions & 3 deletions build/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ readonly KUBE_RSYNC_PORT="${KUBE_RSYNC_PORT:-}"
readonly KUBE_CONTAINER_RSYNC_PORT=8730

# These are the default versions (image tags) for their respective base images.
readonly __default_distroless_iptables_version=v0.7.11
readonly __default_go_runner_version=v2.4.0-go1.24.9-bookworm.0
readonly __default_distroless_iptables_version=v0.7.13
readonly __default_go_runner_version=v2.4.0-go1.24.11-bookworm.0
readonly __default_setcap_version=bookworm-v1.0.6

# These are the base images for the Docker-wrapped binaries.
Expand Down Expand Up @@ -621,7 +621,7 @@ function kube::build::start_rsyncd_container() {
fi

local container_ip
container_ip=$("${DOCKER[@]}" inspect --format '{{ .NetworkSettings.IPAddress }}' "${KUBE_RSYNC_CONTAINER_NAME}")
container_ip=$("${DOCKER[@]}" inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}},{{end}}' "${KUBE_RSYNC_CONTAINER_NAME}" | cut -d',' -f1)

# Sometimes we can reach rsync through localhost and a NAT'd port. Other
# times (when we are running in another docker container on the Jenkins
Expand Down
8 changes: 4 additions & 4 deletions build/dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ dependencies:

# Golang
- name: "golang: upstream version"
version: 1.24.9
version: 1.24.11
refPaths:
- path: .go-version
- path: build/build-image/cross/VERSION
Expand All @@ -137,7 +137,7 @@ dependencies:
match: golang:([0-9]+\.[0-9]+).0-bullseye

- name: "registry.k8s.io/kube-cross: dependents"
version: v1.32.0-go1.24.9-bullseye.0
version: v1.32.0-go1.24.11-bullseye.0
refPaths:
- path: build/build-image/cross/VERSION

Expand Down Expand Up @@ -175,15 +175,15 @@ 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.7.11
version: v0.7.13
refPaths:
- path: build/common.sh
match: __default_distroless_iptables_version=
- path: test/utils/image/manifest.go
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.24.9-bookworm.0
version: v2.4.0-go1.24.11-bookworm.0
refPaths:
- path: build/common.sh
match: __default_go_runner_version=
Expand Down
2 changes: 1 addition & 1 deletion cluster/gce/config-default.sh
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ fi
# By default, the latest image from the image family will be used unless an
# explicit image will be set.
GCI_VERSION=${KUBE_GCI_VERSION:-}
IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-109-lts}
IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-121-lts}
export MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-}
export MASTER_IMAGE_FAMILY=${KUBE_GCE_MASTER_IMAGE_FAMILY:-${IMAGE_FAMILY}}
export MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud}
Expand Down
2 changes: 1 addition & 1 deletion cluster/gce/config-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ ALLOWED_NOTREADY_NODES=${ALLOWED_NOTREADY_NODES:-$(($(get-num-nodes) / 100))}
# By default, the latest image from the image family will be used unless an
# explicit image will be set.
GCI_VERSION=${KUBE_GCI_VERSION:-}
IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-109-lts}
IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-121-lts}
export MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-}
export MASTER_IMAGE_FAMILY=${KUBE_GCE_MASTER_IMAGE_FAMILY:-${IMAGE_FAMILY}}
export MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud}
Expand Down
2 changes: 1 addition & 1 deletion openshift-hack/images/hyperkube/Dockerfile.rhel
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,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.32.10"
io.openshift.build.versions="kubernetes=1.32.11"
21 changes: 11 additions & 10 deletions pkg/kubelet/cm/devicemanager/plugin/v1beta1/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ type server struct {
chandler ClientHandler
clients map[string]Client

// isStarted indicates whether the service has started successfully.
isStarted bool
// lastError records the last runtime error. A server is considered healthy till an actual error occurs.
lastError error
}

// NewServer returns an initialized device plugin registration server.
Expand Down Expand Up @@ -117,7 +117,7 @@ func (s *server) Start() error {
defer s.wg.Done()
s.setHealthy()
if err = s.grpc.Serve(ln); err != nil {
s.setUnhealthy()
s.setUnhealthy(err)
klog.ErrorS(err, "Error while serving device plugin registration grpc server")
}
}()
Expand Down Expand Up @@ -207,18 +207,19 @@ func (s *server) Name() string {
}

func (s *server) Check(_ *http.Request) error {
if s.isStarted {
return nil
}
return fmt.Errorf("device plugin registration gRPC server failed and no device plugins can register")
return s.lastError
}

// setHealthy sets the health status of the gRPC server.
func (s *server) setHealthy() {
s.isStarted = true
s.lastError = nil
}

// setUnhealthy sets the health status of the gRPC server to unhealthy.
func (s *server) setUnhealthy() {
s.isStarted = false
func (s *server) setUnhealthy(err error) {
if err == nil {
s.lastError = fmt.Errorf("device registration error: device plugin registration gRPC server failed and no device plugins can register")
return
}
s.lastError = fmt.Errorf("device registration error: device plugin registration gRPC server failed and no device plugins can register: %w", err)
}
15 changes: 7 additions & 8 deletions pkg/volume/csi/csi_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ package csi
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"

Expand Down Expand Up @@ -171,8 +170,8 @@ func (m *csiBlockMapper) stageVolumeForBlock(
if csiSource.NodeStageSecretRef != nil {
nodeStageSecrets, err = getCredentialsFromSecret(m.k8s, csiSource.NodeStageSecretRef)
if err != nil {
return "", fmt.Errorf("failed to get NodeStageSecretRef %s/%s: %v",
csiSource.NodeStageSecretRef.Namespace, csiSource.NodeStageSecretRef.Name, err)
return "", volumetypes.NewTransientOperationFailure(log("failed to get NodeStageSecretRef %s/%s: %v",
csiSource.NodeStageSecretRef.Namespace, csiSource.NodeStageSecretRef.Name, err))
}
}

Expand Down Expand Up @@ -223,11 +222,11 @@ func (m *csiBlockMapper) publishVolumeForBlock(
volAttribs := csiSource.VolumeAttributes
podInfoEnabled, err := m.plugin.podInfoEnabled(string(m.driverName))
if err != nil {
return "", errors.New(log("blockMapper.publishVolumeForBlock failed to assemble volume attributes: %v", err))
return "", volumetypes.NewTransientOperationFailure(log("blockMapper.publishVolumeForBlock failed to assemble volume attributes: %v", err))
}
volumeLifecycleMode, err := m.plugin.getVolumeLifecycleMode(m.spec)
if err != nil {
return "", errors.New(log("blockMapper.publishVolumeForBlock failed to get VolumeLifecycleMode: %v", err))
return "", volumetypes.NewTransientOperationFailure(log("blockMapper.publishVolumeForBlock failed to get VolumeLifecycleMode: %v", err))
}
if podInfoEnabled {
volAttribs = mergeMap(volAttribs, getPodInfoAttrs(m.pod, volumeLifecycleMode))
Expand All @@ -237,7 +236,7 @@ func (m *csiBlockMapper) publishVolumeForBlock(
if csiSource.NodePublishSecretRef != nil {
nodePublishSecrets, err = getCredentialsFromSecret(m.k8s, csiSource.NodePublishSecretRef)
if err != nil {
return "", errors.New(log("blockMapper.publishVolumeForBlock failed to get NodePublishSecretRef %s/%s: %v",
return "", volumetypes.NewTransientOperationFailure(log("blockMapper.publishVolumeForBlock failed to get NodePublishSecretRef %s/%s: %v",
csiSource.NodePublishSecretRef.Namespace, csiSource.NodePublishSecretRef.Name, err))
}
}
Expand Down Expand Up @@ -304,7 +303,7 @@ func (m *csiBlockMapper) SetUpDevice() (string, error) {
attachID := getAttachmentName(csiSource.VolumeHandle, csiSource.Driver, nodeName)
attachment, err = m.k8s.StorageV1().VolumeAttachments().Get(context.TODO(), attachID, meta.GetOptions{})
if err != nil {
return "", errors.New(log("blockMapper.SetupDevice failed to get volume attachment [id=%v]: %v", attachID, err))
return "", volumetypes.NewTransientOperationFailure(log("blockMapper.SetupDevice failed to get volume attachment [id=%v]: %v", attachID, err))
}
}

Expand Down Expand Up @@ -366,7 +365,7 @@ func (m *csiBlockMapper) MapPodDevice() (string, error) {
attachID := getAttachmentName(csiSource.VolumeHandle, csiSource.Driver, nodeName)
attachment, err = m.k8s.StorageV1().VolumeAttachments().Get(context.TODO(), attachID, meta.GetOptions{})
if err != nil {
return "", errors.New(log("blockMapper.MapPodDevice failed to get volume attachment [id=%v]: %v", attachID, err))
return "", volumetypes.NewTransientOperationFailure(log("blockMapper.MapPodDevice failed to get volume attachment [id=%v]: %v", attachID, err))
}
}

Expand Down
41 changes: 41 additions & 0 deletions pkg/volume/csi/csi_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package csi

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -491,6 +492,46 @@ func TestBlockMapperMapPodDeviceNoClientError(t *testing.T) {
}
}

func TestBlockMapperMapPodDeviceGetStageSecretsError(t *testing.T) {
transientError := volumetypes.NewTransientOperationFailure("")
plug, tmpDir := newTestPlugin(t, nil)
defer func() {
if err := os.RemoveAll(tmpDir); err != nil {
t.Error(err)
}
}()

csiMapper, _, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
if err != nil {
t.Fatalf("Failed to make a new Mapper: %v", err)
}

// set a stage secret for the pv
pv.Spec.PersistentVolumeSource.CSI.NodePublishSecretRef = &api.SecretReference{
Name: "foo",
Namespace: "default",
}
pvName := pv.GetName()
nodeName := string(plug.host.GetNodeName())

csiMapper.csiClient = setupClient(t, true)

attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), nodeName)
attachment := makeTestAttachment(attachID, nodeName, pvName)
attachment.Status.Attached = true
if _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.Background(), attachment, metav1.CreateOptions{}); err != nil {
t.Fatalf("failed to setup VolumeAttachment: %v", err)
}
t.Log("created attachment ", attachID)

_, err = csiMapper.MapPodDevice()
if err == nil {
t.Errorf("test should fail, but no error occurred")
} else if !errors.As(err, &transientError) {
t.Errorf("expected a transient error but got %v", err)
}
}

func TestBlockMapperTearDownDevice(t *testing.T) {
plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir)
Expand Down
2 changes: 1 addition & 1 deletion staging/publishing/rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2900,4 +2900,4 @@ rules:
- staging/src/k8s.io/externaljwt
recursive-delete-patterns:
- '*/.gitattributes'
default-go-version: 1.24.9
default-go-version: 1.24.11
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package generic

import (
"context"
"fmt"

admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
Expand All @@ -41,8 +42,8 @@ type PolicyMatcher interface {
BindingMatches(a admission.Attributes, o admission.ObjectInterfaces, binding BindingAccessor) (bool, error)

// GetNamespace retrieves the Namespace resource by the given name. The name may be empty, in which case
// GetNamespace must return nil, nil
GetNamespace(name string) (*corev1.Namespace, error)
// GetNamespace must return nil, NotFound
GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error)
}

type matcher struct {
Expand Down Expand Up @@ -82,8 +83,8 @@ func (c *matcher) BindingMatches(a admission.Attributes, o admission.ObjectInter
return isMatch, err
}

func (c *matcher) GetNamespace(name string) (*corev1.Namespace, error) {
return c.Matcher.GetNamespace(name)
func (c *matcher) GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error) {
return c.Matcher.GetNamespace(ctx, name)
}

var _ matching.MatchCriteria = &matchCriteria{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package matching

import (
"context"
"fmt"

v1 "k8s.io/api/admissionregistration/v1"
Expand Down Expand Up @@ -44,8 +45,8 @@ type Matcher struct {
objectMatcher *object.Matcher
}

func (m *Matcher) GetNamespace(name string) (*corev1.Namespace, error) {
return m.namespaceMatcher.GetNamespace(name)
func (m *Matcher) GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error) {
return m.namespaceMatcher.GetNamespace(ctx, name)
}

// NewMatcher initialize the matcher with dependencies requires
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,12 @@ func (d *dispatcher) dispatchInvocations(
// if it is cluster scoped, namespaceName will be empty
// Otherwise, get the Namespace resource.
if namespaceName != "" {
namespace, err = d.matcher.GetNamespace(namespaceName)
namespace, err = d.matcher.GetNamespace(ctx, namespaceName)
if err != nil {
var statusError *k8serrors.StatusError
if errors.As(err, &statusError) {
return nil, statusError
}
return nil, k8serrors.NewNotFound(schema.GroupResource{Group: "", Resource: "namespaces"}, namespaceName)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ func (f *fakeMatcher) ValidateInitialization() error {
return nil
}

func (f *fakeMatcher) GetNamespace(name string) (*v1.Namespace, error) {
func (f *fakeMatcher) GetNamespace(ctx context.Context, name string) (*v1.Namespace, error) {
return nil, nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func (c *dispatcher) Dispatch(ctx context.Context, a admission.Attributes, o adm
// if it is cluster scoped, namespaceName will be empty
// Otherwise, get the Namespace resource.
if namespaceName != "" {
namespace, err = c.matcher.GetNamespace(namespaceName)
namespace, err = c.matcher.GetNamespace(ctx, namespaceName)
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,13 @@ type Matcher struct {
Client clientset.Interface
}

func (m *Matcher) GetNamespace(name string) (*v1.Namespace, error) {
return m.NamespaceLister.Get(name)
func (m *Matcher) GetNamespace(ctx context.Context, name string) (*v1.Namespace, error) {
ns, err := m.NamespaceLister.Get(name)
if apierrors.IsNotFound(err) && len(name) > 0 {
// in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
ns, err = m.Client.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{})
}
return ns, err
}

// Validate checks if the Matcher has a NamespaceLister and Client.
Expand Down
2 changes: 1 addition & 1 deletion test/images/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ REGISTRY ?= registry.k8s.io/e2e-test-images
GOARM ?= 7
DOCKER_CERT_BASE_PATH ?=
QEMUVERSION=v5.1.0-2
GOLANG_VERSION=1.24.9
GOLANG_VERSION=1.24.11
export

ifndef WHAT
Expand Down
2 changes: 1 addition & 1 deletion test/utils/image/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,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.36.1-1"}
configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.7.11"}
configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.7.13"}
configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.5.16-0"}
configs[Httpd] = Config{list.PromoterE2eRegistry, "httpd", "2.4.38-4"}
configs[HttpdNew] = Config{list.PromoterE2eRegistry, "httpd", "2.4.39-4"}
Expand Down