IBM Cloud Docs
성능 튜닝

성능 튜닝

특정 성능 최적화 요구사항이 있는 경우, IBM Cloud® Kubernetes Service의 일부 클러스터 컴포넌트에 대한 기본 설정을 변경할 수 있습니다.

기본 설정을 변경하도록 선택한 경우 사용자가 직접 위험을 감수해야 합니다. 사용자 환경의 변경된 설정으로 인해 발생하는 잠재적 중단에 대해, 그리고 변경된 설정에 대한 테스트의 실행에 대해 사용자가 직접 책임을 져야 합니다.

기본 작업자 노드 설정

기본적으로 워커 노드에는 워커 풀을 만들 때 선택한 워커 노드 플레이버의 운영 체제 및 컴퓨팅 하드웨어가 적용됩니다.

운영 체제 사용자 정의

Kubernetes 버전 정보 에서 클러스터 버전별로 지원되는 운영 체제 목록을 찾을 수 있습니다. 클러스터에서 운영 체제를 혼합하거나 다른 운영 체제를 사용할 수는 없습니다.

작업자 노드를 최적화하려면 다음 정보를 고려하십시오.

  • 이미지 및 버전 업데이트: 작업자 노드 업데이트(예: 이미지 또는 Kubernetes 버전에 대한 보안 패치)는 IBM에서 제공합니다. 하지만, 작업자 노드에 업데이트를 적용하는 시기를 선택합니다. 자세한 정보는 클러스터, 작업자 노드, 클러스터 컴포넌트 업데이트를 참조하십시오.
  • 임시 수정사항: 팟(Pod)에 로그인하거나 다른 프로세스를 사용하여 작업자 노드 설정을 수정하는 경우 수정사항은 일시적입니다. 작업자 노드 라이프사이클 오퍼레이션(예: 자동 복구, 다시 로드, 업데이트 또는 작업자 노드 대체)은 수정사항을 기본 설정으로 다시 변경합니다.
  • 영구 수정: 워커 노드 수명 주기 작업 전반에 걸쳐 수정 사항을 유지하려면 init 컨테이너를 사용하는 데몬 세트를 만드세요. 자세한 정보는 기본 작업자 노드 설정을 수정하여 성능 최적화를 참조하십시오.

운영 체제에 대한 수정은 지원되지 않습니다. 기본 설정을 수정하는 경우 발생하는 문제를 디버그하고 해결하는 작업은 사용자의 책임입니다.

하드웨어 변경사항

작업자 노드당 CPU 및 메모리와 같은 컴퓨팅 하드웨어를 변경하려면 다음 옵션 중에서 선택하십시오.

워커 노드 커널 설정을 수정하여 성능 최적화하기

클러스터 작업자 노드는 대부분의 워크로드의 요구사항을 충족할 것으로 예상되는 안정성, 최적화 및 성능 레벨에 맞게 구성됩니다. 일반적으로 작업자 노드 커널 설정을 변경하면 비정상적이고 의도하지 않은 문제가 발생할 수 있으므로 이를 변경하지 않는 것이 좋습니다. 그러나 워크로드에 커널 설정을 변경해야 하는 매우 고유한 성능 최적화 요구사항이 있는 경우 사용자 정의 Kubernetes 디먼 세트를 적용하여 커널 구성을 변경할 수 있습니다. 이러한 변경사항은 심각한 부정적인 결과를 초래할 수 있으며 사용자 자신의 위험으로커널 설정 구성에 대한 변경사항을 구현해야 합니다.

커널 설정의 구성을 변경하는 경우, 작성한 정확한 변경사항을 문서화하고 저장해야 합니다. 클러스터와 관련된 문제에 대한 지원 티켓을 여는 경우 이러한 변경사항을 지정해야 합니다. 이러한 구성 변경으로 인해 문제가 발생할 수 있으며 문제 조사의 일부로 변경사항을 되돌리도록 요청을 받을 수 있습니다. 이 경우, 사용자는 사용자가 구현하는 커널 구성 변경사항을 되돌릴 책임이 있습니다.

기본 커널 설정을 변경하면 클러스터에 부정적인 영향을 미칠 수 있습니다. 이러한 변경은 사용자가 직접 수행해야 하는 위험이 있습니다.

init 컨테이너 가 있는 사용자 정의 Kubernetes DaemonSet 를 클러스터에 적용하여 기본 커널 설정을 변경할 수 있습니다. 디먼 세트는 기존 모든 작업자 노드에 대한 설정을 수정하고 설정을 클러스터에 프로비저닝된 새 작업자 노드에 적용합니다. init 컨테이너는 다른 파드가 워커 노드에서 스케줄되기 전에 이러한 수정이 이루어지도록 합니다. 팟(Pod)은 영향을 받지 않습니다.

샘플 권한 initContainer 을 실행하려면 모든 네임스페이스에 대해 관리자 IBM Cloud IAM 서비스 액세스 역할이 있어야 합니다. 배치를 위한 컨테이너가 초기화되면 권한이 삭제됩니다.

