Kubernetes 실행기 문제 해결

Kubernetes 실행기를 사용할 때 일반적으로 발생하는 오류는 다음과 같습니다.

Job failed (system failure): timed out waiting for pod to start

클러스터가 poll_timeout에 의해 정의된 시간 초과 전에 빌드 포드를 예약할 수 없는 경우, 빌드 포드는 오류를 반환합니다. Kubernetes 스케줄러가 이를 삭제할 수 있어야 합니다.

이 문제를 해결하려면 config.toml 파일에서 poll_timeout 값을 증가시키십시오.

context deadline exceeded

작업 로그의 context deadline exceeded 오류는 일반적으로 Kubernetes API 클라이언트가 주어진 클러스터 API 요청에 대해 시간 초과에 도달했음을 나타냅니다.

Metrics of the kube-apiserver 클러스터 구성 요소에서 다음과 같은 징후가 있는지 확인하십시오:

  • 응답 지연 시간 증가.
  • 포드, 비밀, ConfigMap 및 기타 핵심(v1) 자원에 대한 일반적인 생성 또는 삭제 작업의 오류 비율.

kube-apiserver 작업에서 시간 초과로 인한 오류 로그는 다음과 같이 나타날 수 있습니다:

Job failed (system failure): prepare environment: context deadline exceeded
Job failed (system failure): prepare environment: setting up build pod: context deadline exceeded

경우에 따라 kube-apiserver 오류 응답은 실패하는 하위 구성 요소에 대한 추가 세부 정보를 제공할 수 있습니다(예: Kubernetes 클러스터의 etcdserver):

Job failed (system failure): prepare environment: etcdserver: request timed out
Job failed (system failure): prepare environment: etcdserver: leader changed
Job failed (system failure): prepare environment: Internal error occurred: resource quota evaluates timeout

이러한 kube-apiserver 서비스 실패는 빌드 포드를 생성하는 동안 또는 완료 후 정리 시도 중에 발생할 수 있습니다:

Error cleaning up secrets: etcdserver: request timed out
Error cleaning up secrets: etcdserver: leader changed

Error cleaning up pod: etcdserver: request timed out, possibly due to previous leader failure
Error cleaning up pod: etcdserver: request timed out
Error cleaning up pod: context deadline exceeded

Dial tcp xxx.xx.x.x:xxx: i/o timeout

이것은 일반적으로 Kubernetes API 서버에 의해 러너 관리자가 접근할 수 없음을 나타내는 Kubernetes 오류입니다.

이 문제를 해결하려면:

  • 네트워크 보안 정책을 사용하는 경우, 일반적으로 포트 443 또는 포트 6443 또는 둘 다에 대해 Kubernetes API에 대한 접근을 허용하십시오.
  • Kubernetes API가 실행 중인지 확인하십시오.

Kubernetes API와 통신할 때 연결이 거부됨

GitLab Runner가 Kubernetes API에 요청을 할 때 실패하는 경우, 이는 kube-apiserver 가 과부하되어 API 요청을 수락하거나 처리할 수 없기 때문일 가능성이 높습니다.

Error cleaning up podJob failed (system failure): prepare environment: waiting for pod running

Kubernetes가 작업 포드를 제때 예약하지 못할 때 다음 오류가 발생합니다.

GitLab Runner는 포드가 준비 상태가 되기를 기다리지만 실패한 후 포드를 정리하려고 시도하며 이 또한 실패할 수 있습니다.

Error: Error cleaning up pod: Delete "https://xx.xx.xx.x:443/api/v1/namespaces/gitlab-runner/runner-0001": dial tcp xx.xx.xx.x:443 connect: connection refused

Error: Job failed (system failure): prepare environment: waiting for pod running: Get "https://xx.xx.xx.x:443/api/v1/namespaces/gitlab-runner/runner-0001": dial tcp xx.xx.xx.x:443 connect: connection refused

문제 해결을 위해 Kubernetes 기본 노드와 kube-apiserver 인스턴스를 실행하는 모든 노드에서 확인하십시오.

