109 lines
3.2 KiB
Go
109 lines
3.2 KiB
Go
package node
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"k8s.io/klog/v2"
|
|
|
|
"example.com/monok8s/pkg/system"
|
|
)
|
|
|
|
const kubeadmUpgradeNodeHostnameBugFixedIn = "v1.35.0"
|
|
|
|
// COMPAT(kubeadm-upgrade-node-hostname)
|
|
// Affects: Kubernetes/kubeadm < v1.35.0
|
|
// Upstream: kubernetes/kubeadm#3244, kubernetes/kubernetes#134319
|
|
// RemoveWhen: minimum supported Kubernetes version >= v1.35.0
|
|
//
|
|
// Affected kubeadm versions can derive the target Node name for
|
|
// `kubeadm upgrade node` from the local OS hostname instead of the existing
|
|
// kubeadm NodeRegistration / kubelet --hostname-override state.
|
|
func needsKubeadmUpgradeNodeHostnameWorkaround(kubeadmVersion string) bool {
|
|
lt, err := versionLt(kubeadmVersion, kubeadmUpgradeNodeHostnameBugFixedIn)
|
|
if err != nil {
|
|
klog.Warningf(
|
|
"could not parse kubeadm version %q; enabling kubeadm upgrade node hostname workaround: %v",
|
|
kubeadmVersion,
|
|
err,
|
|
)
|
|
return true
|
|
}
|
|
return lt
|
|
}
|
|
|
|
// runWithTemporaryHostname works around kubernetes/kubeadm#3244, fixed by
|
|
// kubernetes/kubernetes#134319 in Kubernetes v1.35.0.
|
|
//
|
|
// Affected kubeadm versions can derive the target Node name for
|
|
// `kubeadm upgrade node` from the local OS hostname instead of the existing
|
|
// kubeadm NodeRegistration / kubelet --hostname-override state. That breaks
|
|
// valid setups where the machine hostname differs from the Kubernetes Node
|
|
// name: kubeadm may authenticate as one node but try to get/patch another Node,
|
|
// and the Node authorizer correctly rejects it.
|
|
//
|
|
// Keep this workaround scoped to affected kubeadm versions only. Set the
|
|
// temporary hostname to the Kubernetes Node name, run kubeadm, then restore the
|
|
// configured machine hostname immediately afterward.
|
|
func runWithTemporaryHostname(ctx context.Context, nctx *NodeContext, fn func(context.Context) error) error {
|
|
if nctx == nil {
|
|
return errors.New("node context is nil")
|
|
}
|
|
|
|
temporaryHostname := strings.TrimSpace(nctx.Config.Spec.NodeName)
|
|
if temporaryHostname == "" {
|
|
return errors.New("temporary hostname is required")
|
|
}
|
|
|
|
originalHostname, err := os.Hostname()
|
|
if err != nil {
|
|
return fmt.Errorf("get current hostname: %w", err)
|
|
}
|
|
|
|
if originalHostname == temporaryHostname {
|
|
return fn(ctx)
|
|
}
|
|
|
|
restoreHostname := strings.TrimSpace(nctx.Config.Spec.Network.Hostname)
|
|
if restoreHostname == "" {
|
|
restoreHostname = originalHostname
|
|
}
|
|
|
|
klog.Warningf(
|
|
"temporarily changing hostname for kubeadm upgrade node: current=%q temporary=%q restore=%q",
|
|
originalHostname,
|
|
temporaryHostname,
|
|
restoreHostname,
|
|
)
|
|
|
|
if err := system.SetHostname(temporaryHostname); err != nil {
|
|
return fmt.Errorf("set temporary hostname to %q: %w", temporaryHostname, err)
|
|
}
|
|
|
|
defer func() {
|
|
if err := system.SetHostname(restoreHostname); err != nil {
|
|
klog.Errorf("failed to restore hostname to %q: %v", restoreHostname, err)
|
|
}
|
|
}()
|
|
|
|
return fn(ctx)
|
|
}
|
|
|
|
// COMPAT(kubeadm-upgrade-node-hostname)
|
|
// RemoveWhen: minimum supported Kubernetes version >= v1.35.0
|
|
func runKubeadmUpgradeNodeWithCompat(
|
|
ctx context.Context,
|
|
nctx *NodeContext,
|
|
kubeadmVersion string,
|
|
fn func(context.Context) error,
|
|
) error {
|
|
if needsKubeadmUpgradeNodeHostnameWorkaround(kubeadmVersion) {
|
|
return runWithTemporaryHostname(ctx, nctx, fn)
|
|
}
|
|
|
|
return fn(ctx)
|
|
}
|