mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-01 13:23:01 +02:00
Merge pull request #712 from kernelkit/container-ifname
This commit is contained in:
@@ -13,6 +13,13 @@ addresses for interfaces! For details, see below issue #680.
|
||||
- Update CONTRIBUTING.md for scaling core team and helping external
|
||||
contributors understand the development process, issue #672
|
||||
- OSPF: Add limitation to only allow one interface per area
|
||||
- Add support for "dummy" interfaces, mostly useful for testing
|
||||
- Add support for container hostname format specifiers, just like it
|
||||
already works for the host's hostname setting
|
||||
- Updated container documentation, improved images, detail how to set
|
||||
interface name inside the container, and some syntax fixes
|
||||
- Greatly reduced size of bundled curiOS httpd OCI container image,
|
||||
reduced from 1.8 MiB to 281 KiB
|
||||
- The default builds now include the curiOS nftables container image,
|
||||
which can be used for advanced firewall setups. For an introduction
|
||||
see <https://kernelkit.org/posts/firewall-container/>
|
||||
@@ -37,6 +44,8 @@ addresses for interfaces! For details, see below issue #680.
|
||||
this includes all operational data in ietf-routing:/routing/ribs.
|
||||
- Fix #697: password is not always set for new users, bug introduced
|
||||
in v24.06.0 when replacing Augeas with native user handling
|
||||
- Fix #708: allow all container networks to set interface name inside
|
||||
container, not just auto-generated veth-pair ends for `docker0` bridge
|
||||
- Fix BFD in OSPF, previously you could not enable BFD on a single
|
||||
interface without it was enabled on all interfaces
|
||||
|
||||
|
||||
+45
-27
@@ -1,5 +1,6 @@
|
||||
Containers in Infix
|
||||
===================
|
||||
<img align="right" src="img/docker.webp" alt="Docker whale" width=360>
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Caution](#caution)
|
||||
@@ -78,16 +79,17 @@ In the CLI, containers can be run in one of two ways:
|
||||
1. `container run IMAGE [COMMAND]`, and
|
||||
2. enter `configure` context, then `edit container NAME`
|
||||
|
||||
The first is useful mostly for testing, or running single commands in an
|
||||
image. It is a wrapper for `podman run -it --rm ...`, while the latter
|
||||
is a wrapper and adaptation of `podman create ...`.
|
||||
The former is useful mostly for testing, or running single commands in
|
||||
an image. It is a wrapper for `podman run -it --rm ...`, while the
|
||||
latter is a wrapper and adaptation of `podman create ...`.
|
||||
|
||||
The second create a container with a semi-persistent writable layer that
|
||||
survives container restarts and host system restarts. However, if you
|
||||
change the container configuration or upgrade the image (see below), the
|
||||
container will be recreated and the writable layer is lost. This is why
|
||||
it is recommended to set up a named volume for directories, or use file
|
||||
[Content Mounts][], in your container you want truly persistent content.
|
||||
[Content Mounts](#content-mounts), in your container if you want truly
|
||||
persistent content.
|
||||
|
||||
In fact, in many cases the best way is to create a `read-only` container
|
||||
and use file mounts and volumes only for the critical parts. Podman
|
||||
@@ -299,14 +301,19 @@ Currently two types of of container networks are supported:
|
||||
|
||||
> For more information on VETH pairs, see the [Networking Guide][0].
|
||||
|
||||
|
||||
### Container Bridge
|
||||
|
||||
A container bridge is what most container setups use and users want.
|
||||
|
||||

|
||||
|
||||
The difference from a regular bridge is that the container runtime fully
|
||||
manages them -- connecting containers automatically with VETH pairs and
|
||||
setting up firewall rules between the host and other containers, as well
|
||||
as managing port forwarding. This transparent background management is
|
||||
what makes container use seem to be so simple.
|
||||
manages them -- connecting containers with automatically created VETH
|
||||
pairs (look at the bridge port names) and setting up firewall rules
|
||||
between the host and other containers, as well as managing port
|
||||
forwarding. This transparent background management is what makes
|
||||
container use seem to be so simple.
|
||||
|
||||
All interface configuration is done in configure context.
|
||||
|
||||
@@ -394,20 +401,21 @@ namespace of a container[^3]. This of course works with plain Ethernet
|
||||
interfaces as well, but here we will use one end of a VETH pair as an
|
||||
example.
|
||||
|
||||
The network `option` setting is available also for this case, but only
|
||||
the `interface_name=foo0` option works. Which is still very useful. To
|
||||
change the MAC address, you need to use the `custom-phys-adderss` in the
|
||||
general network settings.
|
||||
|
||||
[^3]: Something which the container bridge network type does behind the
|
||||
scenes with one end of an automatically created VETH pair.
|
||||
|
||||
|
||||
#### Routed Setup
|
||||
|
||||
In this routed setup we reserve 192.168.0.0/24 for the network between
|
||||
the host and the `ntpd` container.
|
||||
|
||||
_____________
|
||||
| |
|
||||
veth0 .1 | .2 eth0 |
|
||||
\ 192.168.0.0/24 | / |
|
||||
'--------------------' [ntpd] |
|
||||
|_____________|
|
||||

|
||||
|
||||
Configuration is a straight-forward VETH pair setup where we name the
|
||||
container-end of pair `ntpd`. This is just a convenience for us when
|
||||
@@ -429,9 +437,12 @@ Adding the interface to the container is the same as before, but since
|
||||
everything for host interfaces is set up in the interfaces context, we
|
||||
can take a bit of a shortcut.
|
||||
|
||||
admin@example:/config/container/ntpd/> set network ntpd
|
||||
admin@example:/config/container/ntpd/> set network interface ntpd
|
||||
admin@example:/config/container/ntpd/> leave
|
||||
|
||||
> Use the `set network inteface ntpd option interface_name=foo0` to set
|
||||
> the name of the interface inside the container to `foo0`.
|
||||
|
||||
The point of the routed case is that port forwarding from the container
|
||||
in this case is limited to a single interface, not *all interfaces* as
|
||||
is the default in the masquerading container bridge setup.
|
||||
@@ -443,21 +454,15 @@ A perhaps more common case is to bridge the other end of the VETH pair
|
||||
with other physical ports. In this section we show how to add a new
|
||||
pair to give our container two interfaces:
|
||||
|
||||
_______________
|
||||
| | .1 br0
|
||||
veth0 .1 | .2 eth0 | / \
|
||||
\ 192.168.0.0/24 | / eth1 .2 | veth1b e1
|
||||
'------------------' \ | 192.168.1.0/24 /
|
||||
| [ntpd] '------------------'
|
||||
|_______________|
|
||||

|
||||
|
||||
We start by adding the second VETH pair:
|
||||
|
||||
admin@example:/config/> edit interface veth1a
|
||||
admin@example:/config/interface/veth1a/> set veth peer veth1b
|
||||
admin@example:/config/interface/veth1a/> set veth peer veth1
|
||||
admin@example:/config/interface/veth1a/> set ipv4 address 192.168.1.2 prefix-length 24
|
||||
|
||||
> The LAN bridge (br0) in this example has IP address 192.168.1.1.
|
||||
> The LAN bridge (br1) in this example has IP address 192.168.1.1.
|
||||
|
||||
When a container has multiple host interfaces it can often be useful to
|
||||
have a default route installed. This can be added from the host with a
|
||||
@@ -473,15 +478,16 @@ have a default route installed. This can be added from the host with a
|
||||
}
|
||||
}
|
||||
veth {
|
||||
peer veth1b;
|
||||
peer veth1;
|
||||
}
|
||||
admin@example:/config/interface/veth1a/> end
|
||||
admin@example:/config/> set interface veth1b bridge-port bridge br0
|
||||
admin@example:/config/> set interface veth1 bridge-port bridge br1
|
||||
|
||||
Please note, container network routes require the base interface also
|
||||
have a static IP address set. Setting only the route, but no address,
|
||||
means the route is skipped.
|
||||
|
||||
|
||||
### Host Networking
|
||||
|
||||
The third use-case is host networking, this is where a container share
|
||||
@@ -491,7 +497,7 @@ the host operating system.
|
||||
|
||||
The host networking setup cannot be combined with any other network.
|
||||
|
||||
For an example, see below.
|
||||
For an example, [see below](#application-container-nftables).
|
||||
|
||||
|
||||
Mounts and Volumes
|
||||
@@ -599,6 +605,17 @@ container ID (hash) is used, but this can be easily changed:
|
||||
admin@example:/> container shell system
|
||||
root@sys101:/#
|
||||
|
||||
In fact, the container `hostname` setting supports the same format
|
||||
specifiers as the host's `hostname` setting:
|
||||
|
||||
- `%i`: OS ID, from `/etc/os-release`, from Menuconfig branding
|
||||
- `%h`: Default hostname, from `/etc/os-release`, from branding
|
||||
- `%m`: NIC specific part of base MAC, e.g., to `c0-ff-ee`
|
||||
- `%%`: Literal %
|
||||
|
||||
The most useful combination is probably `"container-name-%m"`, which in
|
||||
this example give the container hostname `container-name-c0-ff-ee`.
|
||||
|
||||
[^1]: this does not apply to the admin-exec command `container run`.
|
||||
This command is intended to be used for testing and evaluating
|
||||
container images. Such containers are given a private network
|
||||
@@ -626,6 +643,7 @@ Notice how we `set network host`, so the container can see and act on
|
||||
all the host's interfaces, and that we also have to run the container
|
||||
in *privileged* mode.
|
||||
|
||||
|
||||
### Application Container: ntpd
|
||||
|
||||
The default NTP server/client in Infix is Chrony, a fully working and
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 317 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 340 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 269 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
@@ -1625,7 +1625,7 @@ static char *get_mac(struct confd *confd, char *mac, size_t len)
|
||||
*
|
||||
* XXX: PLEASE REFACTOR THIS INTO A PYTHON HELPER FOR FUTURE EXTENSIONS, OR BUGS!
|
||||
*/
|
||||
static int hostnamefmt(struct confd *confd, char **fmt)
|
||||
int hostnamefmt(struct confd *confd, char **fmt)
|
||||
{
|
||||
size_t hostlen, fmt_len;
|
||||
char *hostname;
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#define ACTIVE_QUEUE "/var/lib/containers/active"
|
||||
#define LOGGER "logger -t container -p local1.notice"
|
||||
|
||||
int hostnamefmt(struct confd *confd, char **fmt);
|
||||
|
||||
|
||||
static int add(const char *name, struct lyd_node *cif)
|
||||
{
|
||||
const char *image = lydx_get_cattr(cif, "image");
|
||||
@@ -46,8 +49,16 @@ static int add(const char *name, struct lyd_node *cif)
|
||||
LYX_LIST_FOR_EACH(lyd_child(cif), node, "search")
|
||||
fprintf(fp, " --dns-search %s", lyd_get_value(node));
|
||||
|
||||
if ((string = lydx_get_cattr(cif, "hostname")))
|
||||
fprintf(fp, " --hostname %s", string);
|
||||
if ((string = lydx_get_cattr(cif, "hostname"))) {
|
||||
char *fmt = (char *)string;
|
||||
|
||||
if (hostnamefmt(&confd, &fmt)) {
|
||||
ERRNO("%s: failed setting custom hostname", name);
|
||||
} else {
|
||||
fprintf(fp, " --hostname %s", fmt);
|
||||
free(fmt);
|
||||
}
|
||||
}
|
||||
|
||||
if (lydx_is_enabled(cif, "read-only"))
|
||||
fprintf(fp, " --read-only");
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# REMEMBER TO UPDATE infix-interfaces ALSO IN confd.inc
|
||||
MODULES=(
|
||||
"infix-interfaces@2024-09-23.yang -e vlan-filtering -e containers"
|
||||
"infix-containers@2024-03-27.yang"
|
||||
"infix-containers@2024-10-14.yang"
|
||||
)
|
||||
|
||||
@@ -22,6 +22,17 @@ module infix-containers {
|
||||
prefix infix-if;
|
||||
}
|
||||
|
||||
import infix-system {
|
||||
prefix infix-sys;
|
||||
}
|
||||
|
||||
revision 2024-10-14 {
|
||||
description "Two major changes:
|
||||
- Allow changing name of host interfaces inside container
|
||||
- Support hostname format specifiers, like ietf-system";
|
||||
reference "internal";
|
||||
}
|
||||
|
||||
revision 2024-03-27 {
|
||||
description "Add support for capabilities.";
|
||||
reference "internal";
|
||||
@@ -160,8 +171,11 @@ module infix-containers {
|
||||
}
|
||||
|
||||
leaf hostname {
|
||||
description "Sets the container host name that is available inside the container.";
|
||||
type inet:domain-name;
|
||||
description "Sets the container host name, available inside the container.
|
||||
|
||||
Format specifiers are for, default hostname, ID, and the
|
||||
last three octets in base MAC, e.g., c0-ff-ee";
|
||||
type infix-sys:hostname;
|
||||
}
|
||||
|
||||
leaf privileged {
|
||||
@@ -201,12 +215,16 @@ module infix-containers {
|
||||
}
|
||||
|
||||
leaf-list option {
|
||||
when "deref(../name)/../infix-if:container-network/infix-if:type = 'infix-if:bridge'";
|
||||
description "Options for masquerading container bridges.
|
||||
description "Options for interface inside container, e.g., interface_name=foo0
|
||||
|
||||
Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6)
|
||||
mac=00:01:02:c0:ff:ee -- set fixed MAC address in container
|
||||
interface_name=foo0 -- set interface name inside container";
|
||||
Options: ip=1.2.3.4 -- Set static IPv4 address*
|
||||
ip6=2001:0:130f::9c0:876a:130b -- Set static IPv6 address*
|
||||
mac=00:01:02:c0:ff:ee -- Set fixed MAC address
|
||||
interface_name=foo0 -- Set interface name
|
||||
|
||||
NOTE: Some (*) options only work with masquerading container bridges,
|
||||
which automatically create VETH pairs with one end in the host
|
||||
bridge and the other in the container.";
|
||||
type string;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user