이들이 클러스터에서 확장하려는 포드의 목표 수를 관리하는 데 필요한 모든 리소스를 보유하고 있는지 확인하십시오.

GitLab Runner가 포드가 Ready 상태에 도달하는 데 기다리는 시간을 변경하려면 poll_timeout 설정을 사용하십시오.

포드가 어떻게 예약되는지 또는 제때 예약되지 않는 이유를 더 잘 이해하려면 Kubernetes 스케줄러에 대해 읽어보세요.

요청이 요청된 타임아웃 내에 완료되지 않음

빌드 포드 생성 중에 관찰된 메시지 요청이 요청된 타임아웃 내에 완료되지 않음은 Kubernetes 클러스터에서 구성된 입회 제어 웹훅이 타임아웃되고 있음을 나타냅니다.

입회 제어 웹훅은 API 요청에 대한 모든 스코프를 가로챈 클러스터 수준의 관리 제어입니다. 시간이 지나면 실패를 유발할 수 있습니다.

입회 제어 웹훅은 가로챈 API 요청과 네임스페이스 소스를 세밀하게 제어할 수 있는 필터를 지원합니다. GitLab Runner의 Kubernetes API 호출이 입회 제어 웹훅을 통과할 필요가 없다면, 웹훅의 선택기/필터 구성을 변경하여 GitLab Runner 네임스페이스를 무시하거나, podAnnotations 또는 podLabels를 구성하여 GitLab Runner 포드에 대한 제외 레이블/주석을 적용할 수 있습니다. GitLab Runner Helm 차트 values.yaml에서 가능합니다.

예를 들어, GitLab Runner 관리 포드에서 발생하는 API 요청을 가로채는 DataDog 입회 제어 웹훅을 피하려면, 다음과 같이 추가할 수 있습니다:

podLabels:
  admission.datadoghq.com/enabled: false

Kubernetes 클러스터의 입회 제어 웹훅을 나열하려면 다음 명령을 실행하세요:

kubectl get validatingwebhookconfiguration -o yaml
kubectl get mutatingwebhookconfiguration -o yaml

입회 제어 웹훅이 타임아웃될 때 관찰되는 로그 형태는 다음과 같습니다:

작업 실패(시스템 오류): 환경 준비: 타임아웃: 요청이 요청된 타임아웃 내에 완료되지 않음
작업 실패(시스템 오류): 환경 준비: 자격 증명 설정: 타임아웃: 요청이 요청된 타임아웃 내에 완료되지 않음

입회 제어 웹훅의 실패는 다음과 같이 나타날 수 있습니다:

작업 실패(시스템 오류): 환경 준비: 자격 증명 설정: 내부 오류 발생: 웹훅 "example.webhook.service" 호출 실패

fatal: unable to access 'https://gitlab-ci-token:token@example.com/repo/proj.git/': 호스트를 확인할 수 없음: example.com

헬퍼 이미지alpine 버전을 사용하는 경우, Alpine의 musl의 DNS 리졸버와 관련된 DNS 문제가 있을 수 있습니다.

이 문제는 helper_image_flavor = "ubuntu" 옵션을 사용하면 해결될 수 있습니다.

docker: tcp://docker:2375에서 Docker 데몬에 연결할 수 없습니다. Docker 데몬이 실행되고 있습니까?

이 오류는 Docker-in-Docker를 사용할 때 DIND 서비스가 완전히 시작되기 전에 접근을 시도할 경우 발생할 수 있습니다. 더 자세한 설명은 이 문제를 참조하세요.

curl: (35) OpenSSL SSL_connect: github.com:443에 대한 연결에서 SSL_ERROR_SYSCALL

이 오류는 Docker-in-Docker를 사용할 때 DIND 최대 전송 단위(MTU)가 Kubernetes 오버레이 네트워크보다 클 경우 발생할 수 있습니다. DIND는 기본 MTU로 1500을 사용하며, 이는 기본 오버레이 네트워크를 통해 라우팅하기에는 너무 큽니다. DIND MTU는 서비스 정의 내에서 변경할 수 있습니다:

services:
  - name: docker:dind
    command: ["--mtu=1450"]

