From d9ffd1b44676b4ac59bc7ddfb0f419da8913090596a22e6961fac44ba40160dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Mon, 30 Mar 2026 19:33:44 +0800 Subject: [PATCH] Update ctl init to support env file --- alpine/configure-system.sh | 1 + .../rootfs-extra/etc/init.d/apply-node-config | 23 - .../rootfs-extra/etc/init.d/bootstrap-cluster | 19 +- .../opt/scripts/apply-node-config.sh | 201 ----- .../opt/scripts/bootstrap-cluster.sh | 820 ------------------ clitools/pkg/cmd/initcmd/init.go | 129 ++- clitools/pkg/render/monoks.go | 16 +- clitools/pkg/templates/templates.go | 133 +-- clitools/pkg/templates/values.go | 204 +++++ configs/cluster.env.default | 68 +- configs/node.env.default | 14 - makefile | 13 +- 12 files changed, 450 insertions(+), 1191 deletions(-) delete mode 100755 alpine/rootfs-extra/etc/init.d/apply-node-config delete mode 100755 alpine/rootfs-extra/opt/scripts/apply-node-config.sh delete mode 100755 alpine/rootfs-extra/opt/scripts/bootstrap-cluster.sh create mode 100644 clitools/pkg/templates/values.go delete mode 100644 configs/node.env.default diff --git a/alpine/configure-system.sh b/alpine/configure-system.sh index 9d931d1..77c1354 100755 --- a/alpine/configure-system.sh +++ b/alpine/configure-system.sh @@ -11,3 +11,4 @@ rc-update add fancontrol boot rc-update add loopback boot rc-update add hostname boot rc-update add localmount boot +rc-update add bootstrap-cluster default diff --git a/alpine/rootfs-extra/etc/init.d/apply-node-config b/alpine/rootfs-extra/etc/init.d/apply-node-config deleted file mode 100755 index ccded75..0000000 --- a/alpine/rootfs-extra/etc/init.d/apply-node-config +++ /dev/null @@ -1,23 +0,0 @@ -#!/sbin/openrc-run - -export PATH="/usr/local/bin:/usr/local/sbin:$PATH" - -name="Apply node config" -description="Apply node configurations using node.env from /opt/monok8s/config" - -command="/opt/scripts/apply-node-config.sh" - -LOG_DIR="/var/log/monok8s" -LOG_FILE="$LOG_DIR/apply-node-config.log" - -depend() { - need localmount -} - -start() { - checkpath --directory "$LOG_DIR" - - ebegin "Applying node config" - "$command" >>"$LOG_FILE" 2>&1 - eend $? -} diff --git a/alpine/rootfs-extra/etc/init.d/bootstrap-cluster b/alpine/rootfs-extra/etc/init.d/bootstrap-cluster index d3de5b7..e010305 100755 --- a/alpine/rootfs-extra/etc/init.d/bootstrap-cluster +++ b/alpine/rootfs-extra/etc/init.d/bootstrap-cluster @@ -2,23 +2,24 @@ export PATH="/usr/local/bin:/usr/local/sbin:$PATH" -name="Bootstrap cluster" -description="Apply cluster configurations using node.env from /opt/monok8s/config" +name="Bootstrap the Cluster" +description="Runs the ctl init bootstrap sequence" -command="/opt/scripts/bootstrap-cluster.sh" +command="/usr/local/bin/ctl" +command_args="init --env-file /opt/monok8s/config/cluster.env" LOG_DIR="/var/log/monok8s" -LOG_FILE="$LOG_DIR/bootstrap.log" +LOG_FILE="$LOG_DIR/bootstrap-cluster.log" depend() { - need apply-node-config - use net + need localmount } start() { checkpath --directory "$LOG_DIR" - - ebegin "Applying cluster config" - "$command" >>"$LOG_FILE" 2>&1 & + ebegin "Starting the bootstrap sequence" + start-stop-daemon --start \ + --exec "$command" \ + -- $command_args >>"$LOG_FILE" 2>&1 eend $? } diff --git a/alpine/rootfs-extra/opt/scripts/apply-node-config.sh b/alpine/rootfs-extra/opt/scripts/apply-node-config.sh deleted file mode 100755 index 6de0254..0000000 --- a/alpine/rootfs-extra/opt/scripts/apply-node-config.sh +++ /dev/null @@ -1,201 +0,0 @@ -#!/bin/bash -set -euo pipefail - -CONFIG_DIR="${CONFIG_DIR:-/opt/monok8s/config}" -NODE_ENV="${NODE_ENV:-$CONFIG_DIR/node.env}" - -log() { - echo "[monok8s-node] $*" -} - -fail() { - echo "[monok8s-node] ERROR: $*" >&2 - exit 1 -} - -need_cmd() { - command -v "$1" >/dev/null 2>&1 || fail "missing required command: $1" -} - -require_file() { - [ -f "$1" ] || fail "required file not found: $1" -} - -load_config() { - require_file "$NODE_ENV" - - # shellcheck disable=SC1090 - . "$NODE_ENV" - - HOSTNAME="${HOSTNAME:-}" - MGMT_IFACE="${MGMT_IFACE:-}" - MGMT_ADDRESS="${MGMT_ADDRESS:-}" - MGMT_GATEWAY="${MGMT_GATEWAY:-}" - DNS_NAMESERVERS="${DNS_NAMESERVERS:-}" - DNS_SEARCH_DOMAINS="${DNS_SEARCH_DOMAINS:-}" -} - -validate_config() { - [ -n "$HOSTNAME" ] || fail "HOSTNAME is required" - [ -n "$MGMT_IFACE" ] || fail "MGMT_IFACE is required" - [ -n "$MGMT_ADDRESS" ] || fail "MGMT_ADDRESS is required" - - case "$MGMT_ADDRESS" in - */*) - ;; - *) - fail "MGMT_ADDRESS must include a CIDR prefix, example: 10.0.0.13/24" - ;; - esac - - if [ -n "$DNS_NAMESERVERS" ]; then - for ns in $DNS_NAMESERVERS; do - case "$ns" in - 10.96.0.10) - fail "DNS_NAMESERVERS must not contain cluster DNS service IP (10.96.0.10)" - ;; - esac - done - fi -} - -check_prereqs() { - # only the special one, coreutils should not be checked - need_cmd ip - need_cmd hostname - need_cmd grep -} - -configure_mgmt_interface() { - local addr_ip - - ip link show "$MGMT_IFACE" >/dev/null 2>&1 || fail "interface not found: $MGMT_IFACE" - - log "bringing up interface: $MGMT_IFACE" - ip link set "$MGMT_IFACE" up - - addr_ip="${MGMT_ADDRESS%/*}" - - if ip -o addr show dev "$MGMT_IFACE" | awk '{print $4}' | cut -d/ -f1 | grep -Fx "$addr_ip" >/dev/null 2>&1; then - log "address already present on $MGMT_IFACE: $MGMT_ADDRESS" - else - log "assigning $MGMT_ADDRESS to $MGMT_IFACE" - ip addr add "$MGMT_ADDRESS" dev "$MGMT_IFACE" - fi - - if [ -n "${MGMT_GATEWAY:-}" ]; then - log "ensuring default route via $MGMT_GATEWAY" - ip route replace default via "$MGMT_GATEWAY" dev "$MGMT_IFACE" - fi -} - -set_hostname_if_needed() { - local current_hostname - - current_hostname="$(hostname 2>/dev/null || true)" - - if [ "$current_hostname" != "$HOSTNAME" ]; then - log "setting hostname to $HOSTNAME" - - hostname "$HOSTNAME" - - mkdir -p /etc - printf '%s\n' "$HOSTNAME" > /etc/hostname - - if [ -f /etc/hosts ]; then - if ! grep -Eq "[[:space:]]$HOSTNAME([[:space:]]|$)" /etc/hosts; then - printf '127.0.0.1\tlocalhost %s\n' "$HOSTNAME" >> /etc/hosts - fi - else - cat > /etc/hosts < /proc/sys/net/ipv4/ip_forward - fi - - mkdir -p /etc/sysctl.d - cat > /etc/sysctl.d/99-monok8s.conf <<'EOF' -net.ipv4.ip_forward = 1 -EOF -} - -configure_dns() { - local tmpfile - local ns_count=0 - - if [ -z "$DNS_NAMESERVERS" ]; then - log "DNS_NAMESERVERS not set; leaving /etc/resolv.conf unchanged" - return - fi - - mkdir -p /etc - tmpfile="/etc/resolv.conf.monok8s.tmp" - : > "$tmpfile" - - if [ -n "$DNS_SEARCH_DOMAINS" ]; then - printf 'search %s\n' "$DNS_SEARCH_DOMAINS" >> "$tmpfile" - fi - - for ns in $DNS_NAMESERVERS; do - printf 'nameserver %s\n' "$ns" >> "$tmpfile" - ns_count=$((ns_count + 1)) - done - - [ "$ns_count" -gt 0 ] || fail "DNS_NAMESERVERS is set but no valid nameservers were parsed" - - printf 'options timeout:2 attempts:3\n' >> "$tmpfile" - - mv "$tmpfile" /etc/resolv.conf - log "configured /etc/resolv.conf from DNS_NAMESERVERS" -} - -print_summary() { - log "node configuration applied" - log "hostname: $HOSTNAME" - log "interface: $MGMT_IFACE" - log "address: $MGMT_ADDRESS" - - if [ -n "${MGMT_GATEWAY:-}" ]; then - log "gateway: $MGMT_GATEWAY" - else - log "gateway: " - fi - - if [ -n "${DNS_NAMESERVERS:-}" ]; then - log "dns nameservers: $DNS_NAMESERVERS" - else - log "dns nameservers: " - fi - - if [ -n "${DNS_SEARCH_DOMAINS:-}" ]; then - log "dns search: $DNS_SEARCH_DOMAINS" - else - log "dns search: " - fi -} - -main() { - load_config - validate_config - check_prereqs - - ensure_ip_forward - configure_mgmt_interface - configure_dns - set_hostname_if_needed - print_summary -} - -main "$@" diff --git a/alpine/rootfs-extra/opt/scripts/bootstrap-cluster.sh b/alpine/rootfs-extra/opt/scripts/bootstrap-cluster.sh deleted file mode 100755 index 4477731..0000000 --- a/alpine/rootfs-extra/opt/scripts/bootstrap-cluster.sh +++ /dev/null @@ -1,820 +0,0 @@ -#!/bin/sh -set -eu - -CONFIG_DIR="${CONFIG_DIR:-/opt/monok8s/config}" -CLUSTER_ENV="${CONFIG_DIR}/cluster.env" -KUBEADM_CONFIG_OUT="${KUBEADM_CONFIG_OUT:-/tmp/kubeadm-init.yaml}" -ADMIN_KUBECONFIG="/etc/kubernetes/admin.conf" -KUBELET_KUBECONFIG="/etc/kubernetes/kubelet.conf" - -log() { - echo "[monok8s] $*" -} - -fail() { - echo "[monok8s] ERROR: $*" >&2 - exit 1 -} - -need_cmd() { - command -v "$1" >/dev/null 2>&1 || fail "missing required command: $1" -} - -require_file() { - [ -f "$1" ] || fail "required file not found: $1" -} - -load_config() { - require_file "$CLUSTER_ENV" - - # shellcheck disable=SC1090 - . "$CLUSTER_ENV" - - : "${KUBERNETES_VERSION:?KUBERNETES_VERSION is required}" - : "${NODE_NAME:?NODE_NAME is required}" - : "${APISERVER_ADVERTISE_ADDRESS:?APISERVER_ADVERTISE_ADDRESS is required}" - - POD_SUBNET="${POD_SUBNET:-10.244.0.0/16}" - SERVICE_SUBNET="${SERVICE_SUBNET:-10.96.0.0/12}" - CLUSTER_NAME="${CLUSTER_NAME:-monok8s}" - CLUSTER_DOMAIN="${CLUSTER_DOMAIN:-cluster.local}" - CONTAINER_RUNTIME_ENDPOINT="${CONTAINER_RUNTIME_ENDPOINT:-unix:///var/run/crio/crio.sock}" - SANS="${SANS:-}" - ALLOW_SCHEDULING_ON_CONTROL_PLANE="${ALLOW_SCHEDULING_ON_CONTROL_PLANE:-yes}" - SKIP_IMAGE_CHECK="${SKIP_IMAGE_CHECK:-no}" - KUBE_PROXY_NODEPORT_ADDRESSES="${KUBE_PROXY_NODEPORT_ADDRESSES:-primary}" - - BOOTSTRAP_MODE="${BOOTSTRAP_MODE:-init}" - JOIN_KIND="${JOIN_KIND:-worker}" - API_SERVER_ENDPOINT="${API_SERVER_ENDPOINT:-}" - BOOTSTRAP_TOKEN="${BOOTSTRAP_TOKEN:-}" - DISCOVERY_TOKEN_CA_CERT_HASH="${DISCOVERY_TOKEN_CA_CERT_HASH:-}" - CONTROL_PLANE_CERT_KEY="${CONTROL_PLANE_CERT_KEY:-}" - CNI_PLUGIN="${CNI_PLUGIN:-none}" -} - -kubectl_admin() { - kubectl --kubeconfig "$ADMIN_KUBECONFIG" "$@" -} - -kubectl_kubelet() { - kubectl --kubeconfig "$KUBELET_KUBECONFIG" "$@" -} - -start_kubelet() { - log "starting kubelet..." - rc-service kubelet start >/dev/null 2>&1 || true -} - -restart_kubelet() { - log "restarting kubelet..." - rc-service kubelet restart -} - -check_kubelet_running() { - log "waiting for kubelet to become ready..." - - last_status="unknown" - - for _ in $(seq 1 30); do - if rc-service kubelet status >/dev/null 2>&1; then - log "kubelet is up" - return 0 - fi - last_status="service-not-running" - sleep 1 - done - - fail "kubelet did not become ready in time (${last_status})" -} - -is_local_control_plane_node() { - [ -f /etc/kubernetes/manifests/kube-apiserver.yaml ] -} - -wait_for_local_apiserver() { - need_cmd nc - - log "waiting for local API server on ${APISERVER_ADVERTISE_ADDRESS}:6443..." - - for _ in $(seq 1 90); do - if nc -z "${APISERVER_ADVERTISE_ADDRESS}" 6443 >/dev/null 2>&1; then - log "local API server TCP port is reachable" - return 0 - fi - sleep 2 - done - - fail "local API server did not become reachable on ${APISERVER_ADVERTISE_ADDRESS}:6443" -} - -wait_for_admin_api() { - [ -f "$ADMIN_KUBECONFIG" ] || fail "missing admin kubeconfig: $ADMIN_KUBECONFIG" - - log "waiting for Kubernetes API to respond via admin.conf..." - - for _ in $(seq 1 90); do - if kubectl_admin version -o yaml >/dev/null 2>&1; then - log "Kubernetes API is responding" - return 0 - fi - sleep 2 - done - - fail "Kubernetes API did not become ready in time" -} - -wait_for_existing_cluster_if_needed() { - case "$BOOTSTRAP_MODE" in - init) - if [ -f "$ADMIN_KUBECONFIG" ]; then - start_kubelet - check_kubelet_running - - if is_local_control_plane_node; then - wait_for_local_apiserver - fi - - wait_for_admin_api - fi - ;; - join) - if [ -f "$KUBELET_KUBECONFIG" ]; then - start_kubelet - check_kubelet_running - fi - ;; - esac -} - -get_cluster_server_version() { - kubectl_admin version -o yaml 2>/dev/null \ - | awk ' - $1 == "serverVersion:" { in_server=1; next } - in_server && $1 == "gitVersion:" { print $2; exit } - ' -} - -get_api_server_version_from_kubelet_kubeconfig() { - kubectl_kubelet version -o yaml 2>/dev/null \ - | awk ' - $1 == "serverVersion:" { in_server=1; next } - in_server && $1 == "gitVersion:" { print $2; exit } - ' -} - -validate_cidr_list_or_primary() { - value="$1" - - [ -n "$value" ] || return 0 - - if [ "$value" = "primary" ]; then - return 0 - fi - - old_ifs="$IFS" - IFS=',' - for item in $value; do - trimmed="$(printf '%s' "$item" | sed 's/^ *//;s/ *$//')" - [ -n "$trimmed" ] || fail "KUBE_PROXY_NODEPORT_ADDRESSES contains an empty entry" - - case "$trimmed" in - */*) - ;; - *) - fail "KUBE_PROXY_NODEPORT_ADDRESSES must be 'primary' or a comma-separated list of CIDRs" - ;; - esac - - ip_part="${trimmed%/*}" - prefix_part="${trimmed#*/}" - - printf '%s' "$prefix_part" | grep -Eq '^[0-9]+$' \ - || fail "invalid CIDR prefix in KUBE_PROXY_NODEPORT_ADDRESSES: $trimmed" - - case "$ip_part" in - *:*) - printf '%s' "$prefix_part" | awk '{ exit !($1 >= 0 && $1 <= 128) }' \ - || fail "invalid IPv6 CIDR prefix in KUBE_PROXY_NODEPORT_ADDRESSES: $trimmed" - ;; - *.*.*.*) - printf '%s' "$prefix_part" | awk '{ exit !($1 >= 0 && $1 <= 32) }' \ - || fail "invalid IPv4 CIDR prefix in KUBE_PROXY_NODEPORT_ADDRESSES: $trimmed" - ;; - *) - fail "invalid CIDR entry in KUBE_PROXY_NODEPORT_ADDRESSES: $trimmed" - ;; - esac - done - IFS="$old_ifs" -} - -validate_config() { - case "$BOOTSTRAP_MODE" in - init) - ;; - join) - : "${API_SERVER_ENDPOINT:?API_SERVER_ENDPOINT is required for join mode}" - : "${BOOTSTRAP_TOKEN:?BOOTSTRAP_TOKEN is required for join mode}" - : "${DISCOVERY_TOKEN_CA_CERT_HASH:?DISCOVERY_TOKEN_CA_CERT_HASH is required for join mode}" - - case "$JOIN_KIND" in - worker|control-plane) - ;; - *) - fail "JOIN_KIND must be 'worker' or 'control-plane'" - ;; - esac - - if [ "$JOIN_KIND" = "control-plane" ]; then - : "${CONTROL_PLANE_CERT_KEY:?CONTROL_PLANE_CERT_KEY is required for JOIN_KIND=control-plane}" - fi - ;; - *) - fail "BOOTSTRAP_MODE must be 'init' or 'join'" - ;; - esac - - validate_cidr_list_or_primary "$KUBE_PROXY_NODEPORT_ADDRESSES" -} - -normalize_version() { - # strip leading "v" - echo "${1#v}" -} - -version_major_minor() { - normalize_version "$1" | awk -F. '{ print $1 "." $2 }' -} - -version_eq() { - [ "$(normalize_version "$1")" = "$(normalize_version "$2")" ] -} - -version_lt() { - [ "$(printf '%s\n%s\n' "$(normalize_version "$1")" "$(normalize_version "$2")" | sort -V | head -n1)" != "$(normalize_version "$2")" ] -} - -version_gt() { - [ "$(printf '%s\n%s\n' "$(normalize_version "$1")" "$(normalize_version "$2")" | sort -V | tail -n1)" = "$(normalize_version "$1")" ] \ - && ! version_eq "$1" "$2" -} - -minor_diff() { - a="$(version_major_minor "$1")" - b="$(version_major_minor "$2")" - a_major="${a%.*}" - a_minor="${a#*.}" - b_major="${b%.*}" - b_minor="${b#*.}" - - [ "$a_major" = "$b_major" ] || fail "major version change unsupported here: $1 -> $2" - echo $((b_minor - a_minor)) -} - -get_kubeadm_binary_version() { - kubeadm version -o short -} - -get_cluster_server_version() { - kubectl --kubeconfig /etc/kubernetes/admin.conf version -o yaml \ - | awk ' - $1 == "serverVersion:" { in_server=1; next } - in_server && $1 == "gitVersion:" { print $2; exit } - ' -} - -get_api_server_version_from_kubelet_kubeconfig() { - kubectl --kubeconfig /etc/kubernetes/kubelet.conf version -o yaml \ - | awk ' - $1 == "serverVersion:" { in_server=1; next } - in_server && $1 == "gitVersion:" { print $2; exit } - ' -} - -validate_target_matches_local_binaries() { - kubeadm_ver="$(get_kubeadm_binary_version)" - - if ! version_eq "$kubeadm_ver" "$KUBERNETES_VERSION"; then - fail "kubeadm binary version ($kubeadm_ver) does not match target KUBERNETES_VERSION ($KUBERNETES_VERSION)" - fi -} - -decide_bootstrap_action() { - current_version="" - - case "$BOOTSTRAP_MODE" in - init) - if [ ! -f "$ADMIN_KUBECONFIG" ]; then - BOOTSTRAP_ACTION="init" - log "selected bootstrap action: $BOOTSTRAP_ACTION" - return 0 - fi - - current_version="$(get_cluster_server_version || true)" - [ -n "$current_version" ] || fail "existing control-plane config found, but cluster version could not be determined" - - log "detected existing control-plane version: $current_version" - - if version_eq "$current_version" "$KUBERNETES_VERSION"; then - BOOTSTRAP_ACTION="reconcile-control-plane" - else - BOOTSTRAP_ACTION="upgrade-control-plane" - fi - ;; - join) - if [ ! -f "$KUBELET_KUBECONFIG" ]; then - BOOTSTRAP_ACTION="join" - log "selected bootstrap action: $BOOTSTRAP_ACTION" - return 0 - fi - - current_version="$(get_api_server_version_from_kubelet_kubeconfig || true)" - [ -n "$current_version" ] || fail "existing kubelet config found, but cluster version could not be determined" - - log "detected cluster version visible from this node: $current_version" - - if version_eq "$current_version" "$KUBERNETES_VERSION"; then - BOOTSTRAP_ACTION="reconcile-node" - else - BOOTSTRAP_ACTION="upgrade-node" - fi - ;; - *) - fail "unsupported BOOTSTRAP_MODE: $BOOTSTRAP_MODE" - ;; - esac - - log "selected bootstrap action: $BOOTSTRAP_ACTION" -} - -reconcile_control_plane() { - log "reconciling existing control-plane node" - - start_kubelet - check_kubelet_running - wait_for_local_apiserver - wait_for_admin_api - - apply_local_node_metadata_if_possible - allow_single_node_scheduling -} - -reconcile_node() { - log "reconciling existing joined node" - - start_kubelet - check_kubelet_running -} - -validate_upgrade_path() { - current="$1" - target="$2" - - if version_eq "$current" "$target"; then - log "cluster is already at target version: $target" - return 0 - fi - - if version_gt "$current" "$target"; then - fail "downgrade is not supported: current=$current target=$target" - fi - - diff="$(minor_diff "$current" "$target")" - case "$diff" in - 0|1) - ;; - *) - fail "unsupported upgrade path: current=$current target=$target (minor skip too large)" - ;; - esac -} - -check_upgrade_prereqs() { - validate_target_matches_local_binaries -} - -run_kubeadm_upgrade_apply() { - current_version="$(get_cluster_server_version || true)" - [ -n "$current_version" ] || fail "cannot determine current control-plane version; API server is not reachable" - - log "current control-plane version: $current_version" - log "target control-plane version: $KUBERNETES_VERSION" - - validate_upgrade_path "$current_version" "$KUBERNETES_VERSION" - - if version_eq "$current_version" "$KUBERNETES_VERSION"; then - log "control-plane already at target version; skipping kubeadm upgrade apply" - return 0 - fi - - log "running kubeadm upgrade plan..." - kubeadm upgrade plan "$KUBERNETES_VERSION" - - log "running kubeadm upgrade apply..." - kubeadm upgrade apply -y "$KUBERNETES_VERSION" -} - -run_kubeadm_upgrade_node() { - cluster_version="$(get_api_server_version_from_kubelet_kubeconfig)" - log "cluster/control-plane version visible from this node: $cluster_version" - log "target node version: $KUBERNETES_VERSION" - - if ! version_eq "$cluster_version" "$KUBERNETES_VERSION"; then - fail "control-plane version ($cluster_version) does not match target ($KUBERNETES_VERSION); upgrade control-plane first" - fi - - log "running kubeadm upgrade node..." - kubeadm upgrade node -} - -check_prereqs() { - need_cmd kubeadm - need_cmd kubelet - need_cmd kubectl - need_cmd crictl - need_cmd rc-service - need_cmd awk - need_cmd ip - need_cmd grep - need_cmd sed - need_cmd hostname -} - -check_apiserver_reachable() { - host="${API_SERVER_ENDPOINT%:*}" - port="${API_SERVER_ENDPOINT##*:}" - - need_cmd nc - - log "checking API server reachability: ${host}:${port}" - - for _ in $(seq 1 20); do - if nc -z "$host" "$port" >/dev/null 2>&1; then - log "API server is reachable" - return 0 - fi - sleep 1 - done - - fail "cannot reach API server at ${host}:${port}" -} - -start_crio() { - rc-service crio start -} - -check_crio_running() { - log "waiting for CRI-O to become ready..." - - last_status="unknown" - - for _ in $(seq 1 30); do - if rc-service crio status >/dev/null 2>&1; then - last_status="service-running" - if crictl --runtime-endpoint "$CONTAINER_RUNTIME_ENDPOINT" info >/dev/null 2>&1; then - log "CRI-O is up" - return 0 - fi - last_status="service-running-but-runtime-not-ready" - else - last_status="service-not-running" - fi - sleep 1 - done - - fail "CRI-O did not become ready in time (${last_status})" -} - -image_present() { - wanted="$1" - - repo="${wanted%:*}" - tag="${wanted##*:}" - - crictl --runtime-endpoint "$CONTAINER_RUNTIME_ENDPOINT" images \ - | awk 'NR>1 { print $1 ":" $2 }' \ - | grep -Fx "$repo:$tag" >/dev/null 2>&1 -} - -check_required_images() { - [ "$SKIP_IMAGE_CHECK" = "yes" ] && { - log "skipping image check (SKIP_IMAGE_CHECK=yes)" - return 0 - } - - log "checking required Kubernetes images for $KUBERNETES_VERSION..." - - missing_any=0 - - for img in $(kubeadm config images list --kubernetes-version "$KUBERNETES_VERSION"); do - if image_present "$img"; then - log "found image: $img" - else - echo "[monok8s] MISSING image: $img" >&2 - missing_any=1 - fi - done - - [ "$missing_any" -eq 0 ] || fail "preload the Kubernetes images before bootstrapping" - - log "all required images are present" -} - -check_not_already_bootstrapped() { - case "$BOOTSTRAP_MODE" in - init) - if [ -f /etc/kubernetes/admin.conf ]; then - fail "cluster already appears initialized (/etc/kubernetes/admin.conf exists)" - fi - ;; - join) - if [ -f /etc/kubernetes/kubelet.conf ]; then - fail "node already appears joined (/etc/kubernetes/kubelet.conf exists)" - fi - ;; - esac -} - -run_kubeadm_join() { - log "running kubeadm join..." - - case "$JOIN_KIND" in - worker) - kubeadm join "${API_SERVER_ENDPOINT}" \ - --token "${BOOTSTRAP_TOKEN}" \ - --discovery-token-ca-cert-hash "${DISCOVERY_TOKEN_CA_CERT_HASH}" \ - --node-name "${NODE_NAME}" \ - --cri-socket "${CONTAINER_RUNTIME_ENDPOINT}" - ;; - control-plane) - kubeadm join "${API_SERVER_ENDPOINT}" \ - --token "${BOOTSTRAP_TOKEN}" \ - --discovery-token-ca-cert-hash "${DISCOVERY_TOKEN_CA_CERT_HASH}" \ - --control-plane \ - --certificate-key "${CONTROL_PLANE_CERT_KEY}" \ - --apiserver-advertise-address "${APISERVER_ADVERTISE_ADDRESS}" \ - --node-name "${NODE_NAME}" \ - --cri-socket "${CONTAINER_RUNTIME_ENDPOINT}" - ;; - esac -} - -generate_kube_proxy_config_block() { - if [ -z "${KUBE_PROXY_NODEPORT_ADDRESSES:-}" ]; then - return 0 - fi - - if [ "$KUBE_PROXY_NODEPORT_ADDRESSES" = "primary" ]; then - cat < "$KUBEADM_CONFIG_OUT" <> "$KUBEADM_CONFIG_OUT" -} - -run_kubeadm_init() { - log "running kubeadm init..." - kubeadm init --config "$KUBEADM_CONFIG_OUT" -} - -require_local_ip() { - wanted_ip="$1" - - ip -o addr show | awk '{print $4}' | cut -d/ -f1 | grep -Fx "$wanted_ip" >/dev/null 2>&1 \ - || fail "required local IP is not present on any interface: $wanted_ip" -} - -validate_network_requirements() { - case "$BOOTSTRAP_MODE" in - init) - require_local_ip "$APISERVER_ADVERTISE_ADDRESS" - ;; - join) - require_local_ip "$APISERVER_ADVERTISE_ADDRESS" - check_apiserver_reachable - ;; - *) - fail "unsupported BOOTSTRAP_MODE: $BOOTSTRAP_MODE" - ;; - esac -} - -wait_for_node() { - log "waiting for node registration: $NODE_NAME" - - for _ in $(seq 1 60); do - if kubectl --kubeconfig /etc/kubernetes/admin.conf get node "$NODE_NAME" >/dev/null 2>&1; then - return 0 - fi - sleep 1 - done - - fail "node $NODE_NAME did not register in time" -} - -apply_local_node_metadata_if_possible() { - if [ "$BOOTSTRAP_MODE" != "init" ]; then - log "skipping node labels/annotations from this node (not control-plane init mode)" - return 0 - fi - - wait_for_node - - if [ -n "${NODE_ANNOTATIONS:-}" ]; then - kubectl --kubeconfig /etc/kubernetes/admin.conf annotate node "$NODE_NAME" $(printf '%s' "$NODE_ANNOTATIONS" | tr ',' ' ') --overwrite - fi - if [ -n "${NODE_LABELS:-}" ]; then - kubectl --kubeconfig /etc/kubernetes/admin.conf label node "$NODE_NAME" $(printf '%s' "$NODE_LABELS" | tr ',' ' ') --overwrite - fi -} - -install_cni_if_requested() { - case "${CNI_PLUGIN}" in - none) - if [ -f /etc/cni/net.d/10-crio-bridge.conflist ]; then - mv /etc/cni/net.d/10-crio-bridge.conflist \ - /etc/cni/net.d/10-crio-bridge.conflist.disabled - fi - log "bootstrap bridge CNI disabled; install a cluster CNI (e.g., flannel) for pod networking" - ;; - bridge) - if [ -f /etc/cni/net.d/10-crio-bridge.conflist.disabled ]; then - mv /etc/cni/net.d/10-crio-bridge.conflist.disabled \ - /etc/cni/net.d/10-crio-bridge.conflist - fi - log "bootstrap bridge CNI enabled" - ;; - *) - fail "unsupported CNI_PLUGIN: ${CNI_PLUGIN}" - ;; - esac -} - -allow_single_node_scheduling() { - if [ "$ALLOW_SCHEDULING_ON_CONTROL_PLANE" != "yes" ]; then - log "leaving control-plane taint in place" - return 0 - fi - - log "removing control-plane taint so this single node can schedule workloads..." - kubectl --kubeconfig /etc/kubernetes/admin.conf taint nodes "$NODE_NAME" node-role.kubernetes.io/control-plane- >/dev/null 2>&1 || true -} - -print_next_steps() { - echo - echo "[monok8s] bootstrap complete" - echo - - case "$BOOTSTRAP_MODE" in - init) - cat <} -EOF - ;; - join) - cat <= 2 { + if (val[0] == '"' && val[len(val)-1] == '"') || (val[0] == '\'' && val[len(val)-1] == '\'') { + val = val[1 : len(val)-1] + } + } + + if err := os.Setenv(key, val); err != nil { + return fmt.Errorf("line %d: set %q: %w", lineNum, key, err) + } + } + + if err := scanner.Err(); err != nil { + return err + } + + return nil +} + func parseStepSelection(raw string, max int) (bootstrap.StepSelection, error) { raw = strings.TrimSpace(raw) if raw == "" { diff --git a/clitools/pkg/render/monoks.go b/clitools/pkg/render/monoks.go index c4f7645..845f5b2 100644 --- a/clitools/pkg/render/monoks.go +++ b/clitools/pkg/render/monoks.go @@ -7,11 +7,12 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer/json" "undecided.project/monok8s/pkg/scheme" - tmpl "undecided.project/monok8s/pkg/templates" + "undecided.project/monok8s/pkg/templates" ) func RenderMonoKSConfig() (string, error) { - cfg := tmpl.DefaultMonoKSConfig() + vals := templates.LoadTemplateValuesFromEnv() + cfg := templates.DefaultMonoKSConfig(vals) s := runtime.NewScheme() if err := scheme.AddToScheme(s); err != nil { @@ -19,9 +20,7 @@ func RenderMonoKSConfig() (string, error) { } serializer := json.NewYAMLSerializer( - json.DefaultMetaFactory, - s, - s, + json.DefaultMetaFactory, s, s, ) var buf bytes.Buffer @@ -33,7 +32,8 @@ func RenderMonoKSConfig() (string, error) { } func RenderOSUpgrade() (string, error) { - cfg := tmpl.DefaultOSUpgrade() + vals := templates.LoadTemplateValuesFromEnv() + cfg := templates.DefaultOSUpgrade(vals) s := runtime.NewScheme() if err := scheme.AddToScheme(s); err != nil { @@ -41,9 +41,7 @@ func RenderOSUpgrade() (string, error) { } serializer := json.NewYAMLSerializer( - json.DefaultMetaFactory, - s, - s, + json.DefaultMetaFactory, s, s, ) var buf bytes.Buffer diff --git a/clitools/pkg/templates/templates.go b/clitools/pkg/templates/templates.go index 7598a09..48e8514 100644 --- a/clitools/pkg/templates/templates.go +++ b/clitools/pkg/templates/templates.go @@ -1,26 +1,13 @@ package templates import ( - "os" + "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "undecided.project/monok8s/pkg/apis/monok8s/v1alpha1" - buildinfo "undecided.project/monok8s/pkg/buildinfo" ) -var ValAPIServerEndPoint string = "10.0.0.10:6443" -var ValHostname string = "monoks-master-1" -var ValBootstrapToken string = "abcd12.ef3456789abcdef0" -var ValDiscoveryTokenCACertHash string = "sha256:9f1c2b3a4d5e6f7890abc1234567890abcdef1234567890abcdef1234567890ab" - -func init() { - ValBootstrapToken = os.Getenv("HOSTNAME") - ValBootstrapToken = os.Getenv("BOOTSTRAP_TOKEN") - ValDiscoveryTokenCACertHash = os.Getenv("TOKEN_CACERT_HASH") - ValAPIServerEndPoint = os.Getenv("API_SERVER_ENDPOINT") -} - -func DefaultMonoKSConfig() types.MonoKSConfig { +func DefaultMonoKSConfig(v TemplateValues) types.MonoKSConfig { return types.MonoKSConfig{ TypeMeta: metav1.TypeMeta{ APIVersion: "monok8s.io/v1alpha1", @@ -31,66 +18,51 @@ func DefaultMonoKSConfig() types.MonoKSConfig { Namespace: "kube-system", }, Spec: types.MonoKSConfigSpec{ - KubernetesVersion: buildinfo.Version, - NodeName: ValHostname, + KubernetesVersion: v.KubernetesVersion, + NodeName: firstNonEmpty(v.NodeName, v.Hostname), - ClusterRole: "control-plane", - InitControlPlane: true, + ClusterRole: clusterRoleFromTemplateValues(v), + InitControlPlane: initControlPlaneFromTemplateValues(v), - ClusterName: "monok8s", - ClusterDomain: "cluster.local", + ClusterName: v.ClusterName, + ClusterDomain: v.ClusterDomain, - PodSubnet: "10.244.0.0/16", - ServiceSubnet: "10.96.0.0/12", + PodSubnet: v.PodSubnet, + ServiceSubnet: v.ServiceSubnet, - APIServerAdvertiseAddress: "10.0.0.10", - APIServerEndpoint: ValAPIServerEndPoint, + APIServerAdvertiseAddress: v.APIServerAdvertiseAddress, + APIServerEndpoint: v.APIServerEndpoint, - // Fake token and hash for placeholder purpose - BootstrapToken: ValBootstrapToken, - DiscoveryTokenCACertHash: ValDiscoveryTokenCACertHash, + BootstrapToken: v.BootstrapToken, + DiscoveryTokenCACertHash: v.DiscoveryTokenCACertHash, - ContainerRuntimeEndpoint: "unix:///var/run/crio/crio.sock", + ContainerRuntimeEndpoint: v.ContainerRuntimeEndpoint, + CNIPlugin: v.CNIPlugin, - CNIPlugin: "default", - - AllowSchedulingOnControlPlane: true, - SkipImageCheck: false, + AllowSchedulingOnControlPlane: v.AllowSchedulingOnControlPlane, + SkipImageCheck: v.SkipImageCheck, KubeProxyNodePortAddresses: []string{ "primary", }, - SubjectAltNames: []string{ - "10.0.0.10", "localhost", ValHostname, - }, - - NodeLabels: map[string]string{ - "monok8s.io/label": "value", - }, - - NodeAnnotations: map[string]string{ - "monok8s.io/annotation": "value", - }, + SubjectAltNames: copyStringSlice(v.SubjectAltNames), + NodeLabels: copyStringMap(v.NodeLabels), + NodeAnnotations: copyStringMap(v.NodeAnnotations), Network: types.NetworkSpec{ - Hostname: "monok8s-worker-1", - ManagementIface: "eth1", - ManagementCIDR: "10.0.0.10/24", - ManagementGW: "10.0.0.1", - DNSNameservers: []string{ - "1.1.1.1", - "8.8.8.8", - }, - DNSSearchDomains: []string{ - "lan", - }, + Hostname: firstNonEmpty(v.Hostname, v.NodeName), + ManagementIface: v.MgmtIface, + ManagementCIDR: v.MgmtAddress, + ManagementGW: v.MgmtGateway, + DNSNameservers: copyStringSlice(v.DNSNameservers), + DNSSearchDomains: copyStringSlice(v.DNSSearchDomains), }, }, } } -func DefaultOSUpgrade() types.OSUpgrade { +func DefaultOSUpgrade(v TemplateValues) types.OSUpgrade { return types.OSUpgrade{ TypeMeta: metav1.TypeMeta{ APIVersion: "monok8s.io/v1alpha1", @@ -105,9 +77,56 @@ func DefaultOSUpgrade() types.OSUpgrade { ImageURL: "https://example.invalid/images/monok8s-v0.0.1.img.zst", TargetPartition: "B", NodeSelector: []string{ - ValHostname, + firstNonEmpty(v.NodeName, v.Hostname), }, Force: false, }, } } + +func clusterRoleFromTemplateValues(v TemplateValues) string { + switch strings.ToLower(strings.TrimSpace(v.BootstrapMode)) { + case "init": + return "control-plane" + case "join": + if strings.EqualFold(strings.TrimSpace(v.JoinKind), "control-plane") { + return "control-plane" + } + return "worker" + default: + return "control-plane" + } +} + +func initControlPlaneFromTemplateValues(v TemplateValues) bool { + return strings.EqualFold(strings.TrimSpace(v.BootstrapMode), "init") +} + +func firstNonEmpty(xs ...string) string { + for _, x := range xs { + if strings.TrimSpace(x) != "" { + return strings.TrimSpace(x) + } + } + return "" +} + +func copyStringSlice(in []string) []string { + if len(in) == 0 { + return nil + } + out := make([]string, len(in)) + copy(out, in) + return out +} + +func copyStringMap(in map[string]string) map[string]string { + if len(in) == 0 { + return nil + } + out := make(map[string]string, len(in)) + for k, v := range in { + out[k] = v + } + return out +} \ No newline at end of file diff --git a/clitools/pkg/templates/values.go b/clitools/pkg/templates/values.go new file mode 100644 index 0000000..efd5072 --- /dev/null +++ b/clitools/pkg/templates/values.go @@ -0,0 +1,204 @@ +package templates + +import ( + "os" + "strings" + + buildinfo "undecided.project/monok8s/pkg/buildinfo" +) + +type TemplateValues struct { + Hostname string + NodeName string + KubernetesVersion string + ClusterName string + ClusterDomain string + PodSubnet string + ServiceSubnet string + APIServerAdvertiseAddress string + APIServerEndpoint string + BootstrapToken string + DiscoveryTokenCACertHash string + ControlPlaneCertKey string + ContainerRuntimeEndpoint string + CNIPlugin string + + BootstrapMode string // init, join + JoinKind string // worker, control-plane + + AllowSchedulingOnControlPlane bool + SkipImageCheck bool + + MgmtIface string + MgmtAddress string + MgmtGateway string + DNSNameservers []string + DNSSearchDomains []string + + SubjectAltNames []string + NodeLabels map[string]string + NodeAnnotations map[string]string +} + +func defaultTemplateValues() TemplateValues { + return TemplateValues{ + Hostname: "monok8s-master-1", + NodeName: "monok8s-master-1", + KubernetesVersion: buildinfo.Version, + ClusterName: "monok8s", + ClusterDomain: "cluster.local", + PodSubnet: "10.244.0.0/16", + ServiceSubnet: "10.96.0.0/12", + APIServerAdvertiseAddress: "10.0.0.10", + APIServerEndpoint: "10.0.0.10:6443", + BootstrapToken: "abcd12.ef3456789abcdef0", + DiscoveryTokenCACertHash: "sha256:9f1c2b3a4d5e6f7890abc1234567890abcdef1234567890abcdef1234567890ab", + ControlPlaneCertKey: "", + ContainerRuntimeEndpoint: "unix:///var/run/crio/crio.sock", + CNIPlugin: "default", + + BootstrapMode: "init", + JoinKind: "worker", + + AllowSchedulingOnControlPlane: true, + SkipImageCheck: false, + + MgmtIface: "eth1", + MgmtAddress: "10.0.0.10/24", + MgmtGateway: "10.0.0.1", + + DNSNameservers: []string{"1.1.1.1", "8.8.8.8"}, + DNSSearchDomains: []string{"lan"}, + + SubjectAltNames: []string{"10.0.0.10", "localhost", "monok8s-master-1"}, + + NodeLabels: map[string]string{ + "monok8s.io/label": "value", + }, + NodeAnnotations: map[string]string{ + "monok8s.io/annotation": "value", + }, + } +} + +func LoadTemplateValuesFromEnv() TemplateValues { + v := defaultTemplateValues() + + v.Hostname = getenvDefault("MKS_HOSTNAME", v.Hostname) + v.NodeName = getenvDefault("MKS_NODE_NAME", v.Hostname) + + v.KubernetesVersion = getenvDefault("MKS_KUBERNETES_VERSION", v.KubernetesVersion) + v.ClusterName = getenvDefault("MKS_CLUSTER_NAME", v.ClusterName) + v.ClusterDomain = getenvDefault("MKS_CLUSTER_DOMAIN", v.ClusterDomain) + v.PodSubnet = getenvDefault("MKS_POD_SUBNET", v.PodSubnet) + v.ServiceSubnet = getenvDefault("MKS_SERVICE_SUBNET", v.ServiceSubnet) + + v.APIServerAdvertiseAddress = getenvDefault("MKS_APISERVER_ADVERTISE_ADDRESS", v.APIServerAdvertiseAddress) + v.APIServerEndpoint = getenvDefault("MKS_API_SERVER_ENDPOINT", v.APIServerEndpoint) + + v.BootstrapToken = getenvDefault("MKS_BOOTSTRAP_TOKEN", v.BootstrapToken) + v.DiscoveryTokenCACertHash = getenvDefault("MKS_DISCOVERY_TOKEN_CA_CERT_HASH", v.DiscoveryTokenCACertHash) + v.ControlPlaneCertKey = getenvDefault("MKS_CONTROL_PLANE_CERT_KEY", v.ControlPlaneCertKey) + + v.ContainerRuntimeEndpoint = getenvDefault("MKS_CONTAINER_RUNTIME_ENDPOINT", v.ContainerRuntimeEndpoint) + v.CNIPlugin = getenvDefault("MKS_CNI_PLUGIN", v.CNIPlugin) + + v.BootstrapMode = getenvDefault("MKS_BOOTSTRAP_MODE", v.BootstrapMode) + v.JoinKind = getenvDefault("MKS_JOIN_KIND", v.JoinKind) + + v.AllowSchedulingOnControlPlane = getenvBoolDefault("MKS_ALLOW_SCHEDULING_ON_CONTROL_PLANE", v.AllowSchedulingOnControlPlane) + v.SkipImageCheck = getenvBoolDefault("MKS_SKIP_IMAGE_CHECK", v.SkipImageCheck) + + v.MgmtIface = getenvDefault("MKS_MGMT_IFACE", v.MgmtIface) + v.MgmtAddress = getenvDefault("MKS_MGMT_ADDRESS", v.MgmtAddress) + v.MgmtGateway = getenvDefault("MKS_MGMT_GATEWAY", v.MgmtGateway) + + if xs := splitWhitespaceList(os.Getenv("MKS_DNS_NAMESERVERS")); len(xs) > 0 { + v.DNSNameservers = xs + } + if xs := splitWhitespaceList(os.Getenv("MKS_DNS_SEARCH_DOMAINS")); len(xs) > 0 { + v.DNSSearchDomains = xs + } + if xs := splitCommaList(os.Getenv("MKS_SANS")); len(xs) > 0 { + v.SubjectAltNames = xs + } + if m := parseKeyValueMap(os.Getenv("MKS_NODE_LABELS")); len(m) > 0 { + v.NodeLabels = m + } + if m := parseKeyValueMap(os.Getenv("MKS_NODE_ANNOTATIONS")); len(m) > 0 { + v.NodeAnnotations = m + } + + return v +} + +func getenvDefault(key, def string) string { + s := strings.TrimSpace(os.Getenv(key)) + if s == "" { + return def + } + return s +} + +func getenvBoolDefault(key string, def bool) bool { + s := strings.TrimSpace(strings.ToLower(os.Getenv(key))) + if s == "" { + return def + } + switch s { + case "1", "true", "yes", "y", "on": + return true + case "0", "false", "no", "n", "off": + return false + default: + return def + } +} + +func splitCommaList(s string) []string { + if strings.TrimSpace(s) == "" { + return nil + } + parts := strings.Split(s, ",") + out := make([]string, 0, len(parts)) + for _, p := range parts { + p = strings.TrimSpace(p) + if p != "" { + out = append(out, p) + } + } + return out +} + +func splitWhitespaceList(s string) []string { + if strings.TrimSpace(s) == "" { + return nil + } + return strings.Fields(s) +} + +func parseKeyValueMap(s string) map[string]string { + out := map[string]string{} + if strings.TrimSpace(s) == "" { + return out + } + + for _, item := range strings.Split(s, ",") { + item = strings.TrimSpace(item) + if item == "" { + continue + } + k, val, ok := strings.Cut(item, "=") + if !ok { + continue + } + k = strings.TrimSpace(k) + val = strings.TrimSpace(val) + if k == "" { + continue + } + out[k] = val + } + + return out +} diff --git a/configs/cluster.env.default b/configs/cluster.env.default index efc09b5..188c00a 100644 --- a/configs/cluster.env.default +++ b/configs/cluster.env.default @@ -1,44 +1,58 @@ -# Required -KUBERNETES_VERSION=v1.35.3 -NODE_NAME=monok8s-master -APISERVER_ADVERTISE_ADDRESS=192.168.1.50 +## Host config +MKS_HOSTNAME=monok8s-master +MKS_NODE_NAME=monok8s-master + +# RJ45 Ports from left to right (interface name inside the OS) +# - eth1, eth2, eth0 +MKS_MGMT_IFACE=eth1 +MKS_MGMT_ADDRESS=10.0.0.14/24 +MKS_MGMT_GATEWAY=10.0.0.1 + +# Space-separated real upstream DNS servers. +# Do NOT put the cluster DNS Service IP here. +MKS_DNS_NAMESERVERS="10.0.0.1 1.1.1.1 1.0.0.1" + +# Optional. Space-separated. +MKS_DNS_SEARCH_DOMAINS="lan" + +## k8s config +MKS_KUBERNETES_VERSION=v1.35.3 +MKS_APISERVER_ADVERTISE_ADDRESS=10.0.0.14 # Optional but strongly recommended -CLUSTER_NAME=monok8s -POD_SUBNET=10.244.0.0/16 -SERVICE_SUBNET=10.96.0.0/12 -CLUSTER_DOMAIN=cluster.local +MKS_CLUSTER_NAME=monok8s +MKS_POD_SUBNET=10.244.0.0/16 +MKS_SERVICE_SUBNET=10.96.0.0/12 +MKS_CLUSTER_DOMAIN=cluster.local # Bootstrap mode: init, join -BOOTSTRAP_MODE=init +MKS_BOOTSTRAP_MODE=init # For join mode: worker, control-plane -JOIN_KIND=worker -API_SERVER_ENDPOINT= -BOOTSTRAP_TOKEN= -DISCOVERY_TOKEN_CA_CERT_HASH= -CONTROL_PLANE_CERT_KEY= +MKS_JOIN_KIND=worker +MKS_API_SERVER_ENDPOINT= +MKS_BOOTSTRAP_TOKEN= +MKS_DISCOVERY_TOKEN_CA_CERT_HASH= +MKS_CONTROL_PLANE_CERT_KEY= -# none: Install manually -# bridge: CRIO's default bridge CNI -CNI_PLUGIN=none +# none: install manually +# default|bridge: CRI-O default bridge CNI +MKS_CNI_PLUGIN=none # Node registration metadata -NODE_LABELS=topology.kubernetes.io/zone=lab,node.kubernetes.io/instance-type=mono-gateway -NODE_ANNOTATIONS=mono.si/board=ls1046a,mono.si/image-version=dev +# Comma-separated key=value pairs +MKS_NODE_LABELS=topology.kubernetes.io/zone=lab,node.kubernetes.io/instance-type=mono-gateway +MKS_NODE_ANNOTATIONS=mono.si/board=ls1046a,mono.si/image-version=dev # Optional # Extra API server SANs, comma-separated -SANS=127.0.0.1,localhost,monok8s-master - -# Single-node mode: allow workloads on the control plane -ALLOW_SCHEDULING_ON_CONTROL_PLANE=yes +MKS_SANS=127.0.0.1,localhost,monok8s-master,10.0.0.14 # CRI-O socket -CONTAINER_RUNTIME_ENDPOINT=unix:///var/run/crio/crio.sock +MKS_CONTAINER_RUNTIME_ENDPOINT=unix:///var/run/crio/crio.sock -# Usually leave this alone -KUBECONFIG_USER_HOME=/root +# Optional +MKS_ALLOW_SCHEDULING_ON_CONTROL_PLANE=true # Emergency override only -SKIP_IMAGE_CHECK=no +MKS_SKIP_IMAGE_CHECK=no \ No newline at end of file diff --git a/configs/node.env.default b/configs/node.env.default deleted file mode 100644 index 3fec91b..0000000 --- a/configs/node.env.default +++ /dev/null @@ -1,14 +0,0 @@ -HOSTNAME=monok8s-master - -# RJ45 Ports from left to right (interface name inside the OS) -# - eth1, eth2, eth0 -MGMT_IFACE=eth0 -MGMT_ADDRESS=10.0.0.13/24 -MGMT_GATEWAY=10.0.0.1 - -# Space-separated real upstream DNS servers. -# Do NOT put the cluster DNS Service IP here. -DNS_NAMESERVERS="10.0.0.1 1.1.1.1 1.0.0.1" - -# Optional -DNS_SEARCH_DOMAINS="lan" diff --git a/makefile b/makefile index f7d26e2..04f8179 100644 --- a/makefile +++ b/makefile @@ -238,18 +238,7 @@ check-functions: @echo "Missing functions:" @comm -23 /tmp/called.txt /tmp/defined.txt || true -# ---- node targets ------------------------------------------------------------ - -node-config: $(NODE_ENV_DEFAULT) $(SCRIPTS_DIR)/merge-env.sh | $(OUT_DIR) - sh $(SCRIPTS_DIR)/merge-env.sh $(NODE_ENV_DEFAULT) $(NODE_ENV) - -node-defconfig: $(NODE_ENV_DEFAULT) | $(OUT_DIR) - cp $(NODE_ENV_DEFAULT) $(NODE_ENV) - -node-print: - @cat $(NODE_ENV) - -# ---- cluster targets ------------------------------------------------------------ +# ---- config targets ------------------------------------------------------------ cluster-config: $(CLUSTER_ENV_DEFAULT) $(SCRIPTS_DIR)/merge-env.sh | $(OUT_DIR) sh $(SCRIPTS_DIR)/merge-env.sh $(CLUSTER_ENV_DEFAULT) $(CLUSTER_ENV)