2026-02-28 16:04:14 +00:00
|
|
|
{ config, lib, pkgs, ... }:
|
2026-02-28 14:16:55 +00:00
|
|
|
|
2026-02-28 16:04:14 +00:00
|
|
|
let
|
|
|
|
|
pinnedK8s = lib.attrByPath [ "kubernetes_1_31" ] pkgs.kubernetes pkgs;
|
|
|
|
|
kubeVipImage = "ghcr.io/kube-vip/kube-vip:v0.8.9";
|
|
|
|
|
in
|
2026-02-28 14:16:55 +00:00
|
|
|
{
|
2026-02-28 16:04:14 +00:00
|
|
|
options.terrahome.kubeadm = {
|
|
|
|
|
k8sMinor = lib.mkOption {
|
|
|
|
|
type = lib.types.str;
|
|
|
|
|
default = "1.31";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
controlPlaneInterface = lib.mkOption {
|
|
|
|
|
type = lib.types.str;
|
|
|
|
|
default = "eth0";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
controlPlaneVipSuffix = lib.mkOption {
|
|
|
|
|
type = lib.types.int;
|
|
|
|
|
default = 250;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
podSubnet = lib.mkOption {
|
|
|
|
|
type = lib.types.str;
|
|
|
|
|
default = "10.244.0.0/16";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
serviceSubnet = lib.mkOption {
|
|
|
|
|
type = lib.types.str;
|
|
|
|
|
default = "10.96.0.0/12";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
clusterDomain = lib.mkOption {
|
|
|
|
|
type = lib.types.str;
|
|
|
|
|
default = "cluster.local";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config = {
|
2026-02-28 14:16:55 +00:00
|
|
|
boot.kernelModules = [ "overlay" "br_netfilter" ];
|
|
|
|
|
|
|
|
|
|
boot.kernel.sysctl = {
|
|
|
|
|
"net.ipv4.ip_forward" = 1;
|
|
|
|
|
"net.bridge.bridge-nf-call-iptables" = 1;
|
|
|
|
|
"net.bridge.bridge-nf-call-ip6tables" = 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
virtualisation.containerd.enable = true;
|
2026-02-28 16:04:14 +00:00
|
|
|
virtualisation.containerd.settings = {
|
|
|
|
|
plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options.SystemdCgroup = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
swapDevices = lib.mkForce [ ];
|
2026-02-28 14:16:55 +00:00
|
|
|
|
|
|
|
|
services.openssh.enable = true;
|
|
|
|
|
services.openssh.settings = {
|
|
|
|
|
PasswordAuthentication = false;
|
|
|
|
|
KbdInteractiveAuthentication = false;
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-01 13:31:36 +00:00
|
|
|
users.users.micqdf = {
|
|
|
|
|
isNormalUser = true;
|
|
|
|
|
extraGroups = [ "wheel" ];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
security.sudo.wheelNeedsPassword = false;
|
|
|
|
|
|
2026-02-28 20:03:26 +00:00
|
|
|
nix.settings.trusted-users = [ "root" "micqdf" ];
|
2026-02-28 21:24:16 +00:00
|
|
|
nix.gc = {
|
|
|
|
|
automatic = true;
|
|
|
|
|
dates = "daily";
|
|
|
|
|
options = "--delete-older-than 3d";
|
|
|
|
|
};
|
|
|
|
|
nix.settings.auto-optimise-store = true;
|
2026-02-28 20:03:26 +00:00
|
|
|
|
2026-02-28 16:04:14 +00:00
|
|
|
environment.variables = {
|
|
|
|
|
KUBECONFIG = "/etc/kubernetes/admin.conf";
|
|
|
|
|
KUBE_VIP_IMAGE = kubeVipImage;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
environment.systemPackages = (with pkgs; [
|
2026-02-28 14:16:55 +00:00
|
|
|
containerd
|
|
|
|
|
cri-tools
|
|
|
|
|
cni-plugins
|
2026-02-28 16:04:14 +00:00
|
|
|
pinnedK8s
|
2026-02-28 14:16:55 +00:00
|
|
|
kubernetes-helm
|
|
|
|
|
conntrack-tools
|
|
|
|
|
socat
|
|
|
|
|
ethtool
|
|
|
|
|
ipvsadm
|
2026-02-28 16:04:14 +00:00
|
|
|
iproute2
|
|
|
|
|
iptables
|
|
|
|
|
ebtables
|
2026-02-28 14:16:55 +00:00
|
|
|
jq
|
|
|
|
|
curl
|
|
|
|
|
vim
|
2026-02-28 16:04:14 +00:00
|
|
|
gawk
|
|
|
|
|
]) ++ [
|
|
|
|
|
(pkgs.writeShellScriptBin "th-kubeadm-init" ''
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
2026-03-02 02:02:38 +00:00
|
|
|
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy NO_PROXY
|
|
|
|
|
|
2026-02-28 16:04:14 +00:00
|
|
|
iface="${config.terrahome.kubeadm.controlPlaneInterface}"
|
2026-03-01 17:34:09 +00:00
|
|
|
if ! ip link show "$iface" >/dev/null 2>&1; then
|
|
|
|
|
iface="$(ip -o -4 route show to default | awk 'NR==1 {print $5}')"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ -z "''${iface:-}" ]; then
|
|
|
|
|
echo "Could not determine network interface for kube-vip"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-28 16:04:14 +00:00
|
|
|
suffix="${toString config.terrahome.kubeadm.controlPlaneVipSuffix}"
|
|
|
|
|
pod_subnet="${config.terrahome.kubeadm.podSubnet}"
|
|
|
|
|
service_subnet="${config.terrahome.kubeadm.serviceSubnet}"
|
|
|
|
|
domain="${config.terrahome.kubeadm.clusterDomain}"
|
2026-03-04 01:17:44 +00:00
|
|
|
node_name="${config.networking.hostName}"
|
2026-02-28 16:04:14 +00:00
|
|
|
|
|
|
|
|
local_ip_cidr=$(ip -4 -o addr show dev "$iface" | awk 'NR==1 {print $4}')
|
2026-02-28 16:12:25 +00:00
|
|
|
if [ -z "''${local_ip_cidr:-}" ]; then
|
2026-02-28 16:04:14 +00:00
|
|
|
echo "Could not determine IPv4 CIDR on interface $iface"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
subnet_prefix=$(echo "$local_ip_cidr" | cut -d/ -f1 | awk -F. '{print $1"."$2"."$3}')
|
|
|
|
|
vip="$subnet_prefix.$suffix"
|
|
|
|
|
|
|
|
|
|
echo "Using control-plane endpoint: $vip:6443"
|
|
|
|
|
echo "Using kube-vip interface: $iface"
|
2026-03-04 01:17:44 +00:00
|
|
|
echo "Using kubeadm node name: $node_name"
|
|
|
|
|
|
2026-03-04 01:35:41 +00:00
|
|
|
hostname "$node_name" || true
|
2026-02-28 16:04:14 +00:00
|
|
|
|
2026-03-02 17:58:05 +00:00
|
|
|
rm -f /var/lib/kubelet/config.yaml /var/lib/kubelet/kubeadm-flags.env
|
|
|
|
|
|
2026-03-02 12:44:40 +00:00
|
|
|
systemctl unmask kubelet || true
|
2026-03-02 02:02:38 +00:00
|
|
|
systemctl stop kubelet || true
|
2026-03-02 13:58:49 +00:00
|
|
|
systemctl reset-failed kubelet || true
|
2026-03-02 02:36:57 +00:00
|
|
|
env -i PATH=/run/current-system/sw/bin:/usr/bin:/bin kubeadm reset -f || true
|
2026-03-04 01:35:41 +00:00
|
|
|
rm -f /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf
|
|
|
|
|
rm -f /var/lib/kubelet/kubeconfig /var/lib/kubelet/instance-config.yaml
|
|
|
|
|
rm -rf /var/lib/kubelet/pki
|
2026-03-02 02:02:38 +00:00
|
|
|
|
2026-03-02 13:58:49 +00:00
|
|
|
systemctl daemon-reload
|
|
|
|
|
systemctl unmask kubelet || true
|
2026-03-03 01:04:50 +00:00
|
|
|
systemctl enable kubelet || true
|
2026-03-02 13:58:49 +00:00
|
|
|
|
2026-03-02 14:43:57 +00:00
|
|
|
echo "==> Ensuring containerd is running"
|
|
|
|
|
systemctl start containerd || true
|
|
|
|
|
sleep 2
|
|
|
|
|
if ! systemctl is-active containerd; then
|
|
|
|
|
echo "ERROR: containerd not running"
|
|
|
|
|
journalctl -xeu containerd --no-pager -n 30
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-03-02 22:09:10 +00:00
|
|
|
mkdir -p /etc/kubernetes/manifests
|
2026-03-02 16:49:21 +00:00
|
|
|
mkdir -p /tmp/kubeadm
|
|
|
|
|
cat > /tmp/kubeadm/init-config.yaml << 'KUBEADMCONFIG'
|
|
|
|
|
apiVersion: kubeadm.k8s.io/v1beta4
|
|
|
|
|
kind: InitConfiguration
|
|
|
|
|
nodeRegistration:
|
2026-03-04 01:17:44 +00:00
|
|
|
name: "KUBEADM_NODE_NAME"
|
2026-03-02 16:49:21 +00:00
|
|
|
criSocket: unix:///run/containerd/containerd.sock
|
2026-03-04 01:35:41 +00:00
|
|
|
kubeletExtraArgs:
|
2026-03-04 02:00:07 +00:00
|
|
|
- name: hostname-override
|
|
|
|
|
value: "KUBEADM_NODE_NAME"
|
2026-03-02 16:49:21 +00:00
|
|
|
---
|
|
|
|
|
apiVersion: kubeadm.k8s.io/v1beta4
|
|
|
|
|
kind: ClusterConfiguration
|
|
|
|
|
controlPlaneEndpoint: "KUBEADM_ENDPOINT"
|
|
|
|
|
networking:
|
|
|
|
|
podSubnet: "KUBEADM_POD_SUBNET"
|
|
|
|
|
serviceSubnet: "KUBEADM_SERVICE_SUBNET"
|
|
|
|
|
dnsDomain: "KUBEADM_DNS_DOMAIN"
|
|
|
|
|
KUBEADMCONFIG
|
|
|
|
|
|
|
|
|
|
sed -i "s|KUBEADM_ENDPOINT|$vip:6443|g" /tmp/kubeadm/init-config.yaml
|
|
|
|
|
sed -i "s|KUBEADM_POD_SUBNET|$pod_subnet|g" /tmp/kubeadm/init-config.yaml
|
|
|
|
|
sed -i "s|KUBEADM_SERVICE_SUBNET|$service_subnet|g" /tmp/kubeadm/init-config.yaml
|
|
|
|
|
sed -i "s|KUBEADM_DNS_DOMAIN|$domain|g" /tmp/kubeadm/init-config.yaml
|
2026-03-04 01:17:44 +00:00
|
|
|
sed -i "s|KUBEADM_NODE_NAME|$node_name|g" /tmp/kubeadm/init-config.yaml
|
2026-03-02 16:49:21 +00:00
|
|
|
|
2026-03-02 18:35:41 +00:00
|
|
|
echo "==> Pre-pulling kubeadm images"
|
|
|
|
|
env -i PATH=/run/current-system/sw/bin:/usr/bin:/bin kubeadm config images pull --config /tmp/kubeadm/init-config.yaml || true
|
|
|
|
|
|
2026-03-02 22:09:10 +00:00
|
|
|
echo "==> Creating kube-vip static pod manifest"
|
|
|
|
|
ctr image pull "${kubeVipImage}"
|
|
|
|
|
ctr run --rm --net-host "${kubeVipImage}" kube-vip-manifest /kube-vip manifest pod \
|
2026-03-03 00:25:25 +00:00
|
|
|
--log 4 \
|
2026-03-02 22:09:10 +00:00
|
|
|
--interface "$iface" \
|
|
|
|
|
--address "$vip" \
|
|
|
|
|
--controlplane \
|
|
|
|
|
--arp \
|
|
|
|
|
> /etc/kubernetes/manifests/kube-vip.yaml
|
|
|
|
|
|
|
|
|
|
# kube-vip bootstrap workaround for Kubernetes >=1.29.
|
|
|
|
|
# During early kubeadm phases, super-admin.conf is available before admin.conf is fully usable.
|
2026-03-02 23:59:41 +00:00
|
|
|
sed -i 's#path: /etc/kubernetes/admin.conf#path: /etc/kubernetes/super-admin.conf#' /etc/kubernetes/manifests/kube-vip.yaml || true
|
|
|
|
|
echo "==> kube-vip manifest kubeconfig mount"
|
|
|
|
|
grep -E 'mountPath:|path:' /etc/kubernetes/manifests/kube-vip.yaml | grep -E 'kubernetes/(admin|super-admin)\.conf' || true
|
2026-03-02 22:09:10 +00:00
|
|
|
|
2026-03-04 03:00:34 +00:00
|
|
|
KUBEADM_INIT_LOG=/tmp/kubeadm-init.log
|
|
|
|
|
if ! env -i PATH=/run/current-system/sw/bin:/usr/bin:/bin kubeadm init \
|
2026-03-02 16:49:21 +00:00
|
|
|
--config /tmp/kubeadm/init-config.yaml \
|
2026-02-28 16:04:14 +00:00
|
|
|
--upload-certs \
|
2026-03-04 03:00:34 +00:00
|
|
|
--ignore-preflight-errors=NumCPU,HTTPProxyCIDR,Port-10250 2>&1 | tee "$KUBEADM_INIT_LOG"; then
|
|
|
|
|
if grep -q "error writing CRISocket for this node: nodes" "$KUBEADM_INIT_LOG" && [ -f /etc/kubernetes/admin.conf ]; then
|
|
|
|
|
echo "==> kubeadm hit CRISocket race; waiting for node registration"
|
2026-03-04 18:37:50 +00:00
|
|
|
echo "==> forcing kubelet restart to pick bootstrap flags"
|
|
|
|
|
systemctl daemon-reload || true
|
|
|
|
|
systemctl restart kubelet || true
|
|
|
|
|
sleep 3
|
|
|
|
|
echo "==> kubelet bootstrap flags"
|
|
|
|
|
cat /var/lib/kubelet/kubeadm-flags.env || true
|
2026-03-04 03:00:34 +00:00
|
|
|
registered=0
|
|
|
|
|
for i in $(seq 1 60); do
|
|
|
|
|
if KUBECONFIG=/etc/kubernetes/admin.conf kubectl get node "$node_name" >/dev/null 2>&1; then
|
|
|
|
|
echo "==> node $node_name registered; uploading kubelet config"
|
|
|
|
|
env -i PATH=/run/current-system/sw/bin:/usr/bin:/bin kubeadm init phase upload-config kubelet --config /tmp/kubeadm/init-config.yaml
|
|
|
|
|
registered=1
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
sleep 2
|
|
|
|
|
done
|
|
|
|
|
if [ "$registered" -ne 1 ]; then
|
|
|
|
|
echo "==> node $node_name did not register after kubeadm init failure"
|
|
|
|
|
KUBECONFIG=/etc/kubernetes/admin.conf kubectl get nodes -o wide || true
|
2026-03-04 18:37:50 +00:00
|
|
|
echo "==> kubelet logs (registration hints)"
|
|
|
|
|
journalctl -u kubelet --no-pager -n 120 | grep -Ei "register|node|bootstrap|certificate|forbidden|unauthorized|refused|x509" || true
|
2026-03-04 03:00:34 +00:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
echo "==> kubeadm init failed, checking pod status:"
|
|
|
|
|
crictl pods || true
|
|
|
|
|
crictl ps -a || true
|
|
|
|
|
echo "==> kube-vip containers:"
|
|
|
|
|
crictl ps -a --name kube-vip || true
|
|
|
|
|
echo "==> kube-vip logs:"
|
|
|
|
|
for container_id in $(crictl ps -a --name kube-vip -q 2>/dev/null); do
|
|
|
|
|
echo "--- kube-vip container $container_id ---"
|
|
|
|
|
crictl logs "$container_id" 2>/dev/null || true
|
|
|
|
|
crictl inspect "$container_id" 2>/dev/null | jq -r '.status | "exitCode=\(.exitCode) reason=\(.reason // "") message=\(.message // "")"' || true
|
|
|
|
|
done
|
|
|
|
|
echo "==> Checking if VIP is bound:"
|
|
|
|
|
ip -4 addr show | grep "$vip" || echo "VIP NOT BOUND"
|
|
|
|
|
echo "==> kubelet logs:"
|
|
|
|
|
journalctl -xeu kubelet --no-pager -n 50
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
fi
|
2026-02-28 16:04:14 +00:00
|
|
|
|
2026-03-02 19:37:06 +00:00
|
|
|
echo "==> Waiting for kube-vip to claim VIP $vip"
|
2026-03-02 22:09:10 +00:00
|
|
|
for i in $(seq 1 90); do
|
2026-03-02 19:37:06 +00:00
|
|
|
if ip -4 addr show | grep -q "$vip"; then
|
|
|
|
|
echo "==> VIP $vip is bound"
|
|
|
|
|
break
|
|
|
|
|
fi
|
2026-03-02 22:09:10 +00:00
|
|
|
if [ "$i" -eq 90 ]; then
|
|
|
|
|
echo "==> ERROR: VIP not bound after 3 minutes"
|
|
|
|
|
crictl ps -a --name kube-vip || true
|
|
|
|
|
for container_id in $(crictl ps -a --name kube-vip -q 2>/dev/null); do
|
|
|
|
|
echo "--- kube-vip container $container_id ---"
|
|
|
|
|
crictl logs "$container_id" 2>/dev/null || true
|
|
|
|
|
done
|
|
|
|
|
exit 1
|
2026-03-02 19:37:06 +00:00
|
|
|
fi
|
|
|
|
|
sleep 2
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo "==> Waiting for API server to be ready"
|
|
|
|
|
for i in $(seq 1 60); do
|
|
|
|
|
if curl -sk "https://$vip:6443/healthz" 2>/dev/null | grep -q "ok"; then
|
|
|
|
|
echo "==> API server is healthy"
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
if [ "$i" -eq 60 ]; then
|
|
|
|
|
echo "==> ERROR: API server not healthy after 2 minutes"
|
|
|
|
|
crictl pods || true
|
|
|
|
|
crictl ps -a || true
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
sleep 2
|
|
|
|
|
done
|
|
|
|
|
|
2026-03-02 22:09:10 +00:00
|
|
|
# Switch kube-vip to normal admin.conf after bootstrap finishes.
|
2026-03-02 23:59:41 +00:00
|
|
|
sed -i 's#path: /etc/kubernetes/super-admin.conf#path: /etc/kubernetes/admin.conf#' /etc/kubernetes/manifests/kube-vip.yaml || true
|
2026-03-02 20:38:45 +00:00
|
|
|
|
2026-02-28 16:04:14 +00:00
|
|
|
mkdir -p /root/.kube
|
|
|
|
|
cp /etc/kubernetes/admin.conf /root/.kube/config
|
|
|
|
|
chmod 600 /root/.kube/config
|
|
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
echo "Next: install Cilium, then generate join commands:"
|
|
|
|
|
echo " kubeadm token create --print-join-command"
|
|
|
|
|
echo " kubeadm token create --print-join-command --certificate-key <key>"
|
|
|
|
|
'')
|
|
|
|
|
|
|
|
|
|
(pkgs.writeShellScriptBin "th-kubeadm-join-control-plane" ''
|
|
|
|
|
set -euo pipefail
|
2026-03-02 02:02:38 +00:00
|
|
|
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy NO_PROXY
|
2026-02-28 16:04:14 +00:00
|
|
|
if [ "$#" -lt 1 ]; then
|
|
|
|
|
echo "Usage: th-kubeadm-join-control-plane '<kubeadm join ... --control-plane --certificate-key ...>'"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
iface="${config.terrahome.kubeadm.controlPlaneInterface}"
|
2026-03-01 17:34:09 +00:00
|
|
|
if ! ip link show "$iface" >/dev/null 2>&1; then
|
|
|
|
|
iface="$(ip -o -4 route show to default | awk 'NR==1 {print $5}')"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ -z "''${iface:-}" ]; then
|
|
|
|
|
echo "Could not determine network interface for kube-vip"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-28 16:04:14 +00:00
|
|
|
suffix="${toString config.terrahome.kubeadm.controlPlaneVipSuffix}"
|
|
|
|
|
local_ip_cidr=$(ip -4 -o addr show dev "$iface" | awk 'NR==1 {print $4}')
|
2026-02-28 16:12:25 +00:00
|
|
|
if [ -z "''${local_ip_cidr:-}" ]; then
|
2026-02-28 16:04:14 +00:00
|
|
|
echo "Could not determine IPv4 CIDR on interface $iface"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
subnet_prefix=$(echo "$local_ip_cidr" | cut -d/ -f1 | awk -F. '{print $1"."$2"."$3}')
|
|
|
|
|
vip="$subnet_prefix.$suffix"
|
|
|
|
|
|
|
|
|
|
mkdir -p /etc/kubernetes/manifests
|
2026-03-02 01:27:44 +00:00
|
|
|
ctr image pull "${kubeVipImage}"
|
|
|
|
|
ctr run --rm --net-host "${kubeVipImage}" kube-vip /kube-vip manifest pod \
|
2026-03-03 00:25:25 +00:00
|
|
|
--log 4 \
|
2026-02-28 16:04:14 +00:00
|
|
|
--interface "$iface" \
|
|
|
|
|
--address "$vip" \
|
|
|
|
|
--controlplane \
|
|
|
|
|
--arp \
|
|
|
|
|
--leaderElection \
|
|
|
|
|
> /etc/kubernetes/manifests/kube-vip.yaml
|
|
|
|
|
|
2026-03-02 17:58:05 +00:00
|
|
|
rm -f /var/lib/kubelet/config.yaml /var/lib/kubelet/kubeadm-flags.env
|
|
|
|
|
|
2026-03-02 12:44:40 +00:00
|
|
|
systemctl unmask kubelet || true
|
2026-03-02 02:02:38 +00:00
|
|
|
systemctl stop kubelet || true
|
2026-03-04 00:26:37 +00:00
|
|
|
systemctl enable kubelet || true
|
2026-03-02 13:58:49 +00:00
|
|
|
systemctl reset-failed kubelet || true
|
|
|
|
|
systemctl daemon-reload
|
2026-02-28 16:04:14 +00:00
|
|
|
eval "$1"
|
|
|
|
|
'')
|
|
|
|
|
|
|
|
|
|
(pkgs.writeShellScriptBin "th-kubeadm-join-worker" ''
|
|
|
|
|
set -euo pipefail
|
2026-03-02 02:02:38 +00:00
|
|
|
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy NO_PROXY
|
2026-02-28 16:04:14 +00:00
|
|
|
if [ "$#" -lt 1 ]; then
|
|
|
|
|
echo "Usage: th-kubeadm-join-worker '<kubeadm join ...>'"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-03-02 17:58:05 +00:00
|
|
|
rm -f /var/lib/kubelet/config.yaml /var/lib/kubelet/kubeadm-flags.env
|
|
|
|
|
|
2026-03-02 12:44:40 +00:00
|
|
|
systemctl unmask kubelet || true
|
2026-03-02 02:02:38 +00:00
|
|
|
systemctl stop kubelet || true
|
2026-03-04 00:26:37 +00:00
|
|
|
systemctl enable kubelet || true
|
2026-03-02 13:58:49 +00:00
|
|
|
systemctl reset-failed kubelet || true
|
|
|
|
|
systemctl daemon-reload
|
2026-02-28 16:04:14 +00:00
|
|
|
eval "$1"
|
|
|
|
|
'')
|
|
|
|
|
|
|
|
|
|
(pkgs.writeShellScriptBin "th-kubeadm-status" ''
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
systemctl is-active containerd || true
|
|
|
|
|
systemctl is-active kubelet || true
|
|
|
|
|
crictl info >/dev/null && echo "crictl: ok" || echo "crictl: not-ready"
|
|
|
|
|
'')
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
systemd.services.kubelet = {
|
|
|
|
|
description = "Kubernetes Kubelet";
|
2026-03-04 00:55:20 +00:00
|
|
|
wantedBy = [ "multi-user.target" ];
|
2026-02-28 16:19:37 +00:00
|
|
|
wants = [ "network-online.target" ];
|
2026-02-28 16:04:14 +00:00
|
|
|
after = [ "containerd.service" "network-online.target" ];
|
|
|
|
|
serviceConfig = {
|
2026-03-02 16:49:21 +00:00
|
|
|
Environment = [
|
|
|
|
|
"KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
|
|
|
|
|
"KUBELET_KUBEADM_ARGS="
|
|
|
|
|
"KUBELET_EXTRA_ARGS="
|
|
|
|
|
];
|
2026-03-02 03:44:35 +00:00
|
|
|
EnvironmentFile = [
|
|
|
|
|
"-/var/lib/kubelet/kubeadm-flags.env"
|
|
|
|
|
"-/etc/default/kubelet"
|
|
|
|
|
];
|
2026-03-02 16:49:21 +00:00
|
|
|
ExecStart = "${pinnedK8s}/bin/kubelet \$KUBELET_CONFIG_ARGS \$KUBELET_KUBEADM_ARGS \$KUBELET_EXTRA_ARGS";
|
|
|
|
|
Restart = "on-failure";
|
2026-02-28 16:04:14 +00:00
|
|
|
RestartSec = "10";
|
|
|
|
|
};
|
2026-03-02 16:49:21 +00:00
|
|
|
unitConfig = {
|
|
|
|
|
ConditionPathExists = "/var/lib/kubelet/config.yaml";
|
|
|
|
|
};
|
2026-02-28 16:04:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
systemd.tmpfiles.rules = [
|
|
|
|
|
"d /etc/kubernetes 0755 root root -"
|
|
|
|
|
"d /etc/kubernetes/manifests 0755 root root -"
|
2026-03-02 14:43:57 +00:00
|
|
|
"d /var/lib/kubelet 0755 root root -"
|
|
|
|
|
"d /var/lib/kubelet/pki 0755 root root -"
|
2026-02-28 14:16:55 +00:00
|
|
|
];
|
2026-02-28 16:04:14 +00:00
|
|
|
};
|
2026-02-28 14:16:55 +00:00
|
|
|
}
|