![](/img/trans.png)
[英]How to have a logic (piece of code) that executes only once inside pods which are replicated in k8s?
[英]How to collect k8s pods logs in parallel using golang only for a duration of time
我是 golang 的新手,我有一個收集應用程序日志的任務,應用程序作為部署在 k8s 集群中運行,總共有 4 個 pod。 作為測試自動化的一部分,我需要在對應用程序執行一些操作並將日志寫入文件的同時並行收集應用程序日志(僅在測試操作期間),然后轉到下一個操作並執行相同的。
最后,我一個一個地遍歷日志文件,過濾與我的操作相對應的某些關鍵字,並驗證日志是否正確。
我正在考慮直接使用 kubectl 命令獲取 pod 日志,而不是使用 go-sdk,因為我面臨丟失的日志條目,我無法通過多次嘗試對其進行分類。
kubectl logs -f -l app=my-app -n dev > /usr/mylogs.txt
我找到了一種使用 exec.Command 運行此命令的方法
command := exec.Command("/bin/sh", "-c", "kubectl logs -f -l app=my-app -n dev > /usr/mylogs.txt")
err := command.Start()
現在我需要在 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}
}
您可以使用 Kube.netes go-client 從 pod 獲取日志。 首先從 kub.netes 配置創建客戶端。 您可以使用 InclusterConfig 或集群外配置。 我在這里使用了集群配置。
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")
}
}
收集日志,需要先列大神。 然后從每個 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.