MountVolume.SetUp failed for volume "kube-api-access-xxxxx" : chown은 Windows에서 지원되지 않습니다

CI/CD 작업을 실행할 때 다음과 같은 오류가 발생할 수 있습니다:

MountVolume.SetUp failed for volume "kube-api-access-xxxxx" : chown c:\var\lib\kubelet\pods\xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\volumes\kubernetes.io~projected\kube-api-access-xxxxx\..2022_07_07_20_52_19.102630072\token: not supported by windows

이 문제는 서로 다른 운영 체제와 아키텍처를 가진 노드에서 빌드를 실행하기 위해 노드 선택기를 사용할 때 발생합니다.

문제를 해결하려면 nodeSelector를 구성하여 러너 관리자 포드가 항상 리눅스 노드에서 예약되도록 하세요. 예를 들어, values.yaml 파일에는 다음과 같은 내용이 포함되어야 합니다:

nodeSelector:
  kubernetes.io/os: linux

빌드 포드가 러너 IAM 역할 대신 워커 노드의 IAM 역할에 할당됩니다

이 문제는 워커 노드 IAM 역할에 올바른 역할을 가정할 권한이 없을 때 발생합니다. 이를 해결하려면, 워커 노드의 IAM 역할의 신뢰 관계에 sts:AssumeRole 권한을 추가하세요:

{
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::<AWS_ACCOUNT_NUMBER>:role/<IAM_ROLE_NAME>"
    },
    "Action": "sts:AssumeRole"
}

Preparation failed: invalid pull policy for image 'image-name:latest': pull_policy ([Always])가 GitLab 파이프라인 구성에서 허용된 pull_policies ([])에 포함되지 않음

이 문제는 .gitlab-ci.yml에서 pull_policy를 지정했지만 러너의 구성 파일에 정책이 구성되지 않았을 때 발생합니다. 이를 해결하려면 Docker pull policies 제한하기에 따라 allowed_pull_policies를 구성에 추가하세요.

백그라운드 프로세스가 작업을 중단시키고 타임아웃을 발생시킵니다

작업 실행 중 시작된 백그라운드 프로세스가 빌드 작업 종료를 방해할 수 있습니다. 이를 피하기 위해 다음과 같은 방법을 사용할 수 있습니다:

  • 프로세스를 더블 포크합니다. 예를 들어, command_to_run < /dev/null &> /dev/null &.
  • 작업 스크립트 종료 전에 프로세스를 종료합니다.

캐시 관련 permission denied 오류

작업에서 생성된 파일과 폴더는 특정 UNIX 소유권 및 권한을 가집니다.

파일 및 폴더가 아카이브되거나 추출될 때 UNIX 세부정보가 유지됩니다.

그러나 파일과 폴더는 헬퍼 이미지USER 구성과 불일치할 수 있습니다.

Creating cache ... 단계에서 권한 관련 오류가 발생하는 경우, 다음을 수행할 수 있습니다:

  • 해결책으로, 소스 데이터가 수정되었는지 조사합니다. 예를 들어, 캐시된 파일을 생성하는 작업 스크립트에서 수정된 경우입니다.

  • 해결 방법으로, 일치하는 chownchmod 명령을 추가합니다. (before_/after_)script: 지시문에 추가하세요.

빌드 컨테이너에서 init 시스템과 함께 나타나는 중복된 셸 프로세스

프로세스 트리에는 다음 중 하나일 때 셸 프로세스가 포함될 수 있습니다:

  • FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGYfalse이고 FF_USE_DUMB_INIT_WITH_KUBERNETES_EXECUTORtrue입니다.
  • 빌드 이미지의 ENTRYPOINT가 init 시스템(예: tini-init 또는 dumb-init)입니다.
