Skip to content

Commit

Permalink
Added Kubernetes cluster configuration (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
spietras authored Feb 5, 2024
1 parent c20106c commit 0112e8a
Show file tree
Hide file tree
Showing 7 changed files with 400 additions and 4 deletions.
108 changes: 107 additions & 1 deletion src/hosts/xenon/modules/constants/default.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Reusable constants are defined here
# All options have default values
# You can use them in other modules
{lib, ...}: {
{
config,
lib,
...
}: {
options = {
constants = {
name = lib.mkOption {
Expand All @@ -10,6 +14,108 @@
type = lib.types.str;
};

kubernetes = {
cluster = {
name = lib.mkOption {
default = "main";
description = "Name of the Kubernetes cluster";
type = lib.types.str;
};
};

directories = {
state = lib.mkOption {
default = "/var/lib/kubernetes/k3s/";
description = "Directory to store state in";
type = lib.types.path;
};
};

files = {
kubeconfig = lib.mkOption {
default = "/etc/kubernetes/kubeconfig.yaml";
description = "File to store the kubeconfig in";
type = lib.types.path;
};
};

flux = {
source = {
branch = lib.mkOption {
default = "main";
description = "Branch of the Git repository";
type = lib.types.str;
};

path = lib.mkOption {
default = "src/clusters/${config.constants.kubernetes.cluster.name}";
description = "Path to the directory with manifests";
type = lib.types.str;
};

url = lib.mkOption {
default = "https://github.com/spietras/clusters";
description = "URL of the Git repository";
type = lib.types.str;
};
};
};

network = {
addresses = {
cluster = lib.mkOption {
default = "10.42.0.0/16,2001:cafe:42::/56";
description = "IP address allocation range for pods";
type = lib.types.str;
};

service = lib.mkOption {
default = "10.43.0.0/16,2001:cafe:43::/112";
description = "IP address allocation range for services";
type = lib.types.str;
};
};

ports = {
api = lib.mkOption {
default = 6443;
description = "Port for API server";
type = lib.types.int;
};
};
};

resources = {
reserved = {
system = {
cpu = lib.mkOption {
default = "500m";
description = "Reserved CPU for system";
type = lib.types.str;
};

memory = lib.mkOption {
default = "500Mi";
description = "Reserved memory for system";
type = lib.types.str;
};

storage = lib.mkOption {
default = "5Gi";
description = "Reserved storage for system";
type = lib.types.str;
};

pid = lib.mkOption {
default = 100;
description = "Reserved number of process IDs for system";
type = lib.types.int;
};
};
};
};
};

network = {
hostId = lib.mkOption {
default = "9f86d081";
Expand Down
1 change: 1 addition & 0 deletions src/hosts/xenon/modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
./hardware
./home
./install
./kubernetes
./locales
./misc
./motd
Expand Down
195 changes: 195 additions & 0 deletions src/hosts/xenon/modules/kubernetes/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# Kubernetes
{
config,
lib,
pkgs,
...
}: let
kubeletConfig = pkgs.writeTextFile {
name = "kubelet.yaml";
text = ''
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
systemReserved:
# Reserved CPU for system
cpu: '${config.constants.kubernetes.resources.reserved.system.cpu}'
# Reserved memory for system
memory: '${config.constants.kubernetes.resources.reserved.system.memory}'
# Reserved storage for system
ephemeral-storage: '${config.constants.kubernetes.resources.reserved.system.storage}'
# Reserved number of process IDs for system
pid: '${toString config.constants.kubernetes.resources.reserved.system.pid}'
'';
};
in {
boot = {
kernelModules = [
# Enable kernel module for WireGuard
"wireguard"
];
};

environment = {
persistence = {
"/hardstate" = {
directories = [
# Kubernetes state
config.constants.kubernetes.directories.state
];
};
};

systemPackages = [
# Install flux CLI
pkgs.fluxcd

# Install kubectl
pkgs.kubectl
];
};

networking = {
firewall = {
allowedTCPPorts = [
# Allow Kubernetes API server
config.constants.kubernetes.network.ports.api
];

allowedUDPPorts = [
# Allow WireGuard (IPv4)
51820

# Allow WireGuard (IPv6)
51821
];
};
};

services = {
k3s = {
# Enable k3s
enable = true;

extraFlags = lib.strings.concatStringsSep " " [
# Specify IP address allocation range for pods
"--cluster-cidr ${config.constants.kubernetes.network.addresses.cluster}"

# Specify directory for storing state
"--data-dir ${config.constants.kubernetes.directories.state}"

# Disable local storage
"--disable local-storage"

# Disable metrics server
"--disable metrics-server"

# Disable ServiceLB
"--disable servicelb"

# Disable Traefik
"--disable traefik"

# Disable cloud controller manager
"--disable-cloud-controller"

# Disable Helm controller
"--disable-helm-controller"

# Disable network policy
"--disable-network-policy"

# Use WireGuard for Container Network Interface
"--flannel-backend wireguard-native"

# Specify port for the API server
"--https-listen-port ${toString config.constants.kubernetes.network.ports.api}"

# Pass configuration to kubelet
"--kubelet-arg '--config=${kubeletConfig}'"

# Enable secret encryption
"--secrets-encryption"

# Specify IP address allocation range for services
"--service-cidr ${config.constants.kubernetes.network.addresses.service}"

# Add hostname to the list of SANs in the TLS certificate
"--tls-san ${config.networking.hostName}"

# Create kubeconfig file for local access
"--write-kubeconfig ${config.constants.kubernetes.files.kubeconfig}"
];

# Use xenon as the k3s server
role = "server";

# Shared secret used by all nodes to join the cluster
tokenFile = config.sops.secrets."k3s/token".path;
};
};

systemd = {
services = {
flux = {
after = [
# Run after network is online
"network-online.target"

# Run after k3s is running
"k3s.service"
];

description = "Setup Flux";

requires = [
# Require network to be online
"network-online.target"

# Require k3s to be running
"k3s.service"
];

serviceConfig = {
# Run only once at startup
Type = "oneshot";
};

script = builtins.readFile (
pkgs.substituteAll {
src = ./flux.sh;

flux = "${pkgs.fluxcd}/bin/flux";
kubeconfig = config.constants.kubernetes.files.kubeconfig;
kubectl = "${pkgs.k3s}/bin/kubectl";
printf = "${pkgs.coreutils}/bin/printf";
seq = "${pkgs.coreutils}/bin/seq";
sleep = "${pkgs.coreutils}/bin/sleep";
sourceBranch = config.constants.kubernetes.flux.source.branch;
sourcePath = config.constants.kubernetes.flux.source.path;
sourceUrl = config.constants.kubernetes.flux.source.url;
}
);

wantedBy = [
# Run at startup
"multi-user.target"
];
};

k3s = {
after = [
# Run after connecting to Tailscale
"tailscale-up.service"
];

requires = [
# Require Tailscale connection
"tailscale-up.service"
];
};
};
};
}
Loading

0 comments on commit 0112e8a

Please sign in to comment.