시작하기 전에: 계정에 로그인하십시오. If applicable, target the appropriate resource group. 클러스터에 대한 컨텍스트를 설정하십시오.

  1. worker-node-kernel-settings.yaml 파일에 다음 디먼 세트를 저장하십시오. spec.template.spec.initContainers 섹션에 조정할 sysctl 매개변수의 필드와 값을 추가하십시오. 이 디먼 세트 예에서는 net.core.somaxconn 설정을 통해 환경에 허용되고 net.ipv4.ip_local_port_range 설정을 통해 임시 포트 범위에 허용되는 기본 최대 연결 수를 변경합니다.
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: kernel-optimization
      namespace: kube-system
      labels:
        tier: management
        app: kernel-optimization
    spec:
      selector:
        matchLabels:
          name: kernel-optimization
      template:
        metadata:
          labels:
            name: kernel-optimization
        spec:
          hostNetwork: true
          hostPID: true
          hostIPC: true
          initContainers:
            - command:
                - sh
                - -c
                - sysctl -w net.ipv4.tcp_syn_retries="5"; sysctl -w net.ipv4.tcp_fin_timeout="15";
              image: us.icr.io/armada-master/network-alpine:latest
              imagePullPolicy: Always
              name: sysctl
              resources: {}
              securityContext:
                privileged: true
                capabilities:
                  add:
                    - NET_ADMIN
              volumeMounts:
                - name: modifysys
                  mountPath: /sys
          containers:
            - resources:
                requests:
                  cpu: 0.01
              image: us.icr.io/armada-master/network-alpine:latest
              name: sleepforever
              command: ["/bin/sh", "-c"]
              args:
                - >
                  while true; do
                    sleep 100000;
                  done
          volumes:
            - name: modifysys
              hostPath:
                path: /sys
    
  2. 작업자 노드에 디먼 세트를 적용하십시오. 변경사항은 즉시 적용됩니다.
    kubectl apply -f worker-node-kernel-settings.yaml
    

작업자 노드 sysctl 매개변수를 기본값으로 되돌리려면 다음 단계를 따르세요.

  1. 디먼 세트를 삭제하십시오. 사용자 정의 설정을 적용한 initContainers가 제거됩니다.
    kubectl delete ds kernel-optimization
    
  2. 클러스터의 모든 작업자 노드를 재부팅하십시오. 작업자 노드는 기본값이 적용되어 다시 온라인 상태가 됩니다.

팟(Pod) 성능 최적화

특정 성능 워크로드 요구가 있는 경우 팟(Pod) 네트워크 네임스페이스의 Linux 커널 sysctl 매개변수에 대한 기본 설정을 변경할 수 있습니다.

앱 파드의 커널 설정을 최적화하려면 각 배포에 대해 initContainer 패치를 각 배포에 대해 pod/ds/rs/deployment YAML에 삽입하면 됩니다. initContainer는 해당 성능의 최적화를 원하는 팟(Pod) 네트워크 네임스페이스에 있는 각 앱 배치에 추가됩니다.

시작하기 전에 샘플 권한 initContainer 을 실행할 수 있도록 모든 네임스페이스에 대해 관리자 IBM Cloud IAM 서비스 액세스 역할이 있는지 확인하세요. 배치를 위한 컨테이너가 초기화되면 권한이 삭제됩니다.

  1. 이름이 initContainer인 파일에 다음의 pod-patch.yaml 패치를 저장하고 튜닝할 sysctl 매개변수의 필드와 값을 추가하십시오. 이 initContainer 예는 net.core.somaxconn 설정을 통해 환경에서 허용되는 기본 최대 연결 수를 변경하고, net.ipv4.ip_local_port_range 설정을 통해 임시 포트 범위를 변경합니다.
    spec:
      template:
        spec:
          initContainers:
          - command:
            - sh
            - -c
            - sysctl -e -w net.core.somaxconn=32768;  sysctl -e -w net.ipv4.ip_local_port_range="1025 65535";
            image: alpine:3.6
            imagePullPolicy: IfNotPresent
            name: sysctl
            resources: {}
            securityContext:
              privileged: true
    
  2. 각 배치를 패치하십시오.
    kubectl patch deployment <deployment_name> --patch pod-patch.yaml
    
  3. 커널 설정에서 net.core.somaxconn 값을 변경한 경우에는 대부분의 앱이 업데이트된 값을 자동으로 사용할 수 있습니다. 그러나 일부 앱에서는 커널 값과 일치하도록 앱 코드의 대응되는 값을 수동으로 변경해야 할 수도 있습니다. 예를 들어, NGINX 앱이 실행되는 팟(Pod)의 성능을 튜닝 중인 경우에는 일치시킬 NGINX 앱 코드의 backlog 필드 값을 변경해야 합니다. 자세한 내용은 이 NGINX 블로그 게시물을 참조하세요.

네트워크 활성 유지 (keepalive) sysctl 설정 최적화

팟 (Pod) 에 일정 기간 동안 유휴 상태일 때 가끔 연결이 끊어지는 장기 실행 TCP 연결이 있는 경우, 팟 (Pod) 에 대한 sysctl 활성 유지 설정을 변경하는 것이 도움이 될 수 있습니다.

현재 클러스터의 모든 팟 (Pod) 에서 이러한 sysctl 활성 유지 (keepalive) 설정을 기본적으로 설정하는 방법은 없습니다. 모든 팟 (Pod) 에서 설정을 수정하는 가장 좋은 방법은 권한 있는 initContainer 를 사용하는 것입니다. test-ns 네임스페이스에서 배치를 위해 initContainer 를 설정하는 방법에 대한 다음 예제를 검토하십시오.

