kubeadm: add kubeproxydaemonset patch target

This commit is contained in:
SataQiu 2026-03-29 11:56:38 +08:00
parent c6a95ffd4c
commit 4df6d0904c
9 changed files with 86 additions and 13 deletions

View file

@ -487,7 +487,7 @@ type HostPathMount struct {
type Patches struct {
// Directory is a path to a directory that contains files named "target[suffix][+patchtype].extension".
// For example, "kube-apiserver0+merge.yaml" or just "etcd.json". "target" can be one of
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment".
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment", "kubeproxydaemonset".
// "patchtype" can be one of "strategic" "merge" or "json" and they match the patch formats supported by kubectl.
// The default "patchtype" is "strategic". "extension" must be either "json" or "yaml".
// "suffix" is an optional string that can be used to determine which patches are applied

View file

@ -441,7 +441,7 @@ type HostPathMount struct {
type Patches struct {
// Directory is a path to a directory that contains files named "target[suffix][+patchtype].extension".
// For example, "kube-apiserver0+merge.yaml" or just "etcd.json". "target" can be one of
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment".
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment", "kubeproxydaemonset".
// "patchtype" can be one of "strategic" "merge" or "json" and they match the patch formats supported by kubectl.
// The default "patchtype" is "strategic". "extension" must be either "json" or "yaml".
// "suffix" is an optional string that can be used to determine which patches are applied

View file

@ -507,7 +507,7 @@ type HostPathMount struct {
type Patches struct {
// Directory is a path to a directory that contains files named "target[suffix][+patchtype].extension".
// For example, "kube-apiserver0+merge.yaml" or just "etcd.json". "target" can be one of
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment".
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment", "kubeproxydaemonset".
// "patchtype" can be one of "strategic" "merge" or "json" and they match the patch formats supported by kubectl.
// The default "patchtype" is "strategic". "extension" must be either "json" or "yaml".
// "suffix" is an optional string that can be used to determine which patches are applied

View file

@ -105,7 +105,7 @@ func AddPatchesFlag(fs *pflag.FlagSet, patchesDir *string) {
const usage = `Path to a directory that contains files named ` +
`"target[suffix][+patchtype].extension". For example, ` +
`"kube-apiserver0+merge.yaml" or just "etcd.json". ` +
`"target" can be one of "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment". ` +
`"target" can be one of "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment", "kubeproxydaemonset". ` +
`"patchtype" can be one of "strategic", "merge" or "json" and they match the patch formats ` +
`supported by kubectl. The default "patchtype" is "strategic". "extension" must be either ` +
`"json" or "yaml". "suffix" is an optional string that can be used to determine ` +

View file

@ -114,11 +114,11 @@ func runCoreDNSAddon(c workflow.RunData) error {
// runKubeProxyAddon installs KubeProxy addon to a Kubernetes cluster
func runKubeProxyAddon(c workflow.RunData) error {
cfg, client, _, out, err := getInitData(c)
cfg, client, patchesDir, out, err := getInitData(c)
if err != nil {
return err
}
return proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, printManifest)
return proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, patchesDir, out, printManifest)
}
func getAddonPhaseFlags(name string) []string {

View file

@ -118,7 +118,7 @@ func runCoreDNSAddon(c workflow.RunData) error {
func runKubeProxyAddon(c workflow.RunData) error {
const skipMessagePrefix = "[upgrade/addon] Skipping the addon/kube-proxy phase."
cfg, client, _, out, dryRun, isControlPlaneNode, err := getInitData(c)
cfg, client, patchesDir, out, dryRun, isControlPlaneNode, err := getInitData(c)
if err != nil {
return err
}
@ -141,7 +141,7 @@ func runKubeProxyAddon(c workflow.RunData) error {
return nil
}
if err := proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, out, dryRun); err != nil {
if err := proxyaddon.EnsureProxyAddon(&cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, client, patchesDir, out, dryRun); err != nil {
return err
}
@ -154,7 +154,7 @@ func getAddonPhaseFlags(name string) []string {
options.KubeconfigPath,
options.DryRun,
}
if name == "all" || name == "coredns" {
if name == "all" || name == "coredns" || name == "kube-proxy" {
flags = append(flags,
options.Patches,
)

View file

@ -30,6 +30,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
clientset "k8s.io/client-go/kubernetes"
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/yaml"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
@ -38,6 +39,7 @@ import (
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
"k8s.io/kubernetes/cmd/kubeadm/app/util/errors"
"k8s.io/kubernetes/cmd/kubeadm/app/util/patches"
)
const (
@ -49,13 +51,13 @@ const (
)
// EnsureProxyAddon creates the kube-proxy addons
func EnsureProxyAddon(cfg *kubeadmapi.ClusterConfiguration, localEndpoint *kubeadmapi.APIEndpoint, client clientset.Interface, out io.Writer, printManifest bool) error {
func EnsureProxyAddon(cfg *kubeadmapi.ClusterConfiguration, localEndpoint *kubeadmapi.APIEndpoint, client clientset.Interface, patchesDir string, out io.Writer, printManifest bool) error {
cmByte, err := createKubeProxyConfigMap(cfg, localEndpoint, client, printManifest)
if err != nil {
return err
}
dsByte, err := createKubeProxyAddon(cfg, client, printManifest)
dsByte, err := createKubeProxyAddon(cfg, client, patchesDir, out, printManifest)
if err != nil {
return err
}
@ -245,7 +247,7 @@ func createKubeProxyConfigMap(cfg *kubeadmapi.ClusterConfiguration, localEndpoin
return []byte(""), apiclient.CreateOrUpdate(client.CoreV1().ConfigMaps(kubeproxyConfigMap.GetNamespace()), kubeproxyConfigMap)
}
func createKubeProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, printManifest bool) ([]byte, error) {
func createKubeProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, patchesDir string, output io.Writer, printManifest bool) ([]byte, error) {
daemonSetbytes, err := kubeadmutil.ParseTemplate(KubeProxyDaemonSet19, struct{ Image, ProxyConfigMap, ProxyConfigMapKey string }{
Image: images.GetKubernetesImage(constants.KubeProxy, cfg),
ProxyConfigMap: constants.KubeProxyConfigMap,
@ -255,6 +257,13 @@ func createKubeProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset
return []byte(""), errors.Wrap(err, "error when parsing kube-proxy daemonset template")
}
if len(patchesDir) != 0 {
daemonSetbytes, err = applyKubeProxyDaemonSetPatches(daemonSetbytes, patchesDir, output)
if err != nil {
return []byte(""), errors.Wrap(err, "could not apply patches to the kube-proxy DaemonSet")
}
}
if printManifest {
return daemonSetbytes, nil
}
@ -270,3 +279,27 @@ func createKubeProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset
// Create the DaemonSet for kube-proxy or update it in case it already exists
return []byte(""), apiclient.CreateOrUpdate(client.AppsV1().DaemonSets(kubeproxyDaemonSet.GetNamespace()), kubeproxyDaemonSet)
}
// applyKubeProxyDaemonSetPatches reads patches from a directory and applies them over the input kubeProxyDaemonSetBytes.
func applyKubeProxyDaemonSetPatches(kubeProxyDaemonSetBytes []byte, patchesDir string, output io.Writer) ([]byte, error) {
patchManager, err := patches.GetPatchManagerForPath(patchesDir, patches.KnownTargets(), output)
if err != nil {
return nil, err
}
patchTarget := &patches.PatchTarget{
Name: patches.KubeProxyDaemonSet,
StrategicMergePatchObject: apps.DaemonSet{},
Data: kubeProxyDaemonSetBytes,
}
if err := patchManager.ApplyPatchesToTarget(patchTarget); err != nil {
return nil, err
}
kubeProxyDaemonSetBytes, err = yaml.JSONToYAML(patchTarget.Data)
if err != nil {
return nil, err
}
return kubeProxyDaemonSetBytes, nil
}

View file

@ -20,6 +20,7 @@ import (
"bytes"
"context"
"os"
"path/filepath"
"strings"
"testing"
"time"
@ -156,7 +157,7 @@ func TestEnsureProxyAddon(t *testing.T) {
initConfiguration.ClusterConfiguration.Networking.PodSubnet = "2001:101::/48"
}
err = EnsureProxyAddon(&initConfiguration.ClusterConfiguration, &initConfiguration.LocalAPIEndpoint, client, os.Stdout, false)
err = EnsureProxyAddon(&initConfiguration.ClusterConfiguration, &initConfiguration.LocalAPIEndpoint, client, "", os.Stdout, false)
// Compare actual to expected errors
actErr := "No error"
@ -178,6 +179,42 @@ func TestEnsureProxyAddon(t *testing.T) {
}
}
func TestApplyKubeProxyDaemonSetPatches(t *testing.T) {
daemonSetBytes, err := kubeadmutil.ParseTemplate(KubeProxyDaemonSet19, struct{ Image, ProxyConfigMap, ProxyConfigMapKey string }{
Image: "foo",
ProxyConfigMap: "bar",
ProxyConfigMapKey: "baz",
})
if err != nil {
t.Fatalf("unexpected ParseTemplate failure: %v", err)
}
tmpDir := t.TempDir()
patchFile := filepath.Join(tmpDir, "kubeproxydaemonset+strategic.yaml")
patch := `spec:
template:
spec:
hostNetwork: false
`
if err := os.WriteFile(patchFile, []byte(patch), 0600); err != nil {
t.Fatalf("failed writing patch file: %v", err)
}
patchedDaemonSetBytes, err := applyKubeProxyDaemonSetPatches(daemonSetBytes, tmpDir, os.Stdout)
if err != nil {
t.Fatalf("applyKubeProxyDaemonSetPatches returned error: %v", err)
}
kubeproxyDaemonSet := &apps.DaemonSet{}
if err := runtime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), patchedDaemonSetBytes, kubeproxyDaemonSet); err != nil {
t.Fatalf("unable to decode kube-proxy daemonset: %v", err)
}
if kubeproxyDaemonSet.Spec.Template.Spec.HostNetwork {
t.Fatal("expected patched kube-proxy daemonset hostNetwork to be false")
}
}
func TestDaemonSetsHaveSystemNodeCriticalPriorityClassName(t *testing.T) {
testCases := []struct {
name string

View file

@ -82,6 +82,8 @@ const (
KubeletConfiguration = "kubeletconfiguration"
// CoreDNSDeployment defines the corednsdeployment patch target.
CoreDNSDeployment = "corednsdeployment"
// KubeProxyDaemonSet defines the kubeproxydaemonset patch target.
KubeProxyDaemonSet = "kubeproxydaemonset"
)
var (
@ -107,6 +109,7 @@ var (
kubeadmconstants.KubeScheduler,
KubeletConfiguration,
CoreDNSDeployment,
KubeProxyDaemonSet,
}
)