Documentationcurrent version
Help us improve the docs by fixing typos and proposing enhancements.

Nikita

Action "system.cgroups"

Nikita action to manipulate cgroups. cgconfig.conf(5) describes the configuration file used by libcgroup to define control groups, their parameters and also mount points. The configuration file is identical on Ubuntu, RedHat and CentOS.

Implementation

When reading the current config, nikita uses cgsnapshot command in order to have a well formatted file. It is available on CentOS with the libcgroup-tools package.

If docker is installed and started, informations about live containers could be printed, that's why all path under docker/* are ignored.

Example

Example of a group object:

bibi:
  perm:
    admin:
      uid: 'bibi'
      gid: 'bibi'
    task:
      uid: 'bibi'
      gid: 'bibi'
  controllers:
    cpu:
      'cpu.rt_period_us': '"1000000"'
      'cpu.rt_runtime_us': '"0"'
      'cpu.cfs_period_us': '"100000"'

Which will result in a file:

group bibi {
  perm {
    admin {
      uid = bibi;
      gid = bibi;
    }
    task {
      uid = bibi;
      gid = bibi;
    }
  }
  cpu {
    cpu.rt_period_us = "1000000";
    cpu.rt_runtime_us = "0";
    cpu.cfs_period_us = "100000";
  }
}

Schema definitions

definitions =
  config:
    type: 'object'
    properties:
      'default':
        $ref: '#/definitions/group'
        description: '''
        The default object of cgconfig file.
        '''
      'groups':
        type: 'object'
        description: '''
        Object of cgroups to add to cgconfig file. The keys are the
        cgroup name, and the values are the cgroup configuration.
        '''
        patternProperties:
          '.*': # cgroup name
            $ref: '#/definitions/group'
        additionalProperties: false
      'ignore':
        type: 'array'
        items: type: 'string'
        description: '''
        List of group path to ignore. Only used when merging.
        '''
      'mounts':
        type: 'array'
        description: '''
        List of mount object to add to cgconfig file.
        '''
      'merge':
        type: 'boolean'
        default: true
        description: '''
        Default to true. Read the config from cgsnapshot command and merge
        mounts part of the cgroups.
        '''
      'target':
        type: 'string'
        description: '''
        The cgconfig configuration file. By default nikita detects provider
        based on os.
        '''
    anyOf: [
      required: ['groups']
    ,
      required: ['mounts']
    ,
      required: ['default']
    ]
  group:
    type: 'object'
    description: '''
    Controllers in the cgroup where the keys represent the name of the
    controler.
    '''
    properties:
      perm:
        type: 'object'
        description: '''
        Object to describe the taks and limits permissions.
        '''
        properties:
          'admin':
            $ref: '#/definitions/group_perm'
            description: '''
            Who can manage limits
            '''
          'task':
            $ref: '#/definitions/group_perm'
            description: '''
            Who can add tasks to this group
            '''
      cpuset: $ref: '#/definitions/group_controller'
      cpu: $ref: '#/definitions/group_controller'
      cpuacct: $ref: '#/definitions/group_controller'
      blkio: $ref: '#/definitions/group_controller'
      memory: $ref: '#/definitions/group_controller'
      devices: $ref: '#/definitions/group_controller'
      freezer: $ref: '#/definitions/group_controller'
      net_cls: $ref: '#/definitions/group_controller'
      perf_event: $ref: '#/definitions/group_controller'
      net_prio: $ref: '#/definitions/group_controller'
      hugetlb: $ref: '#/definitions/group_controller'
      pids: $ref: '#/definitions/group_controller'
      rdma: $ref: '#/definitions/group_controller'
  group_perm:
    type: 'object'
    properties:
      'uid': oneOf: [
        type: 'integer'
      ,
        type: 'string'
      ]
      'gid': oneOf: [
        type: 'integer'
      ,
        type: 'string'
      ]
  group_controller:
    type: 'object'
    patternProperties:
      '.*': oneOf: [
        type: 'integer'
      ,
        type: 'string'
      ]
    additionalProperties: false

Handler

handler = ({config}) ->
  # throw Error 'Missing cgroups content' unless config.groups? or config.mounts? or config.default?
  config.mounts ?= []
  config.groups ?= {}
  config.merge ?= true
  config.cgconfig = {}
  config.cgconfig['mounts'] = config.mounts
  config.cgconfig['groups'] = config.groups
  config.cgconfig['groups'][''] = config.default if config.default?
  config.ignore ?= []
  config.ignore = [config.ignore] unless Array.isArray config.ignore
  # Detect Os and version
  {os} = await @system.info.os()
  # configure parameters based on previous OS dection
  store = {}
  if ['redhat','centos'].includes os.distribution
    {stdout} = await @execute
      $shy: true
      command: 'cgsnapshot -s 2>&1'
    cgconfig = utils.cgconfig.parse stdout
    cgconfig.mounts ?= []
    cpus = cgconfig.mounts.filter (mount) ->
      mount.type is 'cpu'
    cpuaccts = cgconfig.mounts.filter (mount) ->
      mount.type is 'cpuacct'
    # We choose a path which is mounted by default
    # if not @store['nikita:cgroups:cpu_path']?
    if cpus.length > 0
      store.cpu_path = cpus[0]['path'].split(',')[0]
      # @store['nikita:cgroups:cpu_path'] ?= cpu_path
    # a arbitrary path is given based on the
    else
      switch os.distribution
        when 'redhat', 'centos'
          majorVersion = os.version.split('.')[0]
          switch majorVersion
            when '6'
              store.cpu_path = '/cgroups/cpu'
            when '7'
              store.cpu_path = '/sys/fs/cgroup/cpu'
            else
              throw Error "Nikita does not support cgroups for your RedHat or CentOS version}"
        else throw Error "Nikita does not support cgroups on your OS #{os.distribution}"
    store.mount = "#{path.posix.dirname store.cpu_path}"
    # Running docker containers are remove from cgsnapshot output
    if config.merge
      groups = {}
      for name, group of cgconfig.groups
        groups[name] = group unless (name.indexOf('docker/') isnt -1) or (name in config.ignore)
      config.cgconfig.groups = merge groups, config.groups
      config.cgconfig.mounts.push cgconfig.mounts...
  # Write the configuration
  config.target ?= '/etc/cgconfig.conf' if ['redhat', 'centos'].includes os.distribution
  @file config,
    content: utils.cgconfig.stringify config.cgconfig
  cgroups:
    cpu_path: store.cpu_path
    mount: store.mount

Exports

module.exports =
  handler: handler
  metadata:
    definitions: definitions

Dependencies

utils = require './utils'
{merge} = require 'mixme'
path = require 'path'
Edit on GitHub
Navigate
About

Nikita is an open source project hosted on GitHub and developed by Adaltas.