UID    PID   PPID  C STIME TTY          TIME CMD
root     1      0  0 21:58 ?        00:00:00 /scripts-37474587-5556589047/dumb-init -- sh -c if [ -x /usr/local/bin/bash ]; then .exec /usr/local/bin/bash  elif [ -x /usr/bin/bash ]; then .exec /usr/bin/bash  elif [ -x /bin/bash ]; then .exec /bin/bash  elif [ -x /usr/local/bin/sh ]; then .exec /usr/local/bin/sh  elif [ -x /usr/bin/sh ]; then .exec /usr/bin/sh  elif [ -x /bin/sh ]; then .exec /bin/sh  elif [ -x /busybox/sh ]; then .exec /busybox/sh  else .echo shell not found .exit 1 fi
root     7      1  0 21:58 ?        00:00:00 /usr/bin/bash <---------------- 이건 뭐죠???
root    26      1  0 21:58 ?        00:00:00 sh -c (/scripts-37474587-5556589047/detect_shell_script /scripts-37474587-5556589047/step_script 2>&1 | tee -a /logs-37474587-5556589047/output.log) &
root    27     26  0 21:58 ?        00:00:00  \_ /usr/bin/bash /scripts-37474587-5556589047/step_script
root    32     27  0 21:58 ?        00:00:00  |   \_ /usr/bin/bash /scripts-37474587-5556589047/step_script
root    37     32  0 21:58 ?        00:00:00  |       \_ ps -ef --forest
root    28     26  0 21:58 ?        00:00:00  \_ tee -a /logs-37474587-5556589047/output.log

이 셸 프로세스는 sh, bash 또는 busybox일 수 있으며, PPID가 1이고 PID가 6 또는 7인 셸입니다. 이는 init 시스템(PID 1 위)에서 실행된 셸 감지 스크립트에 의해 시작된 셸입니다. 이 프로세스는 중복되지 않으며, 빌드 컨테이너가 init 시스템과 함께 실행될 때의 전형적인 운영입니다.

러너 포드가 작업 결과를 실행하지 않고 타임 아웃 발생

러너 포드가 GitLab에 등록된 후, 작업을 실행하려고 시도하지만 실행하지 않으며 작업이 결국 타임 아웃됩니다. 다음과 같은 오류가 보고됩니다:

타임아웃 실패가 발생했거나 작업이 중단되었습니다. 타임아웃 제한을 확인하거나 다시 시도하세요.

이 작업에는 추적이 없습니다.

이 경우, 러너는 다음과 같은 오류를 받을 수 있습니다,

HTTP 204 No content 응답 코드가 `jobs/request` API에 연결할 때 발생했습니다.

이 문제를 해결하려면, API에 POST 요청을 수동으로 보내 TCP 연결이 중단되었는지 확인하세요. TCP 연결이 중단된 경우, 러너는 CI 작업 페이로드를 요청할 수 없게 될 수 있습니다.

init-permissions 컨테이너에 대한 container name 예약 실패 gcs-fuse-csi-driver 사용 시

gcs-fuse-csi-driver csi 드라이버는 init 컨테이너에 대한 볼륨 마운트를 지원하지 않습니다. 이로 인해 이 드라이버를 사용할 때 init 컨테이너 시작이 실패할 수 있습니다. 이 버그를 해결하려면 Kubernetes 1.28에 도입된 기능이 드라이버 프로젝트에서 지원되어야 합니다.

오류: 오직 읽기 전용 루트 파일 시스템 컨테이너만 허용됩니다

읽기 전용으로 마운트된 루트 파일 시스템에서 컨테이너를 실행하도록 강제하는 승인 정책이 있는 클러스터에서는 다음과 같은 경우 이 오류가 발생할 수 있습니다:

  • GitLab Runner를 설치할 때.
  • GitLab Runner가 빌드 파드를 예약하려고 할 때.

이러한 승인 정책은 일반적으로 Gatekeeper 또는 Kyverno와 같은 승인 컨트롤러에 의해 시행됩니다. 예를 들어, 컨테이너가 읽기 전용 루트 파일 시스템에서 실행되도록 강제하는 정책은 readOnlyRootFilesystem Gatekeeper 정책입니다.

이 문제를 해결하려면:

  • 클러스터에 배포된 모든 파드는 securityContext.readOnlyRootFilesystemtrue로 설정하여 승인 정책을 준수해야 하며, 이를 통해 승인 컨트롤러가 파드를 차단하지 않도록 해야 합니다.

  • 컨테이너는 루트 파일 시스템이 읽기 전용으로 마운트된 상태에서도 성공적으로 실행되고 파일 시스템에 쓸 수 있어야 합니다.

