wmic cpu get processorid获取的都一样_go|使用docker API监控容器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", `http://v1.24/containers/json?all=true`, "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 containersfor _, 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和内存使用率

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

https://github.com/moby/moby/blob/eb131c5383db8cac633919f82abad86c99bffbe5/cli/command/container/stats_helpers.go

https://github.com/moby/moby/blob/c1d090fcc88fa3bc5b804aead91ec60e30207538/api/types/stats.go

https://docs.docker.com/engine/api/v1.24/

代码如下:

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.0previousCPU := s.PreCPUStats.CPUUsage.TotalUsagepreviousSystem := s.PreCPUStats.SystemUsagecpuDelta := 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.0if s.MemoryStats.Limit != 0 {memPercent = float64(s.MemoryStats.Usage) / float64(s.MemoryStats.Limit) * 100.0}return memPercent}var (containerName stringresource      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 *Statuserr = dec.Decode(&s)return s, err}func main() {tr := &http.Transport{Dial: dialDocker,}client := &http.Client{Transport: tr,}// get status based on container namestatsUrl := fmt.Sprintf("http://v1.30/containers/%s/stats?stream=false", 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的监控脚本,所以没有对入参进行校验

输出如下:

4d950e324bbd9004ece1c7e749be933f.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值