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


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

이 가이드는 특히 Docker 실행자가 있는 GitLab Runner가 프록시 뒤에서 작동하도록 하는 데 목적이 있습니다.

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

CNTLM 구성

참고: 이미 인증없이 프록시를 사용 중이라면, 이 섹션은 선택 사항이며 이미지 다운로드용 Docker 구성으로 건너뛸 수 있습니다. CNTLM 구성은 인증이 필요한 프록시 뒤에 있는 경우에만 필요하지만, 어떤 경우에든 사용하는 것이 좋습니다.

CNTLM은 로컬 프록시로 사용할 수 있는 리눅스 프록시로, 프록시 세부 정보를 수동으로 추가하는 것과 비교하여 2가지 주요 이점이 있습니다.

  • 자격 증명을 변경해야 하는 곳이 단일 소스
  • 도커 실행자에서 자격 증명에 접근할 수 없음

CNTLM을 설치했다면, 먼저 구성해야 합니다.

CNTLM이 docker0 인터페이스를 수신 대기하도록 만들기

보안을 강화하고 서버를 외부로부터 보호하기 위해 CNTLM을 도커 호스트에서 도달 가능한 IP가 있는 docker0 인터페이스로 바인딩할 수 있습니다. 이를 통해 도커 컨테이너에서 이를 도달할 수 있지만, 외부에서는 접근할 수 없습니다.

  1. 도커가 사용 중인 IP를 찾습니다:

    ip -4 -oneline addr show dev docker0
    

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

  2. CNTLM 구성 파일(/etc/cntlm.conf)을 엽니다. 사용자 이름, 비밀번호, 도메인, 프록시 호스트를 입력하고, 이전 단계에서 찾은 Listen 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 구성

참고: 다음은 systemd를 지원하는 OS에 해당합니다.

프록시를 사용하는 방법은 Docker 문서를 따릅니다.

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

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

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

프록시 변수는 프록시 뒤에서 GitLab.com에 연결할 수 있도록 GitLab Runner 구성에도 추가되어야 합니다.

기본적으로 Docker 서비스에 프록시를 추가하는 것과 동일합니다:

  1. gitlab-runner 서비스를 위한 systemd 드롭인 디렉토리를 만듭니다:

    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/"
    

    자체 관리 GitLab 인스턴스와 같은 내부 URL에 GitLab Runner를 연결하려면 NO_PROXY 환경 변수에 값을 설정하세요.

    [Service]
    Environment="HTTP_PROXY=http://docker0_interface_ip:3128/"
    Environment="HTTPS_PROXY=http://docker0_interface_ip:3128/"
    Environment="NO_PROXY=gitlab.example.com"
    
  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 컨테이너에 프록시 추가

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

이를 위해 /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 주소입니다.

참고: 여기서는 일부 프로그램이 HTTP_PROXY를 기대하는 경우도 있고 http_proxy를 기대하는 경우도 있기 때문에 소문자와 대문자 변수를 설정하고 있습니다. 불행히도 이러한 종류의 환경 변수에 대한 표준이 없습니다.

dind 서비스 사용 시 프록시 설정

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

dind의 dockerd와 로컬 docker 클라이언트 간의 통신은 root의 Docker 구성에 보관된 프록시 변수를 사용합니다. 여기에 대한 자세한 내용은 다음 링크를 참조하십시오: https://hub.docker.com/_/docker/

이를 구성하려면, porxy 구성을 포함하는 /root/.docker/config.json을 편집해야 합니다. 예를 들어 다음과 같습니다:

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

이 설정을 Docker 실행자의 컨테이너에 전달하려면, 예를 들어 .gitlab-ci.ymlbefore_script로 스크립트화할 수 있습니다:

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"

참고: 이것은 TOML 파일 안의 문자열로 지정된 셸에서 JSON 파일을 생성하는 것이므로 여기에 "를 더로 escaping해야 합니다. YAML이 아니기 때문에 :를 escaping해서는 안 됩니다.

일반적으로 NO_PROXY 목록을 확장해야 하는 경우, 와일드카드 *는 접미사에 대해서만 작동하며, 접두사나 CIDR 표기법에서는 작동하지 않습니다. 더 많은 정보는 https://github.com/moby/moby/issues/9145https://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번 반복하고 나서 속도 제한 때문에 포기함 오류가 반환됩니다.

참고: RateLimit-ResetTime 헤더는 모든 헤더 키가 http.CanonicalHeaderKey 함수를 거치기 때문에 대소문자를 구분하지 않습니다.