Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

CLI 사이드카의 공유 볼륨 요청 규약

파일 기반 사이드카는 입력이 모두 준비된 시점과 결과를 회수한 시점을 알아야 합니다. 컨테이너가 시작되자마자 입력 파일을 읽으면 입력 복사와 경합할 수 있고, 명령 종료와 함께 컨테이너가 사라지면 실행기가 결과를 읽지 못할 수 있습니다.

entrypoint.py와 sidecar_client.py는 이 수명 주기를 요청 단위로 처리합니다. 이 파일 이름과 JSON 구조는 예제 애플리케이션의 통신 규약입니다. Foundry가 정해진 이름의 플래그를 해석하는 플랫폼 API는 아닙니다.

디렉터리와 상태 파일

공유 루트는 /opt/palantir/sidecars/shared-volumes/shared입니다. 각 요청은 requests/request- 뒤에 전체 UUID를 붙인 디렉터리를 사용합니다.

상대 경로작성 주체의미
data/실행기와 명령입력과 출력 파일이 놓이는 작업 디렉터리입니다.
start_flag실행기입력 작성과 파일 닫기를 마쳤으므로 명령을 시작할 수 있습니다.
logfile사이드카명령의 표준 출력과 표준 오류를 합친 바이트를 보관합니다.
done_flag.pending사이드카완료 상태를 작성하는 임시 파일입니다.
done_flag사이드카상태 JSON 작성을 끝내고 이름을 바꾼 최종 완료 파일입니다.
close_flag실행기요청 결과 사용을 마쳤거나 대기를 중단했으므로 요청 디렉터리를 정리할 수 있습니다.

입력 파일과 제어 파일의 디렉터리를 분리하므로 입력 데이터셋에 같은 이름의 파일이 있어도 실행 플래그를 덮어쓰지 않습니다. 요청마다 새 디렉터리를 사용하므로 이전 실행의 완료 파일을 새 실행의 결과로 읽지 않습니다.

사이드카의 실행 순서

진입점은 SHARED_DIR 환경 변수에서 공유 루트를 읽습니다. requests 아래에서 request-로 시작하는 디렉터리를 확인하고, 심볼릭 링크는 요청으로 사용하지 않습니다. 디렉터리 열거 순서에 요청 처리 순서를 의존하지 않습니다.

start_flag가 있고 아직 done_flag가 없는 요청에 대해 다음을 수행합니다.

  1. data를 작업 디렉터리로 삼고 명령을 실행합니다. 표준 입력은 닫힌 입력으로 연결하며, 명령과 인자는 리스트 그대로 전달합니다.
  2. 현재 세션 안에서 명령을 별도 프로세스 그룹으로 시작합니다. 별도 스레드가 표준 출력과 표준 오류를 읽어 logfile과 컨테이너 표준 출력에 기록합니다.
  3. 실행 시간 한도까지 프로세스 종료와 출력 전달을 기다립니다. 시간이 지나면 해당 명령의 프로세스 그룹을 중지하고 종료 코드를 회수합니다.
  4. 종료 코드, 시간 제한 초과 여부와 로그 처리 오류를 JSON으로 작성합니다. 임시 완료 파일을 최종 이름으로 바꿔 클라이언트가 작성 중인 JSON을 읽지 않게 합니다.
  5. 실행기의 close_flag를 기다립니다. 결과 회수 대기 시간이 지나거나 신호를 받으면 해당 요청 디렉터리를 정리합니다.

완료 상태에는 다음 필드가 모두 있습니다.

필드자료형의미
return_code정수 또는 null실제 자식 프로세스 종료 코드입니다. 프로세스를 시작하지 못한 경우에는 null일 수 있습니다.
timed_out불리언명령 또는 출력 전달 대기가 실행 시간 한도를 넘었는지 나타냅니다.
errors문자열 배열프로세스 시작이나 로그 전달 등에서 발생한 오류입니다.

클라이언트는 timed_out이 거짓이고, return_code가 0이며, errors가 비어 있을 때에만 결과를 사용합니다. 완료 파일이 존재한다는 사실만으로 성공을 판단하지 않습니다.

이 실행기는 종료되는 전경 명령을 대상으로 합니다. 명령이 별도 세션의 데몬을 남기거나 표준 출력 파일 설명자를 끝없이 유지하는 구성을 사용하지 않습니다. 계속 살아 있는 서비스가 필요하면 HTTP 서버형 사이드카를 사용합니다.

