-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Default VM to k3s with embedded nix-snapshotter
- Loading branch information
Showing
12 changed files
with
832 additions
and
207 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
traefik-crd = { | ||
url = "https://k3s.io/k3s-charts/assets/traefik-crd/traefik-crd-21.2.1+up21.2.0.tgz"; | ||
sha256 = "05j3vyikb7g2z2i07rij9h4ki5lb2hb2rynpiqfd4l1y5qm0qhw9"; | ||
}; | ||
traefik = { | ||
url = "https://k3s.io/k3s-charts/assets/traefik/traefik-21.2.1+up21.2.0.tgz"; | ||
sha256 = "0gvz0yzph2893scd0q10b938yc7f36b3zqs57pkjgqqpl1d0nwhg"; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
k3sVersion = "1.27.6+k3s1"; | ||
k3sCommit = "bd04941a294793ec92e8703d5e5da14107902e88"; | ||
k3sRepoSha256 = "04chr8gp0yprihigy1yzhvi2baby053fav384gq0sjq6bkp3fzd8"; | ||
# k3sVendorHash = "sha256-LH9OsBK0Pq/NGEHprbIgYKQsslYdR3i4LYVvo5P0K+8="; | ||
# Modified hash for ../../patches/k3s-nix-snapshotter patch | ||
k3sVendorHash = "sha256-ryEnRrmV7xkpPIj55N10tz0+eMPHW62IRfmBIh9IbBw="; | ||
chartVersions = import ./chart-versions.nix; | ||
k3sRootVersion = "0.12.2"; | ||
k3sRootSha256 = "1gjynvr350qni5mskgm7pcc7alss4gms4jmkiv453vs8mmma9c9k"; | ||
k3sCNIVersion = "1.3.0-k3s1"; | ||
k3sCNISha256 = "0zma9g4wvdnhs9igs03xlx15bk2nq56j73zns9xgqmfiixd9c9av"; | ||
containerdVersion = "1.7.6-k3s1.27"; | ||
containerdSha256 = "1kzjqw56pcdpsqdkw2k5a3pnpf8n93dh4jc2yybgqz3nyj4fw0a8"; | ||
criCtlVersion = "1.26.0-rc.0-k3s1"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,358 @@ | ||
lib: | ||
{ | ||
# git tag | ||
k3sVersion, | ||
# commit hash | ||
k3sCommit, | ||
k3sRepoSha256 ? lib.fakeHash, | ||
k3sVendorHash ? lib.fakeHash, | ||
# taken from ./scripts/version.sh VERSION_ROOT https://github.com/k3s-io/k3s/blob/v1.23.3%2Bk3s1/scripts/version.sh#L47 | ||
k3sRootVersion, | ||
k3sRootSha256 ? lib.fakeHash, | ||
# Based on the traefik charts here: https://github.com/k3s-io/k3s/blob/d71ab6317e22dd34673faa307a412a37a16767f6/scripts/download#L29-L32 | ||
# see also https://github.com/k3s-io/k3s/blob/d71ab6317e22dd34673faa307a412a37a16767f6/manifests/traefik.yaml#L8 | ||
chartVersions, | ||
# taken from ./scripts/version.sh VERSION_CNIPLUGINS https://github.com/k3s-io/k3s/blob/v1.23.3%2Bk3s1/scripts/version.sh#L45 | ||
k3sCNIVersion, | ||
k3sCNISha256 ? lib.fakeHash, | ||
# taken from ./scripts/version.sh VERSION_CONTAINERD | ||
containerdVersion, | ||
containerdSha256 ? lib.fakeHash, | ||
# run `grep github.com/kubernetes-sigs/cri-tools go.mod | head -n1 | awk '{print $4}'` in the k3s repo at the tag | ||
criCtlVersion, | ||
updateScript ? null, | ||
}: | ||
|
||
# builder.nix contains a "builder" expression that, given k3s version and hash | ||
# variables, creates a package for that version. | ||
# Due to variance in k3s's build process, this builder only works for k3s 1.26+ | ||
# currently. | ||
# It is likely we will have to split out additional builders for additional | ||
# versions in the future, or customize this one further. | ||
{ lib | ||
, makeWrapper | ||
, socat | ||
, iptables | ||
, iproute2 | ||
, ipset | ||
, bridge-utils | ||
, btrfs-progs | ||
, conntrack-tools | ||
, buildGoModule | ||
, runc | ||
, rsync | ||
, kmod | ||
, libseccomp | ||
, pkg-config | ||
, ethtool | ||
, util-linux | ||
, fetchFromGitHub | ||
, fetchurl | ||
, fetchzip | ||
, fetchgit | ||
, zstd | ||
, yq-go | ||
, sqlite | ||
, nixosTests | ||
, pkgsBuildBuild | ||
}: | ||
|
||
# k3s is a kinda weird derivation. One of the main points of k3s is the | ||
# simplicity of it being one binary that can perform several tasks. | ||
# However, when you have a good package manager (like nix), that doesn't | ||
# actually make much of a difference; you don't really care if it's one binary | ||
# or 10 since with a good package manager, installing and running it is | ||
# identical. | ||
# Since upstream k3s packages itself as one large binary with several | ||
# "personalities" (in the form of subcommands like 'k3s agent' and 'k3s | ||
# kubectl'), it ends up being easiest to mostly mimic upstream packaging, with | ||
# some exceptions. | ||
# K3s also carries patches to some packages (such as containerd and cni | ||
# plugins), so we intentionally use the k3s versions of those binaries for k3s, | ||
# even if the upstream version of those binaries exist in nixpkgs already. In | ||
# the end, that means we have a thick k3s binary that behaves like the upstream | ||
# one for the most part. | ||
# However, k3s also bundles several pieces of unpatched software, from the | ||
# strongswan vpn software, to iptables, to socat, conntrack, busybox, etc. | ||
# Those pieces of software we entirely ignore upstream's handling of, and just | ||
# make sure they're in the path if desired. | ||
let | ||
|
||
baseMeta = with lib; { | ||
description = "A lightweight Kubernetes distribution"; | ||
license = licenses.asl20; | ||
homepage = "https://k3s.io"; | ||
maintainers = with maintainers; [ euank mic92 yajo ]; | ||
platforms = platforms.linux; | ||
|
||
# resolves collisions with other installations of kubectl, crictl, ctr | ||
# prefer non-k3s versions | ||
priority = 5; | ||
}; | ||
|
||
# https://github.com/k3s-io/k3s/blob/5fb370e53e0014dc96183b8ecb2c25a61e891e76/scripts/build#L19-L40 | ||
versionldflags = [ | ||
"-X github.com/rancher/k3s/pkg/version.Version=v${k3sVersion}" | ||
"-X github.com/rancher/k3s/pkg/version.GitCommit=${lib.substring 0 8 k3sCommit}" | ||
"-X k8s.io/client-go/pkg/version.gitVersion=v${k3sVersion}" | ||
"-X k8s.io/client-go/pkg/version.gitCommit=${k3sCommit}" | ||
"-X k8s.io/client-go/pkg/version.gitTreeState=clean" | ||
"-X k8s.io/client-go/pkg/version.buildDate=1970-01-01T01:01:01Z" | ||
"-X k8s.io/component-base/version.gitVersion=v${k3sVersion}" | ||
"-X k8s.io/component-base/version.gitCommit=${k3sCommit}" | ||
"-X k8s.io/component-base/version.gitTreeState=clean" | ||
"-X k8s.io/component-base/version.buildDate=1970-01-01T01:01:01Z" | ||
"-X github.com/kubernetes-sigs/cri-tools/pkg/version.Version=v${criCtlVersion}" | ||
"-X github.com/containerd/containerd/version.Version=v${containerdVersion}" | ||
"-X github.com/containerd/containerd/version.Package=github.com/k3s-io/containerd" | ||
]; | ||
|
||
# bundled into the k3s binary | ||
traefikChart = fetchurl chartVersions.traefik; | ||
traefik-crdChart = fetchurl chartVersions.traefik-crd; | ||
|
||
# so, k3s is a complicated thing to package | ||
# This derivation attempts to avoid including any random binaries from the | ||
# internet. k3s-root is _mostly_ binaries built to be bundled in k3s (which | ||
# we don't care about doing, we can add those as build or runtime | ||
# dependencies using a real package manager). | ||
# In addition to those binaries, it's also configuration though (right now | ||
# mostly strongswan configuration), and k3s does use those files. | ||
# As such, we download it in order to grab 'etc' and bundle it into the final | ||
# k3s binary. | ||
k3sRoot = fetchzip { | ||
# Note: marked as apache 2.0 license | ||
url = "https://github.com/k3s-io/k3s-root/releases/download/v${k3sRootVersion}/k3s-root-amd64.tar"; | ||
sha256 = k3sRootSha256; | ||
stripRoot = false; | ||
}; | ||
k3sCNIPlugins = buildGoModule rec { | ||
pname = "k3s-cni-plugins"; | ||
version = k3sCNIVersion; | ||
vendorHash = null; | ||
|
||
subPackages = [ "." ]; | ||
|
||
src = fetchFromGitHub { | ||
owner = "rancher"; | ||
repo = "plugins"; | ||
rev = "v${version}"; | ||
sha256 = k3sCNISha256; | ||
}; | ||
|
||
postInstall = '' | ||
mv $out/bin/plugins $out/bin/cni | ||
''; | ||
|
||
meta = baseMeta // { | ||
description = "CNI plugins, as patched by rancher for k3s"; | ||
}; | ||
}; | ||
# Grab this separately from a build because it's used by both stages of the | ||
# k3s build. | ||
k3sRepo = fetchgit { | ||
url = "https://github.com/k3s-io/k3s"; | ||
rev = "v${k3sVersion}"; | ||
sha256 = k3sRepoSha256; | ||
}; | ||
# Stage 1 of the k3s build: | ||
# Let's talk about how k3s is structured. | ||
# One of the ideas of k3s is that there's the single "k3s" binary which can | ||
# do everything you need, from running a k3s server, to being a worker node, | ||
# to running kubectl. | ||
# The way that actually works is that k3s is a single go binary that contains | ||
# a bunch of bindata that it unpacks at runtime into directories (either the | ||
# user's home directory or /var/lib/rancher if run as root). | ||
# This bindata includes both binaries and configuration. | ||
# In order to let nixpkgs do all its autostripping/patching/etc, we split this into two derivations. | ||
# First, we build all the binaries that get packed into the thick k3s binary | ||
# (and output them from one derivation so they'll all be suitably patched up). | ||
# Then, we bundle those binaries into our thick k3s binary and use that as | ||
# the final single output. | ||
# This approach was chosen because it ensures the bundled binaries all are | ||
# correctly built to run with nix (we can lean on the existing buildGoModule | ||
# stuff), and we can again lean on that tooling for the final k3s binary too. | ||
# Other alternatives would be to manually run the | ||
# strip/patchelf/remove-references step ourselves in the installPhase of the | ||
# derivation when we've built all the binaries, but haven't bundled them in | ||
# with generated bindata yet. | ||
|
||
k3sServer = buildGoModule { | ||
pname = "k3s-server"; | ||
version = k3sVersion; | ||
|
||
src = k3sRepo; | ||
vendorHash = k3sVendorHash; | ||
|
||
patches = [ ../patches/k3s-nix-snapshotter.patch ]; | ||
|
||
nativeBuildInputs = [ pkg-config ]; | ||
buildInputs = [ libseccomp sqlite.dev ]; | ||
|
||
subPackages = [ "cmd/server" ]; | ||
ldflags = versionldflags; | ||
|
||
tags = [ "ctrd" "libsqlite3" "linux" ]; | ||
|
||
# create the multicall symlinks for k3s | ||
postInstall = '' | ||
mv $out/bin/server $out/bin/k3s | ||
pushd $out | ||
# taken verbatim from https://github.com/k3s-io/k3s/blob/v1.23.3%2Bk3s1/scripts/build#L105-L113 | ||
ln -s k3s ./bin/containerd | ||
ln -s k3s ./bin/crictl | ||
ln -s k3s ./bin/ctr | ||
ln -s k3s ./bin/k3s-agent | ||
ln -s k3s ./bin/k3s-certificate | ||
ln -s k3s ./bin/k3s-completion | ||
ln -s k3s ./bin/k3s-etcd-snapshot | ||
ln -s k3s ./bin/k3s-secrets-encrypt | ||
ln -s k3s ./bin/k3s-server | ||
ln -s k3s ./bin/k3s-token | ||
ln -s k3s ./bin/kubectl | ||
popd | ||
''; | ||
|
||
meta = baseMeta // { | ||
description = "The various binaries that get packaged into the final k3s binary"; | ||
}; | ||
}; | ||
# Only used for the shim since | ||
# https://github.com/k3s-io/k3s/blob/v1.27.2%2Bk3s1/scripts/build#L153 | ||
k3sContainerd = buildGoModule { | ||
pname = "k3s-containerd"; | ||
version = containerdVersion; | ||
src = fetchFromGitHub { | ||
owner = "k3s-io"; | ||
repo = "containerd"; | ||
rev = "v${containerdVersion}"; | ||
sha256 = containerdSha256; | ||
}; | ||
vendorHash = null; | ||
buildInputs = [ btrfs-progs ]; | ||
subPackages = [ "cmd/containerd-shim-runc-v2" ]; | ||
ldflags = versionldflags; | ||
}; | ||
in | ||
buildGoModule rec { | ||
pname = "k3s"; | ||
version = k3sVersion; | ||
|
||
tags = [ "libsqlite3" "linux" "ctrd" ]; | ||
src = k3sRepo; | ||
vendorHash = k3sVendorHash; | ||
|
||
patches = [ ../patches/k3s-nix-snapshotter.patch ]; | ||
|
||
postPatch = '' | ||
# Nix prefers dynamically linked binaries over static binary. | ||
substituteInPlace scripts/package-cli \ | ||
--replace '"$LDFLAGS $STATIC" -o' \ | ||
'"$LDFLAGS" -o' \ | ||
--replace "STATIC=\"-extldflags \'-static\'\"" \ | ||
"" | ||
# Upstream codegen fails with trimpath set. Removes "trimpath" for 'go generate': | ||
substituteInPlace scripts/package-cli \ | ||
--replace '"''${GO}" generate' \ | ||
'GOFLAGS="" \ | ||
GOOS="${pkgsBuildBuild.go.GOOS}" \ | ||
GOARCH="${pkgsBuildBuild.go.GOARCH}" \ | ||
CC="${pkgsBuildBuild.stdenv.cc}/bin/cc" \ | ||
"''${GO}" generate' | ||
''; | ||
|
||
# Important utilities used by the kubelet, see | ||
# https://github.com/kubernetes/kubernetes/issues/26093#issuecomment-237202494 | ||
# Note the list in that issue is stale and some aren't relevant for k3s. | ||
k3sRuntimeDeps = [ | ||
kmod | ||
socat | ||
iptables | ||
iproute2 | ||
ipset | ||
bridge-utils | ||
ethtool | ||
util-linux # kubelet wants 'nsenter' from util-linux: https://github.com/kubernetes/kubernetes/issues/26093#issuecomment-705994388 | ||
conntrack-tools | ||
runc | ||
]; | ||
|
||
buildInputs = k3sRuntimeDeps; | ||
|
||
nativeBuildInputs = [ | ||
makeWrapper | ||
rsync | ||
yq-go | ||
zstd | ||
]; | ||
|
||
# embedded in the final k3s cli | ||
propagatedBuildInputs = [ | ||
k3sCNIPlugins | ||
k3sContainerd | ||
k3sServer | ||
]; | ||
|
||
# We override most of buildPhase due to peculiarities in k3s's build. | ||
# Specifically, it has a 'go generate' which runs part of the package. See | ||
# this comment: | ||
# https://github.com/NixOS/nixpkgs/pull/158089#discussion_r799965694 | ||
# So, why do we use buildGoModule at all? For the `vendorHash` / `go mod download` stuff primarily. | ||
buildPhase = '' | ||
patchShebangs ./scripts/package-cli ./scripts/download ./scripts/build-upload | ||
# copy needed 'go generate' inputs into place | ||
mkdir -p ./bin/aux | ||
rsync -a --no-perms ${k3sServer}/bin/ ./bin/ | ||
ln -vsf ${k3sCNIPlugins}/bin/cni ./bin/cni | ||
ln -vsf ${k3sContainerd}/bin/containerd-shim-runc-v2 ./bin | ||
rsync -a --no-perms --chmod u=rwX ${k3sRoot}/etc/ ./etc/ | ||
mkdir -p ./build/static/charts | ||
cp ${traefikChart} ./build/static/charts | ||
cp ${traefik-crdChart} ./build/static/charts | ||
export ARCH=$GOARCH | ||
export DRONE_TAG="v${k3sVersion}" | ||
export DRONE_COMMIT="${k3sCommit}" | ||
# use ./scripts/package-cli to run 'go generate' + 'go build' | ||
./scripts/package-cli | ||
mkdir -p $out/bin | ||
''; | ||
|
||
# Otherwise it depends on 'getGoDirs', which is normally set in buildPhase | ||
doCheck = false; | ||
|
||
installPhase = '' | ||
# wildcard to match the arm64 build too | ||
install -m 0755 dist/artifacts/k3s* -D $out/bin/k3s | ||
wrapProgram $out/bin/k3s \ | ||
--prefix PATH : ${lib.makeBinPath k3sRuntimeDeps} \ | ||
--prefix PATH : "$out/bin" | ||
ln -s $out/bin/k3s $out/bin/kubectl | ||
ln -s $out/bin/k3s $out/bin/crictl | ||
ln -s $out/bin/k3s $out/bin/ctr | ||
''; | ||
|
||
doInstallCheck = true; | ||
installCheckPhase = '' | ||
$out/bin/k3s --version | grep -F "v${k3sVersion}" >/dev/null | ||
''; | ||
|
||
passthru.updateScript = updateScript; | ||
|
||
passthru.mkTests = version: | ||
let k3s_version = "k3s_" + lib.replaceStrings ["."] ["_"] (lib.versions.majorMinor version); | ||
in { | ||
single-node = nixosTests.k3s.single-node.${k3s_version}; | ||
multi-node = nixosTests.k3s.multi-node.${k3s_version}; | ||
}; | ||
passthru.tests = passthru.mkTests k3sVersion; | ||
|
||
|
||
meta = baseMeta; | ||
} |
Oops, something went wrong.