mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-20 17:49:10 +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:
parent
60372d3750
commit
715cfbd02c
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
|
Loading…
Reference in New Issue
Block a user