@@ -24,17 +24,15 @@ const (
2424 kubeletAPIPodsURL = "http://127.0.0.1:10255/pods"
2525 ignorePath = "/srv/kubernetes/manifests"
2626 activePath = "/etc/kubernetes/manifests"
27- manifestFilename = "apiserver.json"
2827 kubeconfigPath = "/etc/kubernetes/kubeconfig"
2928 secretsPath = "/etc/kubernetes/checkpoint-secrets"
29+
30+ tempAPIServer = "temp-apiserver"
31+ kubeAPIServer = "kube-apiserver"
3032)
3133
3234var (
33- tempAPIServer = []byte ("temp-apiserver" )
34- kubeAPIServer = []byte ("kube-apiserver" )
35- activeManifest = filepath .Join (activePath , manifestFilename )
36- checkpointManifest = filepath .Join (ignorePath , manifestFilename )
37- secureAPIAddr = fmt .Sprintf ("https://%s:%s" , os .Getenv ("KUBERNETES_SERVICE_HOST" ), os .Getenv ("KUBERNETES_SERVICE_PORT_HTTPS" ))
35+ secureAPIAddr = fmt .Sprintf ("https://%s:%s" , os .Getenv ("KUBERNETES_SERVICE_HOST" ), os .Getenv ("KUBERNETES_SERVICE_PORT_HTTPS" ))
3836)
3937
4038var tempAPIServerManifest = v1.Pod {
@@ -44,48 +42,56 @@ var tempAPIServerManifest = v1.Pod{
4442 },
4543 ObjectMeta : v1.ObjectMeta {
4644 Name : "temp-apiserver" ,
47- Namespace : "kube-system" ,
45+ Namespace : api . NamespaceSystem ,
4846 },
4947}
5048
49+ var tempPodSpecMap = map [string ]v1.Pod {
50+ tempAPIServer : tempAPIServerManifest ,
51+ }
52+
5153func main () {
52- glog .Info ("begin apiserver checkpointing..." )
53- run ()
54+ glog .Info ("begin pods checkpointing..." )
55+ run (kubeAPIServer , tempAPIServer , api . NamespaceSystem )
5456}
5557
56- func run () {
58+ func run (actualPodName , tempPodName , namespace string ) {
5759 client := newAPIClient ()
5860 for {
5961 var podList v1.PodList
6062 if err := json .Unmarshal (getPodsFromKubeletAPI (), & podList ); err != nil {
6163 glog .Fatal (err )
6264 }
6365 switch {
64- case bothAPIServersRunning (podList ):
65- glog .Info ("both temp and kube apiserver running, removing temp apiserver" )
66- // Both the self-hosted API Server and the temp API Server are running.
67- // Remove the temp API Server manifest from the config dir so that the
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
6870 // kubelet will stop it.
69- if err := os .Remove (activeManifest ); err != nil {
71+ if err := os .Remove (activeManifest ( tempPodName ) ); err != nil {
7072 glog .Error (err )
7173 }
72- case kubeSystemAPIServerRunning (podList , client ):
73- glog .Info ( "kube-apiserver found, creating temp-apiserver manifest" )
74- // The self-hosted API Server is running. Let's snapshot the pod,
74+ case isPodRunning (podList , client , actualPodName , namespace ):
75+ glog .Infof ( "actual pod %v found, creating temp pod manifest", actualPodName )
76+ // The actual is running. Let's snapshot the pod,
7577 // clean it up a bit, and then save it to the ignore path for
7678 // later use.
77- tempAPIServerManifest .Spec = parseAPIPodSpec (podList )
78- convertSecretsToVolumeMounts (client , & tempAPIServerManifest )
79- writeManifest (tempAPIServerManifest )
80- glog .Infof ("finished creating temp-apiserver manifest at %s\n " , checkpointManifest )
79+ tempSpec , ok := tempPodSpecMap [tempPodName ]
80+ if ! ok {
81+ glog .Fatalf ("cannot find pod spec for %v" , tempPodName )
82+ }
83+ tempSpec .Spec = parseAPIPodSpec (podList , actualPodName , namespace )
84+ convertSecretsToVolumeMounts (client , & tempSpec )
85+ writeManifest (tempSpec , tempPodName )
86+ glog .Infof ("finished creating temp pod %v manifest at %s\n " , tempPodName , checkpointManifest (tempPodName ))
8187
8288 default :
83- glog .Info ("no apiserver running, installing temp apiserver static manifest" )
84- b , err := ioutil .ReadFile (checkpointManifest )
89+ glog .Info ("no actual pod running, installing temp pod static manifest" )
90+ b , err := ioutil .ReadFile (checkpointManifest ( tempPodName ) )
8591 if err != nil {
8692 glog .Error (err )
8793 } else {
88- if err := ioutil .WriteFile (activeManifest , b , 0644 ); err != nil {
94+ if err := ioutil .WriteFile (activeManifest ( tempPodName ) , b , 0644 ); err != nil {
8995 glog .Error (err )
9096 }
9197 }
@@ -115,36 +121,35 @@ func getPodsFromKubeletAPI() []byte {
115121 return pods
116122}
117123
118- func bothAPIServersRunning (pods v1.PodList ) bool {
119- var kubeAPISeen , tempAPISeen bool
124+ func bothRunning (pods v1.PodList , an , tn , ns string ) bool {
125+ var actualPodSeen , tempPodSeen bool
120126 for _ , p := range pods .Items {
121- kubeAPISeen = kubeAPISeen || isKubeAPI ( p )
122- tempAPISeen = tempAPISeen || isTempAPI ( p )
123- if kubeAPISeen && tempAPISeen {
127+ actualPodSeen = actualPodSeen || isPod ( p , an , ns )
128+ tempPodSeen = tempPodSeen || isPod ( p , tn , ns )
129+ if actualPodSeen && tempPodSeen {
124130 return true
125131 }
126132 }
127133 return false
128134}
129135
130- func kubeSystemAPIServerRunning (pods v1.PodList , client clientset.Interface ) bool {
136+ func isPodRunning (pods v1.PodList , client clientset.Interface , n , ns string ) bool {
131137 for _ , p := range pods .Items {
132- if isKubeAPI (p ) {
133- // Make sure it's actually running. Sometimes we get that
134- // pod manifest back, but the server is not actually running.
135- _ , err := client .Discovery ().ServerVersion ()
136- return err == nil
138+ if isPod (p , n , ns ) {
139+ if n == kubeAPIServer {
140+ // Make sure it's actually running. Sometimes we get that
141+ // pod manifest back, but the server is not actually running.
142+ _ , err := client .Discovery ().ServerVersion ()
143+ return err == nil
144+ }
145+ return true
137146 }
138147 }
139148 return false
140149}
141150
142- func isKubeAPI (pod v1.Pod ) bool {
143- return strings .Contains (pod .Name , "kube-apiserver" ) && pod .Namespace == api .NamespaceSystem
144- }
145-
146- func isTempAPI (pod v1.Pod ) bool {
147- return strings .Contains (pod .Name , "temp-apiserver" ) && pod .Namespace == api .NamespaceSystem
151+ func isPod (pod v1.Pod , n , ns string ) bool {
152+ return strings .Contains (pod .Name , n ) && pod .Namespace == ns
148153}
149154
150155// cleanVolumes will sanitize the list of volumes and volume mounts
@@ -172,18 +177,18 @@ func cleanVolumes(p *v1.Pod) {
172177// writeManifest will write the manifest to the ignore path.
173178// It first writes the file to a temp file, and then atomically moves it into
174179// the actual ignore path and correct file name.
175- func writeManifest (manifest v1.Pod ) {
180+ func writeManifest (manifest v1.Pod , name string ) {
176181 m , err := json .Marshal (manifest )
177182 if err != nil {
178183 glog .Fatal (err )
179184 }
180- writeAndAtomicCopy (m , checkpointManifest )
185+ writeAndAtomicCopy (m , checkpointManifest ( name ) )
181186}
182187
183- func parseAPIPodSpec (podList v1.PodList ) v1.PodSpec {
188+ func parseAPIPodSpec (podList v1.PodList , n , ns string ) v1.PodSpec {
184189 var apiPod v1.Pod
185190 for _ , p := range podList .Items {
186- if isKubeAPI ( p ) {
191+ if isPod ( p , n , ns ) {
187192 apiPod = p
188193 break
189194 }
@@ -247,3 +252,11 @@ func writeAndAtomicCopy(data []byte, path string) {
247252 glog .Fatal (err )
248253 }
249254}
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+ }
0 commit comments