다음을 통해 공유


Nexus Kubernetes 노드에서 cgroupsv2 사용 안 함

제어 그룹또는 "cgroups"를 사용하면 Linux 운영 체제가 운영 체제 프로세스의 계층 구조에 리소스(CPU 공유, 메모리, I/O 등)를 할당할 수 있습니다. 이러한 리소스는 다른 프로세스에서 격리될 수 있으며 이러한 방식으로 워크로드를 컨테이너화할 수 있습니다.

제어 그룹의 향상된 버전 2("cgroupsv2")가 Linux 커널 4.5에 포함되었습니다. 원래 cgroups v1과 최신 cgroups v2의 주요 차이점은 v2에서 cgroups의 단일 계층만 cgroups v2에서 허용된다는 것입니다. 이 단일 계층 구조 차이 cgroups 외에도 v2는 cgroups v1이 사용한 의사 파일 시스템에 대해 이전 버전과 호환되지 않는 변경 작업을 수행합니다(예: tasks pseudofile 및 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를 사용하도록 설정합니다.

cgroups v2는 1.27 이전의 Nexus Kubernetes 버전에서 사용하도록 설정되지 않았습니다. 따라서 cgroups v2를 사용하지 않도록 설정하기 위해 이 가이드의 단계를 수행할 필요가 없습니다.

필수 조건

이 방법 가이드를 진행하기 전에 다음을 수행하는 것이 좋습니다.

  • 포괄적인 개요와 관련 단계는 Nexus Kubernetes 클러스터 빠른 시작 가이드를 참조하세요.
  • 가이드를 원활하게 구현하려면 간략한 필수 조건을 충족하는지 확인합니다.

cgroupv2-disabling Daemonset 적용

Warning

이미 실행 중인 워크로드가 있는 Kubernetes 클러스터에서 이 단계를 수행하는 경우 Daemonset이 호스트 컴퓨터를 다시 부팅하기 때문에 Kubernetes 클러스터 노드에서 실행되는 모든 워크로드는 종료됩니다. 따라서 워크로드가 예약되기 전에 새 Nexus Kubernetes 클러스터에 이 Daemonset을 적용하는 것이 매우 좋습니다.

cgroups v2를 사용하지 않도록 설정하려는 Nexus Kubernetes 클러스터에 대해 kubectl 명령을 실행할 수 있는 컴퓨터의 파일에 다음 Daemonset 정의를 복사합니다.

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

위의 Daemonsetcgroup-version=v1 레이블이 적용된 노드를 제외한 클러스터의 모든 Kubernetes 작업자 노드에 적용됩니다. 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이 제거됩니다.