kubeadm: add support for patching a corednsdeployment target

This commit is contained in:
SataQiu 2024-05-11 18:21:20 +08:00
parent 925cb2be30
commit 1329935739
10 changed files with 62 additions and 22 deletions

View File

@ -468,7 +468,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".
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment".
// "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

@ -438,7 +438,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".
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment".
// "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

@ -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".
// "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment".
// "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

@ -99,7 +99,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". ` +
`"target" can be one of "kube-apiserver", "kube-controller-manager", "kube-scheduler", "etcd", "kubeletconfiguration", "corednsdeployment". ` +
`"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

@ -84,10 +84,10 @@ func NewAddonPhase() workflow.Phase {
}
}
func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, io.Writer, error) {
func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, string, io.Writer, error) {
data, ok := c.(InitData)
if !ok {
return nil, nil, nil, errors.New("addon phase invoked with an invalid data struct")
return nil, nil, "", nil, errors.New("addon phase invoked with an invalid data struct")
}
cfg := data.Cfg()
var client clientset.Interface
@ -95,26 +95,27 @@ func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.I
if !printManifest {
client, err = data.Client()
if err != nil {
return nil, nil, nil, err
return nil, nil, "", nil, err
}
}
out := data.OutputWriter()
return cfg, client, out, err
patchesDir := data.PatchesDir()
return cfg, client, patchesDir, out, err
}
// runCoreDNSAddon installs CoreDNS addon to a Kubernetes cluster
func runCoreDNSAddon(c workflow.RunData) error {
cfg, client, out, err := getInitData(c)
cfg, client, patchesDir, out, err := getInitData(c)
if err != nil {
return err
}
return dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client, out, printManifest)
return dnsaddon.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, printManifest)
}
// runKubeProxyAddon installs KubeProxy addon to a Kubernetes cluster
func runKubeProxyAddon(c workflow.RunData) error {
cfg, client, out, err := getInitData(c)
cfg, client, _, out, err := getInitData(c)
if err != nil {
return err
}

View File

@ -78,7 +78,7 @@ func runControlPlane() func(c workflow.RunData) error {
return errors.Wrap(err, "couldn't complete the static pod upgrade")
}
if err := upgrade.PerformAddonsUpgrade(client, cfg, data.OutputWriter()); err != nil {
if err := upgrade.PerformAddonsUpgrade(client, cfg, data.PatchesDir(), data.OutputWriter()); err != nil {
return errors.Wrap(err, "failed to perform addons upgrade")
}

View File

@ -35,6 +35,7 @@ import (
clientset "k8s.io/client-go/kubernetes"
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/klog/v2"
"sigs.k8s.io/yaml"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
@ -42,6 +43,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/image"
"k8s.io/kubernetes/cmd/kubeadm/app/util/patches"
)
const (
@ -85,7 +87,7 @@ func deployedDNSReplicas(client clientset.Interface, replicas int32) (*int32, er
}
// EnsureDNSAddon creates the CoreDNS addon
func EnsureDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, out io.Writer, printManifest bool) error {
func EnsureDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, patchesDir string, out io.Writer, printManifest bool) error {
var replicas *int32
var err error
if !printManifest {
@ -97,10 +99,10 @@ func EnsureDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Inter
var defaultReplicas int32 = coreDNSReplicas
replicas = &defaultReplicas
}
return coreDNSAddon(cfg, client, replicas, out, printManifest)
return coreDNSAddon(cfg, client, replicas, patchesDir, out, printManifest)
}
func coreDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, replicas *int32, out io.Writer, printManifest bool) error {
func coreDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, replicas *int32, patchesDir string, out io.Writer, printManifest bool) error {
// Get the YAML manifest
coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(CoreDNSDeployment, struct {
DeploymentName, Image, ControlPlaneTaintKey string
@ -115,6 +117,14 @@ func coreDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interfa
return errors.Wrap(err, "error when parsing CoreDNS deployment template")
}
// Apply patches to the CoreDNS Deployment
if len(patchesDir) != 0 {
coreDNSDeploymentBytes, err = applyCoreDNSDeploymentPatches(coreDNSDeploymentBytes, patchesDir, out)
if err != nil {
return errors.Wrap(err, "could not apply patches to the CoreDNS Deployment")
}
}
// Get the config file for CoreDNS
coreDNSConfigMapBytes, err := kubeadmutil.ParseTemplate(CoreDNSConfigMap, struct{ DNSDomain, UpstreamNameserver, StubDomain string }{
DNSDomain: cfg.Networking.DNSDomain,
@ -377,3 +387,27 @@ func setCorefile(client clientset.Interface, coreDNSCorefileName string) error {
}
return nil
}
// applyCoreDNSDeploymentPatches reads patches from a directory and applies them over the input coreDNSDeploymentBytes
func applyCoreDNSDeploymentPatches(coreDNSDeploymentBytes []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.CoreDNSDeployment,
StrategicMergePatchObject: apps.Deployment{},
Data: coreDNSDeploymentBytes,
}
if err := patchManager.ApplyPatchesToTarget(patchTarget); err != nil {
return nil, err
}
coreDNSDeploymentBytes, err = yaml.JSONToYAML(patchTarget.Data)
if err != nil {
return nil, err
}
return coreDNSDeploymentBytes, nil
}

View File

@ -865,7 +865,7 @@ metadata:
t.Run(tt.name, func(t *testing.T) {
out := &bytes.Buffer{}
var replicas int32 = 3
if err := coreDNSAddon(tt.args.cfg, tt.args.client, &replicas, out, tt.args.printManifest); (err != nil) != tt.wantErr {
if err := coreDNSAddon(tt.args.cfg, tt.args.client, &replicas, "", out, tt.args.printManifest); (err != nil) != tt.wantErr {
t.Errorf("coreDNSAddon() error = %v, wantErr %v", err, tt.wantErr)
return
}
@ -1148,7 +1148,7 @@ metadata:
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := &bytes.Buffer{}
if err := EnsureDNSAddon(tt.args.cfg, tt.args.client, out, tt.args.printManifest); (err != nil) != tt.wantErr {
if err := EnsureDNSAddon(tt.args.cfg, tt.args.client, "", out, tt.args.printManifest); (err != nil) != tt.wantErr {
t.Errorf("EnsureDNSAddon() error = %v, wantErr %v", err, tt.wantErr)
return
}

View File

@ -105,7 +105,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.InitCon
errs = append(errs, err)
}
if err := PerformAddonsUpgrade(client, cfg, out); err != nil {
if err := PerformAddonsUpgrade(client, cfg, patchesDir, out); err != nil {
errs = append(errs, err)
}
@ -113,7 +113,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.InitCon
}
// PerformAddonsUpgrade performs the upgrade of the coredns and kube-proxy addons.
func PerformAddonsUpgrade(client clientset.Interface, cfg *kubeadmapi.InitConfiguration, out io.Writer) error {
func PerformAddonsUpgrade(client clientset.Interface, cfg *kubeadmapi.InitConfiguration, patchesDir string, out io.Writer) error {
unupgradedControlPlanes, err := unupgradedControlPlaneInstances(client, cfg.NodeRegistration.Name)
if err != nil {
return errors.Wrapf(err, "failed to determine whether all the control plane instances have been upgraded")
@ -147,7 +147,7 @@ func PerformAddonsUpgrade(client clientset.Interface, cfg *kubeadmapi.InitConfig
metav1.NamespaceSystem)
} else {
// Upgrade CoreDNS
if err := dns.EnsureDNSAddon(&cfg.ClusterConfiguration, client, out, false); err != nil {
if err := dns.EnsureDNSAddon(&cfg.ClusterConfiguration, client, patchesDir, out, false); err != nil {
errs = append(errs, err)
}
}

View File

@ -75,8 +75,12 @@ func (ps *patchSet) String() string {
)
}
// KubeletConfiguration defines the kubeletconfiguration patch target.
const KubeletConfiguration = "kubeletconfiguration"
const (
// KubeletConfiguration defines the kubeletconfiguration patch target.
KubeletConfiguration = "kubeletconfiguration"
// CoreDNSDeployment defines the corednsdeployment patch target.
CoreDNSDeployment = "corednsdeployment"
)
var (
pathLock = &sync.RWMutex{}
@ -100,6 +104,7 @@ var (
kubeadmconstants.KubeControllerManager,
kubeadmconstants.KubeScheduler,
KubeletConfiguration,
CoreDNSDeployment,
}
)