Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Foundry 인스턴스 사이의 데이터 수집

Foundry 커넥터는 한 Foundry 플랫폼 인스턴스의 데이터를 다른 인스턴스로 가져옵니다. 양쪽 인스턴스에 접근할 수 있어야 하며 데이터를 제공하는 원천과 데이터를 받는 목적지를 구분합니다. 대부분의 설정과 실행은 목적지에서 수행합니다.

이 경로는 목적지가 원천을 읽는 pull 방식입니다. 가상으로 red.palantirfoundry.com에서 blue.palantirfoundry.com으로 가져온다면 blue가 red에 연결하여 데이터를 가져옵니다.

일반 데이터셋 수집은 View와 제한 뷰(Restricted view)를 입력으로 지원하지 않습니다. 원천에서 먼저 실제 데이터셋으로 구체화해야 합니다.

기능 범위

대량 가져오기, 스트리밍 수집과 증분 수집은 일반 제공(GA)합니다. 가상 테이블은 Beta이며 원천 탐색은 제공 예정 상태입니다. 연산 위임, 테이블 내보내기와 Export tasks는 지원하지 않습니다. 가상 테이블의 테이블 출력과 별도의 테이블 내보내기 기능은 구분합니다.

목적지에서 소스 구성

  1. 목적지 Data Connection의 +New Source에서 Foundry를 선택합니다.
  2. 인터넷 직접 연결 또는 에이전트를 경유하는 경로를 구성합니다. 에이전트 기반 연결에는 Java 21 이상이 필요합니다.
  3. hostname에 원천 Foundry 호스트를 넣습니다. 예시에서는 red.palantirfoundry.com입니다.
  4. 아래의 인증 정보를 입력합니다.
  5. 직접 연결이면 목적지에 원천 호스트의 443 포트 외부 통신 정책을 추가합니다.
  6. 원천의 Control Panel, Network ingress에서 목적지의 출발 IP를 허용합니다.

목적지의 출발 IP는 목적지 Control Panel의 Network egress에서 확인합니다. 에이전트 워커 연결은 Foundry 직접 외부 통신 경로 대신 에이전트 호스트의 연결 경로와 출발 IP를 사용합니다. 원천 ingress에도 그 IP를 허용해야 합니다. Network ingress에 접근할 수 없으면 Palantir 지원에 문의합니다.

데이터 연결 리소스의 hostname은 원천이며, ingress를 허용해야 하는 쪽도 원천입니다. 목적지에는 원천으로 나가는 경로를 구성합니다.

운영용 client credentials

장기간 운영하는 연결은 client credentials를 사용합니다. 원천 인스턴스의 Developer Console에서 다음 절차로 앱을 등록합니다.

https://<SOURCE_FOUNDRY_INSTANCE>.palantirfoundry.com/workspace/developer-console/
    • New application에서 이름을 지정합니다.
  1. No, I will not use an Ontology SDK를 선택합니다.
  2. 소속 조직을 선택하고 앱을 활성화합니다.
  3. Backend service를 선택합니다.
  4. 필요한 Application permissions 또는 User permissions를 설정합니다. 기본 Application permissions 선택을 유지하는 구성이 권장됩니다.
  5. 표시되는 client secret을 보관하여 목적지 연결에 입력합니다.
  6. 저장 후 OAuth & restrictions에서 client ID를 복사합니다.

이 과정에서 서비스 사용자가 만들어집니다. 서비스 사용자에게 원천 프로젝트와 데이터셋의 탐색 및 읽기 권한을 부여합니다. 각 자산의 Check access로 접근 여부를 확인할 수 있습니다. 데이터셋 소유자일 필요는 없으며 조회 권한이 있는 데이터셋을 동기화할 수 있습니다.

임시 개인 토큰

개인 토큰은 임시 사용에만 허용되며 운영 연결에 사용하지 않습니다. 토큰의 수명이 36시간을 초과하면 동기화가 실행 시 실패합니다.

원천의 다음 화면에서 + Create token을 선택하고 이름과 수명을 정합니다. 발급한 토큰은 목적지 소스의 인증 정보에 입력합니다.

https://<SOURCE_FOUNDRY_INSTANCE>.palantirfoundry.com/workspace/settings/tokens

토큰 사용자도 원천의 대상 프로젝트와 데이터셋에 읽기 권한이 있어야 합니다.

수집과 보안 표지

원천 탐색 메뉴를 사용할 수 있는 환경에서는 소스 Overview의 Explore and create syncs에서 프로젝트와 데이터셋을 고르고 Create sync for x datasets를 선택합니다. 원천 탐색의 제공 여부와 수집 기능 자체의 지원을 구분합니다.

보안 표지는 인스턴스 사이에 자동 이전되지 않습니다. 목적지에서 동기화된 데이터에 적절한 권한과 보안 표지를 적용하는 절차를 마련해야 합니다. 민감하거나 분류된 데이터를 옮길 때 원천 접근 제어가 목적지에서도 그대로 유지된다고 가정하면 안 됩니다.

증분 수집의 초기 상태

증분 또는 Append 수집은 최근 수집 상태를 유지하고 새로 추가되거나 변경된 데이터를 가져옵니다.

  • 전체 이력을 먼저 수집하려면 initial incremental state를 충분히 이전 시점으로 설정합니다. 1970년 1월 1일은 예시입니다. 첫 실행에서 초기 범위의 데이터를 읽고 이후에는 새 데이터를 읽습니다.
  • 특정 시점 이전의 기록을 제외하려면 그 시점을 initial incremental state로 지정합니다. 2024년 1월 1일은 예시입니다. 초기 상태에 따른 범위의 데이터를 수집한 뒤 새 데이터를 계속 가져옵니다.

