Kubernetes ではしばしば、何もせずに待機し続ける Pod を立ち上げたくなることがあります。この際 bash -c "sleep infinity" などを使用してもよいのですが、プロセスに PID 1 が割り当てられてしまう影響[1]で Pod 終了時に 30 秒待機しないといけないという不便があります[2]。
このようなときに便利なのが github.com/kubernetes/kubernetes にある pause コマンドです。シグナルハンドラが適切に設定されており SIGTERM や SIGINT が送られてきたときに即座に終了できます。
ということでこのコマンドを組み込んだ Docker イメージを Nix で作ります。
Nixpkgs にある kubernetes パッケージは multiple-output package になっていて kubernetes.pause で pause コマンドを参照できるようになっています。そこで以下のように書くと pause コマンドが入った Docker イメージが作れます。
{
dockerTools,
kubernetes,
runtimeShell,
...
}:
dockerTools.buildLayeredImage {
name = "ghcr.io/ushitora-anqou/pause";
tag = "0.1.0";
created = "now";
contents = [
kubernetes.pause
];
enableFakechroot = true;
config = {
Entrypoint = ["pause"];
};
}
ただしこのバイナリは 40MB 近くもあります:
❯ docker images
i Info → U In Use
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
ghcr.io/ushitora-anqou/pause:0.1.0 3d28987da42c 39.4MB 0B
これを縮めたい場合は、以下のように自前で静的ビルドし remove-references-to を使って不要な依存を消す必要があります[3]:
{
fetchurl,
glibc,
libgcc,
removeReferencesTo,
stdenv,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "pause";
version = "0.1.0";
src = fetchurl {
url = "https://raw.githubusercontent.com/kubernetes/kubernetes/v1.36.1/build/pause/linux/pause.c";
hash = "sha256-FKP+IatfjmKTeitFPnbzuUsNPHwEw9Cbw3GV9UwWleo=";
};
nativeBuildInputs = [glibc.static];
unpackPhase = ":";
buildPhase = ''
runHook preBuild
gcc -Os -Wall -Werror -static -DVERSION=v${finalAttrs.version} -o pause $src
strip pause
${removeReferencesTo}/bin/remove-references-to -t ${glibc.libgcc} -t ${glibc} pause
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp pause $out/bin
runHook postInstall
'';
})
kubernetes.pause の代わりに callPackage ./pause.nix {} のように上記ビルドを埋め込むようにすると、741KB まで縮みました:
❯ docker images
i Info → U In Use
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
ghcr.io/ushitora-anqou/pause:0.1.0 179ee524f495 741kB 0B U