다음 예제 initContainer 를 배치하십시오. containers: 섹션을 사용자 고유의 애플리케이션 컨테이너로 변경해야 합니다. 그런 다음 initContainer 는 팟 (Pod) 의 모든 일반 컨테이너에 대해 sysctl 설정을 설정합니다. 모두 동일한 네트워크 네임스페이스를 공유하기 때문입니다.

```sh {: pre}
kubectl apply -f - << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-sysctl
  namespace: test-ns
  labels:
    run: test-sysctl
spec:
  replicas: 2
  selector:
    matchLabels:
      run: test-sysctl
  template:
    metadata:
      labels:
        run: test-sysctl
    spec:
      initContainers:
      - command:
        - sh
        - -c
        - sysctl -e -w net.ipv4.tcp_keepalive_time=40; sysctl -e -w net.ipv4.tcp_keepalive_intvl=15; sysctl -e -w net.ipv4.tcp_keepalive_probes=6;
        image: us.icr.io/armada-master/alpine:latest
        imagePullPolicy: IfNotPresent
        name: sysctl-init
        resources: {}
        securityContext:
          privileged: true
      containers:
      - name: test-sysctl
        image: us.icr.io/armada-master/alpine:latest
        command: ["sleep", "2592000"]
  EOF
```

클러스터 메트릭 제공자 리소스 조정

클러스터에는 kube-system 네임스페이스의 metrics-server 배치에서 제공하는 메트릭 서비스가 있습니다. metrics-server 리소스 요청은 클러스터의 노드 수를 기반으로 하며 작업자 노드당 30개 이하의 팟이 있는 클러스터에 맞게 최적화됩니다. 메트릭 서비스는 리소스 요청의 메모리 및 CPU 한계와 일치합니다.

메모리 요청이 너무 낮은 경우 metrics-service 컨테이너는 "메모리 부족이 강제 종료" 될 수 있습니다. CPU 요청이 너무 낮으면 CPU 스로틀링으로 인해 매우 느리게 응답하거나 라이브 및 준비 상태 프로브가 실패할 수 있습니다.

메모리 사용은 클러스터의 팟 수에 따라 결정됩니다. CPU 사용은 메트릭에 대한 요청 수 (HPA, kubectl top nodes / pods 등) 및 API 발견 요청에 의해 구동됩니다. metrics-server에서는 Kubernetes API를 제공하므로 API 발견을 사용하는 kubectl과(와) 같은 클라이언트가 메트릭을 사용하지 않는 경우에도 metrics-server에 일부 로드를 배치합니다.

다음 증상은 metrics-server 리소스를 조정할 필요가 있음을 나타낼 수 있습니다.

  • metrics-server이(가) 자주 다시 시작됩니다.

  • 네임스페이스를 삭제하면 네임스페이스가 Terminating 상태로 고착되고 kubectl describe namespace에는 메트릭 API 발견 오류를 보고하는 조건이 포함됩니다.

  • kubectl top pods, kubectl top nodes, 기타 kubectl 명령 또는 Kubernetes API를 사용하는 애플리케이션은 다음과 같이 Kubernetes 오류를 로깅합니다.

The server is currently unable to handle the request (get pods.metrics.k8s.io)
Discovery failed for some groups, 1 failing: unable to retrieve the complete list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to handle the request
  • HorizontalPodAutoscalers(HPA)는 배치를 스케일링하지 않습니다.

  • kubectl get apiservices v1beta1.metrics.k8s.io을(를) 실행하면 다음과 같은 상태가 됩니다.

NAME                     SERVICE                      AVAILABLE                      AGE
v1beta1.metrics.k8s.io   kube-system/metrics-server   False (FailedDiscoveryCheck)   139d

metrics-server-config 구성 맵 수정

총 요청을 컴퓨팅하는 데 사용되는 조정 가능한 "기본" 및 "노드당" 설정이 CPU와 메모리 모두에 있습니다.

  • baseCPU
  • cpuPerNode
  • baseMemory
  • memoryPerNode

여기서:

cpuRequest = baseCPU + cpuPerNode * number_of_nodes
memoryRequest = baseMemory + memoryPerNode * number_of_nodes

해당 계산의 노드 수는 "버킷 크기" 세트를 통해 생성되며 최소 크기는 16개의 노드입니다.

CPU는 1과(와) 같은 값 또는 100m(100밀리코어)과(와) 같은 분수 값을 사용하여 코어 단위로 요청합니다.

메모리는 다음의 선택적 접미부를 사용하여 바이트 단위로 요청합니다.

  • 베이스 2 1Ki = 1024): Ki (킬로바이트), Mi (메가바이트), Gi (기가바이트).
  • 메트릭 1k = 1000): k, M, G.

클러스터의 노드 수가 시간에 따라 증가(또는 변경)될 것으로 예상되는 경우 "노드당" 설정을 조정할 수 있습니다. 노드 수가 정적이면 "기본" 설정을 조정하십시오. 결국 총 CPU 및 메모리 값은 metrics-server 배치 리소스 요청에 설정됩니다.

