프록시 뒤에서 GitLab Runner 실행하기

Tier: Free, Premium, Ultimate
Offering: GitLab.com, Self-Managed

이 안내서는 Docker executor를 사용하여 프록시 뒤에서 GitLab Runner를 작동시키도록 목표로 합니다.

계속하기 전에, 이미 동일한 머신에 Docker를 설치하고 GitLab Runner를 설치했는지 확인하세요.

CNTLM 구성

note

인증 없이 이미 프록시를 사용 중인 경우, 이 섹션은 선택 사항이며 이미지 다운로드를 위해 Docker 구성로 바로 건너뛸 수 있습니다. CNTLM을 구성하는 것은 인증이 필요한 프록시 뒤에 있는 경우에만 필요하지만, 어떤 경우에든 사용하는 것이 권장됩니다.

CNTLM은 로컬 프록시로 사용할 수 있는 Linux 프록시로 매뉴얼으로 프록시 세부 정보를 추가하는 대신에 사용할 수 있는 두 가지 큰 장점이 있습니다:

  • 자격 증명을 변경해야 하는 유일한 원본
  • Docker 러너에서 자격 증명에 액세스할 수 없음

가정족으로 CNTLM을 설치했다면, 먼저 구성해야 합니다.

CNTLM을 docker0 인터페이스에서 수신하도록 설정

추가 보안을 위해 서버를 외부 세계로부터 보호하기 위해 docker0 인터페이스에서 CNTLM을 수신하도록 바인드할 수 있습니다. 이 인터페이스는 컨테이너 내부에서 접근할 수 있는 IP를 가지고 있습니다. CNTLM을 Docker 호스트에서 이 주소로만 바인드하도록 설정하면, Docker 컨테이너에서는 그에 도달할 수 있지만, 외부 세계에서는 도달할 수 없습니다.

  1. Docker가 사용하는 IP를 찾습니다:

    ip -4 -oneline addr show dev docker0
    

    이 주소는 보통 172.17.0.1입니다. 이를 docker0_interface_ip라고 부르겠습니다.

  2. CNTLM의 구성 파일을 엽니다(/etc/cntlm.conf). 사용자 이름, 비밀번호, 도메인 및 프록시 호스트를 입력하고, 이전 단계에서 찾은 수신 IP 주소를 구성합니다. 다음과 같이 보여야 합니다:

    Username     testuser
    Domain       corp-uk
    Password     password
    Proxy        10.0.0.41:8080
    Proxy        10.0.0.42:8080
    Listen       172.17.0.1:3128 # docker0 인터페이스 IP로 변경
    
  3. 변경 사항을 저장하고 서비스를 재시작합니다:

    sudo systemctl restart cntlm
    

이미지 다운로드를 위해 Docker 구성 작업

note

다음 내용은 systemd 지원이 있는 OS에 해당됩니다.

프록시 사용 방법에 대한 Docker 문서를 따르세요.

서비스 파일은 다음과 같아야 합니다:

[Service]
Environment="HTTP_PROXY=http://docker0_interface_ip:3128/"
Environment="HTTPS_PROXY=http://docker0_interface_ip:3128/"

GitLab Runner 구성에 프록시 변수 추가

프록시 변수는 GitLab Runner 구성에도 추가되어야 합니다. 이로써 GitLab Runner가 프록시 뒤에서 GitLab로부터 빌드를 할당받을 수 있습니다.

기본적으로 이는 위에서 설명한 Docker 서비스에 프록시를 추가하는 것과 같습니다:

  1. gitlab-runner 서비스에 대한 systemd drop-in 디렉터리를 생성하세요:

    mkdir /etc/systemd/system/gitlab-runner.service.d
    
  2. HTTP_PROXY 환경 변수를 추가하는 /etc/systemd/system/gitlab-runner.service.d/http-proxy.conf 라는 파일을 생성하세요:

    [Service]
    Environment="HTTP_PROXY=http://docker0_interface_ip:3128/"
    Environment="HTTPS_PROXY=http://docker0_interface_ip:3128/"
    
  3. 파일을 저장하고 변경 사항을 플러시합니다:

    systemctl daemon-reload
    
  4. GitLab Runner를 재시작하세요:

    sudo systemctl restart gitlab-runner
    
  5. 구성이 로드되었는지 확인하세요:

    systemctl show --property=Environment gitlab-runner
    

    다음을 볼 수 있어야 합니다:

    Environment=HTTP_PROXY=http://docker0_interface_ip:3128/ HTTPS_PROXY=http://docker0_interface_ip:3128/
    

Docker 컨테이너에 프록시 추가

러너를 등록한 후, (예: git clone를 위해) Docker 컨테이너에 프록시 설정을 전파하려고 할 수 있습니다.

이를 위해 /etc/gitlab-runner/config.toml 파일을 편집하여 [[runners]] 섹션에 다음을 추가해야 합니다:

