共用方式為


在 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