메트릭 제공자의 configmap을 편집하여 기본 리소스를 변경할 수 있습니다. metrics-server 배치에서 직접 리소스 요청 또는 한계를 수정하지 마십시오. 값은 metrics-server-nanny 컨테이너로 겹쳐씁니다.

기본 metrics-server-config configmap은 다음과 같습니다.

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
    kubernetes.io/cluster-service: "true"
  name: metrics-server-config
  namespace: kube-system
data:
  NannyConfiguration: |-
    apiVersion: nannyconfig/v1alpha1
    kind: NannyConfiguration

이 예제에서는 모든 값이 정의되어 있는 configmap을 보여줍니다.

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
    kubernetes.io/cluster-service: "true"
  name: metrics-server-config
  namespace: kube-system
data:
  NannyConfiguration: |-
    apiVersion: nannyconfig/v1alpha1
    kind: NannyConfiguration
    baseCPU: 200m
    cpuPerNode: 1m
    baseMemory: 40Mi
    memoryPerNode: 6Mi

기본값은 다음과 같습니다.

baseCPU: 200m
cpuPerNode: 1m
baseMemory: 40Mi
memoryPerNode: 6Mi

configmap 편집

kubectl edit 명령을 사용하여 configmap을 편집할 수 있습니다.

kubectl edit cm metrics-server-config -n kube-system

변경하려는 필드를 추가하거나 편집한 다음, configmap을 저장하고 편집기를 종료하십시오.

IBM Cloud 제공 metrics-server에서는 configmap에서 변경사항이 있는지 모니터링하고 배치 리소스 요청을 자동으로 업데이트합니다. metrics-server이(가) 변경을 감지하고 업데이트된 설정을 기반으로 새 팟 세트를 롤아웃하는 데 최대 10분이 소요될 수 있습니다.

기본 설정 복원

metrics-server을(를) 기본 설정으로 복원하려면 구성 맵을 삭제하십시오. 몇 분 안에 다시 작성됩니다.

kubectl delete cm metrics-server-config -n kube-system

조정할 리소스 결정

kubectl describe pod 명령을 사용하여 팟 정의, 상태 정보 및 최근 이벤트를 가져오십시오.

kubectl get pod -n kube-system -l k8s-app=metrics-server
NAME                             READY   STATUS    RESTARTS   AGE
metrics-server-9fb4947d6-s6sgl   3/3     Running   0          2d4h
kubectl describe pod -n kube-system metrics-server-9fb4947d6-s6sgl

출력 예

Containers:
  metrics-server:
    Container ID:  containerd://fe3d07c9a2541242d36da8097de3896f740c1363f6d2bfd01b8d96a641192b1b
    Image:         registry.ng.bluemix.net/armada-master/metrics-server:v0.4.4
    Image ID:      registry.ng.bluemix.net/armada-master/metrics-server@sha256:c2c63900d0e080c2413b5f35c5a59b5ed3b809099355728cf47527aa3f35477c
    Port:          4443/TCP
    Host Port:     0/TCP
    Command:
      /metrics-server
      --metric-resolution=45s
      --secure-port=4443
      --tls-cert-file=/etc/metrics-server-certs/tls.crt
      --tls-private-key-file=/etc/metrics-server-certs/tls.key
    State:          Running
      Started:      Fri, 10 Sep 2021 17:31:39 +0000
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137
      Started:      Fri, 10 Sep 2021 05:59:51 +0000
      Finished:     Fri, 10 Sep 2021 17:31:37 +0000
    Ready:          True
    Restart Count:  36

Last State에서 OOMKilledReason을(를) 표시하면 메트릭 서버가 안정 상태가 되고 OOMkilled 상태가 되지 않고 몇 시간 이상 실행될 때까지 metrics-server-config ConfigMap에서 100Mi 이상씩 증분하여 메모리 요청을 늘리십시오.

Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137

Last state에서 ErrorReason 및 다음 예제의 항목과 같은 이벤트를 표시하면 메트릭 서버가 안정 상태가 되고 프로브 제한시간 때문에 강제 종료되지 않고 몇 시간 이상 실행될 때까지 metrics-server-config configmap에서 100m 이상씩 증분하여 CPU 요청을 늘리십시오.

Last State:     Terminated
  Reason: Error
  Exit Code: 137
Events:
Warning Unhealthy 46m (x5 over 80m) kubelet Liveness probe failed: Get "https://198.18.68.236:4443/livez": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Warning Unhealthy 26m (x65 over 89m) kubelet Liveness probe failed: Get "https://198.18.68.236:4443/livez": net/http: TLS handshake timeout
Warning Unhealthy 21m (x10 over 76m) kubelet Readiness probe failed: Get "https://198.18.68.236:4443/readyz": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning Unhealthy 115s (x93 over 90m) kubelet Readiness probe failed: Get "https://198.18.68.236:4443/readyz": net/http: TLS handshake timeout

먼저 메모리 요청을 조정한 다음 CPU 요청을 조정하여 안정된 구성에 도달하도록 이 프로세스를 몇 번 반복해야 합니다.

대용량 페이지 사용

클래식 인프라 Virtual Private Cloud

