This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
proposed devops verify -

Runner 통합

비목표

이 제안은 Step Runner 바이너리를 대상 환경으로 배포하거나 아래에 설명된 Step Runner gRPC 서비스를 시작하는 것을 다루지 않습니다. 이 제안의 나머지 부분은 Step Runner 바이너리가 대상 환경에 존재하고 gRPC 서비스가 실행되어 로컬 소켓에서 수신 대기 중이라고 가정합니다. 마찬가지로, 이 제안은 ‘Step Runner’ 서비스의 라이프사이클을 다루지 않으며 서비스가 종료된 경우 서비스를 다시 시작하거나 업그레이드하는 방법 등을 다루지 않습니다.

관련 청사진은 배포 및 라이프사이클 관리를 참조하세요.

단계 서비스 gRPC 정의

Step Runner 서비스의 gRPC 정의는 다음과 같습니다.

service StepRunner {
    rpc Run(RunRequest) returns (RunResponse);
    rpc FollowSteps(FollowStepsRequest) returns (stream FollowStepsResponse);
    rpc FollowLogs(FollowLogsRequest) returns (stream FollowLogsResponse);
    rpc Finish(FinishRequest) returns (FinishResponse);
    rpc Status(StatusRequest) returns (StatusResponse);
}

...

Runner는 위의 gRPC 서비스를 통해 Step Runner와 상호 작용하며, 실행 환경의 로컬 소켓에서 시작됩니다. Runner는 먼저 대상 환경에 해당하는 프로토콜을 통해 연결한 후, 제공된 proxy 명령을 사용하여 gRPC 서비스에 연결하고 (seeProxy Command) Runner에서 Step Runner로 gRPC 요청을 투명하게 터널링합니다. Nesting도 동일한 방식으로 전용 Mac 인스턴스에서 gRPC 서비스를 제공합니다. 이 서비스에는 Run, FollowSteps, FollowLogs, FinishStatus의 5개의 RPC가 있습니다.

Run은 단계들의 초기 전달을 의미합니다. FollowSteps는 단계 결과 트레이스를 스트리밍 응답으로 요청합니다. FollowLogs는 프로세스 실행 중에 생성된 출력(stdout/stderr) 및 Step Runner 자체에서 생성된 로그를 스트리밍 응답으로 요청합니다. Finish는 요청 실행을 중지하고 가능한 즉시 리소스를 정리합니다. Status는 지정된 작업의 상태를 나열하거나 지정된 작업이 없는 경우 Step Runner 서비스의 모든 활성 작업(완료된 작업도 포함되지만 Finish 되지 않은 작업)을 나열합니다. 예를 들어 Runner는 충돌 이후 회복하기 위해 Status를 사용할 수 있습니다.

Step Runner gRPC 서비스는 한 번에 여러 Run 페이로드를 실행할 수 있습니다. 즉, 각각의 Run 호출은 새로운 고루틴을 시작하고 완료될 때까지 단계를 실행합니다. 동시에 여러 Run 호출이 발생할 수 있습니다.

단계가 실행되는 동안, 단계 결과 트레이스 및 하위 프로세스 로그가 GitLab Runner로 스트리밍될 수 있습니다. 이를 통해 Runner(또는 다른 호출자)는 단계 결과 트레이스(FollowSteps) 수준 및 하위 프로세스 및 Step Runner 로그(FollowLogs)로 작성된 실행을 추적할 수 있습니다. 로그는 특정 형식으로 작성되며, 민감한 토큰은 마스킹된 후 Runner로 스트리밍됩니다.

Status를 제외한 모든 API는 중복 호출이 가능합니다. 즉, 동일한 매개변수로 동일한 API에 대한 여러 호출은 동일한 결과를 반환해야 합니다. 예를 들어, Run이 동일한 id로 여러 번 호출된다면 첫 번째 호출만 작업 요청을 처리해야 하며, 후속 호출은 성공 상태를 반환하지만 그 외에 아무 것도 수행하면 안 됩니다. 마찬가지로, 동일한 id로 여러 번의 Finish 호출은 첫 번째 호출로 해당 작업을 완료하고 제거해야 하며, 후속 호출로 아무 작업도 수행하면 안 됩니다.

