Implement podman pods option
This commit is contained in:
		
							parent
							
								
									5e87a5ec0c
								
							
						
					
					
						commit
						2df8a6892c
					
				
					 3 changed files with 229 additions and 0 deletions
				
			
		
							
								
								
									
										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