Kubernetes 버전 1.19 이상을 실행하는 클러스터에서 Kubernetes HugePages 스케줄링을 사용하도록 설정할 수 있습니다. 지원되는 페이지 크기는 페이지당 2MB이며 Kubernetes 기능 게이트의 기본 크기입니다.

대용량 페이지 스케줄은 IBM Cloud Kubernetes Service의 베타 기능이며 변경될 수 있습니다.

기본적으로 작업자 노드의 CPU는 청크나 페이지에 4KB의 RAM을 할당합니다. 앱에 추가 RAM이 필요한 경우 시스템은 계속해서 추가 페이지를 검색해야 하며, 이로 인해 처리 속도가 느려질 수 있습니다. 대용량 페이지를 사용하면 페이지 크기를 2MB로 늘려 인공지능(AI), IoT(Internet of Things) 또는 기계 학습 워크로드에 대한 데이터베이스와 같이 RAM 집약적 앱에 대한 성능을 높일 수 있습니다. 대용량 페이지에 대한 자세한 내용은 Linux 커널 문서를 참조하세요.

작업자 노드를 다시 부팅할 수 잇으며 대용량 페이지 구성이 지속됩니다. 그러나 대규모 페이지 구성은 다른 워커 노드 수명 주기 작업에서 지속되지 않습니다. 작업자 노드를 업데이트하거나 다시 로드하거나 대체하거나 추가할 때마다 인에이블먼트 단계를 반복해야 합니다.

  • IBM Cloud IAM의 클러스터에 대한 운영자 플랫폼 액세스 역할 및 관리자 서비스 액세스 역할

시작하기 전에: 계정에 로그인하십시오. If applicable, target the appropriate resource group. 클러스터에 대한 컨텍스트를 설정하십시오.

  1. hugepages-ds.yaml 구성 파일을 작성하여 대용량 페이지를 사용으로 설정하십시오. 다음 샘플 YAML은 디먼 세트를 사용하여 클러스터의 모든 작업자 노드에서 팟(Pod)을 실행합니다. vm.nr_hugepages 매개변수를 사용하여 작업자 노드에서 사용 가능한 대용량 페이지의 할당을 설정할 수 있습니다. 이 예에서는 대용량 페이지를 위해 총 1GB의 RAM이 할당된 상태에서 512페이지(페이지당 2MB)를 할당합니다.

    RAM 집약적 앱에 사용하는 작업자 풀과 같은 특정 작업자 노드에 대해서만 대용량 페이지를 사용으로 설정하시겠습니까? 워커 풀에 레이블을 지정하고 테스팅한 다음, 데몬 세트에 선호도 규칙을 추가하여 파드가 지정한 워커 풀의 워커 노드에만 배포되도록 합니다.

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: hugepages-enablement
      namespace: kube-system
      labels:
        tier: management
        app: hugepages-enablement
    spec:
      selector:
        matchLabels:
          name: hugepages-enablement
      template:
        metadata:
          labels:
            name: hugepages-enablement
        spec:
          hostPID: true
          initContainers:
            - command:
                - sh
                - -c
                # Customize allocated Hugepages by providing the value
                - "echo vm.nr_hugepages=512 > /etc/sysctl.d/90-hugepages.conf"
              image: alpine:3.6
              imagePullPolicy: IfNotPresent
              name: sysctl
              resources: {}
              securityContext:
                privileged: true
              volumeMounts:
                - name: modify-sysctld
                  mountPath: /etc/sysctl.d
          containers:
            - resources:
                requests:
                  cpu: 0.01
              image: alpine:3.6
              # once the init container completes, keep the pod running for worker node changes
              name: sleepforever
              command: ["/bin/sh", "-c"]
              args:
                - >
                  while true; do
                      sleep 100000;
                  done
          volumes:
            - name: modify-sysctld
              hostPath:
                path: /etc/sysctl.d
    
  2. 이전에 작성한 파일을 적용하십시오.

    kubectl apply -f hugepages-ds.yaml
    
  3. 팟(Pod)이 실행 중인지 확인하십시오.

    kubectl get pods
    
  4. 작업자 노드를 다시 부팅하여 각 작업자 노드에서 실행되는 kubelet을 다시 시작하십시오. kubelet을 다시 시작하려면 작업자 노드를 다시 로드하지 마십시오. kubelet이 대용량 페이지 인에이블먼트를 선택하기 전에 작업자 노드를 다시 로드하면 인에이블먼트가 실패합니다.

    1. 클러스터의 작업자 노드를 나열합니다.
      ibmcloud ks worker ls -c <cluster_name_or_ID>
      
    2. 작업자 노드를 다시 부팅하십시오. 여러 개의 -w 옵션을 포함하여 여러 워커 노드를 재부팅할 수 있지만, 앱이 중단되지 않도록 충분한 워커 노드가 동시에 실행되도록 해야 합니다.
      ibmcloud ks worker reboot -c <cluster_name_or_ID> -w <worker1_ID> -w <worker2_ID>
      
  5. 대용량 페이지를 볼륨으로 마운트하고 리소스 한계 및 요청을 사용하여 팟(Pod)이 사용하는 대용량 페이지 리소스의 양을 설정하는 hugepages-test.yaml 테스트 팟(Pod)을 작성하십시오. 참고: 레이블, 오염 및 친화성 규칙을 사용하여 선택 작업자 노드에만 대용량 페이지를 사용하는 경우 테스트 팟(Pod)에서 동일한 규칙을 포함하십시오.

    apiVersion: v1
    kind: Pod
    metadata:
      name: hugepages-example
    spec:
      containers:
      - name: hugepages-example
        image: fedora:34
        command:
        - sleep
        - inf
        volumeMounts:
        - mountPath: /hugepages-2Mi
          name: hugepage-2mi
        resources:
          limits:
            hugepages-2Mi: 100Mi
            memory: 100Mi
          requests:
            memory: 100Mi
      volumes:
      - name: hugepage-2mi
        emptyDir:
          medium: HugePages-2Mi
    
  6. 이전에 작성한 팟(Pod) 파일을 적용하십시오.

    kubectl apply -f hugepages-pod.yaml
    
  7. 팟(Pod)이 대용량 페이지 리소스를 사용하는지 확인하십시오.

    1. 팟(Pod)이 실행 중인지 확인하십시오. 대용량 페이지가 있는 작업자 노드가 사용 불가능한 경우 팟(Pod)이 실행되지 않습니다.
      kubectl get pods
      
    2. 팟(Pod)에 로그인하십시오.
      kubectl exec -it <pod> /bin/sh
      
    3. 팟(Pod)이 대용량 페이지의 크기를 볼 수 있는지 확인하십시오.
      ls /sys/kernel/mm/hugepages
      
      출력 예
      hugepages-1048576kB  hugepages-2048kB
      
  8. 선택사항: 인에이블먼트 디먼 세트를 제거하십시오. 나중에 대형 페이지를 사용하여 작업자 노드를 업데이트하거나 다시 로드하거나 대체하거나 추가해야 하는 경우 디먼 세트를 다시 작성해야 합니다.

    kubectl -n kube-system delete daemonset hugepages-enablement
    
  9. 작업자 노드를 업데이트하거나 다시 로드하거나 대체하거나 추가할 때마다 이러한 단계를 반복하십시오.

