Kubernetes 실행기 문제 해결
다음 오류는 Kubernetes 실행기를 사용할 때 일반적으로 발생합니다. 클러스터가 poll_timeout으로 정의된 타임아웃 이전에 빌드 Pod를 스케줄링할 수 없는 경우, 빌드 Pod가 오류를 반환합니다. 이 문제를 해결하려면 config.toml 파일에서 poll_timeout 값을 늘리세요.
다음 오류는 Kubernetes 실행기를 사용할 때 일반적으로 발생합니다.
Job failed (system failure): timed out waiting for pod to start#
클러스터가 poll_timeout으로 정의된 타임아웃 이전에 빌드 Pod를 스케줄링할 수 없는 경우, 빌드 Pod가 오류를 반환합니다. Kubernetes 스케줄러가 이를 삭제할 수 있어야 합니다.
이 문제를 해결하려면 config.toml 파일에서 poll_timeout 값을 늘리세요.
context deadline exceeded#
작업 로그에서 context deadline exceeded 오류는 일반적으로 Kubernetes API 클라이언트가 주어진 클러스터 API 요청에 대한 타임아웃에 도달했음을 나타냅니다.
다음 징후가 있는지 kube-apiserver 클러스터 구성 요소의 메트릭을 확인하세요:
- 증가된 응답 지연.
- Pod, 시크릿, 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 서비스 실패는 빌드 Pod 생성 중과 완료 후 정리 시도 중에도 발생할 수 있습니다:
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 pod과 Job failed (system failure): prepare environment: waiting for pod running#
다음 오류는 Kubernetes가 적시에 작업 Pod를 스케줄링하지 못할 때 발생합니다. GitLab Runner는 Pod가 준비될 때까지 기다리지만, 실패하면 Pod를 정리하려고 시도하며 이 역시 실패할 수 있습니다.
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 인스턴스를 실행하는 모든 노드를 확인하세요. 클러스터에서 스케일 업하려는 Pod의 대상 수를 관리하는 데 필요한 모든 리소스가 있는지 확인하세요.
GitLab Runner가 Pod가 Ready 상태가 될 때까지 기다리는 시간을 변경하려면 poll_timeout 설정을 사용하세요.
prepare 단계가 전체적으로 실행될 수 있는 시간(Pod 스케줄링 포함)을 제한하려면 prepare_timeout 설정을 사용하세요.
Pod가 스케줄링되는 방식이나 제때 스케줄링되지 않는 이유를 더 잘 이해하려면 Kubernetes 스케줄러에 대해 읽어보세요.
request did not complete within requested timeout#
빌드 Pod 생성 중에 관찰되는 request did not complete within requested timeout 메시지는 Kubernetes 클러스터의 구성된 어드미션 제어 웹훅이 타임아웃되고 있음을 나타냅니다.
어드미션 제어 웹훅은 클러스터 수준 관리 제어 인터셉터로, 범위가 지정된 모든 API 요청에 대해 작동하며, 제때 실행되지 않으면 실패를 야기할 수 있습니다.
어드미션 제어 웹훅은 인터셉트하는 API 요청과 네임스페이스 소스를 세밀하게 제어하는 필터를 지원합니다. GitLab Runner의 Kubernetes API 호출이 어드미션 제어 웹훅을 통과할 필요가 없는 경우, GitLab Runner 네임스페이스를 무시하도록 웹훅의 셀렉터/필터 구성을 변경하거나, GitLab Runner Helm Chart values.yaml에서 podAnnotations 또는 podLabels를 구성하여 GitLab Runner Pod에 제외 레이블/주석을 적용할 수 있습니다.
예를 들어, GitLab Runner 관리자 Pod가 수행하는 API 요청을 DataDog 어드미션 컨트롤러 웹훅이 인터셉트하지 않도록 하려면 다음을 추가할 수 있습니다:
podLabels:
admission.datadoghq.com/enabled: false
Kubernetes 클러스터의 어드미션 제어 웹훅 목록을 보려면 다음을 실행하세요:
kubectl get validatingwebhookconfiguration -o yaml
kubectl get mutatingwebhookconfiguration -o yaml
어드미션 제어 웹훅이 타임아웃될 때 다음 형태의 로그가 관찰될 수 있습니다:
Job failed (system failure): prepare environment: Timeout: request did not complete within requested timeout
Job failed (system failure): prepare environment: setting up credentials: Timeout: request did not complete within requested timeout
어드미션 제어 웹훅의 실패는 대신 다음과 같이 나타날 수 있습니다:
Job failed (system failure): prepare environment: setting up credentials: Internal error occurred: failed calling webhook "example.webhook.service"
오류 Could not resolve host: example.com#
헬퍼 이미지의 alpine 버전을 사용하는 경우, Alpine의 musl DNS 리졸버와 관련된 DNS 문제가 발생할 수 있습니다. 오류는 다음과 비슷하게 나타날 수 있습니다:
fatal: unable to access 'https://gitlab-ci-token:token@example.com/repo/proj.git/': Could not resolve host: example.com
이 문제를 해결하려면 helper_image_flavor = "ubuntu" 옵션을 사용하세요.
docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?#
이 오류는 DIND 서비스가 완전히 시작되기 전에 접근을 시도하는 경우 Docker-in-Docker 사용 시 발생할 수 있습니다. 자세한 설명은 이 이슈를 참조하세요.
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443#
이 오류는 DIND 최대 전송 단위(MTU)가 Kubernetes 오버레이 네트워크보다 큰 경우 Docker-in-Docker 사용 시 발생할 수 있습니다. DIND는 기본 MTU 1500을 사용하는데, 이는 기본 오버레이 네트워크를 통해 라우팅하기에는 너무 큽니다. DIND MTU는 서비스 정의 내에서 변경할 수 있습니다:
services:
- name: docker:dind
command: ["--mtu=1450"]
MountVolume.SetUp failed for volume "kube-api-access-xxxxx" : chown is not supported by 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
이 문제는 노드 셀렉터를 사용하여 다른 운영 체제와 아키텍처를 가진 노드에서 빌드를 실행할 때 발생합니다.
이 문제를 해결하려면, 러너 관리자 Pod가 항상 Linux 노드에 스케줄링되도록 nodeSelector를 구성하세요. 예를 들어, values.yaml 파일에 다음이 포함되어야 합니다:
nodeSelector:
kubernetes.io/os: linux
빌드 Pod에 Runner IAM 역할 대신 워커 노드의 IAM 역할이 할당됨#
이 문제는 워커 노드 IAM 역할에 올바른 역할을 수임할 권한이 없을 때 발생합니다. 이를 해결하려면, 워커 노드의 IAM 역할의 신뢰 관계에 sts:AssumeRole 권한을 추가하세요:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam:::role/"
},
"Action": "sts:AssumeRole"
}
오류: pull_policy ([Always]) defined in GitLab pipeline config is not one of the allowed_pull_policies#
이 문제는 .gitlab-ci.yml에 pull_policy를 지정했지만 Runner의 구성 파일에 정책이 구성되어 있지 않은 경우 발생합니다. 오류는 다음과 비슷하게 나타날 수 있습니다:
Preparation failed: invalid pull policy for image 'image-name:latest': pull_policy ([Always]) defined in GitLab pipeline config is not one of the allowed_pull_policies ([])
이 문제를 해결하려면 Docker 풀 정책 제한에 따라 구성에 allowed_pull_policies를 추가하세요.
백그라운드 프로세스로 인해 작업이 중단되고 타임아웃 발생#
작업 실행 중에 시작된 백그라운드 프로세스는 빌드 작업이 종료되는 것을 방지할 수 있습니다. 이를 방지하려면:
- 프로세스를 이중 포크하세요. 예:
command_to_run < /dev/null &> /dev/null &. - 작업 스크립트를 종료하기 전에 프로세스를 종료하세요.
캐시 관련 permission denied 오류#
작업에서 생성된 파일과 폴더는 특정 UNIX 소유권 및 권한을 갖습니다. 파일과 폴더가 아카이브되거나 추출될 때 UNIX 세부 정보가 유지됩니다. 그러나 파일과 폴더는 헬퍼 이미지의 USER 구성과 일치하지 않을 수 있습니다.
Creating cache ... 단계에서 권한 관련 오류가 발생하는 경우:
- 해결책으로, 예를 들어 캐시된 파일을 생성하는 작업 스크립트에서 소스 데이터가 수정되는지 조사하세요.
- 해결 방법으로, (
before_/after_)script:지시어에 일치하는 chown 및 chmod 명령을 추가하세요.
init 시스템을 사용하는 빌드 컨테이너에서 명백히 중복된 셸 프로세스#
다음 중 하나에 해당할 때 프로세스 트리에 셸 프로세스가 포함될 수 있습니다:
FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY가false이고FF_USE_DUMB_INIT_WITH_KUBERNETES_EXECUTOR가true인 경우.- 빌드 이미지의
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 <---------------- WHAT IS THIS???
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 시스템으로 실행될 때의 일반적인 동작입니다.
러너 Pod가 성공적인 등록에도 불구하고 작업 실행에 실패하고 타임아웃됨#
러너 Pod가 GitLab에 등록된 후, 작업을 실행하려고 시도하지만 실행하지 못하고 결국 타임아웃됩니다. 다음 오류가 보고됩니다:
There has been a timeout failure or the job got stuck. Check your timeout limits or try again.
This job does not have a trace.
이 경우, 러너는 다음 오류를 받을 수 있습니다:
HTTP 204 No content response code when connecting to the `jobs/request` API.
이 문제를 해결하려면, API에 수동으로 POST 요청을 보내 TCP 연결이 중단되는지 확인하세요. TCP 연결이 중단되는 경우, 러너가 CI 작업 페이로드를 요청할 수 없을 수 있습니다.
gcs-fuse-csi-driver 사용 시 init-permissions 컨테이너에서 failed to reserve container name#
gcs-fuse-csi-driver csi 드라이버는 init 컨테이너에 대한 볼륨 마운트를 지원하지 않습니다. 이로 인해 이 드라이버를 사용할 때 init 컨테이너 시작 실패가 발생할 수 있습니다. 이 버그를 해결하려면 드라이버 프로젝트에서 Kubernetes 1.28에 도입된 기능을 지원해야 합니다.
오류: only read-only root filesystem container is allowed#
컨테이너를 읽기 전용으로 마운트된 루트 파일시스템에서 실행하도록 강제하는 어드미션 정책이 있는 클러스터에서 다음과 같은 경우 이 오류가 나타날 수 있습니다:
- GitLab Runner를 설치하는 경우.
- GitLab Runner가 빌드 Pod를 스케줄링하려고 하는 경우.
이러한 어드미션 정책은 일반적으로 Gatekeeper 또는 Kyverno와 같은 어드미션 컨트롤러에 의해 적용됩니다. 예를 들어, 컨테이너를 읽기 전용 루트 파일시스템에서 실행하도록 강제하는 정책은 readOnlyRootFilesystem Gatekeeper 정책입니다.
이 문제를 해결하려면:
- 클러스터에 배포되는 모든 Pod는 컨테이너의
securityContext.readOnlyRootFilesystem을true로 설정하여 어드미션 정책을 준수해야 합니다. 그래야 어드미션 컨트롤러가 Pod를 차단하지 않습니다. - 컨테이너는 루트 파일시스템이 읽기 전용으로 마운트되어 있어도 성공적으로 실행되고 파일시스템에 쓸 수 있어야 합니다.
GitLab Runner의 경우#
GitLab Runner가 GitLab Runner Helm 차트로 배포된 경우, GitLab 차트 구성을 업데이트해야 합니다:
-
적절한
securityContext값:<...> securityContext: readOnlyRootFilesystem: true <...> -
Pod가 쓸 수 있는 위치에 마운트된 쓰기 가능한 파일 시스템:
<...> volumeMounts: - name: tmp-dir mountPath: /tmp volumes: - name: tmp-dir emptyDir: medium: "Memory" <...>
빌드 Pod의 경우#
빌드 Pod를 읽기 전용 루트 파일 시스템에서 실행하려면, config.toml에서 다른 컨테이너의 보안 컨텍스트를 구성하세요. 빌드 Pod에 전달되는 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
# This section is only needed if jobs with services are used
[runners.kubernetes.service_container_security_context,omitempty]
read_only_root_filesystem = true
<...>
빌드 Pod와 그 컨테이너가 읽기 전용 파일 시스템에서 성공적으로 실행되려면, 빌드 Pod가 쓸 수 있는 위치에 쓰기 가능한 파일시스템이 있어야 합니다. 최소한 빌드 디렉토리와 홈 디렉토리가 이에 해당합니다. 필요한 경우 빌드 프로세스가 다른 위치에도 쓰기 권한을 가질 수 있도록 확인하세요.
홈 디렉토리는 일반적으로 프로그램이 구성 및 성공적인 실행에 필요한 다른 데이터를 저장할 수 있도록 쓰기 가능해야 합니다. git 바이너리는 홈 디렉토리에 쓸 수 있기를 기대하는 프로그램의 한 예입니다.
다른 컨테이너 이미지에서의 경로에 관계없이 홈 디렉토리를 쓰기 가능하게 만들려면:
- 안정적인 경로에 볼륨을 마운트하세요 (사용하는 빌드 이미지에 관계없이).
- 모든 빌드에 대해 전역적으로 환경 변수
$HOME을 설정하여 홈 디렉토리를 변경하세요.
GitLab 차트 변수 runners.config의 값을 업데이트하여 config.toml에서 빌드 Pod와 그 컨테이너를 구성할 수 있습니다.
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: Error cleaning up pod: pods "runner-**" not found or status is "Failed"#
Amazon EKS 영역 재조정 기능은 자동 스케일링 그룹의 가용 영역을 균형 있게 유지합니다. 이 기능은 한 가용 영역의 노드를 중지하고 다른 영역에 새로 만들 수 있습니다.
러너 작업은 중지되어 다른 노드로 이동할 수 없습니다. 이 오류를 해결하려면 러너 작업에 대해 이 기능을 비활성화하세요.
Windows 컨테이너에서 서비스가 지원되지 않음#
Windows 노드에서 서비스를 사용하려고 하면 다음 오류와 함께 실패할 수 있습니다:
ERROR: Job failed (system failure): prepare environment: admission webhook "windows.common-webhooks.networking.gke.io" denied the request: spec.hostAliases: Invalid value: []v1.HostAlias{v1.HostAlias{IP:"127.0.0.1", Hostnames:[]string{"<your windows image>"}}}: Windows does not support this field.
Kubernetes 런타임에 따라 오류가 보고되거나 자동으로 무시될 수 있습니다. 예를 들어, GKE는 오류를 보고합니다.
서비스는 Kubernetes 실행기에서 hostAlias를 사용하여 구현되는데, Windows 컨테이너에서는 지원되지 않습니다.