서비스는 클라이언트가 잘 행동하지 않을 것으로 가정하고, Follow API 중 하나에서 호출을 절대로 하지 않거나 조기에 연결을 해제하는 클라이언트, 그리고 해당 Run 요청에 대해 절대로 Finish를 호출하지 않는 클라이언트를 다룰 수 있어야 합니다. 이를 위해 Step Runner 프로세스는 정기적으로 스캔을 수행하여 오래된 또는 비정상적인 작업을 식별하고 정리할 수 있어야 합니다. 지난 시간 동안(그리고 Finish되지 않은) 완료된 작업일 수 있습니다. 비정상적인 작업은 (긴) 지정된 시간 동안 실행된 작업으로서, 아웃풋을 생성하지 않을 수도 있습니다.

마지막으로, 아래 Runner 실행자에 단계를 통합하기 위해 Run/Follow*/Finish API의 실행을 조정하고, Follow* 호출이 연결을 잃은 경우 단계 실행자 서비스에 다시 연결하고 처리를 할 수 있도록 클라이언트 라이브러리를 제공하는 것이 좋습니다.

RunRequest Parameters

RunRequest.Steps 필드에 단계가 JSON 직렬화된 형식으로 Step Runner에 전달됩니다. 이때 단계 정의에 대한 처리는 Runner 자체에서 필요로하지 않습니다. id 필드는 Step Runner 서비스에서 실행 중인 각 요청을 고유하게 식별합니다. RunRequest.Env 필드에는 각 단계가 실행될 때 주입해야 하는 환경 변수가 포함됩니다.

선택 사항인 Job 매개변수에는 해당 CI 작업에서 선택적인 매개변수가 포함됩니다. Job은 해당 CI 작업의 빌드 디렉토리를 포함할 것이며, Job.BuildDirRunRequest.WorkDir로 복사되어야 하며, 요청의 모든 단계는 기존 작업 스크립트 동작을 보존하기 위해 해당 디렉토리에서 호출되어야 합니다. RunRequest는 또한 CI 작업의 환경 변수 (즉, CI 구성의 작업 및 전역 수준에서 정의된 variables)를 포함할 것입니다. Runner에 의해 RunRequest가 생성되는 경우, 변수는 Job.Variables에 포함되어야 하며 RunRequest.Env는 비워둬야 합니다. 실행 요청이 처리될 때 파일 유형의 변수는 파일에 작성되고, 변수가 확장되어 RunRequest.Env로 복사되며, Job 필드는 요청의 나머지 부분에서 폐기될 것입니다. 변수는 Step Runner 서비스에 의해 확장되어야 하며, 이는 실행 환경 내의 객체를 참조할 수 있으므로 (다른 환경 변수 또는 경로 등) 파일 유형의 변수도 포함됩니다. 이러한 변수는 전통적인 runner 작업 실행과 동일한 경로에 작성되어야 합니다. 마찬가지로, Job.Variables에서 마스킹해야 하는 구절은 추출되어 Masking.Phrases를 채우고, Job.TokenPrefixesMasking.TokenPrefixes로 복사되어야 합니다.

단계를 실행하고자 하는 Runner 이외의 클라이언트는 Job 필드를 생략할 수 있으며, 이 경우에는 MaskingEnv 필드를 호출자가 직접 채워야 합니다.

로그 형식

FollowLogs API로 발생하는 로그 라인은 다음과 같은 형식을 가져야 합니다.

    <timestamp> <stream> <stdout/stderr> <append flag> <message>

이는 이 병합 요청에서 Runner에 도입된 동일한 로그 형식입니다. 이 형식을 생성하기 위해 사용된 로깅 라이브러리는 GitLab RunnerStep Runner 간에 공유되어야 합니다.

마스킹

Step Runner는 민감한 변수나 토큰들을 마스킹하는 것에 대한 책임이 있습니다. 이 작업은 위의 로그 형식으로 형식화되기 전에 이루어져야 합니다. 변수를 마스킹하는 데 사용된 라이브러리는 GitLab RunnerStep Runner 사이에서 공유되어야 합니다. (아래의 관련 모듈을 참조하세요.)

프록시 명령

