aboutsummaryrefslogtreecommitdiffstats
path: root/docs/report/introduction/methodology_containers.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/report/introduction/methodology_containers.rst')
-rw-r--r--docs/report/introduction/methodology_containers.rst421
1 files changed, 421 insertions, 0 deletions
diff --git a/docs/report/introduction/methodology_containers.rst b/docs/report/introduction/methodology_containers.rst
new file mode 100644
index 0000000000..14817df64f
--- /dev/null
+++ b/docs/report/introduction/methodology_containers.rst
@@ -0,0 +1,421 @@
+
+.. _container_orchestration_in_csit:
+
+Container Orchestration in CSIT
+===============================
+
+Overview
+--------
+
+Linux Containers
+~~~~~~~~~~~~~~~~
+
+Linux Containers is an OS-level virtualization method for running
+multiple isolated Linux systems (containers) on a compute host using a
+single Linux kernel. Containers rely on Linux kernel cgroups
+functionality for controlling usage of shared system resources (i.e.
+CPU, memory, block I/O, network) and for namespace isolation. The latter
+enables complete isolation of applications' view of operating
+environment, including process trees, networking, user IDs and mounted
+file systems.
+
+:abbr:`LXC (Linux Containers)` combine kernel's cgroups and support for isolated
+namespaces to provide an isolated environment for applications. Docker
+does use LXC as one of its execution drivers, enabling image management
+and providing deployment services. More information in [lxc]_, [lxcnamespace]_
+and [stgraber]_.
+
+Linux containers can be of two kinds: privileged containers and
+unprivileged containers.
+
+Unprivileged Containers
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Running unprivileged containers is the safest way to run containers in a
+production environment. From LXC 1.0 one can start a full system
+container entirely as a user, allowing to map a range of UIDs on the
+host into a namespace inside of which a user with UID 0 can exist again.
+In other words an unprivileged container does mask the userid from the
+host, making it impossible to gain a root access on the host even if a
+user gets root in a container. With unprivileged containers, non-root
+users can create containers and will appear in the container as the
+root, but will appear as userid <non-zero> on the host. Unprivileged
+containers are also better suited to supporting multi-tenancy operating
+environments. More information in [lxcsecurity]_ and [stgraber]_.
+
+Privileged Containers
+~~~~~~~~~~~~~~~~~~~~~
+
+Privileged containers do not mask UIDs, and container UID 0 is mapped to
+the host UID 0. Security and isolation is controlled by a good
+configuration of cgroup access, extensive AppArmor profile preventing
+the known attacks as well as container capabilities and SELinux. Here a
+list of applicable security control mechanisms:
+
+- Capabilities - keep (whitelist) or drop (blacklist) Linux capabilities,
+ [capabilities]_.
+- Control groups - cgroups, resource bean counting, resource quotas, access
+ restrictions, [cgroup1]_, [cgroup2]_.
+- AppArmor - apparmor profiles aim to prevent any of the known ways of
+ escaping a container or cause harm to the host, [apparmor]_.
+- SELinux - Security Enhanced Linux is a Linux kernel security module
+ that provides similar function to AppArmor, supporting access control
+ security policies including United States Department of Defense-style
+ mandatory access controls. Mandatory access controls allow an
+ administrator of a system to define how applications and users can
+ access different resources such as files, devices, networks and inter-
+ process communication, [selinux]_.
+- Seccomp - secure computing mode, enables filtering of system calls,
+ [seccomp]_.
+
+More information in [lxcsecurity]_ and [lxcsecfeatures]_.
+
+**Linux Containers in CSIT**
+
+CSIT is using Privileged Containers as the ``sysfs`` is mounted with RW
+access. Sysfs is required to be mounted as RW due to VPP accessing
+:command:`/sys/bus/pci/drivers/uio_pci_generic/unbind`. This is not the case of
+unprivileged containers where ``sysfs`` is mounted as read-only.
+
+
+Orchestrating Container Lifecycle Events
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Following Linux container lifecycle events need to be addressed by an
+orchestration system:
+
+1. Acquire - acquiring/downloading existing container images via
+ :command:`docker pull` or :command:`lxc-create -t download`.
+
+2. Build - building a container image from scratch or another
+ container image via :command:`docker build <dockerfile/composefile>` or
+ customizing LXC templates in
+ `GitHub <https://github.com/lxc/lxc/tree/master/templates>`_.
+
+3. (Re-)Create - creating a running instance of a container application
+ from anew, or re-creating one that failed. A.k.a. (re-)deploy via
+ :command:`docker run` or :command:`lxc-start`
+
+4. Execute - execute system operations within the container by attaching to
+ running container. THis is done by :command:`lxc-attach` or
+ :command:`docker exec`
+
+5. Distribute - distributing pre-built container images to the compute
+ nodes. Currently not implemented in CSIT.
+
+
+Container Orchestration Systems Used in CSIT
+--------------------------------------------
+
+Current CSIT testing framework integrates following Linux container
+orchestration mechanisms:
+
+- LXC/Docker for complete VPP container lifecycle control.
+
+LXC
+~~~
+
+LXC is the well-known and heavily tested low-level Linux container
+runtime [lxcsource]_, that provides a userspace interface for the Linux kernel
+containment features. With a powerful API and simple tools, LXC enables
+Linux users to easily create and manage system or application
+containers. LXC uses following kernel features to contain processes:
+
+- Kernel namespaces: ipc, uts, mount, pid, network and user.
+- AppArmor and SELinux security profiles.
+- Seccomp policies.
+- Chroot.
+- Cgroups.
+
+CSIT uses LXC runtime and LXC usertools to test VPP data plane performance in
+a range of virtual networking topologies.
+
+**Known Issues**
+
+- Current CSIT restriction: only single instance of lxc runtime due to
+ the cgroup policies used in CSIT. There is plan to add the capability into
+ code to create cgroups per container instance to address this issue. This sort
+ of functionality is better supported in LXC 2.1 but can be done is current
+ version as well.
+
+- CSIT code is currently using cgroup to control the range of CPU cores the
+ LXC container runs on. VPP thread pinning is defined vpp startup.conf.
+
+Docker
+~~~~~~
+
+Docker builds on top of Linux kernel containment features, and
+offers a high-level tool for wrapping the processes, maintaining and
+executing them in containers [docker]_. Currently it is using *runc*,
+a CLI tool for spawning and running containers according to the
+`OCI specification <https://www.opencontainers.org/>`_.
+
+A Docker container image is a lightweight, stand-alone, executable
+package that includes everything needed to run the container:
+code, runtime, system tools, system libraries, settings.
+
+CSIT uses Docker to manage the maintenance and execution of
+containerized applications used in CSIT performance tests.
+
+- Data plane thread pinning to CPU cores - Docker CLI and/or Docker
+ configuration file controls the range of CPU cores the Docker image
+ must run on. VPP thread pinning defined vpp startup.conf.
+
+Implementation
+--------------
+
+CSIT container orchestration is implemented in CSIT Level-1 keyword
+Python libraries following the Builder design pattern. Builder design
+pattern separates the construction of a complex object from its
+representation, so that the same construction process can create
+different representations e.g. LXC, Docker, other.
+
+CSIT Robot Framework keywords are then responsible for higher level
+lifecycle control of of the named container groups. One can have
+multiple named groups, with 1..N containers in a group performing
+different role/functionality e.g. NFs, Switch, Kafka bus, ETCD
+datastore, etc. ContainerManager class acts as a Director and uses
+ContainerEngine class that encapsulate container control.
+
+Current CSIT implementation is illustrated using UML Class diagram:
+
+1. Acquire
+2. Build
+3. (Re-)Create
+4. Execute
+
+::
+
+ +-----------------------------------------------------------------------+
+ | RF Keywords (high level lifecycle control) |
+ +-----------------------------------------------------------------------+
+ | Construct VNF containers on all DUTs |
+ | Acquire all '${group}' containers |
+ | Create all '${group}' containers |
+ | Install all '${group}' containers |
+ | Configure all '${group}' containers |
+ | Stop all '${group}' containers |
+ | Destroy all '${group}' containers |
+ +-----------------+-----------------------------------------------------+
+ | 1
+ |
+ | 1..N
+ +-----------------v-----------------+ +--------------------------+
+ | ContainerManager | | ContainerEngine |
+ +-----------------------------------+ +--------------------------+
+ | __init()__ | | __init(node)__ |
+ | construct_container() | | acquire(force) |
+ | construct_containers() | | create() |
+ | acquire_all_containers() | | stop() |
+ | create_all_containers() | 1 1 | destroy() |
+ | execute_on_container() <>-------| info() |
+ | execute_on_all_containers() | | execute(command) |
+ | install_vpp_in_all_containers() | | system_info() |
+ | configure_vpp_in_all_containers() | | install_supervisor() |
+ | stop_all_containers() | | install_vpp() |
+ | destroy_all_containers() | | restart_vpp() |
+ +-----------------------------------+ | create_vpp_exec_config() |
+ | create_vpp_startup_config|
+ | is_container_running() |
+ | is_container_present() |
+ | _configure_cgroup() |
+ +-------------^------------+
+ |
+ |
+ |
+ +----------+---------+
+ | |
+ +------+------+ +------+------+
+ | LXC | | Docker |
+ +-------------+ +-------------+
+ | (inherited) | | (inherited) |
+ +------+------+ +------+------+
+ | |
+ +----------+---------+
+ |
+ | constructs
+ |
+ +---------v---------+
+ | Container |
+ +-------------------+
+ | __getattr__(a) |
+ | __setattr__(a, v) |
+ +-------------------+
+
+Sequentional diagram that illustrates the creation of a single container.
+
+::
+
+ Legend:
+ e = engine [Docker|LXC]
+ .. = kwargs (variable number of keyword argument)
+
+ +-------+ +------------------+ +-----------------+
+ | RF KW | | ContainerManager | | ContainerEngine |
+ +---+---+ +--------+---------+ +--------+--------+
+ | | |
+ | 1: new ContainerManager(e) | |
+ +-+---------------------------->+-+ |
+ |-| |-| 2: new ContainerEngine |
+ |-| |-+----------------------->+-+
+ |-| |-| |-|
+ |-| +-+ +-+
+ |-| | |
+ |-| 3: construct_container(..) | |
+ |-+---------------------------->+-+ |
+ |-| |-| 4: init() |
+ |-| |-+----------------------->+-+
+ |-| |-| |-| 5: new +-------------+
+ |-| |-| |-+-------->| Container A |
+ |-| |-| |-| +-------------+
+ |-| |-|<-----------------------+-|
+ |-| +-+ +-+
+ |-| | |
+ |-| 6: acquire_all_containers() | |
+ |-+---------------------------->+-+ |
+ |-| |-| 7: acquire() |
+ |-| |-+----------------------->+-+
+ |-| |-| |-|
+ |-| |-| |-+--+
+ |-| |-| |-| | 8: is_container_present()
+ |-| |-| True/False |-|<-+
+ |-| |-| |-|
+ |-| |-| |-|
+ +---------------------------------------------------------------------------------------------+
+ | |-| ALT [isRunning & force] |-| |-|--+ |
+ | |-| |-| |-| | 8a: destroy() |
+ | |-| |-| |-<--+ |
+ +---------------------------------------------------------------------------------------------+
+ |-| |-| |-|
+ |-| +-+ +-+
+ |-| | |
+ |-| 9: create_all_containers() | |
+ |-+---------------------------->+-+ |
+ |-| |-| 10: create() |
+ |-| |-+----------------------->+-+
+ |-| |-| |-+--+
+ |-| |-| |-| | 11: wait('RUNNING')
+ |-| |-| |-<--+
+ |-| +-+ +-+
+ |-| | |
+ +---------------------------------------------------------------------------------------------+
+ | |-| ALT | | |
+ | |-| (install_vpp, configure_vpp) | | |
+ | |-| | | |
+ +---------------------------------------------------------------------------------------------+
+ |-| | |
+ |-| 12: destroy_all_containers() | |
+ |-+---------------------------->+-+ |
+ |-| |-| 13: destroy() |
+ |-| |-+----------------------->+-+
+ |-| |-| |-|
+ |-| +-+ +-+
+ |-| | |
+ +++ | |
+ | | |
+ + + +
+
+Container Data Structure
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Container is represented in Python L1 library as a separate Class with instance
+variables and no methods except overriden ``__getattr__`` and ``__setattr__``.
+Instance variables are assigned to container dynamically during the
+``construct_container(**kwargs)`` call and are passed down from the RF keyword.
+
+There is no parameters check functionality. Passing the correct arguments
+is a responsibility of the caller.
+
+Examples
+~~~~~~~~
+
+This section contains a high-level example of multiple initialization steps
+via ContainerManager; taken from an actual CSIT code,
+but with non-code lines (comments, Documentation) removed for brevity.
+
+:
+
+.. code-block:: robotframework
+
+ | Start containers for test
+ | | [Arguments] | ${dut}=${None} | ${nf_chains}=${1} | ${nf_nodes}=${1}
+ | | ... | ${auto_scale}=${True} | ${pinning}=${True}
+ | |
+ | | Set Test Variable | @{container_groups} | @{EMPTY}
+ | | Set Test Variable | ${container_group} | CNF
+ | | Set Test Variable | ${nf_nodes}
+ | | Import Library | resources.libraries.python.ContainerUtils.ContainerManager
+ | | ... | engine=${container_engine} | WITH NAME | ${container_group}
+ | | Construct chains of containers
+ | | ... | dut=${dut} | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
+ | | ... | auto_scale=${auto_scale} | pinning=${pinning}
+ | | Acquire all '${container_group}' containers
+ | | Create all '${container_group}' containers
+ | | Configure VPP in all '${container_group}' containers
+ | | Start VPP in all '${container_group}' containers
+ | | Append To List | ${container_groups} | ${container_group}
+ | | Save VPP PIDs
+
+Kubernetes
+~~~~~~~~~~
+
+For the future use, Kubernetes [k8sdoc]_ is implemented as separate library
+``KubernetesUtils.py``, with a class with the same name. This utility provides
+an API for L2 Robot Keywords to control ``kubectl`` installed on each of DUTs.
+One time initialization script, ``resources/libraries/bash/k8s_setup.sh``
+does reset/init kubectl, and initializes the ``csit`` namespace. CSIT
+namespace is required to not to interfere with existing setups and it
+further simplifies apply/get/delete Pod/ConfigMap operations on SUTs.
+
+Kubernetes utility is based on YAML templates to avoid crafting the huge
+YAML configuration files, what would lower the readability of code and
+requires complicated algorithms.
+
+Two types of YAML templates are defined:
+
+- Static - do not change between deployments, that is infrastructure
+ containers like Kafka, Calico, ETCD.
+
+- Dynamic - per test suite/case topology YAML files.
+
+Making own python wrapper library of ``kubectl`` instead of using the
+official Python package allows to control and deploy environment over
+the SSH library without the need of using isolated driver running on
+each of DUTs.
+
+Tested Topologies
+~~~~~~~~~~~~~~~~~
+
+Listed CSIT container networking test topologies are defined with DUT
+containerized VPP switch forwarding packets between NF containers. Each
+NF container runs their own instance of VPP in L2XC configuration.
+
+Following container networking topologies are tested in |csit-release|:
+
+- LXC topologies:
+
+ - eth-l2xcbase-eth-2memif-1lxc.
+ - eth-l2bdbasemaclrn-eth-2memif-1lxc.
+
+- Docker topologies:
+
+ - eth-l2xcbase-eth-2memif-1docker.
+ - eth-l2xcbase-eth-1memif-1docker
+
+References
+~~~~~~~~~~
+
+.. [lxc] `Linux Containers <https://linuxcontainers.org/>`_
+.. [lxcnamespace] `Resource management: Linux kernel Namespaces and cgroups <https://www.cs.ucsb.edu/~rich/class/cs293b-cloud/papers/lxc-namespace.pdf>`_.
+.. [stgraber] `LXC 1.0: Blog post series <https://stgraber.org/2013/12/20/lxc-1-0-blog-post-series/>`_.
+.. [lxcsecurity] `Linux Containers Security <https://linuxcontainers.org/lxc/security/>`_.
+.. [capabilities] `Linux manual - capabilities - overview of Linux capabilities <http://man7.org/linux/man-pages/man7/capabilities.7.html>`_.
+.. [cgroup1] `Linux kernel documentation: cgroups <https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt>`_.
+.. [cgroup2] `Linux kernel documentation: Control Group v2 <https://www.kernel.org/doc/Documentation/cgroup-v2.txt>`_.
+.. [selinux] `SELinux Project Wiki <http://selinuxproject.org/page/Main_Page>`_.
+.. [lxcsecfeatures] `LXC 1.0: Security features <https://stgraber.org/2014/01/01/lxc-1-0-security-features/>`_.
+.. [lxcsource] `Linux Containers source <https://github.com/lxc/lxc>`_.
+.. [apparmor] `Ubuntu AppArmor <https://wiki.ubuntu.com/AppArmor>`_.
+.. [seccomp] `SECure COMPuting with filters <https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt>`_.
+.. [docker] `Docker <https://www.docker.com/what-docker>`_.
+.. [k8sdoc] `Kubernetes documentation <https://kubernetes.io/docs/home/>`_.