mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-10 04:27:54 +00:00
kubeadm: add support for patching a corednsdeployment target
This commit is contained in:
parent
925cb2be30
commit
1329935739
@ -468,7 +468,7 @@ type HostPathMount struct {
|
|||||||
type Patches struct {
|
type Patches struct {
|
||||||
// Directory is a path to a directory that contains files named "target[suffix][+patchtype].extension".
|
// 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
|
// 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.
|
// "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".
|
// 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
|
// "suffix" is an optional string that can be used to determine which patches are applied
|
||||||
|
@ -438,7 +438,7 @@ type HostPathMount struct {
|
|||||||
type Patches struct {
|
type Patches struct {
|
||||||
// Directory is a path to a directory that contains files named "target[suffix][+patchtype].extension".
|
// 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
|
// 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.
|
// "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".
|
// 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
|
// "suffix" is an optional string that can be used to determine which patches are applied
|
||||||
|
@ -487,7 +487,7 @@ type HostPathMount struct {
|
|||||||
type Patches struct {
|
type Patches struct {
|
||||||
// Directory is a path to a directory that contains files named "target[suffix][+patchtype].extension".
|
// 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
|
// 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.
|
// "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".
|
// 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
|
// "suffix" is an optional string that can be used to determine which patches are applied
|
||||||
|
@ -99,7 +99,7 @@ func AddPatchesFlag(fs *pflag.FlagSet, patchesDir *string) {
|
|||||||
const usage = `Path to a directory that contains files named ` +
|
const usage = `Path to a directory that contains files named ` +
|
||||||
`"target[suffix][+patchtype].extension". For example, ` +
|
`"target[suffix][+patchtype].extension". For example, ` +
|
||||||
`"kube-apiserver0+merge.yaml" or just "etcd.json". ` +
|
`"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 ` +
|
`"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 ` +
|
`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 ` +
|
`"json" or "yaml". "suffix" is an optional string that can be used to determine ` +
|
||||||
|
@ -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)
|
data, ok := c.(InitData)
|
||||||
if !ok {
|
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()
|
cfg := data.Cfg()
|
||||||
var client clientset.Interface
|
var client clientset.Interface
|
||||||
@ -95,26 +95,27 @@ func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.I
|
|||||||
if !printManifest {
|
if !printManifest {
|
||||||
client, err = data.Client()
|
client, err = data.Client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, "", nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out := data.OutputWriter()
|
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
|
// runCoreDNSAddon installs CoreDNS addon to a Kubernetes cluster
|
||||||
func runCoreDNSAddon(c workflow.RunData) error {
|
func runCoreDNSAddon(c workflow.RunData) error {
|
||||||
cfg, client, out, err := getInitData(c)
|
cfg, client, patchesDir, out, err := getInitData(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// runKubeProxyAddon installs KubeProxy addon to a Kubernetes cluster
|
||||||
func runKubeProxyAddon(c workflow.RunData) error {
|
func runKubeProxyAddon(c workflow.RunData) error {
|
||||||
cfg, client, out, err := getInitData(c)
|
cfg, client, _, out, err := getInitData(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ func runControlPlane() func(c workflow.RunData) error {
|
|||||||
return errors.Wrap(err, "couldn't complete the static pod upgrade")
|
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")
|
return errors.Wrap(err, "failed to perform addons upgrade")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
@ -42,6 +43,7 @@ import (
|
|||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/image"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/image"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/patches"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -85,7 +87,7 @@ func deployedDNSReplicas(client clientset.Interface, replicas int32) (*int32, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EnsureDNSAddon creates the CoreDNS addon
|
// 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 replicas *int32
|
||||||
var err error
|
var err error
|
||||||
if !printManifest {
|
if !printManifest {
|
||||||
@ -97,10 +99,10 @@ func EnsureDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Inter
|
|||||||
var defaultReplicas int32 = coreDNSReplicas
|
var defaultReplicas int32 = coreDNSReplicas
|
||||||
replicas = &defaultReplicas
|
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
|
// Get the YAML manifest
|
||||||
coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(CoreDNSDeployment, struct {
|
coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(CoreDNSDeployment, struct {
|
||||||
DeploymentName, Image, ControlPlaneTaintKey string
|
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")
|
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
|
// Get the config file for CoreDNS
|
||||||
coreDNSConfigMapBytes, err := kubeadmutil.ParseTemplate(CoreDNSConfigMap, struct{ DNSDomain, UpstreamNameserver, StubDomain string }{
|
coreDNSConfigMapBytes, err := kubeadmutil.ParseTemplate(CoreDNSConfigMap, struct{ DNSDomain, UpstreamNameserver, StubDomain string }{
|
||||||
DNSDomain: cfg.Networking.DNSDomain,
|
DNSDomain: cfg.Networking.DNSDomain,
|
||||||
@ -377,3 +387,27 @@ func setCorefile(client clientset.Interface, coreDNSCorefileName string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
@ -865,7 +865,7 @@ metadata:
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
out := &bytes.Buffer{}
|
out := &bytes.Buffer{}
|
||||||
var replicas int32 = 3
|
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)
|
t.Errorf("coreDNSAddon() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1148,7 +1148,7 @@ metadata:
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
out := &bytes.Buffer{}
|
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)
|
t.Errorf("EnsureDNSAddon() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.InitCon
|
|||||||
errs = append(errs, err)
|
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)
|
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.
|
// 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)
|
unupgradedControlPlanes, err := unupgradedControlPlaneInstances(client, cfg.NodeRegistration.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to determine whether all the control plane instances have been upgraded")
|
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)
|
metav1.NamespaceSystem)
|
||||||
} else {
|
} else {
|
||||||
// Upgrade CoreDNS
|
// 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)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,12 @@ func (ps *patchSet) String() string {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KubeletConfiguration defines the kubeletconfiguration patch target.
|
const (
|
||||||
const KubeletConfiguration = "kubeletconfiguration"
|
// KubeletConfiguration defines the kubeletconfiguration patch target.
|
||||||
|
KubeletConfiguration = "kubeletconfiguration"
|
||||||
|
// CoreDNSDeployment defines the corednsdeployment patch target.
|
||||||
|
CoreDNSDeployment = "corednsdeployment"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
pathLock = &sync.RWMutex{}
|
pathLock = &sync.RWMutex{}
|
||||||
@ -100,6 +104,7 @@ var (
|
|||||||
kubeadmconstants.KubeControllerManager,
|
kubeadmconstants.KubeControllerManager,
|
||||||
kubeadmconstants.KubeScheduler,
|
kubeadmconstants.KubeScheduler,
|
||||||
KubeletConfiguration,
|
KubeletConfiguration,
|
||||||
|
CoreDNSDeployment,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user