초기 증분 상태는 수집의 시작 위치입니다. 행 안의 임의 업무 날짜 필드에 적용하는 SQL 필터와 혼동하지 않습니다.

스트리밍 수집

원천 데이터셋이 스트림이어야 합니다. 데이터셋 RID와 브랜치 이름으로 연결하고 스키마를 지정한 뒤 처음 실행하면 목적지에 새 데이터셋이 생성됩니다.

새로 생성하는 행만 읽거나 기존 스트림의 모든 행부터 읽도록 offset을 선택할 수 있습니다. 큰 스트림의 과거 행을 모두 가져오면 시간과 연산 비용이 커질 수 있습니다.

관리형 Iceberg 가상 테이블

일반 데이터셋은 가상 테이블로 연결할 수 없습니다. 원천 Foundry의 관리형 Iceberg 테이블만 가상화할 수 있습니다.

대량 등록과 자동 등록은 지원하지 않습니다. Code Repositories와 Pipeline Builder의 테이블 입력 및 출력을 사용할 수 있고 증분 파이프라인을 지원합니다. 연산 위임은 지원하지 않습니다.

목적지는 원천 Foundry뿐 아니라 Iceberg 테이블의 기반 버킷에도 접근할 수 있어야 합니다. 버킷 측에서도 목적지의 유입 연결을 허용해야 합니다.

코드에서 Foundry API 호출

동기화가 제공하지 않는 작업은 외부 변환에서 Foundry API를 직접 호출할 수 있습니다. 대상 Foundry를 hostname으로 하는 REST API 소스를 만들고, 등록한 타사 앱의 client ID와 secret을 추가 비밀 정보로 저장합니다. 서비스 사용자에게 접근할 프로젝트, 데이터셋과 온톨로지 리소스의 권한을 부여합니다.

호출 대상이 같은 인스턴스이면 그 호스트를 사용합니다. 다른 인스턴스이면 목적지의 외부 통신과 원천 ingress를 앞서 설명한 방향으로 구성합니다.

토큰 엔드포인트는 POST /multipass/api/oauth2/token입니다. 범위가 필요한 API에는 해당 범위를 요청하며 여러 값은 공백으로 구분합니다.

범위 예시용도
api:datasets-read데이터셋 읽기
api:datasets-write데이터셋 쓰기
api:ontologies-read온톨로지 객체와 링크 유형 읽기

프로젝트 자식 리소스 나열

다음 예제는 client credentials로 토큰을 발급하고 GET /api/v2/filesystem/folders/{folderRid}/children을 순회합니다. 소스와 출력 RID 및 예시 프로젝트 RID를 실제 리소스로 바꿉니다. 소스에는 additionalSecretClientId, additionalSecretClientSecret을 설정합니다.

첫 요청에는 pageToken을 보내지 않고 응답의 nextPageToken을 다음 요청에 전달합니다. 페이지 크기는 예제에서 100을 요청하며 해당 엔드포인트의 최대값과 기본값은 2,000입니다. 결과에는 rid, displayName을 옮긴 name, type을 기록합니다.

이 토큰 요청은 선택 매개변수인 scope를 생략합니다. 애플리케이션의 허용 범위와 서비스 사용자의 프로젝트 접근 권한은 여전히 적용됩니다. 다른 API를 호출할 때에는 그 API가 요구하는 범위를 함께 구성합니다.

import logging

import pandas as pd
from transforms.api import Output, transform_pandas
from transforms.external.systems import external_systems, Source, ResolvedSource

logger = logging.getLogger(__name__)


@external_systems(
    foundry_api_source=Source("<source_rid>")
)
@transform_pandas(
    Output("<output_dataset_rid>"),
)
def compute(foundry_api_source: ResolvedSource) -> pd.DataFrame:
    base_url = foundry_api_source.get_https_connection().url
    client = foundry_api_source.get_https_connection().get_client()

    client_id = foundry_api_source.get_secret("additionalSecretClientId")
    client_secret = foundry_api_source.get_secret("additionalSecretClientSecret")

    token_response = client.post(
        base_url + "/multipass/api/oauth2/token",
        data={
            "grant_type": "client_credentials",
            "client_id": client_id,
            "client_secret": client_secret,
        },
        headers={"Content-Type": "application/x-www-form-urlencoded"},
    )
    token_response.raise_for_status()
    access_token = token_response.json()["access_token"]

    auth_headers = {"Authorization": f"Bearer {access_token}"}

    project_rid = "ri.compass.main.folder.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    resources = []
    page_token = None
    while True:
        params = {"pageSize": 100}
        if page_token:
            params["pageToken"] = page_token

        response = client.get(
            base_url + f"/api/v2/filesystem/folders/{project_rid}/children",
            headers=auth_headers,
            params=params,
        )
        response.raise_for_status()
        body = response.json()

        for resource in body.get("data", []):
            resources.append({
                "rid": resource.get("rid"),
                "name": resource.get("displayName"),
                "type": resource.get("type"),
            })

        page_token = body.get("nextPageToken")
        if not page_token:
            break

        logger.info(f"Fetched {len(resources)} resources so far, continuing to next page.")

    return pd.DataFrame(resources)

인증 오류 확인

연결 문제로 의심되면 범위 설정을 바꾸기 전에 원천까지 TLS 연결이 가능한지 확인합니다. 개인 토큰은 임시 사용과 36시간 수명 제한을 따릅니다.

client credentials 미리보기에서 INVALID_ARGUMENT가 발생하면 Developer Console의 앱 제한 범위가 대상 데이터셋 접근을 막는지 확인합니다. 필요한 접근 범위에 맞게 제한을 조정하고 서비스 사용자의 실제 데이터셋 권한도 확인합니다. 토큰 발급 성공과 자산 접근 권한은 별도의 조건입니다.