Step Runner 바이너리에는 (일반적으로 텍스트 기반) stdin/stdout/stderr 기반 프로토콜의 데이터를 gRPC 서비스로 프록시하는 명령이 포함될 것입니다. 이 명령은 gRPC 서비스가 실행 중인 동일한 호스트에서 실행되며, stdin에서 입력을 읽어서 동일한 소켓을 통해 gRPC 서비스로 전달하고, 해당 서비스로부터의 출력을 동일한 소켓을 통해 수신하여 이를 stdout/stderr를 통해 클라이언트에 전달합니다. 이 명령을 통해 클라이언트 (Runner와 같은)는 stdin/stderr/stdout 기반 프로토콜을 통해 gRPC 서비스로 투명하게 터널링할 수 있으며, 이를 통해 도커 이미지에서 Step Runner 서비스의 gRPC 포트를 노출할 필요가 없어지거나 VM에서 SSH 포트 포워딩을 설정할 필요가 없어지며, Runner가 설립된 프로토콜 (즉, SSH 및 docker exec)을 사용하여 Step Runner와 상호 작용할 수 있게 됩니다. stdoutStep Runner 서비스로부터의 응답 작성을 위해 예약되어야 하며, stderr프록시 명령 자체에서 발생하는 오류를 위해 예약되어야 합니다.

Executors

다음은 각 Runner 실행 프로그램에서 Step Runner에 연결할 방법입니다:

인스턴스

인스턴스 실행 프로그램은 현재와 같이 SSH를 통해 접근됩니다. 그러나 명령어를 파이핑하고 bash 셸을 시작하는 대신 프록시 명령을 호출하게 되며, 이 명령은 다시 알려진 위치에 있는 Step Runner 소켓에 연결합니다. Runner는 그러면 직접 gRPC 호출을 수행하고 SSH 연결을 통해 gRPC 서비스에 투명하게 터널링할 수 있습니다. 이것은 Runner가 VM에서 VM을 만들기 위해 전용 Mac 인스턴스의 중첩 서버를 호출하는 방법과 동일합니다.

이는 Step Runner가 작업 실행 환경에 존재하고 시작되어 있어야 한다는 조건이 필요합니다.

Docker

같은 요구사항이 Docker 실행 프로그램에도 적용됩니다 (그리고 docker-autoscaler에도). 그러나 컨테이너 내에서 gRPC 서비스에 연결하려면 Runner는 컨테이너 내부의 gRPC 서비스에 docker exec를 수행하고 해당 프록시 명령을 실행하여 컨테이너 내부의 gRPC 서비스에 연결하게 됩니다. 클라이언트는 그럼 docker execstdin로 작성할 수 있으며, 이는 자동적으로 gRPC 서비스로 프록시가 될 것이며, 해당 서비스로부터의 응답이 담긴 stdout/stderr에서 읽게 됩니다.

쿠버네티스

쿠버네티스 노드의 Kubelet은 실행 중인 Pod의 컨테이너에서 프로세스를 시작할 exec API를 노출합니다. 이를 사용하여 Docker executor와 유사하게 Pod 내부에서 gRPC 호출을 할 수 있는 브릿지 프로세스를 exec create할 것입니다.

이 보호된 Kubelet API에 액세스하려면 Pod의 exec 하위 리소스를 제공하는 Kubernetes API를 사용해야 합니다. 호출자는 /exec로 끝나는 Pod의 URL에 POST할 수 있으며, 그런 다음 연결을 양방향 바이트 스트리밍을 위해 SPDY 프로토콜로 협상할 수 있습니다. 따라서 GitLab Runner는 Kubernetes API를 사용하여 Step Runner 서비스에 연결하고 작업 페이로드를 전달할 수 있습니다.

이것은 kubectl exec가 작동하는 방식과 동일합니다. 사실, SPDY 협상과 같은 대부분의 내부 기능은 client-go 라이브러리에서 제공됩니다. 따라서 Runner는 필요한 라이브러리를 가져와서 Kubectl을 사용하는 대신 직접 Kubernetes API를 호출할 수 있습니다.

과거 쿠버네티스 Executor의 약점 중 하나는 하나의 exec를 통해 전체 작업을 실행하는 것이었습니다. 이를 완화하기 위해 Runner는 “존재하는 쉘 프로세스에 다시 연결할 수 있는” attach 명령을 사용합니다.

그러나 Step Runner의 경우 이것은 필요하지 않습니다. 왜냐하면 exec는 장기간 실행되는 gRPC 프로세스에 대한 브릿지를 설정하기 때문입니다. 연결이 끊겨도 Runner는 다른 연결을 exec하여 follow와 같은 RPC 호출을 계속할 것입니다.