@@ -39,6 +39,15 @@ import (
39
39
var cfgFile string
40
40
var parFile string
41
41
42
+ type container struct {
43
+ Name string `json:"Name"`
44
+ }
45
+
46
+ type containers struct {
47
+ Containers []container `json:"Containers"`
48
+ Duration string `json:"Duration"`
49
+ }
50
+
42
51
type target struct {
43
52
Name string `json:"Name"`
44
53
Namespace string `json:"Namespace"`
@@ -59,10 +68,15 @@ type targetPods struct {
59
68
Pods []target `json:"Pods"`
60
69
}
61
70
62
- func dropErr (e error ) {
63
- if e != nil {
64
- panic (e )
65
- }
71
+ /*
72
+ func getNode(client *kubernetes.Clientset) *nodeSet {
73
+ nodes, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
74
+ return nodes
75
+ }*/
76
+
77
+ func createNodeSet (nodeSet map [string ][]string , targetPod * target ) error {
78
+ nodeSet [targetPod .Node ] = append (nodeSet [targetPod .Node ], "k8s_POD_" + targetPod .Name + "_" + targetPod .Namespace + "_" + targetPod .Uid )
79
+ return nil
66
80
}
67
81
68
82
func getPodStatus (client * kubernetes.Clientset , data * targets ) * []target {
@@ -126,64 +140,89 @@ func parse(p string) (*rest.Config, *kubernetes.Clientset, *targets) {
126
140
return restConfig , client , & data
127
141
}
128
142
129
- func getPodDef ( pod * target , duration string ) * apicore.Pod {
143
+ func createManifests ( node string , targetContainers [] string , duration string ) ( * apicore.Pod , * apicore. ConfigMap ) {
130
144
n := 2
131
145
temp := make ([]byte , n )
132
146
rand .Read (temp )
133
147
suffix := hex .EncodeToString (temp )
134
148
var privileged bool
135
149
privileged = true
136
- var command string
150
+ // var command string
137
151
var probeCommand []string
138
- command = "rm -rf /tmp/" + pod .Name + "_" + pod .Namespace + ".cap; rm -rf /tmp/complete-" + pod .Name + "_" + pod .Namespace + "; nsenter -t $(docker inspect $(docker ps |grep '" + pod .Uid + "'|grep -v pause|awk '{print $1}')| grep '\" Pid\" :' | grep -Eo '[0-9]*') -n timeout " + duration + " tcpdump -i any -w /tmp/" + pod .Name + "_" + pod .Namespace + ".cap; sleep 2;touch /tmp/complete-" + pod .Name + "_" + pod .Namespace + "; tail -f /dev/null"
152
+ // command = "rm -rf /tmp/" + pod.Name + "_" + pod.Namespace + ".cap; rm -rf /tmp/complete-" + pod.Name + "_" + pod.Namespace + "; nsenter -t $(docker inspect $(docker ps |grep '" + pod.Uid + "'|grep -v pause|awk '{print $1}')| grep '\"Pid\":' | grep -Eo '[0-9]*') -n timeout " + duration + " tcpdump -i any -w /tmp/" + pod.Name + "_" + pod.Namespace + ".cap; sleep 2;touch /tmp/complete-" + pod.Name + "_" + pod.Namespace + "; tail -f /dev/null"
139
153
//log.Info(command)
140
- probeCommand = []string {"ls" , "/tmp/complete-" + pod .Name + "_" + pod .Namespace }
154
+ probeCommand = []string {"ls" , "/tmp/containerTcpdumpComplete" }
155
+ cmContainers := containers {}
156
+ cmContainer := container {}
157
+ for _ , targetContainer := range targetContainers {
158
+ cmContainer .Name = targetContainer
159
+ cmContainers .Containers = append (cmContainers .Containers , cmContainer )
160
+ }
161
+ cmContainers .Duration = duration
162
+ cmContainersJson , _ := json .Marshal (cmContainers )
141
163
//log.Info(probeCommand)
142
164
return & apicore.Pod {
143
- ObjectMeta : metav1.ObjectMeta {
144
- Name : pod . Name + "-" + suffix ,
145
- Namespace : pod . Namespace ,
146
- Labels : map [string ]string {
147
- "tdn " : pod . Name ,
148
- "tdns" : pod . Namespace ,
165
+ ObjectMeta : metav1.ObjectMeta {
166
+ Name : node + "-" + suffix ,
167
+ Namespace : "default" ,
168
+ Labels : map [string ]string {
169
+ "k8stcpdump " : "true" ,
170
+ } ,
149
171
},
150
- },
151
- Spec : apicore.PodSpec {
152
- Containers : []apicore. Container {
153
- {
154
- Name : pod . Name ,
155
- Image : "docker.io/library/alpine" ,
156
- ImagePullPolicy : apicore .PullIfNotPresent ,
157
- Command : [] string {
158
- "nsenter" ,
159
- "-t" ,
160
- "1" ,
161
- "-m" ,
162
- "-u" ,
163
- "-i" ,
164
- "-n" ,
165
- "-p" ,
166
- "--" ,
167
- "bash" ,
168
- "-c " ,
169
- command ,
170
- } ,
171
- SecurityContext : & apicore. SecurityContext {
172
- Privileged : & privileged ,
172
+ Spec : apicore. PodSpec {
173
+ Containers : [] apicore.Container {
174
+ {
175
+ Name : "k8stcpdump" ,
176
+ Image : "shawnlu/containertcpdump:20201130" ,
177
+ ImagePullPolicy : apicore . PullIfNotPresent ,
178
+ SecurityContext : & apicore.SecurityContext {
179
+ Privileged : & privileged ,
180
+ } ,
181
+ ReadinessProbe : & apicore. Probe {
182
+ Handler : apicore. Handler {
183
+ Exec : & apicore. ExecAction {
184
+ Command : probeCommand ,
185
+ } ,
186
+ } ,
187
+ } ,
188
+ VolumeMounts : []apicore. VolumeMount {
189
+ {
190
+ Name : "containers " ,
191
+ MountPath : "/mnt/containerTcpdump/containers.json" ,
192
+ SubPath : "containers.json" ,
193
+ },
194
+ } ,
173
195
},
174
- ReadinessProbe : & apicore.Probe {
175
- Handler : apicore.Handler {
176
- Exec : & apicore.ExecAction {
177
- Command : probeCommand ,
196
+ },
197
+ NodeName : node ,
198
+ HostPID : true ,
199
+ Volumes : []apicore.Volume {
200
+ {
201
+ Name : "containers" ,
202
+ VolumeSource : apicore.VolumeSource {
203
+ ConfigMap : & apicore.ConfigMapVolumeSource {
204
+ LocalObjectReference : apicore.LocalObjectReference {
205
+ Name : node + "-" + suffix ,
206
+ },
178
207
},
179
208
},
180
209
},
181
210
},
182
211
},
183
- NodeName : pod .Node ,
184
- HostPID : true ,
185
212
},
186
- }
213
+ & apicore.ConfigMap {
214
+ ObjectMeta : metav1.ObjectMeta {
215
+ Name : node + "-" + suffix ,
216
+ Namespace : "default" ,
217
+ Labels : map [string ]string {
218
+ "k8stcpdump" : "true" ,
219
+ },
220
+ },
221
+ BinaryData : map [string ][]byte {
222
+ "containers.json" : cmContainersJson ,
223
+ },
224
+ }
225
+
187
226
}
188
227
189
228
func watchPodStatus (client * kubernetes.Clientset , tcpdumpPod * apicore.Pod ) wait.ConditionFunc {
@@ -206,19 +245,24 @@ func watchPodStatus(client *kubernetes.Clientset, tcpdumpPod *apicore.Pod) wait.
206
245
}
207
246
}
208
247
209
- func createPod (client * kubernetes.Clientset , targetPod * target , duration string ) (* apicore.Pod , error ) {
210
- podDefinition := getPodDef (targetPod , duration )
211
- tcpdumpPod , err := client .CoreV1 ().Pods (podDefinition .ObjectMeta .Namespace ).Create (context .TODO (), podDefinition , metav1.CreateOptions {})
248
+ func createPod (client * kubernetes.Clientset , node string , containers []string , duration string ) (* apicore.Pod , error ) {
249
+ podManifest , cmManifest := createManifests (node , containers , duration )
250
+ _ , err := client .CoreV1 ().ConfigMaps (cmManifest .ObjectMeta .Namespace ).Create (context .TODO (), cmManifest , metav1.CreateOptions {})
251
+ if err != nil {
252
+ log .Warn (fmt .Sprintf ("Failed to create the configmap for node %q due to %q" , node , err ))
253
+ return nil , err
254
+ }
255
+ tcpdumpPod , err := client .CoreV1 ().Pods (podManifest .ObjectMeta .Namespace ).Create (context .TODO (), podManifest , metav1.CreateOptions {})
212
256
if err == nil {
213
257
log .Info (fmt .Sprintf ("Pod '%s' in the namespace '%s' has been created." , tcpdumpPod .Name , tcpdumpPod .Namespace ))
214
258
} else {
215
- log .Warn (fmt .Sprintf ("Pod '%s' in the namespace '%s' failed to be created due to '%s'." , podDefinition .ObjectMeta .Name , podDefinition .ObjectMeta .Namespace , err .Error ()))
259
+ log .Warn (fmt .Sprintf ("Pod '%s' in the namespace '%s' failed to be created due to '%s'." , podManifest .ObjectMeta .Name , podManifest .ObjectMeta .Namespace , err .Error ()))
216
260
}
217
261
return tcpdumpPod , err
218
262
}
219
263
220
- func downloadFromPod (restConfig * rest.Config , client * kubernetes.Clientset , tcpdumpPod * apicore.Pod ) error {
221
- path := "/tmp/" + tcpdumpPod . Spec . Containers [ 0 ]. Name + "_" + tcpdumpPod . ObjectMeta . Namespace + ".cap"
264
+ func downloadFromPod (restConfig * rest.Config , client * kubernetes.Clientset , tcpdumpPod * apicore.Pod , targetContainer string ) error {
265
+ path := "/tmp/" + targetContainer + ".cap"
222
266
command := []string {"tar" , "cf" , "-" , path }
223
267
req := client .CoreV1 ().RESTClient ().Post ().Namespace (tcpdumpPod .ObjectMeta .Namespace ).Resource ("pods" ).Name (tcpdumpPod .ObjectMeta .Name ).SubResource ("exec" ).VersionedParams (& apicore.PodExecOptions {
224
268
Container : tcpdumpPod .Spec .Containers [0 ].Name ,
@@ -255,7 +299,8 @@ func downloadFromPod(restConfig *rest.Config, client *kubernetes.Clientset, tcpd
255
299
}
256
300
break
257
301
}
258
- destFileName := "./" + tcpdumpPod .Spec .Containers [0 ].Name + "-" + tcpdumpPod .ObjectMeta .Namespace + ".cap"
302
+ destFileName := "./" + targetContainer + ".cap"
303
+ //log.Info(fmt.Sprintf("Create" + destFileName))
259
304
outFile , err := os .Create (destFileName )
260
305
if err != nil {
261
306
log .Warn (fmt .Sprintf ("Error while creating the local dump file for pod '%s'" , tcpdumpPod .ObjectMeta .Name ))
@@ -278,6 +323,10 @@ func cleanUp(client *kubernetes.Clientset, tcpdumpPod *apicore.Pod) error {
278
323
//var GracePeriodSeconds int64
279
324
//GracePeriodSeconds = 0
280
325
err := client .CoreV1 ().Pods (tcpdumpPod .ObjectMeta .Namespace ).Delete (context .TODO (), tcpdumpPod .ObjectMeta .Name , metav1.DeleteOptions {})
326
+ if err != nil {
327
+ return err
328
+ }
329
+ err = client .CoreV1 ().ConfigMaps (tcpdumpPod .ObjectMeta .Namespace ).Delete (context .TODO (), tcpdumpPod .ObjectMeta .Name , metav1.DeleteOptions {})
281
330
return err
282
331
}
283
332
@@ -297,9 +346,9 @@ func cleanUp(client *kubernetes.Clientset, tcpdumpPod *apicore.Pod) error {
297
346
// return false
298
347
//}
299
348
300
- func podOperation (workerGroup * sync.WaitGroup , restConfig * rest.Config , client * kubernetes.Clientset , targetPod * target , duration string , sleepTime time.Duration ) error {
349
+ func podOperation (workerGroup * sync.WaitGroup , restConfig * rest.Config , client * kubernetes.Clientset , node string , containers [] string , duration string , sleepTime time.Duration ) error {
301
350
defer workerGroup .Done ()
302
- tcpdumpPod , err := createPod (client , targetPod , duration )
351
+ tcpdumpPod , err := createPod (client , node , containers , duration )
303
352
if err == nil {
304
353
305
354
err = wait .PollImmediate (time .Second * 1 , sleepTime , watchPodStatus (client , tcpdumpPod ))
@@ -326,10 +375,15 @@ func podOperation(workerGroup *sync.WaitGroup, restConfig *rest.Config, client *
326
375
log .Warn (fmt .Sprintf ("Timeout while waiting tcpdump for pod '%s' in the namespace '%s' to complete" , tcpdumpPod .ObjectMeta .Name , tcpdumpPod .ObjectMeta .Namespace ))
327
376
//log.Fatal(err)
328
377
} else {
329
- err = downloadFromPod (restConfig , client , tcpdumpPod )
330
- if err != nil {
331
- log .Warn (fmt .Sprintf ("Failed to download dump file from pod '%s' in the namespace '%s'" , tcpdumpPod .ObjectMeta .Name , tcpdumpPod .ObjectMeta .Namespace ))
378
+ for _ , container := range containers {
379
+ err = downloadFromPod (restConfig , client , tcpdumpPod , container )
380
+ if err != nil {
381
+ log .Warn (fmt .Sprintf ("Failed to download dump file for the container %q from pod '%s' in the namespace '%s'" , container , tcpdumpPod .ObjectMeta .Name , tcpdumpPod .ObjectMeta .Namespace ))
382
+ } else {
383
+ log .Info (fmt .Sprintf ("Download the dump file for the container %q successfully" , container ))
384
+ }
332
385
}
386
+
333
387
}
334
388
err = cleanUp (client , tcpdumpPod )
335
389
if err != nil {
@@ -361,13 +415,18 @@ func Run(parFile string) {
361
415
podList := * targetPods
362
416
count := len (podList )
363
417
364
- var workerGroup sync. WaitGroup
418
+ nodeSet := make ( map [ string ][] string )
365
419
for i := 0 ; i < count ; i ++ {
420
+ err = createNodeSet (nodeSet , & podList [i ])
421
+ }
422
+
423
+ var workerGroup sync.WaitGroup
424
+ for node , targetContainers := range nodeSet {
366
425
workerGroup .Add (1 )
367
- go podOperation (& workerGroup , restConfig , client , & podList [ i ] , duration , sleepTime )
426
+ go podOperation (& workerGroup , restConfig , client , node , targetContainers , duration , sleepTime )
368
427
}
369
- //fmt.Println("Wait for workers")
370
428
workerGroup .Wait ()
429
+
371
430
//fmt.Println("All workers have completed")
372
431
log .Info ("All operations have been completed. EXIT now." )
373
432
}
0 commit comments