Skip to content

Commit f0418ac

Browse files
authored
Merge pull request kubernetes#75082 from neolit123/reset-clean-status
kubeadm-reset: add means to clear the ClusterStatus
2 parents 0b48018 + a9eea0a commit f0418ac

File tree

4 files changed

+90
-6
lines changed

4 files changed

+90
-6
lines changed

cmd/kubeadm/app/cmd/reset.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
3939
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
4040
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
41+
uploadconfig "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
4142
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
4243
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
4344
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
@@ -140,10 +141,15 @@ func NewReset(in io.Reader, ignorePreflightErrors sets.String, forceReset bool,
140141
// Run reverts any changes made to this host by "kubeadm init" or "kubeadm join".
141142
func (r *Reset) Run(out io.Writer, client clientset.Interface, cfg *kubeadmapi.InitConfiguration) error {
142143
var dirsToClean []string
143-
// Only clear etcd data when using local etcd.
144-
etcdManifestPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, "etcd.yaml")
145144

145+
// Reset the ClusterStatus for a given control-plane node.
146+
if isControlPlane() && cfg != nil {
147+
uploadconfig.ResetClusterStatusForNode(cfg.NodeRegistration.Name, client)
148+
}
149+
150+
// Only clear etcd data when using local etcd.
146151
klog.V(1).Infoln("[reset] Checking for etcd config")
152+
etcdManifestPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, "etcd.yaml")
147153
etcdDataDir, err := getEtcdDataDir(etcdManifestPath, cfg)
148154
if err == nil {
149155
dirsToClean = append(dirsToClean, etcdDataDir)
@@ -318,3 +324,13 @@ func resetDetectCRISocket(cfg *kubeadmapi.InitConfiguration) (string, error) {
318324
// if this fails, try to detect it
319325
return utilruntime.DetectCRISocket()
320326
}
327+
328+
// isControlPlane checks if a node is a control-plane node by looking up
329+
// the kube-apiserver manifest file
330+
func isControlPlane() bool {
331+
filepath := kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, kubeadmconstants.GetStaticPodDirectory())
332+
if _, err := os.Stat(filepath); os.IsNotExist(err) {
333+
return false
334+
}
335+
return true
336+
}

cmd/kubeadm/app/phases/uploadconfig/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ go_library(
2020
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
2121
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
2222
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
23+
"//vendor/github.com/pkg/errors:go_default_library",
24+
"//vendor/k8s.io/klog:go_default_library",
2325
],
2426
)
2527

cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ package uploadconfig
1919
import (
2020
"fmt"
2121

22-
"k8s.io/api/core/v1"
22+
"github.com/pkg/errors"
23+
v1 "k8s.io/api/core/v1"
2324
rbac "k8s.io/api/rbac/v1"
2425
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2526
clientset "k8s.io/client-go/kubernetes"
27+
"k8s.io/klog"
2628
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
2729
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
2830
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
@@ -37,6 +39,69 @@ const (
3739
NodesKubeadmConfigClusterRoleName = "kubeadm:nodes-kubeadm-config"
3840
)
3941

42+
// ResetClusterStatusForNode removes the APIEndpoint of a given control-plane node
43+
// from the ClusterStatus and updates the kubeadm ConfigMap
44+
func ResetClusterStatusForNode(nodeName string, client clientset.Interface) error {
45+
fmt.Printf("[reset] Removing info for node %q from the ConfigMap %q in the %q Namespace\n",
46+
nodeName, kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
47+
48+
// Get the kubeadm ConfigMap
49+
configMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(kubeadmconstants.KubeadmConfigConfigMap, metav1.GetOptions{})
50+
if err != nil {
51+
return errors.Wrap(err, "failed to get config map")
52+
}
53+
54+
// Handle missing ClusterConfiguration in the ConfigMap. Should only happen if someone manually
55+
// interacted with the ConfigMap.
56+
clusterConfigurationYaml, ok := configMap.Data[kubeadmconstants.ClusterConfigurationConfigMapKey]
57+
if !ok {
58+
return errors.Errorf("cannot find key %q in ConfigMap %q in the %q Namespace",
59+
kubeadmconstants.ClusterConfigurationConfigMapKey, kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
60+
}
61+
62+
// Obtain the existing ClusterStatus object
63+
clusterStatus, err := configutil.UnmarshalClusterStatus(configMap.Data)
64+
if err != nil {
65+
return err
66+
}
67+
68+
// Handle a nil APIEndpoints map. Should only happen if someone manually
69+
// interacted with the ConfigMap.
70+
if clusterStatus.APIEndpoints == nil {
71+
return errors.Errorf("APIEndpoints from ConfigMap %q in the %q Namespace is nil",
72+
kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
73+
}
74+
75+
// Check for existence of the nodeName key in the list of APIEndpoints.
76+
// Return early if it's missing.
77+
apiEndpoint, ok := clusterStatus.APIEndpoints[nodeName]
78+
if !ok {
79+
klog.Warningf("No APIEndpoint registered for node %q", nodeName)
80+
return nil
81+
}
82+
83+
klog.V(2).Infof("Removing APIEndpoint %#v for node %q", apiEndpoint, nodeName)
84+
delete(clusterStatus.APIEndpoints, nodeName)
85+
86+
// Marshal the ClusterStatus back into YAML
87+
clusterStatusYaml, err := configutil.MarshalKubeadmConfigObject(clusterStatus)
88+
if err != nil {
89+
return err
90+
}
91+
92+
// Update the ClusterStatus in the ConfigMap
93+
return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{
94+
ObjectMeta: metav1.ObjectMeta{
95+
Name: kubeadmconstants.KubeadmConfigConfigMap,
96+
Namespace: metav1.NamespaceSystem,
97+
},
98+
Data: map[string]string{
99+
kubeadmconstants.ClusterConfigurationConfigMapKey: clusterConfigurationYaml,
100+
kubeadmconstants.ClusterStatusConfigMapKey: string(clusterStatusYaml),
101+
},
102+
})
103+
}
104+
40105
// UploadConfiguration saves the InitConfiguration used for later reference (when upgrading for instance)
41106
func UploadConfiguration(cfg *kubeadmapi.InitConfiguration, client clientset.Interface) error {
42107
fmt.Printf("[upload-config] storing the configuration used in ConfigMap %q in the %q Namespace\n", kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)

cmd/kubeadm/app/util/config/cluster.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func getNodeNameFromKubeletConfig(kubeconfigDir string) (string, error) {
167167
// getAPIEndpoint returns the APIEndpoint for the current node
168168
func getAPIEndpoint(data map[string]string, nodeName string, apiEndpoint *kubeadmapi.APIEndpoint) error {
169169
// gets the ClusterStatus from kubeadm-config
170-
clusterStatus, err := unmarshalClusterStatus(data)
170+
clusterStatus, err := UnmarshalClusterStatus(data)
171171
if err != nil {
172172
return err
173173
}
@@ -210,15 +210,16 @@ func GetClusterStatus(client clientset.Interface) (*kubeadmapi.ClusterStatus, er
210210
return nil, err
211211
}
212212

213-
clusterStatus, err := unmarshalClusterStatus(configMap.Data)
213+
clusterStatus, err := UnmarshalClusterStatus(configMap.Data)
214214
if err != nil {
215215
return nil, err
216216
}
217217

218218
return clusterStatus, nil
219219
}
220220

221-
func unmarshalClusterStatus(data map[string]string) (*kubeadmapi.ClusterStatus, error) {
221+
// UnmarshalClusterStatus takes raw ConfigMap.Data and converts it to a ClusterStatus object
222+
func UnmarshalClusterStatus(data map[string]string) (*kubeadmapi.ClusterStatus, error) {
222223
clusterStatusData, ok := data[constants.ClusterStatusConfigMapKey]
223224
if !ok {
224225
return nil, errors.Errorf("unexpected error when reading kubeadm-config ConfigMap: %s key value pair missing", constants.ClusterStatusConfigMapKey)

0 commit comments

Comments
 (0)