github.com/demonoid81/containerd@v1.3.4/metrics/cgroups/cgroups.go (about)

     1  // +build linux
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package cgroups
    20  
    21  import (
    22  	"context"
    23  
    24  	"github.com/containerd/cgroups"
    25  	eventstypes "github.com/containerd/containerd/api/events"
    26  	"github.com/containerd/containerd/errdefs"
    27  	"github.com/containerd/containerd/events"
    28  	"github.com/containerd/containerd/log"
    29  	"github.com/containerd/containerd/namespaces"
    30  	"github.com/containerd/containerd/platforms"
    31  	"github.com/containerd/containerd/plugin"
    32  	"github.com/containerd/containerd/runtime"
    33  	"github.com/containerd/containerd/runtime/v1/linux"
    34  	metrics "github.com/docker/go-metrics"
    35  	"github.com/sirupsen/logrus"
    36  )
    37  
    38  // Config for the cgroups monitor
    39  type Config struct {
    40  	NoPrometheus bool `toml:"no_prometheus"`
    41  }
    42  
    43  func init() {
    44  	plugin.Register(&plugin.Registration{
    45  		Type:   plugin.TaskMonitorPlugin,
    46  		ID:     "cgroups",
    47  		InitFn: New,
    48  		Config: &Config{},
    49  	})
    50  }
    51  
    52  // New returns a new cgroups monitor
    53  func New(ic *plugin.InitContext) (interface{}, error) {
    54  	var ns *metrics.Namespace
    55  	config := ic.Config.(*Config)
    56  	if !config.NoPrometheus {
    57  		ns = metrics.NewNamespace("container", "", nil)
    58  	}
    59  	collector := newCollector(ns)
    60  	oom, err := newOOMCollector(ns)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	if ns != nil {
    65  		metrics.Register(ns)
    66  	}
    67  	ic.Meta.Platforms = append(ic.Meta.Platforms, platforms.DefaultSpec())
    68  	return &cgroupsMonitor{
    69  		collector: collector,
    70  		oom:       oom,
    71  		context:   ic.Context,
    72  		publisher: ic.Events,
    73  	}, nil
    74  }
    75  
    76  type cgroupsMonitor struct {
    77  	collector *collector
    78  	oom       *oomCollector
    79  	context   context.Context
    80  	publisher events.Publisher
    81  }
    82  
    83  func (m *cgroupsMonitor) Monitor(c runtime.Task) error {
    84  	if err := m.collector.Add(c); err != nil {
    85  		return err
    86  	}
    87  	t, ok := c.(*linux.Task)
    88  	if !ok {
    89  		return nil
    90  	}
    91  	cg, err := t.Cgroup()
    92  	if err != nil {
    93  		if errdefs.IsNotFound(err) {
    94  			return nil
    95  		}
    96  		return err
    97  	}
    98  	err = m.oom.Add(c.ID(), c.Namespace(), cg, m.trigger)
    99  	if err == cgroups.ErrMemoryNotSupported {
   100  		logrus.WithError(err).Warn("OOM monitoring failed")
   101  		return nil
   102  	}
   103  	return err
   104  }
   105  
   106  func (m *cgroupsMonitor) Stop(c runtime.Task) error {
   107  	m.collector.Remove(c)
   108  	return nil
   109  }
   110  
   111  func (m *cgroupsMonitor) trigger(id, namespace string, cg cgroups.Cgroup) {
   112  	ctx := namespaces.WithNamespace(m.context, namespace)
   113  	if err := m.publisher.Publish(ctx, runtime.TaskOOMEventTopic, &eventstypes.TaskOOM{
   114  		ContainerID: id,
   115  	}); err != nil {
   116  		log.G(m.context).WithError(err).Error("post OOM event")
   117  	}
   118  }