[英]How to collect k8s pods logs in parallel using golang only for a duration of time
I am new to golang, I have a task to collect the application logs, application is running as deployment in k8s cluster, there are 4 pods in total.我是 golang 的新手,我有一个收集应用程序日志的任务,应用程序作为部署在 k8s 集群中运行,总共有 4 个 pod。 As part of test automation, I need to collect the application logs (only for the duration of my test operation) in parallel while I perform some operations on the application and write the logs to a file, and move to the next operation and do the same.
作为测试自动化的一部分,我需要在对应用程序执行一些操作并将日志写入文件的同时并行收集应用程序日志(仅在测试操作期间),然后转到下一个操作并执行相同的。
Finally I iterate through the log files one-by-one and filter for certain keywords corresponding to my operation and validate the logs are correct/not.最后,我一个一个地遍历日志文件,过滤与我的操作相对应的某些关键字,并验证日志是否正确。
I am thinking to get the pod logs using kubectl command directly, instead of using the go-sdk as I am facing missing log entries which I couldn't triage with many attempts.我正在考虑直接使用 kubectl 命令获取 pod 日志,而不是使用 go-sdk,因为我面临丢失的日志条目,我无法通过多次尝试对其进行分类。
kubectl logs -f -l app=my-app -n dev > /usr/mylogs.txt
I found a way to run this command using exec.Command我找到了一种使用 exec.Command 运行此命令的方法
command := exec.Command("/bin/sh", "-c", "kubectl logs -f -l app=my-app -n dev > /usr/mylogs.txt")
err := command.Start()
Now I need to do this in golang,现在我需要在 golang 中做这个,
func myTest(t *testing.T){
go collectApplicationLogs("test1")
// do application operation
// run test
stopLogsCollection () -------> how to achieve this?
}
func collectApplicationLogs(fileName string){
// command to collect the logs to a file
// kubectl logs -f -l app=my-app -n dev > /usr/{fileName}
}
You can use Kube.netes go-client to get logs from the pods.您可以使用 Kube.netes go-client 从 pod 获取日志。 At first create the clientset from kub.netes config.
首先从 kub.netes 配置创建客户端。 You can use InclusterConfig or Out of cluster config.
您可以使用 InclusterConfig 或集群外配置。 I have used out of cluster config here.
我在这里使用了集群配置。
const (
// set namespace and label
namespace = "dev"
label = "app=my-app"
)
func main() {
// parse the .kubeconfig file
var kubeconfig *string
if home := homedir.HomeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()
// use the current context in kubeconfig
ctx := context.TODO()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
log.Println(err, "Failed to build config from flags")
return
}
err = collectApplicationLogs(ctx, config, "/usr/mylogs.txt")
if err != nil {
log.Println(err, "Failed to collect logs")
}
}
To collect logs, you need to list the gods first.收集日志,需要先列大神。 Then get logs from each of those pods and append them to the file concurrently.
然后从每个 pod 中获取日志并将它们 append 同时写入文件。
func collectApplicationLogs(ctx context.Context, config *rest.Config, filename string) error {
// create the clientset
clientSet, err := kubernetes.NewForConfig(config)
if err != nil {
log.Println("Failed to create clientset from the given config")
return err
}
// get the pods as ListItems
pods, err := clientSet.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{
LabelSelector: label,
})
if err != nil {
log.Println(err, "Failed to get pods")
return err
}
// If the file doesn't exist, create it or append to the file
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return err
}
defer file.Close()
// get the pod lists first
// then get the podLogs from each of the pods
// write to files concurrently
// use channel for blocking reasons
ch := make(chan bool)
podItems := pods.Items
for i := 0; i < len(podItems); i++ {
podLogs, err := clientSet.CoreV1().Pods(namespace).GetLogs(podItems[i].Name, &v1.PodLogOptions{
Follow: true,
}).Stream(ctx)
if err != nil {
return err
}
buffer := bufio.NewReader(podLogs)
go writeLogs(buffer, file, ch)
}
<-ch
return nil
}
func writeLogs(buffer *bufio.Reader, file *os.File, ch chan bool) {
defer func() {
ch <- true
}()
for {
str, readErr := buffer.ReadString('\n')
if readErr == io.EOF {
break
}
_, err := file.Write([]byte(str))
if err != nil {
return
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.