Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expanding containers documentation #1780

Merged
merged 3 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 0 additions & 117 deletions docs/plugin/execution-modes.md

This file was deleted.

64 changes: 64 additions & 0 deletions docs/plugin/execution-modes/containers/container.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Container

!!! note
Container support is not enabled by default.

To enable it, build Thunder with the `-DPROCESSCONTAINERS=ON` CMake option and specify the desired backend using the `-DPROCESSCONTAINERS_XXX=ON` where `XXX` corresponds to the backend you wish to use.

In container mode which is an extension to the out-of-process mode, ThunderPlugin host will run within a containerised environment.

Thunder supports multiple container integrations through the `ProcessContainer` abstraction mechanism in Thunder core.

If you have only one container integration, that will be the default one. However, if you have enabled multiple container integrations, you must specify the one you want to use.

There are two ways to do this:

- Specify it in the plugin configuration:

This method allows you to specify which integration to use for the plugin.
```
"configuration":{
"root":{
"mode":"Container",
"configuration" : {
"containertype":"lxc"
}
}
}
```

- Specify the default integration in the Thunder configuration.

This method allows you to set a default integration for plugins that do not have a specified container type in their configuration; they will use this default integration.
```
"processcontainers" : {
"default" : "runc"
}
```

## Supported Containers

- [LXC ](https://linuxcontainers.org/)
- [runc](https://github.com/opencontainers/runc)
- [crun](https://github.com/containers/crun)
- [Dobby](https://github.com/rdkcentral/Dobby) (Maintained by RDK)
- AWC (Maintained Externally)

To run a plugin in a container, a suitable container configuration must already exist. Thunder does not create container configurations dynamically. Thunder will search for existing container configurations in the following locations, in order of priority:

1. `<volatile path>/<callsign>/Container`
1. `<persistent path>/<callsign>/Container`
1. `<data path>/<classname>/Container`

For instance, the configuratoin for a plugin with the callsign SamplePlugin might be stored in `/opt/thunder/SamplePlugin/Container` if the persistent path is set to `/opt/thunder` in Thunder configuration.

**Advantages**

* Retains all the benefits of OOP plugins.
* Enhanced security - Containers have restricted access to the host system including filesystem and device access.
* Improved resource management - Containers can use cgroups to tightly control and monitor resource usage.

**Disadvantages**

* Maintenance - Requires managing container configurations and appropriately configuring access to resources. (e.g. device nodes)
* Startup time - Plugin activation may take longer due to the additional overhead of setting up the container environment.
129 changes: 129 additions & 0 deletions docs/plugin/execution-modes/containers/lxc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# What is LXC ?
LXC (Linux Containers) is a lightweight virtualization method that provides an environment similar to a complete Linux system but without the overhead of a full virtual machine. It uses a combination of Linux kernel features like namespaces and cgroups to isolate processes and manage resource allocation..

# Setup in Buildroot/Lithosphere

1. Make sure kernel has all the futures needed for containerization. The easiest way to enable them is to use raspberrypi3_wpe_ml_container_defconfig.

2. Enable containers support in Thunder.
```
Thunder -> Extensions -> Process Containers
```

3. Select RunC as the backend engine for containers.
```
Thunder -> Extensions -> Process Containers -> Containers Backend -> LXC
```

4. (optional) Enable containers plugin for info about running containers
```
Thunder -> Plugins -> ProcessContainers
```


# Setting Up LXC Container
For demo purposes, we will use the OCDM plugin. To run a containerized ThunderNanoService you will need to create rootfs with all of the dependencies of the nanoservice and ThunderPlugin as executable. For this tutorial rootfs.tar generated by buildroot/lithosphere/yocto will be used as reference roots.

1) Before running the system, create a folder named 'Container' under /rootfs/usr/share/Thunder/OCDM/

2) Create another folder named 'rootfs' under /rootfs/usr/share/Thunder/OCDM/Container

3) Copy the whole rootfs of the sdcard into /rootfs/usr/share/Thunder/OCDM/Container/rootfs


# Adjusting Configuration for Thunder

1. Create a file named 'config' under /rootfs/usr/share/Thunder/OCDM/Container and place the below content in it.
```
# Template used to create this container: /usr/share/lxc/templates/lxc-download
# Parameters passed to the template: --no-validate
# Template script checksum (SHA-1): 273c51343604eb85f7e294c8da0a5eb769d648f3
# For additional config options, please look at lxc.container.conf(5)

# Uncomment the following line to support nesting containers:
#lxc.include = /usr/share/lxc/config/nesting.conf
# (Be aware this has security implications)

lxc.mount.entry = /tmp tmp none bind,optional 0 0

# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
lxc.include = /usr/share/lxc/config/userns.conf
lxc.arch = linux32

# Container specific configuration
# if you see access related issue, disable user/group id settings below
lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536
lxc.rootfs.path = dir:/usr/share/Thunder/OCDM/Container/rootfs
lxc.uts.name = OCDM

# Inherit envionment needed by Thunder nanoservices
lxc.environment = PATH
lxc.environment = MESSAGE_DISPATCHER_CONFIG

# Network configuration
lxc.net.0.type = empty
#lxc.net.0.type = veth
#lxc.net.0.link = lxcbr0
#lxc.net.0.flags = up
#lxc.net.0.hwaddr = 00:16:XX:XX:XX:XX
```

2. Comment out below line in /usr/share/lxc/config/common.conf:
```
# lxc.seccomp.profile = /usr/share/lxc/config/common.seccomp
```

3. In plugin configuration (eg. `/etc/Thunder/plugin/OCDM.json` for OCDM) change
```"mode": Local```
to
```"mode": "Container"```

4. If everything works fine, you should see OCDM working just lie an ordinary OOP plugin.

# Mounting a shared directory between host and LXC container

Most often, we may need to securely share files between the host machine and a container.

Example : File logging from a container to a logging system folder located at the host machine.

1. Create a directory in host.
```
mkdir /testshare && chmod 7770 /testshare
```
2. Create a directory in lxc container (eg: OCDM container)
```
mkdir /usr/share/Thunder/OCDM/Container/rootfs/TestLogging && chmod 7770 /usr/share/Thunder/OCDM/Container/rootfs/TestLogging
```
3. Edit container config file (eg: /usr/share/Thunder/OCDM/Container/config)
```
lxc.mount.entry = /testshare TestLogging none bind,rw 0 0
```
4. UID/GID mapping
```
# Container specific configuration
#lxc.idmap = u 0 100000 65536
#lxc.idmap = g 0 100000 65536

# Container's UID/GID 0-65535 are mapped to host's 100000-165535,
# but UID/GID 1000 on the container is mapped to host's UID/GID 1000.
lxc.idmap = u 0 100000 1000
lxc.idmap = g 0 100000 1000
lxc.idmap = u 1000 1000 1
lxc.idmap = g 1000 1000 1
lxc.idmap = u 1001 101001 64535
lxc.idmap = g 1001 101001 64535
```
5. Accessing contents from a shared folder and permissions .

Use case 1 :
Host has created a domain socket within the shared folder.
Container running in non-privileged mode (not root mode), trying to write to this domain socket.
In this use case, the write operation will fail, if there is NO write permission for "other" user (eg: 775 instead of 777).
So make sure that the domain socket has been created with the required access right.

## Good To Know

- lxc API to kill a container is blocking, not guarenteed to work and therefore not used
- If ifconfig is not available in the container use the ip command (e.g. "ip address" to get IP address info for the device)
Loading