Implement podman pods option
This commit is contained in:
parent
5e87a5ec0c
commit
2df8a6892c
|
@ -14,6 +14,8 @@
|
|||
system = "x86_64-linux";
|
||||
|
||||
modules = [
|
||||
(import ./modules)
|
||||
|
||||
(import ./configuration)
|
||||
(import ./configuration/linode.nix)
|
||||
(import ./configuration/hardware-configuration.nix)
|
||||
|
@ -25,6 +27,8 @@
|
|||
system = "x86_64-linux";
|
||||
|
||||
modules = [
|
||||
(import ./modules)
|
||||
|
||||
(import ./configuration)
|
||||
({ ... }: {
|
||||
users.users.tlater.password = "insecure";
|
||||
|
|
5
modules/default.nix
Normal file
5
modules/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [ ./virtualisation/pods.nix ];
|
||||
}
|
220
modules/virtualisation/pods.nix
Normal file
220
modules/virtualisation/pods.nix
Normal file
|
@ -0,0 +1,220 @@
|
|||
{ lib, config, options, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.virtualisation.pods;
|
||||
list-to-args = arg: list:
|
||||
concatStringsSep " " (map (e: "--${arg}=${escapeShellArg e}") list);
|
||||
possibly-unset-arg = arg: val:
|
||||
(optionalString (val != null) "--${arg}=${escapeShellArg val}");
|
||||
|
||||
mkPod = name: pod: rec {
|
||||
path = [ config.virtualisation.podman.package ];
|
||||
|
||||
wants = [ "network.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" "default.target" ];
|
||||
|
||||
environment.PODMAN_SYSTEMD_UNIT = "%n";
|
||||
|
||||
preStart = concatStringsSep " " [
|
||||
"mkdir -p /run/podman/pods/ ;"
|
||||
"podman pod create"
|
||||
"--infra-conmon-pidfile=${escapeShellArg "/run/podman/pods/${name}.pid"}"
|
||||
"--name=${escapeShellArg name}"
|
||||
"--replace"
|
||||
(list-to-args "add-host" pod.added-hosts)
|
||||
(possibly-unset-arg "cgroup-parent" pod.cgroup-parent)
|
||||
(list-to-args "dns" pod.dns)
|
||||
(list-to-args "dns-opt" pod.dns-opt)
|
||||
(list-to-args "dns-search" pod.dns-search)
|
||||
(possibly-unset-arg "hostname" pod.hostname)
|
||||
(possibly-unset-arg "infra" pod.infra)
|
||||
(possibly-unset-arg "infra-command" pod.infra-command)
|
||||
(possibly-unset-arg "infra-image" pod.infra-image)
|
||||
(possibly-unset-arg "ip" pod.ip)
|
||||
(possibly-unset-arg "mac-address" pod.mac-address)
|
||||
(possibly-unset-arg "network" pod.network)
|
||||
(possibly-unset-arg "network-alias" pod.network-alias)
|
||||
(possibly-unset-arg "no-hosts" pod.no-hosts)
|
||||
(list-to-args "publish" pod.publish)
|
||||
(list-to-args "share" pod.share)
|
||||
];
|
||||
|
||||
script = "podman pod start ${escapeShellArg name}";
|
||||
preStop = "podman pod stop ${escapeShellArg name}";
|
||||
# `podman generate systemd` generates a second stop after the
|
||||
# first; not sure why but clearly it's recommended.
|
||||
postStop = preStop;
|
||||
|
||||
serviceConfig = rec {
|
||||
Type = "forking";
|
||||
TimeoutStopSec = 70;
|
||||
Restart = "on-failure";
|
||||
PIDFile = "/run/podman/pods/${name}.pid";
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
options.virtualisation.pods = mkOption {
|
||||
type = with types;
|
||||
attrsOf (submodule {
|
||||
options = {
|
||||
added-hosts = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description =
|
||||
"Additional hosts to add to /etc/hosts for each container.";
|
||||
example = literalExample ''
|
||||
[ "database:10.0.0.1" ]
|
||||
'';
|
||||
};
|
||||
|
||||
cgroup-parent = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description =
|
||||
"The cgroups path under which the pod cgroup will be created.";
|
||||
};
|
||||
|
||||
dns = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = "The dns servers to set in /etc/resolv.conf.";
|
||||
};
|
||||
|
||||
dns-opt = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = "dns options to set in /etc/resolv.conf.";
|
||||
};
|
||||
|
||||
dns-search = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = "Search domains to set in /etc/resolv.conf.";
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "The pod hostname.";
|
||||
};
|
||||
|
||||
infra = mkOption {
|
||||
type = nullOr bool;
|
||||
default = null;
|
||||
description = "Whether to create the infra container for the pod.";
|
||||
};
|
||||
|
||||
infra-command = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "The command to run in the infra container.";
|
||||
};
|
||||
|
||||
infra-image = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "The image to use for the infra container.";
|
||||
};
|
||||
|
||||
ip = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "A static IP address for the pod network.";
|
||||
};
|
||||
|
||||
# TODO: set up label file stuff.
|
||||
#
|
||||
# labels = mkOption {};
|
||||
|
||||
mac-address = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "A static mac address for the pod network.";
|
||||
};
|
||||
|
||||
network = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Network configuration for the pod.";
|
||||
};
|
||||
|
||||
network-alias = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "DNS alias for the pod.";
|
||||
};
|
||||
|
||||
no-hosts = mkOption {
|
||||
type = nullOr bool;
|
||||
default = null;
|
||||
description = "Whether to disable /etc/hosts creation for the pod.";
|
||||
};
|
||||
|
||||
publish = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = "List of ports to publish from the pod.";
|
||||
};
|
||||
|
||||
share = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = "List of kernel namespaces to share.";
|
||||
};
|
||||
|
||||
containers = options.virtualisation.oci-containers.containers;
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "Podman pods to run as systemd services.";
|
||||
};
|
||||
|
||||
config = let
|
||||
# Merge a list of attribute sets together
|
||||
#
|
||||
# TODO: See if there's a generic version for this somewhere in the
|
||||
# pkgs lib?
|
||||
mergeAttrs = attrList: foldr (a: b: a // b) { } attrList;
|
||||
|
||||
# Create services for all defined pods
|
||||
pod-services = mapAttrs' (n: v: nameValuePair "pod-${n}" (mkPod n v)) cfg;
|
||||
|
||||
# Override the systemd-specific settings of containers defined in
|
||||
# pods.
|
||||
#
|
||||
# I.e., make a systemd unit dependency on the pod service.
|
||||
pod-container-services = mergeAttrs (mapAttrsToList (pname: pod:
|
||||
mapAttrs' (cname: container:
|
||||
nameValuePair "podman-${pname}-${cname}" rec {
|
||||
after = [ "pod-${pname}.service" ];
|
||||
requires = after;
|
||||
}) pod.containers) cfg);
|
||||
|
||||
# Override the oci-container settings for containers defined in pods.
|
||||
#
|
||||
# I.e., set the --pod=podname setting, and update the dependsOn so
|
||||
# it points to containers in the same pod.
|
||||
podifyContainer = container: podname:
|
||||
container // {
|
||||
dependsOn =
|
||||
map (dependency: "${podname}-${dependency}") container.dependsOn;
|
||||
extraOptions = container.extraOptions ++ [ "--pod=${podname}" ];
|
||||
};
|
||||
|
||||
in lib.mkIf (cfg != { }) {
|
||||
virtualisation.podman.enable = true;
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
|
||||
systemd.services = pod-services // pod-container-services;
|
||||
|
||||
virtualisation.oci-containers.containers = mergeAttrs (mapAttrsToList
|
||||
(pname: pod:
|
||||
mapAttrs' (cname: container:
|
||||
nameValuePair "${pname}-${cname}" (podifyContainer container pname))
|
||||
pod.containers) cfg);
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue