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-
4133var (
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+
4552func 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
201199func 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