mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-24 22:43:05 +00:00
Some of the "k8s distros" allow using CRI-O in a non-official way, and
if that's done we cannot simply assume they're on containerd, otherwise
kata-deploy will simply not work.
In order to avoid such issue, let's check for `cri-o` as the container
engine as the first place and only proceed with the checks for the "k8s
distros" after we rule out that CRI-O is not being used.
Signed-off-by: Fabiano Fidêncio <fabiano.fidencio@intel.com>
(cherry picked from commit 358dc2f569
)
487 lines
14 KiB
Bash
Executable File
487 lines
14 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Copyright (c) 2019 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
set -o errexit
|
|
set -o pipefail
|
|
set -o nounset
|
|
|
|
crio_drop_in_conf_dir="/etc/crio/crio.conf.d/"
|
|
crio_drop_in_conf_file="${crio_drop_in_conf_dir}/99-kata-deploy"
|
|
crio_drop_in_conf_file_debug="${crio_drop_in_conf_dir}/100-debug"
|
|
containerd_conf_file="/etc/containerd/config.toml"
|
|
containerd_conf_file_backup="${containerd_conf_file}.bak"
|
|
|
|
IFS=' ' read -a shims <<< "$SHIMS"
|
|
|
|
default_shim="$DEFAULT_SHIM"
|
|
|
|
# If we fail for any reason a message will be displayed
|
|
die() {
|
|
msg="$*"
|
|
echo "ERROR: $msg" >&2
|
|
exit 1
|
|
}
|
|
|
|
function host_systemctl() {
|
|
nsenter --target 1 --mount systemctl "${@}"
|
|
}
|
|
|
|
function print_usage() {
|
|
echo "Usage: $0 [install/cleanup/reset]"
|
|
}
|
|
|
|
function create_runtimeclasses() {
|
|
echo "Creating the runtime classes"
|
|
|
|
for shim in "${shims[@]}"; do
|
|
echo "Creating the kata-${shim} runtime class"
|
|
kubectl apply -f /opt/kata-artifacts/runtimeclasses/kata-${shim}.yaml
|
|
done
|
|
|
|
if [[ "${CREATE_DEFAULT_RUNTIMECLASS}" == "true" ]]; then
|
|
echo "Creating the kata runtime class for the default shim (an alias for kata-${default_shim})"
|
|
cp /opt/kata-artifacts/runtimeclasses/kata-${default_shim}.yaml /tmp/kata.yaml
|
|
sed -i -e 's/name: kata-'${default_shim}'/name: kata/g' /tmp/kata.yaml
|
|
kubectl apply -f /tmp/kata.yaml
|
|
rm -f /tmp/kata.yaml
|
|
fi
|
|
}
|
|
|
|
function delete_runtimeclasses() {
|
|
echo "Deleting the runtime classes"
|
|
|
|
for shim in "${shims[@]}"; do
|
|
echo "Deleting the kata-${shim} runtime class"
|
|
kubectl delete -f /opt/kata-artifacts/runtimeclasses/kata-${shim}.yaml
|
|
done
|
|
|
|
|
|
if [[ "${CREATE_DEFAULT_RUNTIMECLASS}" == "true" ]]; then
|
|
echo "Deleting the kata runtime class for the default shim (an alias for kata-${default_shim})"
|
|
cp /opt/kata-artifacts/runtimeclasses/kata-${default_shim}.yaml /tmp/kata.yaml
|
|
sed -i -e 's/name: kata-'${default_shim}'/name: kata/g' /tmp/kata.yaml
|
|
kubectl delete -f /tmp/kata.yaml
|
|
rm -f /tmp/kata.yaml
|
|
fi
|
|
}
|
|
|
|
function get_container_runtime() {
|
|
|
|
local runtime=$(kubectl get node $NODE_NAME -o jsonpath='{.status.nodeInfo.containerRuntimeVersion}')
|
|
if [ "$?" -ne 0 ]; then
|
|
die "invalid node name"
|
|
fi
|
|
|
|
if echo "$runtime" | grep -qE "cri-o"; then
|
|
echo "cri-o"
|
|
elif echo "$runtime" | grep -qE 'containerd.*-k3s'; then
|
|
if host_systemctl is-active --quiet rke2-agent; then
|
|
echo "rke2-agent"
|
|
elif host_systemctl is-active --quiet rke2-server; then
|
|
echo "rke2-server"
|
|
elif host_systemctl is-active --quiet k3s-agent; then
|
|
echo "k3s-agent"
|
|
else
|
|
echo "k3s"
|
|
fi
|
|
# Note: we assumed you used a conventional k0s setup and k0s will generate a systemd entry k0scontroller.service and k0sworker.service respectively
|
|
# and it is impossible to run this script without a kubelet, so this k0s controller must also have worker mode enabled
|
|
elif host_systemctl is-active --quiet k0scontroller; then
|
|
echo "k0s-controller"
|
|
elif host_systemctl is-active --quiet k0sworker; then
|
|
echo "k0s-worker"
|
|
else
|
|
echo "$runtime" | awk -F '[:]' '{print $1}'
|
|
fi
|
|
}
|
|
|
|
function install_artifacts() {
|
|
echo "copying kata artifacts onto host"
|
|
cp -au /opt/kata-artifacts/opt/kata/* /opt/kata/
|
|
chmod +x /opt/kata/bin/*
|
|
[ -d /opt/kata/runtime-rs/bin ] && \
|
|
chmod +x /opt/kata/runtime-rs/bin/*
|
|
|
|
# Allow enabling debug for Kata Containers
|
|
if [[ "${DEBUG}" == "true" ]]; then
|
|
config_path="/opt/kata/share/defaults/kata-containers/"
|
|
for shim in "${shims[@]}"; do
|
|
sed -i -e 's/^#\(enable_debug\).*=.*$/\1 = true/g' "${config_path}/configuration-${shim}.toml"
|
|
sed -i -e 's/^#\(debug_console_enabled\).*=.*$/\1 = true/g' "${config_path}/configuration-${shim}.toml"
|
|
sed -i -e 's/^kernel_params = "\(.*\)"/kernel_params = "\1 agent.log=debug initcall_debug"/g' "${config_path}/configuration-${shim}.toml"
|
|
done
|
|
fi
|
|
|
|
# Allow Mariner to use custom configuration.
|
|
if [ "${HOST_OS:-}" == "cbl-mariner" ]; then
|
|
config_path="/opt/kata/share/defaults/kata-containers/configuration-clh.toml"
|
|
clh_path="/opt/kata/bin/cloud-hypervisor-glibc"
|
|
sed -i -E 's|(enable_annotations) = .+|\1 = ["enable_iommu", "initrd", "kernel"]|' "${config_path}"
|
|
sed -i -E "s|(valid_hypervisor_paths) = .+|\1 = [\"${clh_path}\"]|" "${config_path}"
|
|
sed -i -E "s|(path) = \".+/cloud-hypervisor\"|\1 = \"${clh_path}\"|" "${config_path}"
|
|
fi
|
|
|
|
if [[ "${CREATE_RUNTIMECLASSES}" == "true" ]]; then
|
|
create_runtimeclasses
|
|
fi
|
|
}
|
|
|
|
function wait_till_node_is_ready() {
|
|
local ready="False"
|
|
|
|
while ! [[ "${ready}" == "True" ]]; do
|
|
sleep 2s
|
|
ready=$(kubectl get node $NODE_NAME -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}')
|
|
done
|
|
}
|
|
|
|
function configure_cri_runtime() {
|
|
configure_different_shims_base
|
|
|
|
case $1 in
|
|
crio)
|
|
configure_crio
|
|
;;
|
|
containerd | k3s | k3s-agent | rke2-agent | rke2-server | k0s-controller | k0s-worker)
|
|
configure_containerd "$1"
|
|
;;
|
|
esac
|
|
if [ "$1" == "k0s-worker" ] || [ "$1" == "k0s-controller" ]; then
|
|
# do nothing, k0s will automatically load the config on the fly
|
|
:
|
|
else
|
|
host_systemctl daemon-reload
|
|
host_systemctl restart "$1"
|
|
fi
|
|
|
|
wait_till_node_is_ready
|
|
}
|
|
|
|
function backup_shim() {
|
|
local shim_file="$1"
|
|
local shim_backup="${shim_file}.bak"
|
|
|
|
if [ -f "${shim_file}" ]; then
|
|
echo "warning: ${shim_file} already exists" >&2
|
|
if [ ! -f "${shim_backup}" ]; then
|
|
mv "${shim_file}" "${shim_backup}"
|
|
else
|
|
rm -f "${shim_file}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function configure_different_shims_base() {
|
|
# Currently containerd has an assumption on the location of the shimv2 implementation
|
|
# This forces kata-deploy to create files in a well-defined location that's part of
|
|
# the PATH, pointing to the containerd-shim-kata-v2 binary in /opt/kata/bin
|
|
# Issues:
|
|
# https://github.com/containerd/containerd/issues/3073
|
|
# https://github.com/containerd/containerd/issues/5006
|
|
|
|
local default_shim_file="/usr/local/bin/containerd-shim-kata-v2"
|
|
|
|
mkdir -p /usr/local/bin
|
|
|
|
for shim in "${shims[@]}"; do
|
|
local shim_binary="containerd-shim-kata-${shim}-v2"
|
|
local shim_file="/usr/local/bin/${shim_binary}"
|
|
|
|
backup_shim "${shim_file}"
|
|
|
|
if [[ "${shim}" == "dragonball" ]]; then
|
|
ln -sf /opt/kata/runtime-rs/bin/containerd-shim-kata-v2 "${shim_file}"
|
|
else
|
|
ln -sf /opt/kata/bin/containerd-shim-kata-v2 "${shim_file}"
|
|
fi
|
|
chmod +x "$shim_file"
|
|
|
|
if [ "${shim}" == "${default_shim}" ]; then
|
|
backup_shim "${default_shim_file}"
|
|
|
|
echo "Creating the default shim-v2 binary"
|
|
ln -sf "${shim_file}" "${default_shim_file}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
function restore_shim() {
|
|
local shim_file="$1"
|
|
local shim_backup="${shim_file}.bak"
|
|
|
|
if [ -f "${shim_backup}" ]; then
|
|
mv "$shim_backup" "$shim_file"
|
|
fi
|
|
}
|
|
|
|
function cleanup_different_shims_base() {
|
|
local default_shim_file="/usr/local/bin/containerd-shim-kata-v2"
|
|
|
|
for shim in "${shims[@]}"; do
|
|
local shim_binary="containerd-shim-kata-${shim}-v2"
|
|
local shim_file="/usr/local/bin/${shim_binary}"
|
|
|
|
rm -f "${shim_file}"
|
|
|
|
restore_shim "${shim_file}"
|
|
done
|
|
|
|
rm -f "${default_shim_file}"
|
|
restore_shim "${default_shim_file}"
|
|
|
|
if [[ "${CREATE_RUNTIMECLASSES}" == "true" ]]; then
|
|
delete_runtimeclasses
|
|
fi
|
|
}
|
|
|
|
function configure_crio_runtime() {
|
|
local runtime="kata"
|
|
local configuration="configuration"
|
|
if [ -n "${1-}" ]; then
|
|
runtime+="-$1"
|
|
configuration+="-$1"
|
|
fi
|
|
|
|
local kata_path="/usr/local/bin/containerd-shim-${runtime}-v2"
|
|
local kata_conf="crio.runtime.runtimes.${runtime}"
|
|
local kata_config_path="/opt/kata/share/defaults/kata-containers/$configuration.toml"
|
|
|
|
cat <<EOF | tee -a "$crio_drop_in_conf_file"
|
|
|
|
# Path to the Kata Containers runtime binary that uses the $1
|
|
[$kata_conf]
|
|
runtime_path = "${kata_path}"
|
|
runtime_type = "vm"
|
|
runtime_root = "/run/vc"
|
|
runtime_config_path = "${kata_config_path}"
|
|
privileged_without_host_devices = true
|
|
EOF
|
|
}
|
|
|
|
function configure_crio() {
|
|
# Configure crio to use Kata:
|
|
echo "Add Kata Containers as a supported runtime for CRIO:"
|
|
|
|
# As we don't touch the original configuration file in any way,
|
|
# let's just ensure we remove any exist configuration from a
|
|
# previous deployment.
|
|
mkdir -p "$crio_drop_in_conf_dir"
|
|
rm -f "$crio_drop_in_conf_file"
|
|
touch "$crio_drop_in_conf_file"
|
|
|
|
for shim in "${shims[@]}"; do
|
|
configure_crio_runtime $shim
|
|
done
|
|
|
|
|
|
if [ "${DEBUG}" == "true" ]; then
|
|
cat <<EOF | tee -a $crio_drop_in_conf_file_debug
|
|
[crio]
|
|
log_level = "debug"
|
|
EOF
|
|
fi
|
|
}
|
|
|
|
function configure_containerd_runtime() {
|
|
local runtime="kata"
|
|
local configuration="configuration"
|
|
if [ -n "${2-}" ]; then
|
|
runtime+="-$2"
|
|
configuration+="-$2"
|
|
fi
|
|
local pluginid=cri
|
|
|
|
# if we are running k0s auto containerd.toml generation, the base template is by default version 2
|
|
# we can safely assume to reference the older version of cri
|
|
if grep -q "version = 2\>" $containerd_conf_file || [ "$1" == "k0s-worker" ] || [ "$1" == "k0s-controller" ]; then
|
|
pluginid=\"io.containerd.grpc.v1.cri\"
|
|
fi
|
|
local runtime_table="plugins.${pluginid}.containerd.runtimes.$runtime"
|
|
local runtime_type="io.containerd.$runtime.v2"
|
|
local options_table="$runtime_table.options"
|
|
local config_path="/opt/kata/share/defaults/kata-containers/$configuration.toml"
|
|
if grep -q "\[$runtime_table\]" $containerd_conf_file; then
|
|
echo "Configuration exists for $runtime_table, overwriting"
|
|
sed -i "/\[$runtime_table\]/,+1s#runtime_type.*#runtime_type = \"${runtime_type}\"#" $containerd_conf_file
|
|
else
|
|
cat <<EOF | tee -a "$containerd_conf_file"
|
|
[$runtime_table]
|
|
runtime_type = "${runtime_type}"
|
|
privileged_without_host_devices = true
|
|
pod_annotations = ["io.katacontainers.*"]
|
|
EOF
|
|
fi
|
|
|
|
if grep -q "\[$options_table\]" $containerd_conf_file; then
|
|
echo "Configuration exists for $options_table, overwriting"
|
|
sed -i "/\[$options_table\]/,+1s#ConfigPath.*#ConfigPath = \"${config_path}\"#" $containerd_conf_file
|
|
else
|
|
cat <<EOF | tee -a "$containerd_conf_file"
|
|
[$options_table]
|
|
ConfigPath = "${config_path}"
|
|
EOF
|
|
fi
|
|
|
|
if [ "${DEBUG}" == "true" ]; then
|
|
if grep -q "\[debug\]" $containerd_conf_file; then
|
|
sed -i 's/level.*/level = \"debug\"/' $containerd_conf_file
|
|
else
|
|
cat <<EOF | tee -a "$containerd_conf_file"
|
|
[debug]
|
|
level = "debug"
|
|
EOF
|
|
fi
|
|
|
|
fi
|
|
}
|
|
|
|
function configure_containerd() {
|
|
# Configure containerd to use Kata:
|
|
echo "Add Kata Containers as a supported runtime for containerd"
|
|
|
|
mkdir -p /etc/containerd/
|
|
|
|
if [ -f "$containerd_conf_file" ]; then
|
|
# backup the config.toml only if a backup doesn't already exist (don't override original)
|
|
cp -n "$containerd_conf_file" "$containerd_conf_file_backup"
|
|
fi
|
|
|
|
# Add default Kata runtime configuration
|
|
configure_containerd_runtime "$1"
|
|
|
|
for shim in "${shims[@]}"; do
|
|
configure_containerd_runtime "$1" $shim
|
|
done
|
|
}
|
|
|
|
function remove_artifacts() {
|
|
echo "deleting kata artifacts"
|
|
rm -rf /opt/kata/*
|
|
}
|
|
|
|
function cleanup_cri_runtime() {
|
|
cleanup_different_shims_base
|
|
|
|
case $1 in
|
|
crio)
|
|
cleanup_crio
|
|
;;
|
|
containerd | k3s | k3s-agent | rke2-agent | rke2-server | k0s-controller | k0s-worker)
|
|
cleanup_containerd
|
|
;;
|
|
esac
|
|
|
|
}
|
|
|
|
function cleanup_crio() {
|
|
rm -f $crio_drop_in_conf_file
|
|
if [[ "${DEBUG}" == "true" ]]; then
|
|
rm -f $crio_drop_in_conf_file_debug
|
|
fi
|
|
}
|
|
|
|
function cleanup_containerd() {
|
|
rm -f $containerd_conf_file
|
|
if [ -f "$containerd_conf_file_backup" ]; then
|
|
mv "$containerd_conf_file_backup" "$containerd_conf_file"
|
|
fi
|
|
}
|
|
|
|
function reset_runtime() {
|
|
kubectl label node "$NODE_NAME" katacontainers.io/kata-runtime-
|
|
if [ "$1" == "k0s-worker" ] || [ "$1" == "k0s-controller" ]; then
|
|
# do nothing, k0s will auto restart
|
|
:
|
|
else
|
|
host_systemctl daemon-reload
|
|
host_systemctl restart "$1"
|
|
fi
|
|
|
|
if [ "$1" == "crio" ] || [ "$1" == "containerd" ]; then
|
|
host_systemctl restart kubelet
|
|
fi
|
|
|
|
wait_till_node_is_ready
|
|
}
|
|
|
|
function main() {
|
|
echo "Environment variables passed to this script"
|
|
echo "* NODE_NAME: ${NODE_NAME}"
|
|
echo "* DEBUG: ${DEBUG}"
|
|
echo "* SHIMS: ${SHIMS}"
|
|
echo "* DEFAULT_SHIM: ${DEFAULT_SHIM}"
|
|
echo "* CREATE_RUNTIMECLASSES: ${CREATE_RUNTIMECLASSES}"
|
|
echo "* CREATE_DEFAULT_RUNTIMECLASS: ${CREATE_DEFAULT_RUNTIMECLASS}"
|
|
|
|
# script requires that user is root
|
|
euid=$(id -u)
|
|
if [[ $euid -ne 0 ]]; then
|
|
die "This script must be run as root"
|
|
fi
|
|
|
|
runtime=$(get_container_runtime)
|
|
|
|
# CRI-O isn't consistent with the naming -- let's use crio to match the service file
|
|
if [ "$runtime" == "cri-o" ]; then
|
|
runtime="crio"
|
|
elif [ "$runtime" == "k3s" ] || [ "$runtime" == "k3s-agent" ] || [ "$runtime" == "rke2-agent" ] || [ "$runtime" == "rke2-server" ]; then
|
|
containerd_conf_tmpl_file="${containerd_conf_file}.tmpl"
|
|
if [ ! -f "$containerd_conf_tmpl_file" ]; then
|
|
cp "$containerd_conf_file" "$containerd_conf_tmpl_file"
|
|
fi
|
|
|
|
containerd_conf_file="${containerd_conf_tmpl_file}"
|
|
containerd_conf_file_backup="${containerd_conf_file}.bak"
|
|
elif [ "$runtime" == "k0s-worker" ] || [ "$runtime" == "k0s-controller" ]; then
|
|
# From 1.27.1 onwards k0s enables dynamic configuration on containerd CRI runtimes.
|
|
# This works by k0s creating a special directory in /etc/k0s/containerd.d/ where user can drop-in partial containerd configuration snippets.
|
|
# k0s will automatically pick up these files and adds these in containerd configuration imports list.
|
|
containerd_conf_file="/etc/containerd/kata-containers.toml"
|
|
else
|
|
# runtime == containerd
|
|
if [ ! -f "$containerd_conf_file" ] && [ -d $(dirname "$containerd_conf_file") ] && \
|
|
[ -x $(command -v containerd) ]; then
|
|
containerd config default > "$containerd_conf_file"
|
|
fi
|
|
fi
|
|
|
|
action=${1:-}
|
|
if [ -z "$action" ]; then
|
|
print_usage
|
|
die "invalid arguments"
|
|
fi
|
|
|
|
# only install / remove / update if we are dealing with CRIO or containerd
|
|
if [[ "$runtime" =~ ^(crio|containerd|k3s|k3s-agent|rke2-agent|rke2-server|k0s-worker|k0s-controller)$ ]]; then
|
|
|
|
case "$action" in
|
|
install)
|
|
install_artifacts
|
|
configure_cri_runtime "$runtime"
|
|
kubectl label node "$NODE_NAME" --overwrite katacontainers.io/kata-runtime=true
|
|
;;
|
|
cleanup)
|
|
cleanup_cri_runtime "$runtime"
|
|
kubectl label node "$NODE_NAME" --overwrite katacontainers.io/kata-runtime=cleanup
|
|
remove_artifacts
|
|
;;
|
|
reset)
|
|
reset_runtime $runtime
|
|
;;
|
|
*)
|
|
echo invalid arguments
|
|
print_usage
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
#It is assumed this script will be called as a daemonset. As a result, do
|
|
# not return, otherwise the daemon will restart and rexecute the script
|
|
sleep infinity
|
|
}
|
|
|
|
main "$@"
|