Implement podman pods option
This commit is contained in:
		
							parent
							
								
									5e87a5ec0c
								
							
						
					
					
						commit
						2df8a6892c
					
				
					 3 changed files with 229 additions and 0 deletions
				
			
		|  | @ -14,6 +14,8 @@ | ||||||
|           system = "x86_64-linux"; |           system = "x86_64-linux"; | ||||||
| 
 | 
 | ||||||
|           modules = [ |           modules = [ | ||||||
|  |             (import ./modules) | ||||||
|  | 
 | ||||||
|             (import ./configuration) |             (import ./configuration) | ||||||
|             (import ./configuration/linode.nix) |             (import ./configuration/linode.nix) | ||||||
|             (import ./configuration/hardware-configuration.nix) |             (import ./configuration/hardware-configuration.nix) | ||||||
|  | @ -25,6 +27,8 @@ | ||||||
|           system = "x86_64-linux"; |           system = "x86_64-linux"; | ||||||
| 
 | 
 | ||||||
|           modules = [ |           modules = [ | ||||||
|  |             (import ./modules) | ||||||
|  | 
 | ||||||
|             (import ./configuration) |             (import ./configuration) | ||||||
|             ({ ... }: { |             ({ ... }: { | ||||||
|               users.users.tlater.password = "insecure"; |               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…
	
	Add table
		Add a link
		
	
		Reference in a new issue