mirror of
				https://github.com/linuxkit/linuxkit.git
				synced 2025-10-31 01:37:42 +00:00 
			
		
		
		
	First cut of swap image and example
Signed-off-by: Avi Deitcher <avi@deitcher.net> Fix spaces after commas Remove MAINTAINER Signed-off-by: Avi Deitcher <avi@deitcher.net> Simplify swap.yml example to remove files section Signed-off-by: Avi Deitcher <avi@deitcher.net> Switch swap.sh to sh from bash and remove bash from image Signed-off-by: Avi Deitcher <avi@deitcher.net> Replace fallocate with dd and update calculation function to support it Signed-off-by: Avi Deitcher <avi@deitcher.net> Fix indentation Signed-off-by: Avi Deitcher <avi@deitcher.net> Change link to swap to just swap.sh Signed-off-by: Avi Deitcher <avi@deitcher.net> Fix indent Signed-off-by: Avi Deitcher <avi@deitcher.net>
This commit is contained in:
		
							
								
								
									
										83
									
								
								examples/swap.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								examples/swap.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | kernel: | ||||||
|  |   image: "linuxkit/kernel:4.9.x" | ||||||
|  |   cmdline: "console=ttyS0 console=tty0 page_poison=1" | ||||||
|  | init: | ||||||
|  |   - linuxkit/init:42fe8cb1508b3afed39eb89821906e3cc7a70551 | ||||||
|  |   - linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9 | ||||||
|  |   - linuxkit/containerd:60e2486a74c665ba4df57e561729aec20758daed | ||||||
|  |   - linuxkit/ca-certificates:eabc5a6e59f05aa91529d80e9a595b85b046f935 | ||||||
|  | onboot: | ||||||
|  |   - name: sysctl | ||||||
|  |     image: "linuxkit/sysctl:2cf2f9d5b4d314ba1bfc22b2fe931924af666d8c" | ||||||
|  |     net: host | ||||||
|  |     pid: host | ||||||
|  |     ipc: host | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_SYS_ADMIN | ||||||
|  |     readonly: true | ||||||
|  |   - name: binfmt | ||||||
|  |     image: "linuxkit/binfmt:8881283ac627be1542811bd25c85e7782aebc692" | ||||||
|  |     binds: | ||||||
|  |      - /proc/sys/fs/binfmt_misc:/binfmt_misc | ||||||
|  |     readonly: true | ||||||
|  |   - name: dhcpcd | ||||||
|  |     image: "linuxkit/dhcpcd:48e249ebef6a521eed886b3bce032db69fbb4afa" | ||||||
|  |     binds: | ||||||
|  |      - /var:/var | ||||||
|  |      - /tmp/etc:/etc | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_NET_ADMIN | ||||||
|  |      - CAP_NET_BIND_SERVICE | ||||||
|  |      - CAP_NET_RAW | ||||||
|  |     net: host | ||||||
|  |     command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"] | ||||||
|  |   - name: format | ||||||
|  |     image: "linuxkit/format:53748000acf515549d398e6ae68545c26c0f3a2e" | ||||||
|  |     binds: | ||||||
|  |      - /dev:/dev | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_SYS_ADMIN | ||||||
|  |      - CAP_MKNOD | ||||||
|  |   - name: mount | ||||||
|  |     image: "linuxkit/mount:d2669e7c8ddda99fa0618a414d44261eba6e299a" | ||||||
|  |     binds: | ||||||
|  |      - /dev:/dev | ||||||
|  |      - /var:/var:rshared,rbind | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_SYS_ADMIN | ||||||
|  |     rootfsPropagation: shared | ||||||
|  |     command: ["/mount.sh", "/var/external"] | ||||||
|  |   - name: swap | ||||||
|  |     image: "linuxkit/swap:68deee354ec4bbed405c5efedb25d60bb799b07d" | ||||||
|  |     net: host | ||||||
|  |     pid: host | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_SYS_ADMIN | ||||||
|  |     readonly: true | ||||||
|  |     binds: | ||||||
|  |      - /var:/var | ||||||
|  |      - /dev:/dev | ||||||
|  |     command: ["swap.sh", "--path", "/var/external/swap", "--size","1G"] | ||||||
|  | services: | ||||||
|  |   - name: rngd | ||||||
|  |     image: "linuxkit/rngd:3dad6dd43270fa632ac031e99d1947f20b22eec9" | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_SYS_ADMIN | ||||||
|  |     oomScoreAdj: -800 | ||||||
|  |     readonly: true | ||||||
|  |   - name: nginx | ||||||
|  |     image: "nginx:alpine" | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_NET_BIND_SERVICE | ||||||
|  |      - CAP_CHOWN | ||||||
|  |      - CAP_SETUID | ||||||
|  |      - CAP_SETGID | ||||||
|  |      - CAP_DAC_OVERRIDE | ||||||
|  |     net: host | ||||||
|  | trust: | ||||||
|  |   image: | ||||||
|  |     - linuxkit/kernel | ||||||
|  | outputs: | ||||||
|  |   - format: kernel+initrd | ||||||
|  |   - format: iso-bios | ||||||
|  |   - format: iso-efi | ||||||
							
								
								
									
										13
									
								
								pkg/swap/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								pkg/swap/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | FROM alpine:3.5 | ||||||
