Tech story/Container

Container의 kernel 튜닝

kt cloud 테크블로그 2024. 11. 7. 14:00

[kt cloud Container개발팀 정선훈 님]

 

Container의 kernel 튜닝

 

Kubernetes Worker Node는 대부분의 워크로드의 요구사항을 충족하는 안정성 및 최적화, 성능에 맞게 구성되지만 특정 워크로드의 성능 최적화를 위해 kernel 설정을 변경해야 하는 경우가 있을 수 있습니다.

 

Kubernetes에서는 sysctl 설정을 통해 Pod에 독립적으로 kernel 파라미터 수정을 할 수 있도록 제공하고 있습니다.

 

본 글은 워크로드 성능 최적화를 위해 Pod별로 kernel 파라미터를 변경하는 방법에 대한 내용 입니다.

 

 

Container Kernel 파라미터

  • 컨테이너의 격리 메커니즘Linux의 Namespace를 통해 각각의 컨테이너는 독립적인 환경에서 실행되며, 호스트(VM)와 분리된 커널 파라미터를 가질 수 있습니다.
    • Namespace(Linux) : Linux에서 프로세스를 격리 시키는 기술/기능.
    • cgroup : cgroup 설정(각 컨테이너에 CPU, 메모리, 디스크 I/O 등의 리소스를 할당 및 제한. )은 kernel 파라미터에 영향을 미침.
  • Kubernetes는 namespace와 cgroup을 통해 container와 호스트(VM)의 kernel 파라미터를 격리하여 보안과 안정성을 강화하고 각각의 컨테이너가 독립적으로 운영되도록 하여, 호스트와 다른 kernel 파라미터를 가질 수 있게 만들어 줍니다.

sysctl 설정

 

  • Linux kernel 동작을 제어하는 명령어입니다.
  • K8S의 sysctls 설정은 Global(node-level)과 Namespace 항목으로 구분됩니다..
    • Global(node-level) - Host OS에서 kernel 파라미터를 변경하면 Pod kernel 파라미터도 변경.
    • Namespace - Host OS와는 격리되어 Host OS kernel을 변경하여도 Pod kernel 파라미터는 별개로 동작. Pod마다 sysctl로 kernel 파라미터 설정 가능.
  • K8S의 Namespace sysctls 설정은 safe와 unsafe 파라미터로 구분하여 관리됩니다.
  • safe 파라미터는 default로 enable 상태입니다.
  • unsafe 파라미터는 관리자의 수동작업 필요합니다. (사용 가능하게끔 enable 작업 필요)
  • K8S에서 커널 파라미터 변경을 위해 {spec.securityContest.sysctls} 에서 설정 가능합니다.

 

[safe 파라미터]

  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.tcp_syncookies
  • net.ipv4.ping_group_range
  • net.ipv4.ip_unprivileged_port_start

[unsafe 파라미터]

  • kernel.shm*
  • kernel.msg*
  • kernel.sem
  • fs.mqueue.*
  • net.*
  • “--allowed_unsafe_sysctls” 수동 설정 필요
  • 미설정 시 forbidden sysctl: ""커널 파라미터 명"" not allowlisted 에러 발생하며 컨테이너는ContainerStatusUnknown 상태가 됨.
  • 일부 파라미터는 지원되지 않아 설정 불가.
  • pod 내부에서 sysctl 조회시 조회되지않는 파라미터는 수정 불가.
  • 지원하지 않는 파라미터를 sysctls 설정시 pod 정상 기동 불가.
    (/proc/sys/ 하위 경로의 파라미터 설정값을 찾지 못해 No such file or directory 에러 발생)"

 

 

 

 

K8S 설정 방법

  • K8S 1.27 기준

unsafe sysctl 활성화 방법

1.. kubelet drop-in 파일 확인

systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
...중략...

 

2. kubelet EnvironmentFile 경로 확인

cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
...중략...
EnvironmentFile=-/etc/sysconfig/kubelet
...중략....
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

 

3.EnvironmentFile에 KUBELET_EXTRA_ARGS 추가.

vi /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--allowed-unsafe-sysctls=kernel.msg*,kernel.shm*,kernel.sem,fs.mqueue.*,net.*"
아래 네임스페이스 이외의 unsafe sysctl를 allow 할 경우 kubelet이 정상 동작 하지 않을 수 있음. (kubelet 에러 발생.)
  • kernel.shm*
  • kernel.msg*
  • kernel.sem
  • fs.mqueue.*
  • net.*

 

4.kubelet 재기동

systemctl daemon-reload
systemctl restart kubelet

 

5. 적용 확인

ps -ef | grep kubelet | grep allowed-unsafe

 

활성화된 unsafe sysctl를 container에 적용하는 방법

  1. pod의 security context 필드에 사용하려는 sysctl 파라미터 추가
    • deployment, statefulset, daemonset 모두 동일하게 사용 가능
apiVersion: v1
…중략…
spec:
  template:
    spec:
      securityContext:
        sysctls:
        - name: kernel.msgmax
          valule: "65536"
        - name: kernel.sem
          value: "32000  1024000000  10000  32000"
...중략...
  • unsafe sysctl 활성화 설정한 커널 파라미터 또는 safe sysctl 커널 파라미터만 지정
  • 활성화 하지 않은 unsafe sysctl 사용시, not allowlisted 에러 발생하며 컨테이너는ContainerStatusUnknown 상태가 됨

 

 

OCP/OKD 설정 방법

  • OKD 4.10 기준

unsafe sysctl 활성화 방법

1.machine config pool에 labels 추가

oc edit machineconfigpool worker
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfigPool
metadata:
  generation: 1
  labels:
    custom-kubelet: sysctl    ##추가
...중략....

 

2.kubelet config에 대한 custom resource (CR) 생성

vi set-sysctl-worker.yaml
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
metadata:
  name: custom-kubelet
spec:
  machineConfigPoolSelector:
    matchLabels:
      custom-kubelet: sysctl    ##1번의 labels과 동일하게 설정
  kubeletConfig:
    allowedUnsafeSysctls:         ##sysctl 허용할 커널 파라미터 명
      - "kernel.msgmax"
      - "kernel.msgmnb"

 

3.custom resource (CR) 적용

  • mcp가 수행되며 노드 재기동 발생.
oc apply -f set-sysctl-worker.yaml
아래 네임스페이스 이외의 unsafe sysctl를 allow 할 경우 mcp가 정상 동작 하지 않을 수 있음. (kubelet 에러 발생.)
  • kernel.shm*
  • kernel.msg*
  • kernel.sem
  • fs.mqueue.*
  • net.*

 

4.적용 확인

oc get machineconfig {99-worker-generated-kubelet} -o json | grep ownerReference -A7
…중략...
"ownerReferences": [
            {
                "apiVersion": "machineconfiguration.openshift.io/v1",
                "blockOwnerDeletion": true,
                "controller": true,
                "kind": "KubeletConfig",
                "name": "custom-kubelet",
…중략...

 

활성화된 unsafe sysctl를 container에 적용하는 방법

  1. pod의 security context 필드에 사용하려는 sysctl 파라미터 추가
    • deployment, statefulset, daemonset 모두 동일하게 사용 가능
apiVersion: v1
…중략…
spec:
  template:
    spec:
      securityContext:
        sysctls:
        - name: kernel.msgmax
          valule: "65536"
        - name: kernel.sem
          value: "32000  1024000000  10000  32000"
...중략...
  • unsafe sysctl 활성화 설정한 커널 파라미터 또는 safe sysctl 커널 파라미터만 지정
  • 활성화 하지 않은 unsafe sysctl 사용시, not allowlisted 에러 발생하며 컨테이너는ContainerStatusUnknown 상태가 됨