Skip to content
This repository was archived by the owner on Jul 30, 2021. It is now read-only.

Commit ab8b336

Browse files
authored
Merge pull request #231 from aaronlevy/checkpoint_revert
Checkpoint revert
2 parents 45dbd0b + 5ebb538 commit ab8b336

File tree

1 file changed

+63
-90
lines changed

1 file changed

+63
-90
lines changed

cmd/checkpoint/main.go

Lines changed: 63 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"io/ioutil"
88
"net/http"
99
"os"
10-
"path"
1110
"path/filepath"
1211
"strings"
1312
"time"
@@ -26,69 +25,70 @@ const (
2625
kubeletAPIPodsURL = "http://127.0.0.1:10255/pods"
2726
ignorePath = "/srv/kubernetes/manifests"
2827
activePath = "/etc/kubernetes/manifests"
28+
manifestFilename = "apiserver.json"
2929
kubeconfigPath = "/etc/kubernetes/kubeconfig"
3030
secretsPath = "/etc/kubernetes/checkpoint-secrets"
31-
32-
tempAPIServer = "temp-apiserver"
33-
kubeAPIServer = "kube-apiserver"
3431
)
3532

36-
var podAPIServerMeta = unversioned.TypeMeta{
37-
APIVersion: "v1",
38-
Kind: "Pod",
39-
}
40-
4133
var (
42-
secureAPIAddr = fmt.Sprintf("https://%s:%s", os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT_HTTPS"))
34+
tempAPIServer = []byte("temp-apiserver")
35+
kubeAPIServer = []byte("kube-apiserver")
36+
activeManifest = filepath.Join(activePath, manifestFilename)
37+
checkpointManifest = filepath.Join(ignorePath, manifestFilename)
38+
secureAPIAddr = fmt.Sprintf("https://%s:%s", os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT_HTTPS"))
4339
)
4440

41+
var tempAPIServerManifest = v1.Pod{
42+
TypeMeta: unversioned.TypeMeta{
43+
APIVersion: "v1",
44+
Kind: "Pod",
45+
},
46+
ObjectMeta: v1.ObjectMeta{
47+
Name: "temp-apiserver",
48+
Namespace: "kube-system",
49+
},
50+
}
51+
4552
func main() {
4653
flag.Set("logtostderr", "true")
4754
defer glog.Flush()
48-
checkpoints, err := getCheckpointManifests()
49-
if err != nil {
50-
glog.Fatalf("failed to load existing checkpoint manifests: %v", err)
51-
}
52-
glog.Info("begin pods checkpointing...")
53-
run(kubeAPIServer, tempAPIServer, api.NamespaceSystem, checkpoints)
55+
glog.Info("begin apiserver checkpointing...")
56+
run()
5457
}
5558

56-
func run(actualPodName, tempPodName, namespace string, checkpoints map[string]struct{}) {
59+
func run() {
5760
client := newAPIClient()
5861
for {
59-
_, checkpointed := checkpoints[checkpointManifest(tempPodName)]
60-
6162
var podList v1.PodList
6263
if err := json.Unmarshal(getPodsFromKubeletAPI(), &podList); err != nil {
6364
glog.Fatal(err)
6465
}
6566
switch {
66-
case bothRunning(podList, actualPodName, tempPodName, namespace):
67-
glog.Infof("both temp %v and actual %v pods running, removing temp pod", actualPodName, tempPodName)
68-
// Both the temp and actual pods are running.
69-
// Remove the temp manifest from the config dir so that the
67+
case bothAPIServersRunning(podList):
68+
glog.Info("both temp and kube apiserver running, removing temp apiserver")
69+
// Both the self-hosted API Server and the temp API Server are running.
70+
// Remove the temp API Server manifest from the config dir so that the
7071
// kubelet will stop it.
71-
if err := os.Remove(activeManifest(tempPodName)); err != nil {
72+
if err := os.Remove(activeManifest); err != nil {
7273
glog.Error(err)
7374
}
74-
case isPodRunning(podList, client, actualPodName, namespace):
75-
glog.Infof("actual pod %v found, creating checkpoint pod manifest", actualPodName)
76-
// The actual is running. Let's snapshot the pod,
75+
case kubeSystemAPIServerRunning(podList, client):
76+
glog.Info("kube-apiserver found, creating temp-apiserver manifest")
77+
// The self-hosted API Server is running. Let's snapshot the pod,
7778
// clean it up a bit, and then save it to the ignore path for
7879
// later use.
79-
checkpointPod := createCheckpointPod(podList, actualPodName, namespace)
80-
convertSecretsToVolumeMounts(client, &checkpointPod)
81-
writeManifest(checkpointPod, tempPodName)
82-
checkpoints[checkpointManifest(tempPodName)] = struct{}{}
83-
glog.Infof("finished creating checkpoint pod %v manifest at %s\n", tempPodName, checkpointManifest(tempPodName))
84-
85-
case checkpointed:
86-
glog.Info("no actual pod running, installing checkpoint pod static manifest")
87-
b, err := ioutil.ReadFile(checkpointManifest(tempPodName))
80+
tempAPIServerManifest.Spec = parseAPIPodSpec(podList)
81+
convertSecretsToVolumeMounts(client, &tempAPIServerManifest)
82+
writeManifest(tempAPIServerManifest)
83+
glog.Infof("finished creating temp-apiserver manifest at %s\n", checkpointManifest)
84+
85+
default:
86+
glog.Info("no apiserver running, installing temp apiserver static manifest")
87+
b, err := ioutil.ReadFile(checkpointManifest)
8888
if err != nil {
8989
glog.Error(err)
9090
} else {
91-
if err := ioutil.WriteFile(activeManifest(tempPodName), b, 0644); err != nil {
91+
if err := ioutil.WriteFile(activeManifest, b, 0644); err != nil {
9292
glog.Error(err)
9393
}
9494
}
@@ -118,35 +118,36 @@ func getPodsFromKubeletAPI() []byte {
118118
return pods
119119
}
120120

121-
func bothRunning(pods v1.PodList, an, tn, ns string) bool {
122-
var actualPodSeen, tempPodSeen bool
121+
func bothAPIServersRunning(pods v1.PodList) bool {
122+
var kubeAPISeen, tempAPISeen bool
123123
for _, p := range pods.Items {
124-
actualPodSeen = actualPodSeen || isPod(p, an, ns)
125-
tempPodSeen = tempPodSeen || isPod(p, tn, ns)
126-
if actualPodSeen && tempPodSeen {
124+
kubeAPISeen = kubeAPISeen || isKubeAPI(p)
125+
tempAPISeen = tempAPISeen || isTempAPI(p)
126+
if kubeAPISeen && tempAPISeen {
127127
return true
128128
}
129129
}
130130
return false
131131
}
132132

133-
func isPodRunning(pods v1.PodList, client clientset.Interface, n, ns string) bool {
133+
func kubeSystemAPIServerRunning(pods v1.PodList, client clientset.Interface) bool {
134134
for _, p := range pods.Items {
135-
if isPod(p, n, ns) {
136-
if n == kubeAPIServer {
137-
// Make sure it's actually running. Sometimes we get that
138-
// pod manifest back, but the server is not actually running.
139-
_, err := client.Discovery().ServerVersion()
140-
return err == nil
141-
}
142-
return true
135+
if isKubeAPI(p) {
136+
// Make sure it's actually running. Sometimes we get that
137+
// pod manifest back, but the server is not actually running.
138+
_, err := client.Discovery().ServerVersion()
139+
return err == nil
143140
}
144141
}
145142
return false
146143
}
147144

148-
func isPod(pod v1.Pod, n, ns string) bool {
149-
return strings.Contains(pod.Name, n) && pod.Namespace == ns
145+
func isKubeAPI(pod v1.Pod) bool {
146+
return strings.Contains(pod.Name, "kube-apiserver") && pod.Namespace == api.NamespaceSystem
147+
}
148+
149+
func isTempAPI(pod v1.Pod) bool {
150+
return strings.Contains(pod.Name, "temp-apiserver") && pod.Namespace == api.NamespaceSystem
150151
}
151152

152153
// cleanVolumes will sanitize the list of volumes and volume mounts
@@ -174,28 +175,25 @@ func cleanVolumes(p *v1.Pod) {
174175
// writeManifest will write the manifest to the ignore path.
175176
// It first writes the file to a temp file, and then atomically moves it into
176177
// the actual ignore path and correct file name.
177-
func writeManifest(manifest v1.Pod, name string) {
178+
func writeManifest(manifest v1.Pod) {
178179
m, err := json.Marshal(manifest)
179180
if err != nil {
180181
glog.Fatal(err)
181182
}
182-
writeAndAtomicCopy(m, checkpointManifest(name))
183+
writeAndAtomicCopy(m, checkpointManifest)
183184
}
184185

185-
func createCheckpointPod(podList v1.PodList, n, ns string) v1.Pod {
186-
var checkpointPod v1.Pod
186+
func parseAPIPodSpec(podList v1.PodList) v1.PodSpec {
187+
var apiPod v1.Pod
187188
for _, p := range podList.Items {
188-
if isPod(p, n, ns) {
189-
checkpointPod = p
189+
if isKubeAPI(p) {
190+
apiPod = p
190191
break
191192
}
192193
}
193-
// the pod we manifest we got from kubelet does not have TypeMeta.
194-
// Add it now.
195-
checkpointPod.TypeMeta = podAPIServerMeta
196-
cleanVolumes(&checkpointPod)
197-
stripNonessentialInfo(&checkpointPod)
198-
return checkpointPod
194+
cleanVolumes(&apiPod)
195+
stripNonessentialInfo(&apiPod)
196+
return apiPod.Spec
199197
}
200198

201199
func newAPIClient() clientset.Interface {
@@ -252,28 +250,3 @@ func writeAndAtomicCopy(data []byte, path string) {
252250
glog.Fatal(err)
253251
}
254252
}
255-
256-
func activeManifest(name string) string {
257-
return filepath.Join(activePath, name+".json")
258-
}
259-
260-
func checkpointManifest(name string) string {
261-
return filepath.Join(ignorePath, name+".json")
262-
}
263-
264-
func getCheckpointManifests() (map[string]struct{}, error) {
265-
checkpoints := make(map[string]struct{})
266-
267-
fs, err := ioutil.ReadDir(ignorePath)
268-
if err != nil {
269-
if os.IsNotExist(err) {
270-
return checkpoints, nil
271-
}
272-
return nil, err
273-
}
274-
for _, f := range fs {
275-
glog.Infof("found checkpoint pod manifests %v", f.Name())
276-
checkpoints[path.Join(ignorePath, f.Name())] = struct{}{}
277-
}
278-
return checkpoints, nil
279-
}

0 commit comments

Comments
 (0)