diff --git a/package/k3s.spec b/package/k3s.spec deleted file mode 100644 index 686888ebcb..0000000000 --- a/package/k3s.spec +++ /dev/null @@ -1,57 +0,0 @@ -# vim: sw=4:ts=4:et - -%define install_path /usr/bin -%define util_path %{_datadir}/k3s -%define install_sh %{util_path}/.install.sh -%define uninstall_sh %{util_path}/.uninstall.sh - -Name: k3s -Version: %{k3s_version} -Release: %{k3s_release}%{?dist} -Summary: Lightweight Kubernetes - -Group: System Environment/Base -License: ASL 2.0 -URL: http://k3s.io - -BuildRequires: systemd -Requires(post): k3s-selinux >= %{k3s_policyver} - -%description -The certified Kubernetes distribution built for IoT & Edge computing. - -%install -install -d %{buildroot}%{install_path} -install dist/artifacts/%{k3s_binary} %{buildroot}%{install_path}/k3s -install -d %{buildroot}%{util_path} -install install.sh %{buildroot}%{install_sh} - -%post -# do not run install script on upgrade -echo post-install args: $@ -if [ $1 == 1 ]; then - INSTALL_K3S_BIN_DIR=%{install_path} \ - INSTALL_K3S_SKIP_DOWNLOAD=true \ - INSTALL_K3S_SKIP_ENABLE=true \ - UNINSTALL_K3S_SH=%{uninstall_sh} \ - %{install_sh} -fi -%systemd_post k3s.service -exit 0 - -%postun -echo post-uninstall args: $@ -# do not run uninstall script on upgrade -if [ $1 == 0 ]; then - %{uninstall_sh} - rm -rf %{util_path} -fi -exit 0 - -%files -%{install_path}/k3s -%{install_sh} - -%changelog -* Mon Mar 2 2020 Erik Wilson 0.1-1 -- Initial version diff --git a/package/rpm/install.sh b/package/rpm/install.sh new file mode 100755 index 0000000000..5d418ed66b --- /dev/null +++ b/package/rpm/install.sh @@ -0,0 +1,800 @@ +#!/bin/sh +set -e + +# Usage: +# curl ... | ENV_VAR=... sh - +# or +# ENV_VAR=... ./install.sh +# +# Example: +# Installing a server without traefik: +# curl ... | INSTALL_K3S_EXEC="--no-deploy=traefik" sh - +# Installing an agent to point at a server: +# curl ... | K3S_TOKEN=xxx K3S_URL=https://server-url:6443 sh - +# +# Environment variables: +# - K3S_* +# Environment variables which begin with K3S_ will be preserved for the +# systemd service to use. Setting K3S_URL without explicitly setting +# a systemd exec command will default the command to "agent", and we +# enforce that K3S_TOKEN or K3S_CLUSTER_SECRET is also set. +# +# - INSTALL_K3S_SKIP_DOWNLOAD +# If set to true will not download k3s hash or binary. +# +# - INSTALL_K3S_UPGRADE +# If set to true will not overwrite env file. +# +# - INSTALL_K3S_SYMLINK +# If set to 'skip' will not create symlinks, 'force' will overwrite, +# default will symlink if command does not exist in path. +# +# - INSTALL_K3S_SKIP_ENABLE +# If set to true will not enable or start k3s service. +# +# - INSTALL_K3S_SKIP_START +# If set to true will not start k3s service. +# +# - INSTALL_K3S_VERSION +# Version of k3s to download from github. Will attempt to download the +# latest version if not specified. +# +# - INSTALL_K3S_COMMIT +# Commit of k3s to download from temporary cloud storage. +# * (for developer & QA use) +# +# - INSTALL_K3S_BIN_DIR +# Directory to install k3s binary, links, and uninstall script to, or use +# /usr/local/bin as the default +# +# - INSTALL_K3S_BIN_DIR_READ_ONLY +# If set to true will not write files to INSTALL_K3S_BIN_DIR, forces +# setting INSTALL_K3S_SKIP_DOWNLOAD=true +# +# - INSTALL_K3S_SYSTEMD_DIR +# Directory to install systemd service files to, or use +# /etc/systemd/system as the default +# +# - INSTALL_K3S_CONFIG_DIR +# Directory to install environment and flag files to, or use +# /etc/rancher/k3s as the default +# +# - INSTALL_K3S_EXEC or script arguments +# Command with flags to use for launching k3s in the systemd service, if +# the command is not specified will default to "agent" if K3S_URL is set +# or "server" if not. The final systemd command resolves to a combination +# of EXEC and script args ($@). +# +# The following commands result in the same behavior: +# curl ... | INSTALL_K3S_EXEC="--no-deploy=traefik" sh -s - +# curl ... | INSTALL_K3S_EXEC="server --no-deploy=traefik" sh -s - +# curl ... | INSTALL_K3S_EXEC="server" sh -s - --no-deploy=traefik +# curl ... | sh -s - server --no-deploy=traefik +# curl ... | sh -s - --no-deploy=traefik +# +# - INSTALL_K3S_NAME +# Name of systemd service to create, will default from the k3s exec command +# if not specified. If specified the name will be prefixed with 'k3s-'. +# +# - INSTALL_K3S_TYPE +# Type of systemd service to create, will default from the k3s exec command +# if not specified. +# +# - INSTALL_K3S_DEBUG +# Set to true for debug shell scripit output (set -x). +# +# - KILLALL_K3S_SH +# Full path of killall script to create. +# +# - UNINSTALL_K3S_SH +# Full path of uninstall script to create. + +if [ "$INSTALL_K3S_DEBUG" = "true" ]; then + set -x +fi + +GITHUB_URL=https://github.com/rancher/k3s/releases +STORAGE_URL=https://storage.googleapis.com/k3s-ci-builds +DOWNLOADER= + +# --- helper functions for logs --- +info() +{ + echo '[INFO] ' "$@" +} +warn() +{ + echo '[WARN] ' "$@" >&2 +} +fatal() +{ + echo '[ERROR] ' "$@" >&2 + exit 1 +} + +# --- fatal if no systemd or openrc --- +verify_system() { + if [ -x /sbin/openrc-run ]; then + HAS_OPENRC=true + return + fi + if [ -d /run/systemd ]; then + HAS_SYSTEMD=true + return + fi + fatal 'Can not find systemd or openrc to use as a process supervisor for k3s' +} + +# --- add quotes to command arguments --- +quote() { + for arg in "$@"; do + printf '%s\n' "$arg" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/" + done +} + +# --- add indentation and trailing slash to quoted args --- +quote_indent() { + printf ' \\\n' + for arg in "$@"; do + printf '\t%s \\\n' "$(quote "$arg")" + done + printf ' \n' +} + +# --- escape most punctuation characters, except quotes, forward slash, and space --- +escape() { + printf '%s' "$@" | sed -e 's/\([][!#$%&()*;<=>?\_`{|}]\)/\\\1/g;' +} + +# --- escape double quotes --- +escape_dq() { + printf '%s' "$@" | sed -e 's/"/\\"/g' +} + +# --- define needed environment variables --- +setup_env() { + case "$1" in + (--debug) + export K3S_DEBUG=true + shift + ;; + esac + # --- use command args if passed or create default --- + case "$1" in + # --- if we only have flags discover if command should be server or agent --- + (-*|"") + if [ -z "${K3S_URL}" ]; then + CMD_K3S=server + else + if [ -z "${K3S_TOKEN}" ] && [ -z "${K3S_CLUSTER_SECRET}" ]; then + fatal "Defaulted k3s exec command to 'agent' because K3S_URL is defined, but K3S_TOKEN or K3S_CLUSTER_SECRET is not defined." + fi + CMD_K3S=agent + fi + ;; + # --- command is provided --- + (*) + CMD_K3S=$1 + shift + ;; + esac + CMD_K3S_ARGS=$(quote "$@") + CMD_K3S_ARGS_VAR=K3S_$(echo "${CMD_K3S}" | tr [a-z] [A-Z])_ARGS + + # --- use systemd name if defined or create default --- + if [ -n "${INSTALL_K3S_NAME}" ]; then + SERVICE_NAME=k3s-${INSTALL_K3S_NAME} + else + if [ "${CMD_K3S}" = server ]; then + SERVICE_NAME=k3s + else + SERVICE_NAME=k3s-${CMD_K3S} + fi + fi + + # --- check for invalid characters in system name --- + valid_chars=$(printf '%s' "${SERVICE_NAME}" | sed -e 's/[][!#$%&()*;<=>?\_`{|}/[:space:]]/^/g;' ) + if [ "${SERVICE_NAME}" != "${valid_chars}" ]; then + invalid_chars=$(printf '%s' "${valid_chars}" | sed -e 's/[^^]/ /g') + fatal "Invalid characters for system name: + ${SERVICE_NAME} + ${invalid_chars}" + fi + + # --- use sudo if we are not already root --- + SUDO=sudo + if [ $(id -u) -eq 0 ]; then + SUDO= + fi + + # --- use systemd type if defined or create default --- + if [ -n "${INSTALL_K3S_TYPE}" ]; then + SYSTEMD_TYPE=${INSTALL_K3S_TYPE} + else + if [ "${CMD_K3S}" = server ]; then + SYSTEMD_TYPE=notify + else + SYSTEMD_TYPE=exec + fi + fi + + # --- use binary install directory if defined or create default --- + BIN_DIR=${INSTALL_K3S_BIN_DIR:-/usr/local/bin} + DATA_DIR=/var/lib/rancher/k3s + + # --- set related files from system name --- + UNINSTALL_K3S_SH=${UNINSTALL_K3S_SH:-${BIN_DIR}/k3s-uninstall.sh} + KILLALL_K3S_SH=${KILLALL_K3S_SH:-${BIN_DIR}/k3s-killall.sh} + + # --- use systemd directory if defined or create default --- + if [ -n "${INSTALL_K3S_SYSTEMD_DIR}" ]; then + warn "INSTALL_K3S_SYSTEMD_DIR is deprecated, use INSTALL_K3S_SERVICE_DIR instead" + [ -n "${INSTALL_K3S_SERVICE_DIR}" ] && \ + error "INSTALL_K3S_SERVICE_DIR is defined, but so is INSTALL_K3S_SYSTEMD_DIR" + SERVICE_DIR="${INSTALL_K3S_SYSTEMD_DIR}" + fi + # --- use service directory if defined or create default --- + if [ -n "${INSTALL_K3S_SERVICE_DIR}" ]; then + SERVICE_DIR="${INSTALL_K3S_SERVICE_DIR}" + fi + + # --- use service or environment location depending on systemd/openrc --- + CONFIG_DIR=${INSTALL_K3S_CONFIG_DIR:-/etc/rancher/k3s} + if [ "${HAS_SYSTEMD}" = true ]; then + SERVICE_FILE=${SERVICE_NAME}.service + SERVICE_DIR=${SERVICE_DIR:-/etc/systemd/system} + elif [ "${HAS_OPENRC}" = true ]; then + SERVICE_FILE=${SERVICE_NAME} + SERVICE_DIR=${SERVICE_DIR:-/etc/init.d} + fi + + $SUDO mkdir -p ${CONFIG_DIR} + FILE_K3S_SERVICE=${SERVICE_DIR}/${SERVICE_FILE} + FILE_K3S_ENV=${CONFIG_DIR}/${SERVICE_NAME}.env + # FILE_K3S_FLAGS=${CONFIG_DIR}/${SERVICE_NAME}.flags + + # --- get hash of config & exec for currently installed k3s --- + PRE_INSTALL_HASHES=$(get_installed_hashes) + + # --- if bin directory is read only skip download --- + if [ "${INSTALL_K3S_BIN_DIR_READ_ONLY}" = true ]; then + INSTALL_K3S_SKIP_DOWNLOAD=true + fi +} + +# --- check if skip download environment variable set --- +can_skip_download() { + if [ "${INSTALL_K3S_SKIP_DOWNLOAD}" != true ]; then + return 1 + fi +} + +# --- verify an executabe k3s binary is installed --- +verify_k3s_is_executable() { + if [ ! -x ${BIN_DIR}/k3s ]; then + fatal "Executable k3s binary not found at ${BIN_DIR}/k3s" + fi +} + +# --- set arch and suffix, fatal if architecture not supported --- +setup_verify_arch() { + if [ -z "$ARCH" ]; then + ARCH=$(uname -m) + fi + case $ARCH in + amd64) + ARCH=amd64 + SUFFIX= + ;; + x86_64) + ARCH=amd64 + SUFFIX= + ;; + arm64) + ARCH=arm64 + SUFFIX=-${ARCH} + ;; + aarch64) + ARCH=arm64 + SUFFIX=-${ARCH} + ;; + arm*) + ARCH=arm + SUFFIX=-${ARCH}hf + ;; + *) + fatal "Unsupported architecture $ARCH" + esac +} + +# --- verify existence of network downloader executable --- +verify_downloader() { + # Return failure if it doesn't exist or is no executable + [ -x "$(which $1)" ] || return 1 + + # Set verified executable as our downloader program and return success + DOWNLOADER=$1 + return 0 +} + +# --- verify existence of semanage when SELinux is enabled --- +verify_semanage() { + if [ -x "$(which getenforce)" ]; then + if [ "Disabled" != $(getenforce) ] && [ ! -x "$(which semanage)" ]; then + fatal 'SELinux is enabled but semanage is not found' + fi + fi +} + +# --- create tempory directory and cleanup when done --- +setup_tmp() { + TMP_DIR=$(mktemp -d -t k3s-install.XXXXXXXXXX) + TMP_HASH=${TMP_DIR}/k3s.hash + TMP_BIN=${TMP_DIR}/k3s.bin + cleanup() { + code=$? + set +e + trap - EXIT + rm -rf ${TMP_DIR} + exit $code + } + trap cleanup INT EXIT +} + +# --- use desired k3s version if defined or find latest --- +get_release_version() { + if [ -n "${INSTALL_K3S_COMMIT}" ]; then + VERSION_K3S="commit ${INSTALL_K3S_COMMIT}" + elif [ -n "${INSTALL_K3S_VERSION}" ]; then + VERSION_K3S=${INSTALL_K3S_VERSION} + else + info "Finding latest release" + case $DOWNLOADER in + curl) + VERSION_K3S=$(curl -w '%{url_effective}' -I -L -s -S ${GITHUB_URL}/latest -o /dev/null | sed -e 's|.*/||') + ;; + wget) + VERSION_K3S=$(wget -SqO /dev/null ${GITHUB_URL}/latest 2>&1 | grep Location | sed -e 's|.*/||') + ;; + *) + fatal "Incorrect downloader executable '$DOWNLOADER'" + ;; + esac + fi + info "Using ${VERSION_K3S} as release" +} + +# --- download from github url --- +download() { + [ $# -eq 2 ] || fatal 'download needs exactly 2 arguments' + + case $DOWNLOADER in + curl) + curl -o $1 -sfL $2 + ;; + wget) + wget -qO $1 $2 + ;; + *) + fatal "Incorrect executable '$DOWNLOADER'" + ;; + esac + + # Abort if download command failed + [ $? -eq 0 ] || fatal 'Download failed' +} + +# --- download hash from github url --- +download_hash() { + if [ -n "${INSTALL_K3S_COMMIT}" ]; then + HASH_URL=${STORAGE_URL}/k3s${SUFFIX}-${INSTALL_K3S_COMMIT}.sha256sum + else + HASH_URL=${GITHUB_URL}/download/${VERSION_K3S}/sha256sum-${ARCH}.txt + fi + info "Downloading hash ${HASH_URL}" + download ${TMP_HASH} ${HASH_URL} + HASH_EXPECTED=$(grep " k3s${SUFFIX}$" ${TMP_HASH}) + HASH_EXPECTED=${HASH_EXPECTED%%[[:blank:]]*} +} + +# --- check hash against installed version --- +installed_hash_matches() { + if [ -x ${BIN_DIR}/k3s ]; then + HASH_INSTALLED=$(sha256sum ${BIN_DIR}/k3s) + HASH_INSTALLED=${HASH_INSTALLED%%[[:blank:]]*} + if [ "${HASH_EXPECTED}" = "${HASH_INSTALLED}" ]; then + return + fi + fi + return 1 +} + +# --- download binary from github url --- +download_binary() { + if [ -n "${INSTALL_K3S_COMMIT}" ]; then + BIN_URL=${STORAGE_URL}/k3s${SUFFIX}-${INSTALL_K3S_COMMIT} + else + BIN_URL=${GITHUB_URL}/download/${VERSION_K3S}/k3s${SUFFIX} + fi + info "Downloading binary ${BIN_URL}" + download ${TMP_BIN} ${BIN_URL} +} + +# --- verify downloaded binary hash --- +verify_binary() { + info "Verifying binary download" + HASH_BIN=$(sha256sum ${TMP_BIN}) + HASH_BIN=${HASH_BIN%%[[:blank:]]*} + if [ "${HASH_EXPECTED}" != "${HASH_BIN}" ]; then + fatal "Download sha256 does not match ${HASH_EXPECTED}, got ${HASH_BIN}" + fi +} + +# --- setup permissions and move binary to system directory --- +setup_binary() { + chmod 755 ${TMP_BIN} + info "Installing k3s to ${BIN_DIR}/k3s" + $SUDO chown root:root ${TMP_BIN} + $SUDO mv -f ${TMP_BIN} ${BIN_DIR}/k3s + + if command -v getenforce >/dev/null 2>&1; then + if [ "Disabled" != $(getenforce) ]; then + info 'SELinux is enabled, setting permissions' + if ! $SUDO semanage fcontext -l | grep "${BIN_DIR}/k3s" > /dev/null 2>&1; then + $SUDO semanage fcontext -a -t bin_t "${BIN_DIR}/k3s" + fi + $SUDO restorecon -v ${BIN_DIR}/k3s > /dev/null + fi + fi +} + +# --- download and verify k3s --- +download_and_verify() { + if can_skip_download; then + info 'Skipping k3s download and verify' + verify_k3s_is_executable + return + fi + + setup_verify_arch + verify_downloader curl || verify_downloader wget || fatal 'Can not find curl or wget for downloading files' + verify_semanage + setup_tmp + get_release_version + download_hash + + if installed_hash_matches; then + info 'Skipping binary downloaded, installed k3s matches hash' + return + fi + + download_binary + verify_binary + setup_binary +} + +# --- add additional utility links --- +create_symlinks() { + [ "${INSTALL_K3S_BIN_DIR_READ_ONLY}" = true ] && return + [ "${INSTALL_K3S_SYMLINK}" = skip ] && return + + for cmd in kubectl crictl ctr; do + if [ ! -e ${BIN_DIR}/${cmd} ] || [ "${INSTALL_K3S_SYMLINK}" = force ]; then + which_cmd=$(which ${cmd} 2>/dev/null || true) + if [ -z "${which_cmd}" ] || [ "${INSTALL_K3S_SYMLINK}" = force ]; then + info "Creating ${BIN_DIR}/${cmd} symlink to k3s" + $SUDO ln -sf k3s ${BIN_DIR}/${cmd} + else + info "Skipping ${BIN_DIR}/${cmd} symlink to k3s, command exists in PATH at ${which_cmd}" + fi + else + info "Skipping ${BIN_DIR}/${cmd} symlink to k3s, already exists" + fi + done +} + +# --- create killall script --- +create_killall() { + [ "${INSTALL_K3S_BIN_DIR_READ_ONLY}" = true ] && return + info "Creating killall script ${KILLALL_K3S_SH}" + $SUDO tee ${KILLALL_K3S_SH} >/dev/null << \EOF +#!/bin/sh +[ $(id -u) -eq 0 ] || exec sudo $0 $@ + +for bin in /var/lib/rancher/k3s/data/**/bin/; do + [ -d $bin ] && export PATH=$PATH:$bin:$bin/aux +done + +set -x + +for service in /etc/systemd/system/k3s*.service; do + [ -s $service ] && systemctl stop $(basename $service) +done + +for service in /etc/init.d/k3s*; do + [ -x $service ] && $service stop +done + +pschildren() { + ps -e -o ppid= -o pid= | \ + sed -e 's/^\s*//g; s/\s\s*/\t/g;' | \ + grep -w "^$1" | \ + cut -f2 +} + +pstree() { + for pid in $@; do + echo $pid + for child in $(pschildren $pid); do + pstree $child + done + done +} + +killtree() { + kill -9 $( + { set +x; } 2>/dev/null; + pstree $@; + set -x; + ) 2>/dev/null +} + +getshims() { + ps -e -o pid= -o args= | sed -e 's/^ *//; s/\s\s*/\t/;' | grep -w 'k3s/data/[^/]*/bin/containerd-shim' | cut -f1 +} + +killtree $({ set +x; } 2>/dev/null; getshims; set -x) + +do_unmount() { + { set +x; } 2>/dev/null + MOUNTS= + while read ignore mount ignore; do + MOUNTS="$mount\n$MOUNTS" + done /dev/null | grep 'master cni0' | while read ignore iface ignore; do + iface=${iface%%@*} + [ -z "$iface" ] || ip link delete $iface +done +ip link delete cni0 +ip link delete flannel.1 +rm -rf /var/lib/cni/ +iptables-save | grep -v KUBE- | grep -v CNI- | iptables-restore +EOF + $SUDO chmod 755 ${KILLALL_K3S_SH} + $SUDO chown root:root ${KILLALL_K3S_SH} +} + +# --- create uninstall script --- +create_uninstall() { + [ "${INSTALL_K3S_BIN_DIR_READ_ONLY}" = true ] && return + info "Creating uninstall script ${UNINSTALL_K3S_SH}" + $SUDO tee ${UNINSTALL_K3S_SH} >/dev/null << EOF +#!/bin/sh +set -x +[ \$(id -u) -eq 0 ] || exec sudo \$0 \$@ + +${KILLALL_K3S_SH} + +if which systemctl; then + for service in ${SERVICE_DIR}/k3s*.service; do + systemctl disable \$service + systemctl reset-failed \$service + rm -f \$service + done + systemctl daemon-reload +fi +if which rc-update; then + for service in ${SERVICE_DIR}/k3s*; do + rc-update delete \$service default + rm -f \$service + done +fi + +remove_uninstall() { + rm -f ${UNINSTALL_K3S_SH} +} +trap remove_uninstall EXIT + +for cmd in kubectl crictl ctr; do + if [ -L ${BIN_DIR}/\$cmd ]; then + rm -f ${BIN_DIR}/\$cmd + fi +done + +rm -rf /var/lib/kubelet +rm -rf ${CONFIG_DIR} +rm -rf ${DATA_DIR} +rm -f ${BIN_DIR}/k3s +rm -f ${KILLALL_K3S_SH} +EOF + $SUDO chmod 755 ${UNINSTALL_K3S_SH} + $SUDO chown root:root ${UNINSTALL_K3S_SH} +} + +# --- disable current service if loaded -- +systemd_disable() { + $SUDO rm -f /etc/systemd/system/${SERVICE_NAME} || true + $SUDO mv /etc/systemd/system/${SERVICE_NAME}.env ${FILE_K3S_ENV} >/dev/null 2>&1 || true + $SUDO systemctl disable ${SERVICE_NAME} >/dev/null 2>&1 || true +} + +# --- capture current env and create file containing k3s_ variables --- +create_env_file() { + if [ -f "${FILE_K3S_ENV}" ] && [ "${INSTALL_K3S_UPGRADE}" = true ]; then + warn "env: Skipping env creation, ${FILE_K3S_ENV} exists and INSTALL_K3S_UPGRADE=true" + return 0 + fi + info "env: Creating environment file ${FILE_K3S_ENV}" + UMASK=$(umask) + umask 0177 + env | grep '^K3S_' | $SUDO tee ${FILE_K3S_ENV} >/dev/null + env | egrep -i '^(NO|HTTP|HTTPS)_PROXY' | $SUDO tee -a ${FILE_K3S_ENV} >/dev/null + echo "${CMD_K3S_ARGS_VAR}=\"${CMD_K3S_ARGS}\"" | $SUDO tee -a ${FILE_K3S_ENV} >/dev/null + umask $UMASK +} + +# --- write systemd service file --- +create_systemd_service_file() { + info "systemd: Creating service file ${FILE_K3S_SERVICE}" + conflicts= + if [ "${SERVICE_NAME}" != 'k3s-agent' ]; then + conflicts='k3s-agent.service' + fi + $SUDO tee ${FILE_K3S_SERVICE} >/dev/null << EOF +[Unit] +Description=Lightweight Kubernetes +Documentation=https://k3s.io +Wants=network-online.target +Conflicts=${conflicts} + +[Install] +WantedBy=multi-user.target + +[Service] +Type=${SYSTEMD_TYPE} +EnvironmentFile=${FILE_K3S_ENV} +KillMode=process +Delegate=yes +LimitNOFILE=infinity +LimitNPROC=infinity +LimitCORE=infinity +TasksMax=infinity +TimeoutStartSec=0 +Restart=always +RestartSec=5s +ExecStartPre=-/sbin/modprobe br_netfilter +ExecStartPre=-/sbin/modprobe overlay +ExecStart=${BIN_DIR}/k3s ${CMD_K3S} \$${CMD_K3S_ARGS_VAR} +EOF +} + +# --- write openrc service file --- +create_openrc_service_file() { + LOG_FILE=/var/log/${SERVICE_NAME}.log + + info "openrc: Creating service file ${FILE_K3S_SERVICE}" + $SUDO tee ${FILE_K3S_SERVICE} >/dev/null << EOF +#!/sbin/openrc-run + +set -o allexport +if [ -f /etc/environment ]; then source /etc/environment; fi +if [ -f ${FILE_K3S_ENV} ]; then source ${FILE_K3S_ENV}; fi +set +o allexport + +depend() { + after network-online + want cgroups +} + +start_pre() { + rm -f /tmp/k3s.* +} + +supervisor=supervise-daemon +name=${SERVICE_NAME} +command="${BIN_DIR}/k3s" +command_args="${CMD_K3S} \$${CMD_K3S_ARGS_VAR} >>${LOG_FILE} 2>&1" + +output_log=${LOG_FILE} +error_log=${LOG_FILE} + +pidfile="/var/run/${SERVICE_NAME}.pid" +respawn_delay=5 +EOF + $SUDO chmod 0755 ${FILE_K3S_SERVICE} + + $SUDO tee /etc/logrotate.d/${SERVICE_NAME} >/dev/null << EOF +${LOG_FILE} { + missingok + notifempty + copytruncate +} +EOF +} + +# --- write systemd or openrc service file --- +create_service_file() { + [ "${HAS_SYSTEMD}" = true ] && create_systemd_service_file + [ "${HAS_OPENRC}" = true ] && create_openrc_service_file + return 0 +} + +# --- get hashes of the current k3s bin and service files +get_installed_hashes() { + $SUDO sha256sum ${BIN_DIR}/k3s ${FILE_K3S_SERVICE} ${FILE_K3S_ENV} 2>&1 || true +} + +# --- enable and start systemd service --- +systemd_enable() { + info "systemd: Enabling ${SERVICE_NAME} unit" + $SUDO systemctl enable ${FILE_K3S_SERVICE} >/dev/null + $SUDO systemctl daemon-reload >/dev/null +} + +systemd_start() { + info "systemd: Starting ${SERVICE_NAME}" + $SUDO systemctl restart ${SERVICE_NAME} +} + +# --- enable and start openrc service --- +openrc_enable() { + info "openrc: Enabling ${SERVICE_NAME} service for default runlevel" + $SUDO rc-update add ${SERVICE_NAME} default >/dev/null +} + +openrc_start() { + info "openrc: Starting ${SERVICE_NAME}" + $SUDO ${FILE_K3S_SERVICE} restart +} + +# --- startup systemd or openrc service --- +service_enable_and_start() { + [ "${INSTALL_K3S_SKIP_ENABLE}" = true ] && return + + [ "${HAS_SYSTEMD}" = true ] && systemd_enable + [ "${HAS_OPENRC}" = true ] && openrc_enable + + [ "${INSTALL_K3S_SKIP_START}" = true ] && return + + POST_INSTALL_HASHES=$(get_installed_hashes) + if [ "${PRE_INSTALL_HASHES}" = "${POST_INSTALL_HASHES}" ]; then + info 'No change detected so skipping service start' + return + fi + + [ "${HAS_SYSTEMD}" = true ] && systemd_start + [ "${HAS_OPENRC}" = true ] && openrc_start + return 0 +} + +# --- re-evaluate args to include env command --- +eval set -- $(escape "${INSTALL_K3S_EXEC}") $(quote "$@") + +# --- run the install process -- +{ + verify_system + setup_env "$@" + download_and_verify + create_symlinks + create_killall + create_uninstall + systemd_disable + create_env_file + create_service_file + service_enable_and_start +} diff --git a/package/rpm/k3s.spec b/package/rpm/k3s.spec new file mode 100644 index 0000000000..0b01e9f1d2 --- /dev/null +++ b/package/rpm/k3s.spec @@ -0,0 +1,71 @@ +# vim: sw=4:ts=4:et + +%define install_path /usr/bin +%define util_path %{_datadir}/k3s +%define install_sh %{util_path}/setup/install.sh +%define uninstall_sh %{util_path}/setup/uninstall.sh + +Name: k3s +Version: %{k3s_version} +Release: %{k3s_release}%{?dist} +Summary: Lightweight Kubernetes + +Group: System Environment/Base +License: ASL 2.0 +URL: http://k3s.io + +BuildRequires: systemd +Requires(post): k3s-selinux >= %{k3s_policyver} + +%description +The certified Kubernetes distribution built for IoT & Edge computing. + +%install +install -d %{buildroot}%{install_path} +install dist/artifacts/%{k3s_binary} %{buildroot}%{install_path}/k3s +install -d %{buildroot}%{util_path}/setup +install package/rpm/install.sh %{buildroot}%{install_sh} + +%post +# do not overwrite env file if present +export INSTALL_K3S_UPGRADE=true +export INSTALL_K3S_BIN_DIR=%{install_path} +export INSTALL_K3S_SKIP_DOWNLOAD=true +export INSTALL_K3S_SKIP_ENABLE=true +export INSTALL_K3S_DEBUG=true +export UNINSTALL_K3S_SH=%{uninstall_sh} + +( + # install server service + INSTALL_K3S_NAME=server \ + %{install_sh} + + # install agent service + INSTALL_K3S_SYMLINK=skip \ + INSTALL_K3S_BIN_DIR_READ_ONLY=true \ + K3S_TOKEN=example-token \ + K3S_URL=https://example-k3s-server:6443/ \ + %{install_sh} agent + +# save debug log of the install +) >%{util_path}/setup/install.log 2>&1 + +%systemd_post k3s-server.service +%systemd_post k3s-agent.service +exit 0 + +%postun +# do not run uninstall script on upgrade +if [ $1 = 0 ]; then + %{uninstall_sh} + rm -rf %{util_path} +fi +exit 0 + +%files +%{install_path}/k3s +%{install_sh} + +%changelog +* Mon Mar 2 2020 Erik Wilson 0.1-1 +- Initial version diff --git a/package/rpm/repo-setup.sh b/package/rpm/repo-setup.sh new file mode 100755 index 0000000000..71cca05f5d --- /dev/null +++ b/package/rpm/repo-setup.sh @@ -0,0 +1,8 @@ +cat </etc/yum.repos.d/rancher.repo +[rancher] +name=Rancher Repository +baseurl=https://rpm.rancher.io/ +enabled=1 +gpgcheck=1 +gpgkey=https://rpm.rancher.io/public.key +EOF diff --git a/scripts/package-rpm b/scripts/package-rpm index 487c794e78..dccb7bc9ed 100755 --- a/scripts/package-rpm +++ b/scripts/package-rpm @@ -47,7 +47,7 @@ rpmbuild \ --define "_srcrpmdir ${PWD}" \ --define "_rpmdir ${PWD}/dist/rpm" \ --define "_buildrootdir ${PWD}/.rpm-build" \ - -bb package/k3s.spec + -bb package/rpm/k3s.spec if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$PRIVATE_KEY"; then echo "PRIVATE_KEY not defined, skipping rpm sign and upload"