在 Nexus Kubernetes 節點上停用 cgroupsv2
控制群組 (或 "cgroups
") 可讓 Linux 作業系統將資源 (CPU 共用、記憶體、I/O 等) 配置到作業系統程序的階層。 這些資源可以與其他程序隔離,藉此啟用工作負載的容器化。
Linux 核心 4.5 中包含控制群組的增強版本 2 ("cgroupsv2")。 原始 cgroups
v1 與較新的 cgroups
v2 之間的主要差異在於,cgroups
v2 中僅允許單一階層的 cgroups
。 除了這項單一階層差異外,cgroups
v2 也對 cgroups
v1 所使用的虛擬檔案系統做了一些不具回溯相容性的變更,例如移除 tasks
虛擬檔案與 clone_children
功能。
不過,某些應用程式可能依賴較舊的 cgroups
v1 行為,本文件說明如何在用於 Operator Nexus Kubernetes 背景工作節點的較新 Linux 作業系統映像上停用 cgroups
v2。
Nexus Kubernetes 1.27 和更新版本
雖然 Kubernetes 1.25 已在 kubelet 中為 cgroups
v2 新增支援,但若要使用 cgroups
v2,就必須在 Linux 核心中加以啟用。
Operator Nexus Kubernetes 背景工作節點會執行與映像所啟用的 Kubernetes 版本相對應的特殊 Microsoft Azure Linux 版本 (先前稱為 CBL Mariner OS)。 背景工作節點的 Linux OS 映像依預設會在 Nexus Kubernetes 1.27 版中啟用 cgroups
v2。
在 1.27 之前的 Nexus Kubernetes 版本中不會啟用 cgroups
v2。
因此,您無須執行本指南中的步驟將 cgroups
v2 停用。
必要條件
在繼續進行本操作指南之前,建議您:
- 如需完整概觀和相關步驟,請參閱 Nexus Kubernetes 叢集快速入門指南。
- 確定您符合列出的必要條件,以確保能夠順暢實作指南。
套用 cgroupv2-disabling Daemonset
警告
如果您在已執行工作負載的 Kubernetes 叢集上執行此步驟,則任何在 Kubernetes 叢集節點上執行的工作負載都會終止,因為 Daemonset
會將主機電腦重新開機。
因此,強烈建議您先在新的 Nexus Kubernetes 叢集上套用此 Daemonset
,再排程工作負載。
將下列 Daemonset
定義複製到電腦上的檔案,以便您對要停用 cgroups
v2 的 Nexus Kubernetes 叢集執行 kubectl
命令。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: revert-cgroups
namespace: kube-system
spec:
selector:
matchLabels:
name: revert-cgroups
template:
metadata:
labels:
name: revert-cgroups
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: cgroup-version
operator: NotIn
values:
- v1
tolerations:
- operator: Exists
effect: NoSchedule
containers:
- name: revert-cgroups
image: mcr.microsoft.com/cbl-mariner/base/core:1.0
command:
- nsenter
- --target
- "1"
- --mount
- --uts
- --ipc
- --net
- --pid
- --
- bash
- -exc
- |
CGROUP_VERSION=`stat -fc %T /sys/fs/cgroup/`
if [ "$CGROUP_VERSION" == "cgroup2fs" ]; then
echo "Using v2, reverting..."
sed -i 's/systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all/systemd.unified_cgroup_hierarchy=0/' /boot/grub2/grub.cfg
reboot
fi
sleep infinity
securityContext:
privileged: true
hostNetwork: true
hostPID: true
hostIPC: true
terminationGracePeriodSeconds: 0
並套用 Daemonset
:
kubectl apply -f /path/to/daemonset.yaml
上述 Daemonset
會套用至叢集中所有的 Kubernetes 背景工作節點,但已套用 cgroup-version=v1
標籤的節點除外。 對於已啟用 cgroups
v2 的背景工作節點,Daemonset
會修改 Linux 核心的開機設定,並將機器重新開機。
您可以執行下列指令碼,藉以監視 Daemonset
的推出及其效果:
#!/bin/bash
set -x
# Set the DaemonSet name and label key-value pair
DAEMONSET_NAME="revert-cgroups"
NAMESPACE="kube-system"
LABEL_KEY="cgroup-version"
LABEL_VALUE="v1"
LOG_PATTERN="sleep infinity"
# Function to check if all pods are completed
check_pods_completed() {
local pods_completed=0
# Get the list of DaemonSet pods
pod_list=$(kubectl get pods -n "${NAMESPACE}" -l name="${DAEMONSET_NAME}" -o jsonpath='{range.items[*]}{.metadata.name}{"\n"}{end}')
# Loop through each pod
for pod in $pod_list; do
# Get the logs from the pod
logs=$(kubectl logs -n "${NAMESPACE}" "${pod}")
# Check if the logs end with the specified pattern
if [[ $logs == *"${LOG_PATTERN}"* ]]; then
((pods_completed++))
fi
done
# Return the number of completed pods
echo $pods_completed
}
# Loop until all pods are completed
while true; do
pods_completed=$(check_pods_completed)
# Get the total number of pods
total_pods=$(kubectl get pods -n "${NAMESPACE}" -l name=${DAEMONSET_NAME} --no-headers | wc -l)
if [ "$pods_completed" -eq "$total_pods" ]; then
echo "All pods are completed."
break
else
echo "Waiting for pods to complete ($pods_completed/$total_pods)..."
sleep 10
fi
done
# Once all pods are completed, add the label to the nodes
node_list=$(kubectl get pods -n "${NAMESPACE}" -l name=${DAEMONSET_NAME} -o jsonpath='{range.items[*]}{.spec.nodeName}{"\n"}{end}' | sort -u)
for node in $node_list; do
kubectl label nodes "${node}" ${LABEL_KEY}=${LABEL_VALUE}
echo "Added label '${LABEL_KEY}:${LABEL_VALUE}' to node '${node}'."
done
echo "Script completed."
上述指令碼會標示已停用 cgroups
v2 的節點。 此標示會從已使用 cgroups
v1 核心設定重新開機的節點中移除 Daemonset
。