confd: update container documentation and YANG models

Due to the deprecation of CNI i Podman[1], and its upcoming removal in
Podman v5.0, we decided to cut our losses and modify all documentation
and models to become backend neutral.  We will continue to use CNI as
long as possible -- it gives us host interfaces, for instance, that is
not part of netawark yet, it seems.

Also, sync mount and volume documentation with YANG model changes.

[1]: https://blog.podman.io/2023/11/cni-deprecation-and-removal-from-podman-5-0/

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2024-02-25 19:49:27 +01:00
parent 81d8643a6f
commit 34b06fa448
4 changed files with 93 additions and 91 deletions
+34 -35
View File
@@ -6,8 +6,8 @@ Containers in Infix
* [Getting Started](#getting-started)
* [Examples](#examples)
* [Networking and Containers](#networking-and-containers)
* [CNI Bridge](#cni-bridge)
* [CNI Host](#cni-host)
* [Container Bridge](#container-bridge)
* [Container Host Interface](#container-host-interface)
* [Host Networking](#host-networking)
* [Mounts and Volumes](#mounts-and-volumes)
* [Content Mounts](#content-mounts)
@@ -31,7 +31,7 @@ is a rare and in many cases *unique* feature of Infix.
All network specific settings are done using the IETF interfaces YANG
model, with augments for containers to ensure smooth integration with
the Container Network Interface ([CNI][]) that podman supports.
container networking in podman.
Caution
@@ -104,9 +104,9 @@ Persistent web server using nginx, sharing the host's network:
admin@example-c0-ff-ee:/config> edit container web
admin@example-c0-ff-ee:/config/container/web> set image docker://nginx:alpine
admin@example-c0-ff-ee:/config/container/web> set publish 80:80
admin@example-c0-ff-ee:/config/container/web> set host-network
admin@example-c0-ff-ee:/config/container/web> set network host
admin@example-c0-ff-ee:/config/container/web> leave
admin@example-c0-ff-ee:/> show container
admin@example-c0-ff-ee:/> show container
Exit to the shell and verify the service with curl, or try to attach
to your device's IP address using your browser:
@@ -123,7 +123,7 @@ Networking and Containers
By default, unlike other systems, persistent[^1] containers have no
networking enabled. All network access has to be set up explicitly.
Currently two types of of [CNI][] networks are supported:
Currently two types of of container networks are supported:
- `cni-host`: one end of a VETH pair, or a physical Ethernet port
- `cni-bridge`: an IP masquerading bridge
@@ -175,7 +175,8 @@ the container. The default, after each stop/start cycle, or reboot of
the host, is to name the interfaces `eth0`, `eth1`, in the order they
are given in the `network` list, and to give the container the next
address in a `cni-bridge`. Below an example of a system container calls
`set network docker0`, here we show how to set options for that network:
`set network interface docker0`, here we show how to set options for
that network:
admin@example-c0-ff-ee:/config/container/ntpd/> edit network docker0
admin@example-c0-ff-ee:/config/container/ntpd/network/docker0/>
@@ -205,13 +206,12 @@ pair as an example along with a regular bridge (where other Ethernet
interfaces may live as well).
admin@example-c0-ff-ee:/config/> edit interface veth0
admin@example-c0-ff-ee:/config/interface/veth0a/> set veth peer ntpd
admin@example-c0-ff-ee:/config/interface/veth0a/> set ipv4 address 192.168.0.1 prefix-length 24
admin@example-c0-ff-ee:/config/interface/veth0a/> end
admin@example-c0-ff-ee:/config/interface/veth0/> set veth peer ntpd
admin@example-c0-ff-ee:/config/interface/veth0/> set ipv4 address 192.168.0.1 prefix-length 24
admin@example-c0-ff-ee:/config/interface/veth0/> end
admin@example-c0-ff-ee:/config/> edit interface ntpd
admin@example-c0-ff-ee:/config/interface/ntpd/> set ipv4 address 192.168.0.2 prefix-length 24
admin@example-c0-ff-ee:/config/interface/ntpd/> set container-network
admin@example-c0-ff-ee:/config/interface/ntpd/container-network/> set
This is a routed setup, where we reserve 192.168.0.0/24 for the network
between the host and the `ntpd` container. A perhaps more common case
@@ -242,14 +242,14 @@ file system:
admin@example-c0-ff-ee:/config/container/system/> edit mount leds
admin@example-c0-ff-ee:/config/container/system/mount/leds> set source /sys/class/leds
admin@example-c0-ff-ee:/config/container/system/mount/leds> set destination /sys/class/leds
admin@example-c0-ff-ee:/config/container/system/mount/leds> set target /sys/class/leds
admin@example-c0-ff-ee:/config/container/system/mount/leds> end
admin@example-c0-ff-ee:/config/container/system/>
Sometimes *volumes* are a better fit. A volume is an automatically
created read-writable entity that follows the life of your container.
admin@example-c0-ff-ee:/config/container/ntpd/> set volume varlib destination /var/lib
admin@example-c0-ff-ee:/config/container/ntpd/> set volume varlib target /var/lib
Volumes survive reboots and upgrading of the base image, unlike the
persistent writable layer you get by default, which does not survive
@@ -273,7 +273,7 @@ file is created using the decoded base64 data from the `content` node.
admin@example-c0-ff-ee:/config/container/ntpd/> edit mount ntpd.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> set content
... interactive editor starts up ...
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> set destination /etc/ntpd.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> set target /etc/ntpd.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntpd.conf> end
admin@example-c0-ff-ee:/config/container/ntpd/>
@@ -298,7 +298,7 @@ we created previously:
admin@example-c0-ff-ee:/> configure
admin@example-c0-ff-ee:/config> edit container system
admin@example-c0-ff-ee:/config/container/system/> set image ghcr.io/kernelkit/curios:edge
admin@example-c0-ff-ee:/config/container/system/> set network docker0
admin@example-c0-ff-ee:/config/container/system/> set network interface docker0
admin@example-c0-ff-ee:/config/container/system/> set publish 222:22
admin@example-c0-ff-ee:/config/container/system/> leave
@@ -314,7 +314,7 @@ container configuration context for the full syntax.)
Available containers can be accessed from admin-exec:
admin@example-c0-ff-ee:/> show container
admin@example-c0-ff-ee:/> show container
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
439af2917b44 ghcr.io/kernelkit/curios:edge 41 hours ago Up 16 hours 0.0.0.0:222->222/tcp system
@@ -322,18 +322,18 @@ This is a system container, so you can "attach" to it by starting a
shell (or logging in with SSH):
admin@example-c0-ff-ee:/> container shell system
root@439af2917b44:/#
root@439af2917b44:/#
Notice how the hostname inside the container changes. By default the
container ID (hash) is used, but this can be easily changed:
root@439af2917b44:/# exit
admin@infix-00-00-00:/> configure
admin@infix-00-00-00:/config/> edit container system
admin@infix-00-00-00:/config/container/system/> set hostname system1
admin@infix-00-00-00:/config/container/system/> leave
admin@infix-00-00-00:/> container shell system
root@system1:/#
admin@infix-00-00-00:/> configure
admin@infix-00-00-00:/config/> edit container system
admin@infix-00-00-00:/config/container/system/> set hostname sys101
admin@infix-00-00-00:/config/container/system/> leave
admin@infix-00-00-00:/> container shell system
root@sys101:/#
[^1]: this does not apply to the admin-exec command `container run`.
This command is intended to be used for testing and evaluating
@@ -350,12 +350,12 @@ For really advanced setups, the following will be the only alternative:
admin@example-c0-ff-ee:/> configure
admin@example-c0-ff-ee:/config> edit container nftables
admin@example-c0-ff-ee:/config/container/system/> set image ghcr.io/kernelkit/curios-nftables:edge
admin@example-c0-ff-ee:/config/container/system/> set host-network
admin@example-c0-ff-ee:/config/container/system/> edit file nftables.conf
admin@example-c0-ff-ee:/config/container/system/file/nftables.conf/> set path /etc/nftables.conf
admin@example-c0-ff-ee:/config/container/system/file/nftables.conf/> set content
admin@example-c0-ff-ee:/config/container/system/> set network host
admin@example-c0-ff-ee:/config/container/system/> edit mount nftables.conf
admin@example-c0-ff-ee:/config/container/system/mount/nftables.conf/> set target /etc/nftables.conf
admin@example-c0-ff-ee:/config/container/system/mount/nftables.conf/> set content
... interactive editor starts up where you can paste your rules ...
admin@example-c0-ff-ee:/config/container/system/file/nftables.conf/> leave
admin@example-c0-ff-ee:/config/container/system/mount/nftables.conf/> leave
### Application Container: ntpd
@@ -373,14 +373,14 @@ use volumes in this example.
admin@example-c0-ff-ee:/> configure
admin@example-c0-ff-ee:/config> edit container ntpd
admin@example-c0-ff-ee:/config/container/ntpd/> set image ghcr.io/kernelkit/curios-ntpd:edge
admin@example-c0-ff-ee:/config/container/ntpd/> set network ntpd # From veth0 above
admin@example-c0-ff-ee:/config/container/ntpd/> edit file ntp.conf
admin@example-c0-ff-ee:/config/container/ntpd/file/ntp.conf/> set path /etc/ntp.conf
admin@example-c0-ff-ee:/config/container/ntpd/file/ntp.conf/> set content
admin@example-c0-ff-ee:/config/container/ntpd/> set network interface ntpd # From veth0 above
admin@example-c0-ff-ee:/config/container/ntpd/> edit mount ntp.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntp.conf/> set target /etc/ntp.conf
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntp.conf/> set content
... interactive editor starts up where you can paste your rules ...
admin@example-c0-ff-ee:/config/container/ntpd/file/ntp.conf/> end
admin@example-c0-ff-ee:/config/container/ntpd/mount/ntp.conf/> end
admin@example-c0-ff-ee:/config/container/ntpd/> edit volume varlib
admin@example-c0-ff-ee:/config/container/ntpd/volume/varlib/> set destination /var/lib
admin@example-c0-ff-ee:/config/container/ntpd/volume/varlib/> set target /var/lib
admin@example-c0-ff-ee:/config/container/ntpd/volume/varlib/> leave
admin@example-c0-ff-ee:/> copy running-config startup-config
@@ -414,6 +414,5 @@ restarted.
[1]: https://github.com/kernelkit/infix/blob/main/src/confd/yang/infix-containers%402023-12-14.yang
[CNI]: https://www.cni.dev/
[2]: https://github.com/troglobit/mg
[podman]: https://podman.io
+27 -30
View File
@@ -28,9 +28,9 @@
static bool iface_is_cni(const char *ifname, struct lyd_node *cif)
{
struct lyd_node *cni = lydx_get_child(cif, "container-network");
struct lyd_node *net = lydx_get_child(cif, "container-network");
if (cni)
if (net)
return true;
return false;
@@ -57,15 +57,14 @@ static void cni_gen_addrs(struct lyd_node *ip, FILE *fp, int *first)
}
#if 0 /* Unused for now, use container specific global dns and search settings instead. */
static void cni_gen_dns(struct lyd_node *cni, FILE *fp, int *first)
static void cni_gen_dns(struct lyd_node *net, FILE *fp, int *first)
{
struct lyd_node *dns;
dns = lydx_get_child(cni, "dns");
dns = lydx_get_child(net, "dns");
if (dns) {
struct lyd_node *node;
puts("Adding DNS to CNI profile!");
fprintf(fp, ",\n \"dns\": {");
*first = 1;
@@ -75,7 +74,6 @@ static void cni_gen_dns(struct lyd_node *cni, FILE *fp, int *first)
else
fprintf(fp, ", ");
printf("Adding DNS nameserver %s to CNI profile!\n", lyd_get_value(node));
fprintf(fp, "\"%s\"", lyd_get_value(node));
(*first)++;
}
@@ -89,7 +87,7 @@ static void cni_gen_dns(struct lyd_node *cni, FILE *fp, int *first)
(*first)++;
}
LYX_LIST_FOR_EACH(lyd_child(cni), node, "search") {
LYX_LIST_FOR_EACH(lyd_child(net), node, "search") {
if (*first)
fprintf(fp, "%s\n \"search\": [ ", *first > 1 ? "," : "");
else
@@ -108,9 +106,9 @@ static void cni_gen_dns(struct lyd_node *cni, FILE *fp, int *first)
* Set up IP masquerading bridge which acts as a gateway for nodes behind it.
* Default subnet, if one is missing in configuration, is: 10.88.0.0/16
*/
static int cni_bridge(struct lyd_node *cni, const char *ifname)
static int cni_bridge(struct lyd_node *net, const char *ifname)
{
struct lyd_node *net;
struct lyd_node *node;
int first = 1;
FILE *fp;
@@ -132,9 +130,9 @@ static int cni_bridge(struct lyd_node *cni, const char *ifname)
" \"ipam\": {\n"
" \"type\": \"host-local\"", ifname, ifname);
LYX_LIST_FOR_EACH(lyd_child(cni), net, "route") {
struct lyd_node *subnet = lydx_get_child(net, "subnet");
struct lyd_node *gateway = lydx_get_child(net, "gateway");
LYX_LIST_FOR_EACH(lyd_child(net), node, "route") {
struct lyd_node *subnet = lydx_get_child(node, "subnet");
struct lyd_node *gateway = lydx_get_child(node, "gateway");
if (first)
fprintf(fp, ",\n \"routes\": [\n");
@@ -155,9 +153,9 @@ static int cni_bridge(struct lyd_node *cni, const char *ifname)
fprintf(fp, ",\n \"routes\": [ { \"dst\": \"0.0.0.0/0\" } ]");
first = 1;
LYX_LIST_FOR_EACH(lyd_child(cni), net, "subnet") {
struct lyd_node *subnet = lydx_get_child(net, "subnet");
struct lyd_node *gateway = lydx_get_child(net, "gateway");
LYX_LIST_FOR_EACH(lyd_child(net), node, "subnet") {
struct lyd_node *subnet = lydx_get_child(node, "subnet");
struct lyd_node *gateway = lydx_get_child(node, "gateway");
if (first)
fprintf(fp, ",\n \"ranges\": [\n");
@@ -202,9 +200,9 @@ static int cni_bridge(struct lyd_node *cni, const char *ifname)
return 0;
}
static int cni_host(struct lyd_node *cni, const char *ifname)
static int cni_host(struct lyd_node *net, const char *ifname)
{
struct lyd_node *net, *ip;
struct lyd_node *node, *ip;
int first = 1;
FILE *fp;
@@ -223,11 +221,11 @@ static int cni_host(struct lyd_node *cni, const char *ifname)
" \"type\": \"static\"", ifname, ifname);
ip = lydx_get_child(lyd_parent(cni), "ipv4");
ip = lydx_get_child(lyd_parent(net), "ipv4");
if (ip)
cni_gen_addrs(ip, fp, &first);
ip = lydx_get_child(lyd_parent(cni), "ipv6");
ip = lydx_get_child(lyd_parent(net), "ipv6");
if (ip)
cni_gen_addrs(ip, fp, &first);
@@ -235,9 +233,9 @@ static int cni_host(struct lyd_node *cni, const char *ifname)
fprintf(fp, "\n ]");
first = 1;
LYX_LIST_FOR_EACH(lyd_child(cni), net, "route") {
struct lyd_node *subnet = lydx_get_child(net, "subnet");
struct lyd_node *gateway = lydx_get_child(net, "gateway");
LYX_LIST_FOR_EACH(lyd_child(net), node, "route") {
struct lyd_node *subnet = lydx_get_child(node, "subnet");
struct lyd_node *gateway = lydx_get_child(node, "gateway");
if (first)
fprintf(fp, ",\n \"routes\": [\n");
@@ -269,17 +267,16 @@ static int cni_host(struct lyd_node *cni, const char *ifname)
static int iface_gen_cni(const char *ifname, struct lyd_node *cif)
{
struct lyd_node *cni = lydx_get_child(cif, "container-network");
const char *type = lydx_get_cattr(cni, "type");
struct lyd_node *net = lydx_get_child(cif, "container-network");
const char *type = lydx_get_cattr(net, "type");
ERROR("Got CNI %s iface %s", type, ifname);
if (!strcmp(type, "cni-host"))
return cni_host(cni, ifname);
if (!strcmp(type, "host"))
return cni_host(net, ifname);
if (!strcmp(type, "cni-bridge"))
return cni_bridge(cni, ifname);
if (!strcmp(type, "bridge"))
return cni_bridge(net, ifname);
ERROR("Unknown CNI interface type %s, skipping.", type);
ERROR("Unknown container network type %s, skipping.", type);
return 0;
}
@@ -165,7 +165,7 @@ module infix-containers {
key name;
leaf name {
description "CNI network (interface name) to connect to the container.";
description "Container network (interface name) to connect to the container.";
type if:interface-ref;
must "/if:interfaces/if:interface[if:name = current()]/infix-if:container-network" {
error-message "Container networks must be interfaces classified as container-network.";
@@ -173,16 +173,20 @@ module infix-containers {
}
leaf-list option {
description "Options for CNI bridges.
Example: ip=1.2.3.4 to request a specific IP, both IPv4 and IPv6.
interface_name=foo0 name to set interface name inside container.";
description "Options for a masquerading container bridges.
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";
type string;
}
}
leaf-list publish {
description "Publish container port, or a range of ports, to the host.
Syntax: [[ip:][hostPort]:]containerPort[/protocol]
Sample: 8080:80 -- forward tcp port 8080 to container port 80
69:69/udp -- forward udp port 69 to container port 69
127.0.0.1:8080:80 -- forward only from loopback interface";
@@ -16,9 +16,9 @@ submodule infix-if-container {
organization "KernelKit";
contact "kernelkit@googlegroups.com";
description "CNI network to interface mapper extension for ietf-interfaces.
This ensures a container interface can never be a bridge port,
or LAG member at the same time.";
description "Container network to interface mapping for ietf-interfaces.
Ensures a container interface can never be a bridge port, or
LAG member, at the same time.";
revision 2024-01-15 {
description "Initial revision.";
@@ -29,18 +29,18 @@ submodule infix-if-container {
* Identities
*/
identity cni-type {
description "CNI network type";
identity container-network {
description "Container network type";
}
identity cni-bridge {
base cni-type;
description "CNI standard bridge with IP masquerading, portmappping, and firewalling.";
identity bridge {
base container-network;
description "Container bridge with IP masquerading, portmappping, and firewalling.";
}
identity cni-host {
base cni-type;
description "CNI host-device, e.g., one end of a VETH pair or other host interface.";
identity host {
base container-network;
description "Host device, e.g., one end of a VETH pair or other host interface.";
}
/*
@@ -48,31 +48,32 @@ submodule infix-if-container {
*/
augment "/if:interfaces/if:interface/infix-if:port" {
description "Augments the interface model with CNI networks.";
description "Augments the interface model with container networks.";
if-feature containers;
case container-network {
container container-network {
presence "Container network (CNI) mapping.";
presence "Container network mapping.";
leaf type {
description "Bridge or host interface";
description "Masquerading container bridge or a host interface";
type identityref {
base cni-type;
base container-network;
}
default cni-host;
}
list subnet {
description "Static IP ranges to hand out addresses to containers from.
A cni-bridge will forward DNS, NTP, and SSH by default to
A container bridge forwards DNS, NTP, and SSH by default to
the host interfaces.";
when "../type = 'infix-if:cni-bridge'";
when "../type = 'infix-if:bridge'";
key subnet;
leaf subnet {
type inet:ip-prefix;
description "Subnet to assign addresses from, round-robin assignment.
The default is from a standard Docker setup.";
default "172.17.0.0/16";
}
@@ -80,16 +81,17 @@ submodule infix-if-container {
leaf gateway {
type inet:ip-address;
description "Optional gateway address for the subnet, defaults to .1.
This will be used as the address of a cni-bridge.";
This will be used as the address of the container bridge.";
}
}
list route {
description "IPv4 or IPv6 routes to be added to container.
For cni-bridge type interfaces the gateway can be omitted,
the the IP address of the CNI bridge will then be used as
the next-hop address.";
For bridge type interfaces the gateway can be omitted, the
IP address of the container bridge will then be used as the
next-hop address.";
key subnet;
leaf subnet {