龙空技术网

go|使用docker API监控容器CPU和内存

博学的书签v 67

前言:

今天兄弟们对“centos监控cpu内存”大体比较关注,你们都想要了解一些“centos监控cpu内存”的相关资讯。那么小编同时在网上网罗了一些有关“centos监控cpu内存””的相关内容,希望大家能喜欢,姐妹们一起来了解一下吧!

需求

想要监控docker容器的状态,CPU,内存等指标,并集成到zabbix监控中

由于服务器docker版本较低(系统为centos6.9,docker 版本为:1.7.1),所以采用API方式获取相关信息。

为了不重启docker,采用socket方式连接docker服务

func dialDocker(proto, addr string) (conn net.Conn, err error) {	  return net.Dial("unix", "/var/run/docker.sock")}

大概思路,使用zabbix自动发现功能,自动发现容器列表并添加监控项。

注意:容器ID每次重建(服务更新)是会变的,但可以保证容器的name不变,所以zabbix监控项的参数要传Container name,而不能是ContainerID,不然,每次更新之前所有监控项都会失效,又添加一批新的监控项。

获取容器列表

生成自动发现JSON数据,用于zabbix自动把所有容器添加到监控项,代码如下:

package mainimport (	"encoding/json"	"flag"	"fmt"	"io/ioutil"	"net"	"net/http"	"strings"	"github.com/tidwall/gjson")var url stringfunc init() {	flag.StringVar(&url, "u", ``, "url")	flag.Parse()}func dialDocker(proto, addr string) (conn net.Conn, err error) {	return net.Dial("unix", "/var/run/docker.sock")}type container struct {	ContainerID   string `json:"{#CONTAINERID},omitempty"`  // 这项可以去掉,这里我们只用获取到所有容器的Container Name即可。	ContainerName string `json:"{#CONTAINERNAME},omitempty"`}type containers struct {	Data []container `json:"data,omitempty"`}func main() {	tr := &http.Transport{		Dial: dialDocker,	}	client := &http.Client{		Transport: tr,	}	resp, err := client.Get(url)	if err != nil {		fmt.Println(err)	}	data, err := ioutil.ReadAll(resp.Body)	if err != nil {		fmt.Println(err)	}	result := gjson.ParseBytes(data)	var d containers	for _, line := range result.Array() {		containerID := line.Get("Id").String()		containerName := strings.TrimLeft(line.Get("Names").Array()[0].String(), "/")		d.Data = append(d.Data, container{ContainerID: containerID, ContainerName: containerName})	}	b, err := json.Marshal(d)	if err != nil {		panic(err)	}	fmt.Println(string(b))}

执行输出:

{"data": [            {            "{#CONTAINERID}": "6913da77edaa1d67ddbcb762da139044a063b251b409e7a532949fdd01978c04",            "{#CONTAINERNAME}": "skywalking-ui"            },            {            "{#CONTAINERID}": "d2d3577447326fdf01f551c6636fee5f6c1ff1ef63dc2cf526c74c5eb4e823b8",            "{#CONTAINERNAME}": "skywalking-oap-server"            },            {            "{#CONTAINERID}": "3635eacdaf7a63dd75e5dcaa33d741c257d74e2faeaa810a5c00db2a0d025f56",            "{#CONTAINERNAME}": "soffice"            },            {            "{#CONTAINERID}": "686a815d229fd5b9f6a6cefb41e3efa72532a80df756c4c17742fae5e65f9ece",            "{#CONTAINERNAME}": "rabbitmq3.7.7"            }      ]}

获取容器CPU和内存使用率

然后根据容器名字获取容器CPU和内存使用率,需要传入两个参数:

-c containerName容器名称-r resource 获取资源类型,cpu/mem/disk/net,

暂时仅实现了获取CPU和内存使用率

结构定义和计算参考文档:

代码如下:

package mainimport (	"encoding/json"	"flag"	"fmt"	"log"	"net"	"net/http")type ThrottlingData struct {	Periods          uint64 `json:"periods,omitempty"`	ThrottledPeriods uint64 `json:"throttled_periods,omitempty"`	ThrottledTime    uint64 `json:"throttled_time,omitempty"`}type CPUUsage struct {	TotalUsage        int64   `json:"total_usage,omitempty"`	PercpuUsage       []int64 `json:"percpu_usage,omitempty"`	UsageInKernelmode int64   `json:"usage_in_kernelmode,omitempty"`	UsageInUsermode   int64   `json:"usage_in_usermode,omitempty"`}type CPUStats struct {	CPUUsage       CPUUsage       `json:"cpu_usage,omitempty"`	SystemUsage    uint64         `json:"system_cpu_usage,omitempty"`	OnlineCPUs     uint32         `json:"online_cpus,omitempty"`	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`}type MemoryStats struct {	Usage    uint64            `json:"usage,omitempty"`	MaxUsage uint64            `json:"max_usage,omitempty"`	Stats    map[string]uint64 `json:"stats,omitempty"`	Failcnt  uint64            `json:"failcnt,omitempty"`	Limit    uint64            `json:"limit,omitempty"`}type Status struct {	CPUStats    CPUStats    `json:"cpu_stats,omitempty"`	PreCPUStats CPUStats    `json:"precpu_stats,omitempty"`	MemoryStats MemoryStats `json:"memory_stats,omitempty"`}func (s *Status) CPUPercent() float64 {	var cpuPercent = 0.0	previousCPU := s.PreCPUStats.CPUUsage.TotalUsage	previousSystem := s.PreCPUStats.SystemUsage	cpuDelta := float64(s.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU)	systemDelta := float64(s.CPUStats.SystemUsage) - float64(previousSystem)	if systemDelta > 0.0 && cpuDelta > 0.0 {		cpuPercent = (cpuDelta / systemDelta) * float64(len(s.CPUStats.CPUUsage.PercpuUsage)) * 100.0	}	return cpuPercent}func (s *Status) MemPercent() float64 {	var memPercent float64 = 0.0	if s.MemoryStats.Limit != 0 {		memPercent = float64(s.MemoryStats.Usage) / float64(s.MemoryStats.Limit) * 100.0	}	return memPercent}var (	containerName string	resource      string)func init() {	flag.StringVar(&containerName, "c", "", "containerName")	flag.StringVar(&resource, "r", "", "mem/cpu/disk/net")	flag.Parse()}func dialDocker(proto, addr string) (conn net.Conn, err error) {	return net.Dial("unix", "/var/run/docker.sock")}func getResponse(client *http.Client, url string) (*Status, error) {	resp, err := client.Get(url)	if err != nil {		return nil, err	}	defer resp.Body.Close()	dec := json.NewDecoder(resp.Body)	var s *Status	err = dec.Decode(&s)	return s, err}func main() {	tr := &http.Transport{		Dial: dialDocker,	}	client := &http.Client{		Transport: tr,	}	// get status based on container name	statsUrl := fmt.Sprintf(";, containerName)	info, err := getResponse(client, statsUrl)	if err != nil {		log.Println(err)	}	switch resource {	case "mem":		fmt.Printf("%.3f", info.MemPercent())	case "cpu":		fmt.Printf("%.3f", info.CPUPercent())	}}

由于是作为zabbix的监控脚本,所以没有对入参进行校验

输出如下:

标签: #centos监控cpu内存