pre_get_sources_script = "git config --global http.proxy $HTTP_PROXY; git config --global https.proxy $HTTPS_PROXY"
environment = ["https_proxy=http://docker0_interface_ip:3128", "http_proxy=http://docker0_interface_ip:3128", "HTTPS_PROXY=docker0_interface_ip:3128", "HTTP_PROXY=docker0_interface_ip:3128"]

여기서 docker0_interface_ipdocker0 인터페이스의 IP 주소입니다.

note

우리의 예제에서는 HTTP_PROXYhttp_proxy 변수를 모두 설정하고 있습니다. 왜냐하면 특정 프로그램은 HTTP_PROXY를 예상하고 다른 프로그램은 http_proxy를 예상하기 때문입니다. 불행히도, 이러한 종류의 환경 변수에 대한 표준이 없습니다.

dind 서비스를 사용할 때의 프록시 설정

Docker-in-Docker executor(dind)를 사용할 때, docker push가 차단되지 않도록 NO_PROXY 환경 변수에 docker:2375,docker:2376를 지정해야 하는 경우가 있습니다.

dind의 dockerd와 로컬 docker 클라이언트 간의 통신(여기에서 설명된 대로: https://hub.docker.com/_/docker/)은 root의 Docker 구성에 보관된 프록시 변수를 사용합니다.

이를 구성하려면 예를 들어 다음과 같이 완전한 프록시 구성이 포함된 /root/.docker/config.json 파일을 편집해야 합니다:

{
    "proxies": {
        "default": {
            "httpProxy": "http://proxy:8080",
            "httpsProxy": "http://proxy:8080",
            "noProxy": "docker:2375,docker:2376"
        }
    }
}

설정을 컨테이너에 전달하려면 .gitlab-ci.ymlbefore_script로 스크립트화된 $HOME/.docker/config.json 파일을 생성해야 합니다:

before_script:
  - mkdir -p $HOME/.docker/
  - 'echo "{ \"proxies\": { \"default\": { \"httpProxy\": \"$HTTP_PROXY\", \"httpsProxy\": \"$HTTPS_PROXY\", \"noProxy\": \"$NO_PROXY\" } } }" > $HOME/.docker/config.json'

또는 영향을 받는 gitlab-runner의 구성(/etc/gitlab-runner/config.toml)에 대해 다음과 같이 구성할 수 있습니다:

[[runners]]
  pre_build_script = "mkdir -p $HOME/.docker/ && echo \"{ \\\"proxies\\\": { \\\"default\\\": { \\\"httpProxy\\\": \\\"$HTTP_PROXY\\\", \\\"httpsProxy\\\": \\\"$HTTPS_PROXY\\\", \\\"noProxy\\\": \\\"$NO_PROXY\\\" } } }\" > $HOME/.docker/config.json"
note

여기서 "를 추가적으로 이스케이핑해야 합니다. 왜냐하면 이것은 TOML 파일 내부에서 하나의 문자열로 지정된 셸로 생성되는 JSON 파일이기 때문입니다. YAML이 아니기 때문에 :를 이스케이핑하지 마십시오.

NO_PROXY 디렉터리을 확장해야 하는 경우, 와일드카드 *는 접미사에 대해서는 작동하지만 접두사나 CIDR 표기법에 대해서는 작동하지 않습니다.

더 많은 정보는 다음을 참조하세요. https://github.com/moby/moby/issues/9145 그리고 https://unix.stackexchange.com/questions/23452/set-a-network-range-in-the-no-proxy-environment-variable.

요청 제한 손실 처리

GitLab 인스턴스는 남용을 방지하기 위해 API 요청에 대한 속도 제한이 있는 리버스 프록시 뒤에 있을 수 있습니다. GitLab 러너는 API로 여러 요청을 보내며 이로 인해 속도 제한을 초과할 수 있습니다.

이에 따라 GitLab 러너는 다음 논리로 속도 제한된 시나리오를 처리합니다.

  1. 429 - TooManyRequests 응답 코드를 받음.
  2. 응답 헤더에서 RateLimit-ResetTime 헤더가 있는지 확인합니다. RateLimit-ResetTime 헤더에는 Wed, 21 Oct 2015 07:28:00 GMT와 같이 유효한 HTTP Date (RFC1123) 값이어야 합니다.
    • 헤더가 존재하고 유효한 값이 있다면 러너는 지정된 시간까지 기다렸다가 다른 요청을 합니다.
    • 헤더가 존재하지만 유효한 날짜가 아닌 경우 1분의 대체값을 사용합니다.
    • 헤더가 없는 경우 추가 조치를 취하지 않고 응답 오류가 반환됩니다.
  3. 위의 과정을 5번 반복한 후 gave up due to rate limit 오류가 반환됩니다.
note
RateLimit-ResetTime 헤더는 모든 헤더 키가 http.CanonicalHeaderKey 함수를 통과하기 때문에 대소문자를 구분하지 않습니다. (http.CanonicalHeaderKey를 참조하세요.)