GitLab Runner에 대하여

GitLab Runner가 GitLab Runner Helm 차트와 함께 배포되는 경우, GitLab 차트 구성을 업데이트하여 다음을 설정해야 합니다:

  • 적절한 securityContext 값:

    <...>
    securityContext:
      readOnlyRootFilesystem: true
    <...>
    
  • 파드가 쓸 수 있는 쓰기 가능한 파일 시스템을 마운트:

    <...>
    volumeMounts:
    - name: tmp-dir
      mountPath: /tmp
    volumes:
    - name: tmp-dir
      emptyDir:
        medium: "Memory"
    <...>
    

빌드 파드에 대하여

빌드 파드가 읽기 전용 루트 파일 시스템에서 실행되도록 하려면, config.toml의 각 컨테이너의 보안 컨텍스트를 설정합니다. GitLab 차트 변수를 runners.config로 설정하여 빌드 파드에 전달할 수 있습니다:

runners:
  config: |
   <...>
   [[runners]]
     [runners.kubernetes.build_container_security_context]
       read_only_root_filesystem = true
     [runners.kubernetes.init_permissions_container_security_context]
       read_only_root_filesystem = true
     [runners.kubernetes.helper_container_security_context,omitempty]
       read_only_root_filesystem = true
     # 이 섹션은 서비스가 있는 작업에만 필요합니다
     [runners.kubernetes.service_container_security_contextomitempty]
       read_only_root_filesystem = true
   <...>

빌드 파드와 해당 컨테이너가 읽기 전용 파일 시스템에서 성공적으로 실행되도록 하려면, 파드가 쓸 수 있는 위치에 쓰기 가능한 파일 시스템이 있어야 합니다.

최소한 이러한 위치는 빌드 및 홈 디렉토리여야 하며, 빌드 프로세스가 필요할 경우 다른 위치에 대한 쓰기 권한도 가질 수 있도록 해야 합니다.

홈 디렉토리는 일반적으로 프로그램이 성공적인 실행을 위해 필요한 구성 및 기타 데이터를 저장할 수 있도록 쓰기 가능해야 합니다. git 바이너리는 홈 디렉토리에 쓸 수 있어야 하는 프로그램의 한 예입니다.

홈 디렉토리를 경로와 관계없이 쓰기 가능하게 만들려면:

  1. 안정적인 경로에 볼륨을 마운트합니다(어떤 빌드 이미지를 사용하든 상관없이).
  2. 모든 빌드에 대해 환경 변수 $HOME을 전역적으로 설정하여 홈 디렉토리를 변경합니다.

config.toml에서 GitLab 차트 변수 runners.config 값을 업데이트하여 빌드 파드와 해당 컨테이너를 구성할 수 있습니다.

runners:
  config: |
   <...>
   [[runners]]
     environment = ["HOME=/build_home"]
     [[runners.kubernetes.volumes.empty_dir]]
       name = "repo"
       mount_path = "/builds"
     [[runners.kubernetes.volumes.empty_dir]]
       name = "build-home"
       mount_path = "/build_home"
   <...>

노트:

emptyDir 대신 다른 지원되는 볼륨 유형을 사용할 수 있습니다. 처리되지 않고 빌드 아티팩트로 저장되지않는 모든 파일은 일반적으로 덧없는 것이기 때문에 emptyDir이 대부분의 경우에 적합합니다.

AWS EKS: 포드를 정리하는 중 오류: pods “runner-**“를 찾을 수 없거나 상태가 “Failed”입니다.

Amazon EKS 존 재분배 기능은 자동 확장 그룹의 가용성 존을 균형 있게 유지합니다. 이 기능은 한 가용성 존에서 노드를 중지하고 다른 곳에 생성할 수 있습니다.

러너 작업은 중지하고 다른 노드로 이동할 수 없습니다. 이 오류를 해결하기 위해 러너 작업에 대해 이 기능을 비활성화하세요.