대용량 페이지가 있는 작업자 노드의 문제점을 해결하기 위해 작업자 노드만 다시 부팅할 수 있습니다. 대용량 페이지 구성은 작업자 노드 업데이트, 다시 로드, 대체 또는 추가와 같은 다른 작업자 노드 라이프사이클 오퍼레이션에서 지속되지 않습니다. 클러스터에서 대용량 페이지 구성을 제거하기 위해 작업자 노드를 모두 업데이트하거나 다시 로드하거나 대체할 수 있습니다.

Calico MTU(maximum transmission unit) 변경

사용자 환경의 네트워크 처리량 요구사항을 충족하도록 Calico 플러그인 MTU(maximum transmission unit)를 줄이거나 늘리십시오.

이 단계는 버전 1.29 이상을 실행하는 클러스터에 적용됩니다. 또한 모든 VPC 워커 노드는 점보 프레임을 지원하지만, 기존 인프라는 베어메탈 워커에서만 점보 프레임을 지원합니다.

특히 복잡한 네트워킹 환경에서는 최대 전송 단위(MTU) 값을 변경하면 예기치 않은 결과가 발생할 수 있습니다. 워크플로 중단을 방지하려면 프로덕션 클러스터를 변경하기 전에 개발 클러스터에서 이러한 변경 사항을 테스트하는 것이 좋습니다.

기본적으로 IBM Cloud Kubernetes Service 클러스터의 Calico 네트워크 플러그인의 MTU는 Satellite 클러스터의 경우 1450바이트, 새틀라이트가 Satellite 클러스터의 경우 1480바이트입니다. 대부분의 경우 이 기본 Calico MTU 값으로 패킷 드롭과 조각화를 방지하기에 충분합니다. 대부분의 호스트가 1500의 MTU 값을 사용하기 때문에 이 기본값은 Satellite 클러스터에 VXLAN 헤더에 50바이트의 추가 바이트를 제공하고 Satellite 클러스터에는 일부 포드-포드 클러스터 네트워크 트래픽에 사용되는 IP 헤더에 20바이트의 추가 바이트를 제공합니다. 클러스터의 모든 워커 노드는 동일한 Calico MTU 값을 사용해야 한다는 점에 유의하세요.

기본 Calico MTU를 수정해야 하는 다음과 같은 경우를 검토하십시오.

  • 포드-포드 네트워크 처리량을 개선해야 하고 클러스터 노드가 더 높은 호스트 MTU를 사용할 수 있는 경우, 호스트와 Calico MTU를 모두 늘릴 수 있습니다. 이를 "점보 프레임" 사용이라고 합니다. 일반적인 점보 프레임 MTU는 9000입니다. 이 경우 호스트 사설 네트워크 인터페이스를 9000의 MTU 값으로 설정하고 Calico MTU는 약간 낮은 값( Satellite 클러스터의 경우 8950, Satellite 클러스터의 경우 8980)으로 설정할 수 있습니다. Azure 가상 머신과 같은 일부 클라우드 공급자 하드웨어 또는 리소스는 점보 프레임을 지원하지 않거나 최대 4000의 MTU 값만 지원할 수 있습니다.
  • 클러스터에 대한 VPN 연결이 설정되어 있는 경우 일부 VPN 연결에서는 기본값보다 적은 수의 Calico MTU가 필요합니다. 더 작은 Calico MTU가 필요한지 여부를 VPN 서비스 제공자에게 확인하십시오.
