intel-device-plugins-for-ku.../DEVEL.md
Graham Whaley f8dbc896a1 devicemanager: qat: use klog for logging and debug
Move the framework, and the qat driver, to use `klog`
for logging and debug.

This has a some noticeable effects:

1) Our default log output gains a bunch of annotation:
From:
    QAT device plugin started in 'dpdk' mode
To:
    I0312 11:51:02.057728    6053 qat_plugin.go:64] QAT device plugin started in 'dpdk' mode

(there is now a command line option to drop those annotations if
necessary).

2) We gain a bunch of command line parameters from klog for controlling log
levels and output. We go from 5 arguments to 17:

---
Usage of ./cmd/qat_plugin/qat_plugin:
  -add_dir_header
        If true, adds the file directory to the header
  -alsologtostderr
        log to standard error as well as files
  -debug
        enable debug output
  -dpdk-driver string
        DPDK Device driver for configuring the QAT device (default "vfio-pci")
  -kernel-vf-drivers string
        Comma separated VF Device Driver of the QuickAssist Devices in the system. Devices supported: DH895xCC,C62x,C3xxx and D15xx (default "dh895xccvf,c6xxvf,c3xxxvf,d15xxvf")
  -log_backtrace_at value
        when logging hits line file:N, emit a stack trace
  -log_dir string
        If non-empty, write log files in this directory
  -log_file string
        If non-empty, use this log file
  -log_file_max_size uint
        Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
  -logtostderr
        log to standard error instead of files (default true)
  -max-num-devices int
        maximum number of QAT devices to be provided to the QuickAssist device plugin (default 32)
  -mode string
        plugin mode which can be either dpdk (default) or kernel (default "dpdk")
  -skip_headers
        If true, avoid header prefixes in the log messages
  -skip_log_headers
        If true, avoid headers when opening log files
  -stderrthreshold value
        logs at or above this threshold go to stderr (default 2)
  -v value
        number for the log level verbosity
  -vmodule value
        comma-separated list of pattern=N settings for file-filtered logging
---

3) Our `-debug` flag is now replaced by the `klog` `-v n` flag.

*NOTE:* This is potentially a minor breaking change. Applying
this debug overlay to any previous (pre-klog edit) images will
cause the container to fail to launch, as it will not recognise
the new `-v` arguments.

We also update the kustomize deployment to move from using
DEBUG env vars to adding a VERBOSITY var that controls both
the log verbosity and now the debug mode enabling.

Signed-off-by: Graham Whaley <graham.whaley@intel.com>
2020-03-19 11:20:48 +00:00

3.3 KiB

How to develop simple device plugins

To create a simple device plugin without the hassle of developing your own gRPC server, you can use a package included in this repository called github.com/intel/intel-device-plugins-for-kubernetes/pkg/deviceplugin.

All you have to do is instantiate a deviceplugin.Manager and call its Run() method:

func main() {
    ...

    manager := dpapi.NewManager(namespace, plugin)
    manager.Run()
}

The manager's constructor accepts two parameters:

  1. namespace which is a string like "color.example.com". All your devices will be exposed under this name space, e.g. "color.example.com/yellow". Please note that one device plugin can register many such "colors". The manager will instantiate multiple gRPC servers for every registered "color".
  2. plugin which is a reference to an object implementing one mandatory interface deviceplugin.Scanner.

deviceplugin.Scanner defines one method Scan() which is called only once for every device plugin by deviceplugin.Manager in a goroutine and operates in an infinite loop. A Scan() implementation scans the host for devices and sends all found devices to a deviceplugin.Notifier instance. The deviceplugin.Notifier is implemented and provided by the deviceplugin package itself. The found devices are organized in an instance of deviceplugin.DeviceTree object. The object is filled in with its AddDevice() method:

func (dp *devicePlugin) Scan(notifier deviceplugin.Notifier) error {
    for {
        devTree := deviceplugin.NewDeviceTree()
        ...
        devTree.AddDevice("yellow", devID, deviceplugin.DeviceInfo{
            State: health,
            Nodes: []pluginapi.DeviceSpec{
                {
                    HostPath:      devPath,
                    ContainerPath: devPath,
                    Permissions:   "rw",
                },
            },
        })
        ...
        notifier.Notify(devTree)
    }
}

Optionally, your device plugin may also implement the deviceplugin.PostAllocator interface. If implemented, its method PostAllocate() modifies pluginapi.AllocateResponse responses just before they are sent to kubelet. To see an example, refer to the FPGA plugin which implements this interface to annotate its responses.

Logging

The framework uses klog as its logging framework. It is encouraged for plugins to also use klog to maintain uniformity in the logs and command line options.

The framework initialises klog, so further calls to klog.InitFlags() by plugins should not be necessary. This does add a number of log configuration options to your plugin, which can be viewed with the -h command line option of your plugin.

The framework tries to adhere to the Kubernetes Logging Conventions. The advise is to use the V() levels for Info() calls, as calling Info() with no set level will make configuration and filtering of logging via the command line more difficult.

The default is to not log Info() calls. This can be changed using the plugin command line -v parameter. The additional annotations prepended to log lines by 'klog' can be disabled with the -skip_headers option.