How can i get the info of container created by kubernetes as types.StatsJSON from docker golang client?

huangapple go评论70阅读模式
英文:

How can i get the info of container created by kubernetes as types.StatsJSON from docker golang client?

问题

在Docker Go客户端库中,要获取容器的types.StatsJSON,可以使用client.ContainerStats方法。但是,根据你提供的代码和示例输出,这种方法无法获取由Kubernetes创建的容器的网络信息。

要获取由Kubernetes创建的容器的网络信息,可以尝试使用Kubernetes客户端库来获取容器的详细信息,包括网络信息。你可以使用clientset.CoreV1().Pods(namespace).Get(podName, metav1.GetOptions{})方法来获取Pod的详细信息,其中namespace是Pod所在的命名空间,podName是Pod的名称。

在获取到Pod的详细信息后,你可以从中提取出容器的网络信息。具体的代码实现可能会有所不同,但以下是一个示例代码,用于获取由Kubernetes创建的容器的网络信息:

import (
	"fmt"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/homedir"
	"path/filepath"
)

func main() {
	// 读取kubeconfig文件
	home := homedir.HomeDir()
	kubeconfig := filepath.Join(home, ".kube", "config")
	config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
	if err != nil {
		panic(err)
	}

	// 创建Kubernetes客户端
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err)
	}

	// 获取Pod的详细信息
	podName := "your-pod-name"
	namespace := "your-namespace"
	pod, err := clientset.CoreV1().Pods(namespace).Get(podName, metav1.GetOptions{})
	if err != nil {
		panic(err)
	}

	// 提取容器的网络信息
	for _, container := range pod.Spec.Containers {
		networkStats := container.Resources.Networks
		fmt.Println(networkStats)
	}
}

请注意,上述代码中的your-pod-nameyour-namespace需要替换为你实际使用的Pod的名称和命名空间。

希望这可以帮助到你获取由Kubernetes创建的容器的网络信息。如果有任何进一步的问题,请随时提问。

英文:

Code in the file github.com/docker/docker/client/container_stats.go shows 2 ways to get container info, client.ContainerStats and client.ContainerStatsOneShot.
But the results both are types.ContainerStats, which doesn't include network info.
How can i get the types.StatsJSON of a container with the Docker Go client library?

type StatsJSON struct {
	Stats

	Name string `json:"name,omitempty"`
	ID   string `json:"id,omitempty"`

	// Networks request version >=1.21
	Networks map[string]NetworkStats `json:"networks,omitempty"`
}
func main() {
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
	panic(err)
}
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
	panic(err)
}
for _, container := range containers {
	containerStats, err := cli.ContainerStats(context.Background(), container.ID, false)
	if err != nil {
		panic(err)
	}
	fmt.Println(containerStats)
	fmt.Println(containerStats.Body)
	buf := new(bytes.Buffer)

	buf.ReadFrom(containerStats.Body)
	newStr := buf.String()
	fmt.Printf(newStr)
}

}

my code is shown above.

I found that if the container is created by kubernetes, the code can't get the network info.