|  |  | ||||||
|  | # swap command - only minimal Alpine install | ||||||
|  |  | ||||||
|  | # use util-linux to get swapfile utils | ||||||
|  | #   at some point, hopefully use our own mkswap and swapon | ||||||
|  | RUN apk add --update util-linux | ||||||
|  |  | ||||||
|  | # add the entrypoint and make it executable | ||||||
|  | COPY . ./ | ||||||
|  |  | ||||||
|  | # ENTRYPOINT | ||||||
|  | ENTRYPOINT swap.sh | ||||||
							
								
								
									
										30
									
								
								pkg/swap/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								pkg/swap/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | # copy from mount | ||||||
|  | .PHONY: tag push clean | ||||||
|  |  | ||||||
|  | BASE=alpine:3.5 | ||||||
|  | IMAGE=linuxkit/swap | ||||||
|  |  | ||||||
|  | default: push | ||||||
|  |  | ||||||
|  | hash: Dockerfile swap.sh | ||||||
|  | 	DOCKER_CONTENT_TRUST=1 docker pull $(BASE) | ||||||
|  | 	tar cf - $^ | docker build --no-cache -t $(IMAGE):build - | ||||||
|  | 	docker run --rm --entrypoint /bin/sh $(IMAGE):build -c "cat $^ /lib/apk/db/installed | sha1sum" | sed 's/ .*//' > $@ | ||||||
|  |  | ||||||
|  | push: hash | ||||||
|  | 	docker pull $(IMAGE):$(shell cat hash) || \ | ||||||
|  | 		(docker tag $(IMAGE):build $(IMAGE):$(shell cat hash) && \ | ||||||
|  | 		 docker push $(IMAGE):$(shell cat hash)) | ||||||
|  | 	docker rmi $(IMAGE):build | ||||||
|  | 	rm -f hash | ||||||
|  |  | ||||||
|  | tag: hash | ||||||
|  | 	docker pull $(IMAGE):$(shell cat hash) || \ | ||||||
|  | 		docker tag $(IMAGE):build $(IMAGE):$(shell cat hash) | ||||||
|  | 	docker rmi $(IMAGE):build | ||||||
|  | 	rm -f hash | ||||||
|  |  | ||||||
|  | clean: | ||||||
|  | 	rm -f hash | ||||||
|  |  | ||||||
|  | .DELETE_ON_ERROR: | ||||||
							
								
								
									
										85
									
								
								pkg/swap/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								pkg/swap/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | # LinuxKit Swap | ||||||