시작하기 전에
워커 노드가 여전히 기본 MTU 값을 실행하는 경우 Calico 플러그인의 MTU 값을 늘리기 전에 먼저 워커 노드의 MTU 값을 늘리세요. 예를 들어, 다음 데몬 세트를 적용하여 워커 노드의 MTU를 9000바이트로 변경할 수 있습니다. ip link 명령에서 사용되는 인터페이스 이름은 작업자 노드의 유형에 따라 다릅니다.
  • Bare Metal 작업자 노드에 대한 예제 명령: ip link set dev bond0 mtu 9000;ip link set dev bond1 mtu 9000;
  • 예제 명령 VPC 2세대작업자 노드: ip link set dev ens3 mtu 9000;
  1. 다음 명령을 실행하여 클러스터 작업자 노드에 로그인하고 한 노드에서 다른 노드로 ping을 실행합니다. 노드 MTU가 1500 또는 1480으로만 설정되어 있으므로 이 시도는 실패할 것으로 예상됩니다. 다음 단계에서는 이러한 명령을 다시 실행하여 변경이 성공적으로 이루어졌는지 확인할 수 있습니다.

    1. 클러스터의 노드를 나열하십시오. 두 개의 정상 노드의 이름과 IP 주소를 저장합니다.

      kubectl get nodes -o wide
      
    2. 노드 중 하나에 로그인합니다. 노드 이름을 지정합니다.

      kubectl debug --image=us.icr.io/armada-master/network-alpine -it node/<NODE_NAME> -- sh
      
    3. 명령을 실행하여 한 노드에서 다른 노드로 핑합니다. 이전 단계에서 참조하지 않은 노드의 IP 주소를 지정합니다.

      ping -c1 -Mdo -s 8972 <OTHER_HOST_IP>
      
  2. 다음 예제 데몬셋을 사용하여 노드 MTU를 변경합니다. 이 MTU 값은 노드 간 트래픽에 적용됩니다. - ip link set dev ens3 mtu <MTU_VALUE> 줄을 수정하여 MTU 값을 포함하도록 합니다(예제에서는 MTU 값 9000을 사용). ens3 노드에 적합하지 않은 경우 ' ens3 인터페이스 이름을 변경해야 할 수도 있습니다.

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      labels:
        app: set-host-mtu
      name: set-host-mtu
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          name: set-host-mtu
      template:
        metadata:
          labels:
            name: set-host-mtu
        spec:
          containers:
          - args:
            - |
              while true; do
                sleep 100000;
              done
            command:
            - /bin/sh
            - -c
            image: us.icr.io/armada-master/network-alpine:latest
            imagePullPolicy: IfNotPresent
            name: sleepforever
            resources:
              requests:
                cpu: 10m
          hostNetwork: true
          initContainers:
          - command:
            - sh
            - -c
            - ip link set dev ens3 mtu 9000
            image: us.icr.io/armada-master/network-alpine:latest
            imagePullPolicy: IfNotPresent
            name: set-host-mtu
            securityContext:
              capabilities:
                add:
                - NET_ADMIN
              privileged: true
            volumeMounts:
            - mountPath: /sys
              name: modifysys
          restartPolicy: Always
          terminationGracePeriodSeconds: 2
          tolerations:
          - operator: Exists
          volumes:
          - hostPath:
              path: /sys
              type: ""
            name: modifysys
      updateStrategy:
        rollingUpdate:
          maxSurge: 0
          maxUnavailable: 1
        type: RollingUpdate
    
  3. 데몬셋을 적용하여 노드 MTU 값을 변경합니다.

      kubectl apply -f <file_name>
    
  4. 명령을 다시 실행하여 큰 패킷 크기를 사용하여 노드에 로그인하고 한 호스트에서 다른 호스트로 핑하는 명령을 실행합니다. 이제 노드 MTU 값을 늘렸으므로 ' ping ' 명령이 성공할 것으로 예상됩니다.

    kubectl debug --image=us.icr.io/armada-master/network-alpine -it node/<NODE_NAME> -- sh
    
    ping -c1 -Mdo -s 8972 <OTHER_HOST_IP>
    
  5. 시간을 내어 새 노드 MTU 값으로 클러스터를 테스트하세요. Calico MTU 값 변경을 계속하기 전에 애플리케이션이 여전히 예상대로 작동하는지 확인하는 것이 좋습니다.

  6. 명령을 실행하여 Calico MTU 값을 업데이트하여 파드 간 트래픽도 더 큰 MTU를 사용할 수 있도록 합니다. Satellite 코어 OS 클러스터의 경우, Calico MTU 값은 노드 MTU 값보다 50바이트 작아야 합니다. 다른 모든 클러스터의 경우 Calico MTU 값은 20바이트 더 작아야 합니다. 예를 들어 노드 MTU에 9000을 지정한 경우, Calico MTU는 Satellite Core OS 클러스터의 경우 8950, 다른 모든 클러스터의 경우 8980이 되어야 합니다.

    kubectl patch installation.operator.tigera.io default --type='merge' -p '{"spec":{"calicoNetwork":{"mtu":<MTU_VALUE>}}}'
    

    ' kubectl edit installation.operator.tigera.io default'을 실행하여 리소스를 직접 편집할 수도 있습니다.

  7. 모든 노드를 신중하게 재부팅하여 이러한 변경 사항을 모든 노드에 적용합니다. 이러한 변경으로 인해 워크로드가 중단될 수 있으므로 이 단계를 계속 진행하기 전에 개발 클러스터에서 이 프로세스를 테스트했는지 확인하세요. 노드를 재부팅하려면 노드를 하나씩 연결 해제하고 전원을 차단한 후 재부팅하는 것이 좋습니다.

