Skip to content

Commit 9e53b85

Browse files
authored
Merge pull request kubernetes#74112 from pytimer/kubeadm-reset
kubeadm: Remove etcd members from the etcd cluster when reset the nodes
2 parents d9f3e96 + 83f5296 commit 9e53b85

File tree

6 files changed

+124
-0
lines changed

6 files changed

+124
-0
lines changed

cmd/kubeadm/app/cmd/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ go_library(
4040
"//cmd/kubeadm/app/images:go_default_library",
4141
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
4242
"//cmd/kubeadm/app/phases/certs:go_default_library",
43+
"//cmd/kubeadm/app/phases/etcd:go_default_library",
4344
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
4445
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
4546
"//cmd/kubeadm/app/preflight:go_default_library",

cmd/kubeadm/app/cmd/reset.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
3737
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
3838
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
39+
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
3940
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
4041
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
4142
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
@@ -139,6 +140,9 @@ func (r *Reset) Run(out io.Writer, client clientset.Interface) error {
139140
etcdDataDir, err := getEtcdDataDir(etcdManifestPath, client)
140141
if err == nil {
141142
dirsToClean = append(dirsToClean, etcdDataDir)
143+
if err := removeEtcdMember(client); err != nil {
144+
klog.Warningf("[reset] failed to remove etcd member: %v\n.Please manually remove this etcd member using etcdctl", err)
145+
}
142146
} else {
143147
fmt.Println("[reset] no etcd config found. Assuming external etcd")
144148
fmt.Println("[reset] please manually reset etcd to prevent further issues")
@@ -205,6 +209,14 @@ func (r *Reset) Run(out io.Writer, client clientset.Interface) error {
205209
return nil
206210
}
207211

212+
func removeEtcdMember(client clientset.Interface) error {
213+
cfg, err := configutil.FetchInitConfigurationFromCluster(client, os.Stdout, "reset", false)
214+
if err != nil {
215+
return err
216+
}
217+
return etcdphase.RemoveStackedEtcdMemberFromCluster(client, cfg)
218+
}
219+
208220
func getEtcdDataDir(manifestPath string, client clientset.Interface) (string, error) {
209221
const etcdVolumeName = "etcd-data"
210222
var dataDir string

cmd/kubeadm/app/phases/etcd/local.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,35 @@ func CheckLocalEtcdClusterStatus(client clientset.Interface, cfg *kubeadmapi.Clu
8181
return nil
8282
}
8383

84+
// RemoveStackedEtcdMemberFromCluster will remove a local etcd member from etcd cluster,
85+
// when reset the control plane node.
86+
func RemoveStackedEtcdMemberFromCluster(client clientset.Interface, cfg *kubeadmapi.InitConfiguration) error {
87+
// creates an etcd client that connects to all the local/stacked etcd members
88+
klog.V(1).Info("[etcd] creating etcd client that connects to etcd pods")
89+
etcdClient, err := etcdutil.NewFromCluster(client, cfg.CertificatesDir)
90+
if err != nil {
91+
return err
92+
}
93+
94+
// notifies the other members of the etcd cluster about the removing member
95+
etcdPeerAddress := etcdutil.GetPeerURL(&cfg.LocalAPIEndpoint)
96+
97+
klog.V(2).Infof("[etcd] get the member id from peer: %s", etcdPeerAddress)
98+
id, err := etcdClient.GetMemberID(etcdPeerAddress)
99+
if err != nil {
100+
return err
101+
}
102+
103+
klog.V(1).Infof("[etcd] removing etcd member: %s, id: %d", etcdPeerAddress, id)
104+
members, err := etcdClient.RemoveMember(id)
105+
if err != nil {
106+
return err
107+
}
108+
klog.V(1).Infof("[etcd] Updated etcd member list: %v", members)
109+
110+
return nil
111+
}
112+
84113
// CreateStackedEtcdStaticPodManifestFile will write local etcd static pod manifest file
85114
// for an additional etcd member that is joining an existing local/stacked etcd cluster.
86115
// Other members of the etcd cluster will be notified of the joining node in beforehand as well.

cmd/kubeadm/app/phases/upgrade/compute_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ func (f fakeEtcdClient) AddMember(name string, peerAddrs string) ([]etcdutil.Mem
113113
return []etcdutil.Member{}, nil
114114
}
115115

116+
func (f fakeEtcdClient) GetMemberID(peerURL string) (uint64, error) {
117+
return 0, nil
118+
}
119+
120+
func (f fakeEtcdClient) RemoveMember(id uint64) ([]etcdutil.Member, error) {
121+
return []etcdutil.Member{}, nil
122+
}
123+
116124
func TestGetAvailableUpgrades(t *testing.T) {
117125
etcdClient := fakeEtcdClient{}
118126
tests := []struct {

cmd/kubeadm/app/phases/upgrade/staticpods_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,14 @@ func (c fakeTLSEtcdClient) AddMember(name string, peerAddrs string) ([]etcdutil.
256256
return []etcdutil.Member{}, nil
257257
}
258258

259+
func (c fakeTLSEtcdClient) GetMemberID(peerURL string) (uint64, error) {
260+
return 0, nil
261+
}
262+
263+
func (c fakeTLSEtcdClient) RemoveMember(id uint64) ([]etcdutil.Member, error) {
264+
return []etcdutil.Member{}, nil
265+
}
266+
259267
type fakePodManifestEtcdClient struct{ ManifestDir, CertificatesDir string }
260268

261269
func (c fakePodManifestEtcdClient) ClusterAvailable() (bool, error) { return true, nil }
@@ -297,6 +305,14 @@ func (c fakePodManifestEtcdClient) AddMember(name string, peerAddrs string) ([]e
297305
return []etcdutil.Member{}, nil
298306
}
299307

308+
func (c fakePodManifestEtcdClient) GetMemberID(peerURL string) (uint64, error) {
309+
return 0, nil
310+
}
311+
312+
func (c fakePodManifestEtcdClient) RemoveMember(id uint64) ([]etcdutil.Member, error) {
313+
return []etcdutil.Member{}, nil
314+
}
315+
300316
func TestStaticPodControlPlane(t *testing.T) {
301317
tests := []struct {
302318
description string

cmd/kubeadm/app/util/etcd/etcd.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ type ClusterInterrogator interface {
4646
WaitForClusterAvailable(retries int, retryInterval time.Duration) (bool, error)
4747
Sync() error
4848
AddMember(name string, peerAddrs string) ([]Member, error)
49+
GetMemberID(peerURL string) (uint64, error)
50+
RemoveMember(id uint64) ([]Member, error)
4951
}
5052

5153
// Client provides connection parameters for an etcd cluster
@@ -146,6 +148,62 @@ type Member struct {
146148
PeerURL string
147149
}
148150

151+
// GetMemberID returns the member ID of the given peer URL
152+
func (c Client) GetMemberID(peerURL string) (uint64, error) {
153+
cli, err := clientv3.New(clientv3.Config{
154+
Endpoints: c.Endpoints,
155+
DialTimeout: 30 * time.Second,
156+
TLS: c.TLS,
157+
})
158+
if err != nil {
159+
return 0, err
160+
}
161+
defer cli.Close()
162+
163+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
164+
resp, err := cli.MemberList(ctx)
165+
cancel()
166+
if err != nil {
167+
return 0, err
168+
}
169+
170+
for _, member := range resp.Members {
171+
if member.GetPeerURLs()[0] == peerURL {
172+
return member.GetID(), nil
173+
}
174+
}
175+
return 0, nil
176+
}
177+
178+
// RemoveMember notifies an etcd cluster to remove an existing member
179+
func (c Client) RemoveMember(id uint64) ([]Member, error) {
180+
cli, err := clientv3.New(clientv3.Config{
181+
Endpoints: c.Endpoints,
182+
DialTimeout: 30 * time.Second,
183+
TLS: c.TLS,
184+
})
185+
if err != nil {
186+
return nil, err
187+
}
188+
defer cli.Close()
189+
190+
// Remove an existing member from the cluster
191+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
192+
resp, err := cli.MemberRemove(ctx, id)
193+
cancel()
194+
if err != nil {
195+
return nil, err
196+
}
197+
198+
// Returns the updated list of etcd members
199+
ret := []Member{}
200+
for _, m := range resp.Members {
201+
ret = append(ret, Member{Name: m.Name, PeerURL: m.PeerURLs[0]})
202+
}
203+
204+
return ret, nil
205+
}
206+
149207
// AddMember notifies an existing etcd cluster that a new member is joining
150208
func (c *Client) AddMember(name string, peerAddrs string) ([]Member, error) {
151209
// Parse the peer address, required to add the client URL later to the list

0 commit comments

Comments
 (0)