|  | Image to enable creation of a swap file for a [linuxkit](https://github.com/linuxkit/linuxkit)-generated image. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Usage | ||||||
|  | Normally, unless you are running explicitly in a desktop version, LinuxKit images do not have swap enabled. If you want swap, add the following to your `moby.yml`: | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | onboot: | ||||||
|  |   - name: swap | ||||||
|  |     image: "linuxkit/swap:1.0.0" | ||||||
|  |     net: none | ||||||
|  |     pid: host | ||||||
|  |     capabilities: | ||||||
|  |      - CAP_SYS_ADMIN | ||||||
|  |     readonly: true | ||||||
|  |     binds: | ||||||
|  |      - /dev:/dev | ||||||
|  |      - /var:/var | ||||||
|  |     command: ["swap.sh","--path","/var/external/swap","--size","2G"] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Note that you **nust** mount the following: | ||||||
|  |  | ||||||
|  | * `/var` to `/var` so it can place the swapfile in the right location. | ||||||
|  | * `/dev` to `/dev` so it can do the right thing for devices | ||||||
|  |  | ||||||
|  | ### Options | ||||||
|  |  | ||||||
|  | Options are passed to it via command-line options. The following are the options. Details follow. | ||||||
|  |  | ||||||
|  | |Option|Parameter|Default|Required|Notes| | ||||||
|  | |---|---|---|---|---| | ||||||
|  | |`--path`|Path to file as seen in the underlying OS||**Yes**|| | ||||||
|  | |`--size`|Target swapfile size||**Yes**|| | ||||||
|  | |`--condition`|_condition_||No|Condition that must be met to create a swapfile| | ||||||
|  | |`--debug`||No|Turns on verbose output from the command making the swap| | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #### File | ||||||
|  | You can create a swapfile at the given path. You **must** provide exactly one swapfile path, or none will be created; there is no default. Passing fewer than or more than one `--path` option causes the container to exit with an error. | ||||||
|  |  | ||||||
|  | The option `--path` takes a single argument _path_, path to the swapfile, e.g. `/var/mnt/swap2`. | ||||||
|  |  | ||||||
|  | You **always** should put the swap file somewhere under `/var`, since that is where read-writable files and mounts exist in linuxkit images. | ||||||
|  |  | ||||||
|  | #### Size | ||||||
|  | `--size <size>` indicates the desired swapfile size, e.g. `2G` `100M` `5670K` `8765432`. There is no default. Acceptable size units are `G`, `M`, `K` and bytes of no unit provided. | ||||||
|  |  | ||||||
|  | If disk space on the requested partition is insufficient to create the swapfile, the container exits with an error. | ||||||
|  |  | ||||||
|  | #### Conditions | ||||||
|  | You may want to create a swapfile only if certain conditions are met. Supported conditions are: | ||||||
|  |  | ||||||
|  | * An external disk is available | ||||||
|  | * Partition on which the swapfile will sit is of a minimum size. | ||||||
|  |  | ||||||
|  | **All** conditions must be met. If a condition fails, the swapfile is not created, but the container exits with no error, unless you set the condition as `required`. | ||||||
|  |  | ||||||
|  | Conditions are structured as follows:    _type_:_parameter_:_required_ | ||||||
|  |  | ||||||
|  | In all cases, you may leave off _required_ if you wish to treat it as false, i.e. do not create swapfile but exit with no error if the condition is not met. | ||||||
|  |  | ||||||
|  | ##### Partition exists | ||||||
|  | LinuxKit may be running from a small disk, and you only want to run if a particular large external disk is available. In that case, pass `--condition part:<path>:<required>` to indicate that swapfile is to be created only if _path_ already exists and is a mount point. | ||||||
|  |  | ||||||
|  | Example: `--condition part:/var/mnt/external` | ||||||
|  |  | ||||||
|  | ##### Size | ||||||
|  | You may set a minimum size for a partition (likely the one on which the swapfile will be created) using the `size` condition of the format `--condition size:<path>:<size>:<required>` to indicate that swapfile is to be created only if the partition on which _path_ exists is of minimum size _size_. Acceptable sizes are identical to those for the swapfile. | ||||||
|  |  | ||||||
|  | Examples: | ||||||
|  |  | ||||||
|  | * `--condition partsize:/var/mnt/external:100G:true` | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Example | ||||||
|  | An example yml file is included in [examples/swap.yml](../../examples/swap.yml). `swap.yml`. Note that you need to attach an external disk - trying to create a swapfile in tmpfs `/var` will fail. | ||||||
|  |  | ||||||
|  | The sample command to run the enclosed is: | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | moby build swap.yml | ||||||
|  | moby run -disk-size 4096 swap | ||||||
|  | ``` | ||||||
							
								
								
									
										135
									
								
								pkg/swap/swap.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										135
									
								
								pkg/swap/swap.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,135 @@ | |||||||
|  | #!/bin/sh | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | while [ $# -gt 1 ]; do | ||||||
|  | 	key="$1" | ||||||
|  |  | ||||||
|  | 	case $key in | ||||||
|  | 		--debug) | ||||||
|  | 			set -x | ||||||
|  | 			;; | ||||||
|  | 		--path) | ||||||
|  | 			path="$2" | ||||||
|  | 			shift # past argument | ||||||
|  | 			;; | ||||||
|  | 		--size) | ||||||
|  | 			size="$2" | ||||||
|  | 			shift # past argument | ||||||
|  | 			;; | ||||||
|  | 		--encrypt) | ||||||
|  | 			ENCRYPT=true | ||||||
|  | 			;; | ||||||
|  | 		--condition) | ||||||
|  | 			CONDITIONS="$CONDITIONS $2" | ||||||
|  | 			shift | ||||||
|  | 			;; | ||||||
|  | 		*) | ||||||
|  | 			echo "Unknown option passed to swapmaker: $key"      # unknown option | ||||||
|  | 			exit 1 | ||||||
|  | 			;; | ||||||
|  | 	esac | ||||||
|  | 	shift # past argument or value | ||||||
|  | done | ||||||
|  |  | ||||||
|  | function disksize_to_count { | ||||||
|  | 	local blocksize=$1 | ||||||
|  | 	local origsize=$2 | ||||||
|  | 	local ret | ||||||
|  | 	case $origsize in | ||||||
|  | 		*G) | ||||||
|  | 			ret=$(( ${origsize%%G} * 1024 * 1024 * 1024 )) | ||||||
|  | 			;; | ||||||
|  | 		*M) | ||||||
|  | 			ret=$(( ${origsize%%M} * 1024 * 1024 )) | ||||||
|  | 			;; | ||||||
|  | 		*K) | ||||||
|  | 			ret=$(( ${origsize%%K} * 1024 )) | ||||||
|  | 			;; | ||||||
|  | 		*) | ||||||
|  | 			ret=$origsize | ||||||
|  | 			;; | ||||||
|  | 	esac | ||||||
|  | 	ret=$(( $ret / $blocksize )) | ||||||
|  | 	echo $ret | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## make sure path is valid | ||||||
|  | if [ -z "${path}" ]; then | ||||||
|  | 	echo "swap: --file <path> must be defined" | ||||||
|  | 	exit 1 | ||||||
|  | fi | ||||||
|  | if [ "${path:0:5}" != "/var/" -o ${#path} -lt 6 ]; then | ||||||
|  | 	echo "--file <path> option must be under /var" | ||||||
|  | 	exit 1 | ||||||
|  | fi | ||||||
|  | if [ -z "${size}" ]; then | ||||||
|  | 	echo "swap: --size <size> must be defined" | ||||||
|  | 	exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## check each of our conditions | ||||||
|  | for cond in $CONDITIONS; do | ||||||
|  | 	# split the condition parts | ||||||
|  | 	IFS=: read condtype arg1 arg2 arg3 arg4 <<< "$cond" | ||||||
|  | 	case $condtype in | ||||||
|  | 		part) | ||||||
|  | 			partition=$arg1 | ||||||
|  | 			required=$arg2 | ||||||
|  | 			# check that the path exists as its own mount point | ||||||
|  | 			set +e | ||||||
|  | 			grep -qs $partition /proc/mounts | ||||||
|  | 			is_mnt=$? | ||||||
|  | 			set -e | ||||||
|  | 			if [ $is_mnt -ne 0 ]; then | ||||||
|  | 				[ "$required" == "true" ] && exit 1 | ||||||
|  | 				exit 0 | ||||||
|  | 			fi | ||||||
|  | 			;; | ||||||
|  | 		partsize) | ||||||
|  | 			partition=$arg1 | ||||||
|  | 			minsize=$arg2 | ||||||
|  | 			required=$arg3 | ||||||
|  | 			# check that the partition on which it exists has sufficient size | ||||||
|  | 			partsize=$(df -k $partition | tail -1 | awk '{print $2}') | ||||||
|  | 			partsize=$(( $partsize * 1024 )) | ||||||
|  | 			# convert minsize to bytes | ||||||
|  | 			minsize=$(disksize_to_count 1 $minsize) | ||||||
|  | 			if [ $partsize -lt $minsize ]; then | ||||||
|  | 				[ "$required" == "true" ] && exit 1 | ||||||
|  | 				exit 0 | ||||||
|  | 			fi | ||||||
|  | 			;; | ||||||
|  | 		*) | ||||||
|  | 			echo "Unknown condition: $cond" | ||||||
|  | 			exit 1 | ||||||
|  | 			;; | ||||||
|  | 	esac | ||||||
|  | done | ||||||
|  | ## if a condition failed: | ||||||
|  | ### Required? exit 1 | ||||||
|  | ### Else? exit 0 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Allocate the file | ||||||
|  | dd if=/dev/zero of=$path bs=1024 count=$(disksize_to_count 1024 $size) | ||||||
|  | chmod 0600 $path | ||||||
|  |  | ||||||
|  | ## was it encrypted? use cryptsetup and get the mapped device | ||||||
|  | if [ "$ENCRYPT" == "true" ]; then | ||||||
|  | 	# might need | ||||||
|  | 	#loop=$(losetup -f) | ||||||
|  | 	#losetup ${loop} ${path} | ||||||
|  |  | ||||||
|  | 	cryptsetup open --type plain --key-file /dev/urandom --key-size=256 --hash=sha256 --cipher=aes-cbc-essiv --offset=0  ${path} swapfile | ||||||
|  | 	SWAPDEV=/dev/mapper/swapfile | ||||||
|  | else | ||||||
|  | 	SWAPDEV=$path | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | ## mkswap and swapon the device | ||||||
|  | /sbin/mkswap $SWAPDEV | ||||||
|  | /sbin/swapon $SWAPDEV | ||||||
		Reference in New Issue
	
	Block a user