프로덕션 클러스터에서 이러한 단계를 완료하는 경우 프로덕션 노드를 업데이트하거나 교체할 때 사용하는 것과 동일한 프로세스를 사용해야 합니다. 프로덕션 클러스터에서 이 단계를 완료하기 전에 테스트 클러스터에서 이 전체 프로세스를 테스트하는 것이 좋습니다.

재부팅 프로세스 중에 일부 파드는 새로운 더 큰 MTU를 사용하고 일부 파드는 여전히 원래의 더 작은 MTU를 사용합니다. 일반적으로 이 시나리오에서는 양측이 정확한 최대 패킷 크기를 협상하기 때문에 문제가 발생하지 않습니다. 그러나 ICMP 패킷을 차단하면 협상이 작동하지 않을 수 있으며 모든 재부팅이 완료될 때까지 클러스터에 파드 연결 문제가 발생할 수 있습니다. 이 프로세스는 먼저 개발 클러스터에서 테스트하는 것이 중요합니다.

포트 맵 플러그인 사용 안함

Calico 컨테이너 네트워크 인터페이스(CNI)의 portmap 플러그인은 작업자 노드의 특정 포트에서 앱 팟(Pod)을 노출시키기 위해 hostPort를 사용할 수 있도록 합니다. 포트 맵 플러그인을 Calico CNI 구성에서 제거하여 iptables 성능 문제를 방지하십시오.

클러스터에 많은 서비스가 있거나(예: 500개 이상의 서비스) 서비스에 많은 포트가 있는 경우(예: 10개 이상의 서비스에 대한 서비스당 50개 이상의 포트) 이러한 서비스의 Calico 및 Kubernetes 네트워크 정책에 대해 많은 iptables 규칙이 생성됩니다. 많은 iptables 규칙을 사용하면 포트 맵 플러그인의 성능 문제가 발생할 수 있으며, 지정된 시간 내에 iptables 규칙을 업데이트하기 위한 잠금이 수신되지 않으면 calico-node 컨테이너가 다시 시작되거나 향후 iptables 규칙의 업데이트가 불가능해질 수 있습니다. 이러한 성능 문제를 방지하려는 경우에는 클러스터의 Calico CNI 구성에서 포트 맵 플러그인을 제거하여 이를 사용 안함으로 설정할 수 있습니다.

hostPorts를 사용해야 하는 경우 포트 맵 플러그인을 사용 안함으로 설정하지 마십시오.

Kubernetes 버전 1.29 이상에서 포트 맵 플러그인 사용 안함

  1. default Calico 설치 리소스를 편집하십시오.
    kubectl edit installation default -n calico-system
    
  2. spec.calicoNetwork 섹션에서 hostPorts의 값을 Disabled로 변경하십시오.
    ...
    spec:
      calicoNetwork:
        hostPorts: Disabled
        ipPools:
        - cidr: 172.30.0.0/16
          encapsulation: IPIPCrossSubnet
          natOutgoing: Enabled
          nodeSelector: all()
        mtu: 1480
        nodeAddressAutodetectionV4:
          interface: (^bond0$|^eth0$|^ens6$|^ens3$)
      kubernetesProvider: OpenShift
      registry: registry.ng.bluemix.net/armada-master/
      variant: Calico
    status:
      variant: Calico
    
  3. 파일을 저장한 후 닫으십시오. 변경사항이 자동으로 적용됩니다.

Kubernetes 버전 1.28 이하에서 포트 맵 플러그인 사용 안함

  1. calico-config configmap 리소스를 편집하십시오.

    kubectl edit cm calico-config -n kube-system
    
  2. data.cni_network_config.plugins 섹션에서 kubernetes 플러그인 뒤에 있는 portmap 플러그인 섹션을 제거하십시오. portmap 섹션을 제거하면 구성이 다음과 유사하게 표시됩니다.

    apiVersion: v1
    data:
      calico_backend: bird
      cni_network_config: |-
        {
          "name": "k8s-pod-network",
          "cniVersion": "0.3.1",
          "plugins": [
            {
              "type": "calico",
              ...
            },
            {
              "type": "tuning",
              ...
            },
            {
              "type": "bandwidth",
              ...
            }
          ]
        }
      typha_service_name: calico-typha
      ...
    

    이 configmap에서 Calico 플러그인에 대한 다른 설정을 변경하는 작업은 지원되지 않습니다.

  3. 모든 calico-node 팟(Pod)을 다시 시작하여 클러스터에 변경사항을 적용하십시오.

    kubectl rollout restart daemonset -n kube-system calico-node