{"read":"2022-04-16T13:19:35.763484238Z","preread":"2022-04-16T13:19:34.758939054Z","pids_stats":{"current":2},"blkio_stats":{"io_service_bytes_recursive":[],"io_serviced_recursive":[],"io_queue_recursive":[],"io_service_time_recursive":[],"io_wait_time_recursive":[],"io_merged_recursive":[],"io_time_recursive":[],"sectors_recursive":[]},"num_procs":0,"storage_stats":{},"cpu_stats":{"cpu_usage":{"total_usage":81301483,"percpu_usage":[0,381774,697871,3974768,0,49920,599904,622885,6274012,858410,0,570611,52635,11229798,100631,0,99914,0,479666,698862,51132727,902108,1941742,633245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"usage_in_kernelmode":40000000,"usage_in_usermode":20000000},"system_cpu_usage":82393060580000000,"online_cpus":24,"throttling_data":{"periods":12,"throttled_periods":8,"throttled_time":811771919}},"precpu_stats":{"cpu_usage":{"total_usage":81301483,"percpu_usage":[0,381774,697871,3974768,0,49920,599904,622885,6274012,858410,0,570611,52635,11229798,100631,0,99914,0,479666,698862,51132727,902108,1941742,633245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"usage_in_kernelmode":40000000,"usage_in_usermode":20000000},"system_cpu_usage":82393036780000000,"online_cpus":24,"throttling_data":{"periods":12,"throttled_periods":8,"throttled_time":811771919}},"memory_stats":{"usage":1515520,"max_usage":7999488,"stats":{"active_anon":196608,"active_file":0,"cache":0,"dirty":0,"hierarchical_memory_limit":419430400,"hierarchical_memsw_limit":0,"inactive_anon":0,"inactive_file":0,"mapped_file":0,"pgfault":2077,"pgmajfault":0,"pgpgin":1658,"pgpgout":1610,"rss":196608,"rss_huge":0,"total_active_anon":196608,"total_active_file":0,"total_cache":0,"total_dirty":0,"total_inactive_anon":0,"total_inactive_file":0,"total_mapped_file":0,"total_pgfault":2077,"total_pgmajfault":0,"total_pgpgin":1658,"total_pgpgout":1610,"total_rss":196608,"total_rss_huge":0,"total_unevictable":0,"total_writeback":0,"unevictable":0,"writeback":0},"limit":419430400},"name":"/k8s_centos_ltstatefulset-b-0_default_19f13fc1-b971-47c0-9519-619b64c01b68_195","id":"b15626bfc4665c457c7fb319f17e162d611262d193e38ec9e7878ca8b3e8b02b"}

if not, the code works.

{"read":"2022-04-16T14:35:12.97263525Z","preread":"2022-04-16T14:35:11.937969083Z","pids_stats":{"current":25},"blkio_stats":{"io_service_bytes_recursive":[{"major":8,"minor":0,"op":"Read","value":11210752},{"major":8,"minor":0,"op":"Write","value":8192},{"major":8,"minor":0,"op":"Sync","value":4096},{"major":8,"minor":0,"op":"Async","value":11214848},{"major":8,"minor":0,"op":"Total","value":11218944}],"io_serviced_recursive":[{"major":8,"minor":0,"op":"Read","value":527},{"major":8,"minor":0,"op":"Write","value":2},{"major":8,"minor":0,"op":"Sync","value":1},{"major":8,"minor":0,"op":"Async","value":528},{"major":8,"minor":0,"op":"Total","value":529}],"io_queue_recursive":[],"io_service_time_recursive":[],"io_wait_time_recursive":[],"io_merged_recursive":[],"io_time_recursive":[],"sectors_recursive":[]},"num_procs":0,"storage_stats":{},"cpu_stats":{"cpu_usage":{"total_usage":349863146,"percpu_usage":[10474676,1510192,454233,1388678,254249,80111,3389261,101473612,416604,8936772,5378206,4940434,0,347495,891133,85645,0,0,168781006,13378842,9622376,4594553,9938770,3526298],"usage_in_kernelmode":80000000,"usage_in_usermode":260000000},"system_cpu_usage":109879214590000000,"online_cpus":24,"throttling_data":{"periods":0,"throttled_periods":0,"throttled_time":0}},"precpu_stats":{"cpu_usage":{"total_usage":349863146,"percpu_usage":[10474676,1510192,454233,1388678,254249,80111,3389261,101473612,416604,8936772,5378206,4940434,0,347495,891133,85645,0,0,168781006,13378842,9622376,4594553,9938770,3526298],"usage_in_kernelmode":80000000,"usage_in_usermode":260000000},"system_cpu_usage":109879190530000000,"online_cpus":24,"throttling_data":{"periods":0,"throttled_periods":0,"throttled_time":0}},"memory_stats":{"usage":33136640,"max_usage":34250752,"stats":{"active_anon":15036416,"active_file":4644864,"cache":11415552,"dirty":0,"hierarchical_memory_limit":9223372036854771712,"hierarchical_memsw_limit":0,"inactive_anon":4096,"inactive_file":6766592,"mapped_file":5271552,"pgfault":9844,"pgmajfault":77,"pgpgin":9350,"pgpgout":2892,"rss":15036416,"rss_huge":0,"total_active_anon":15036416,"total_active_file":4644864,"total_cache":11415552,"total_dirty":0,"total_inactive_anon":4096,"total_inactive_file":6766592,"total_mapped_file":5271552,"total_pgfault":9844,"total_pgmajfault":77,"total_pgpgin":9350,"total_pgpgout":2892,"total_rss":15036416,"total_rss_huge":0,"total_unevictable":0,"total_writeback":0,"unevictable":0,"writeback":0},"limit":50609074176},"name":"/mynginx","id":"4af194a6885917eed220a0c45a235e749b566bd5aa0ab18ae5aaf5c6295fc527","networks":{"eth0":{"rx_bytes":3385,"rx_packets":47,"rx_errors":0,"rx_dropped":1,"tx_bytes":0,"tx_packets":0,"tx_errors":0,"tx_dropped":0}}}

How can i get the network info of the container created by k8s?

答案1

得分: 2

你需要读取ContainerStats的主体,因为它返回的数据在一个名为body的字段中,该字段是一个io.ReadCloser

type ContainerStats struct {
    Body   io.ReadCloser `json:"body"`
    OSType string        `json:"ostype"`
}

下面的代码按预期工作。我可以将主体中的数据解码为StatsJSON结构,并访问Networks字段。

// 创建一个客户端
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
    panic(err)
}

// 获取一些容器统计信息
cs, err := cli.ContainerStats(context.TODO(), "<container id>", false)
if err != nil {
    panic(err)
}
// 不要忘记关闭主体
defer cs.Body.Close()

// 将主体解码为StatsJSON结构
data := types.StatsJSON{}
err = json.NewDecoder(cs.Body).Decode(&data)
if err != nil {
    panic(err)
}

// 访问Networks字段
fmt.Println(data.Networks)
英文:

You need to read the body since ContainerStats returns the data in a field named body which is an io.ReadCloser.

type ContainerStats struct {
	Body   io.ReadCloser `json:&quot;body&quot;`
	OSType string        `json:&quot;ostype&quot;`
}

The below code works as expected. I can decode the data from the body into a StatsJSON struct and access the Networks fields.

// create a client
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
    panic(err)
}

// get some container stats
cs, err := cli.ContainerStats(context.TODO(), &quot;&lt;container id&gt;&quot;, false)
if err != nil {
    panic(err)
}
// dont forget to close the body
defer cs.Body.Close()

// decode the body into a StatsJSON struct
data := types.StatsJSON{}
err = json.NewDecoder(cs.Body).Decode(&amp;data)
if err != nil {
    panic(err)
}

// access the Networks field
fmt.Println(data.Networks)

huangapple
  • 本文由 发表于 2022年4月16日 20:52:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/71894035.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定