진입점은 Python 3.11 이상에서 지원하는 Popen(process_group=0)을 사용합니다. 이 옵션은 setpgid()로 자식 프로세스의 그룹을 분리하여 시간 제한이 지나면 같은 그룹의 하위 프로세스도 함께 종료할 수 있게 합니다. start_new_session=True는 setsid()를 호출하며, Foundry는 이 호출을 차단하고 호출한 프로세스를 종료합니다. 실행할 명령과 그 라이브러리도 컨테이너의 시스템 호출 제한을 따라야 합니다.

실행기의 유틸리티 함수

execute_cli(prepare_input, shared_directory, timeout_seconds)

컨텍스트 관리자가 새 요청을 만들고 prepare_input(data_directory)를 호출합니다. 콜백은 해당 디렉터리에 필요한 입력을 쓰고, 파일을 닫은 뒤 반환해야 합니다. 기본 공유 디렉터리는 위의 shared 볼륨이며 기본 대기 시간은 600초입니다.

콜백이 끝나면 시작 신호를 쓰고 완료 파일을 기다립니다. 시간 제한을 넘으면 TimeoutError를, 명령의 실패 종료나 오류 목록이 있으면 RuntimeError를 발생시킵니다. 성공하면 with 블록에 요청 디렉터리의 Path를 전달합니다. 블록 안에서 출력 CSV를 읽고 필요한 결과를 데이터셋으로 복사합니다.

블록이 정상 종료하거나 예외로 끝나면 close_flag를 씁니다. 입력 준비 단계에서 실패해 시작 신호를 보내지 않은 요청은 클라이언트가 자신의 디렉터리를 정리합니다. 시작 신호 이후의 시간 초과는 명령이 전혀 실행되지 않았음을 보장하지 않으므로, 외부 상태 변경이 있는 명령은 재실행 전에 해당 시스템의 상태를 확인해야 합니다.

copy_dataset_files(source, data_directory)

source.filesystem()에서 파일 목록을 읽고 각 파일을 바이트 단위로 복사합니다. 데이터셋의 상대 경로와 하위 디렉터리를 유지합니다. 절대 경로나 ..를 포함한 경로는 거부합니다. 대상 파일은 새 파일 생성 모드로 열어 같은 요청 안의 예상하지 못한 기존 파일을 덮어쓰지 않습니다.

명령이 입력 전체를 한 번에 처리하는 단일 실행에서 사용합니다. 이 함수는 파일을 복사할 뿐 CSV 스키마를 변환하지 않습니다.

copy_artifacts(output, request, prefix, include_input)

start_flag, outfile.csv, logfile, done_flag를 출력 데이터셋의 파일시스템으로 복사합니다. include_input=True이면 infile.csv도 복사합니다. prefix의 기본값은 빈 문자열이며, 병렬 실행은 요청 이름을 접두사로 전달합니다.

입력과 출력 스트림 모두 바이너리 모드를 사용합니다. 필수 결과 파일이 없거나 데이터셋 쓰기에 실패하면 예외가 호출자에게 전달됩니다. 실패한 파일을 건너뛰고 성공으로 반환하지 않습니다.

시간 제한과 자원 회수

설정기본값측정 범위
서버 RUN_TIMEOUT_SECONDS600초명령 실행과 명령 출력 전달
서버 CLOSE_TIMEOUT_SECONDS600초완료 상태 작성 후 클라이언트의 결과 회수 신호 대기
클라이언트 WAIT_TIMEOUT_SECONDS600초시작 신호 전송 후 완료 상태를 얻을 때까지의 대기

이 값은 예제 프로그램의 정책이며 Foundry 플랫폼의 고정 제한이 아닙니다. 요청이 서버에서 앞선 작업을 기다리는 시간도 클라이언트 대기에 포함됩니다. 큰 결과 파일을 복사하는 경우에는 결과 회수 대기 시간도 충분히 설정해야 합니다. 시간 계산에는 단조 시계를 사용해 시스템 시각 조정에 영향을 받지 않도록 합니다.

close_flag는 해당 요청의 임시 파일을 정리하는 신호입니다. 컨테이너 전체는 계속 실행되어 같은 Spark 실행기의 다음 요청을 처리합니다. 실행기 수명 종료에 따른 컨테이너 정리는 플랫폼이 담당합니다. 이 규약은 Spark의 재시도나 반복 계산을 막지 않으며, UUID는 요청별 파일 격리에 사용합니다.