Snowpark Container Services: 서비스 및 작업의 추가 고려 사항

중요

Snowpark Container Services 작업 기능은 현재 비공개 미리 보기로 제공되며 https://snowflake.com/legal 의 미리 보기 조건이 적용됩니다. 자세한 내용은 Snowflake 담당자에게 문의하십시오.

컨테이너 내부에서 Snowflake에 연결하기

서비스나 작업을 시작하면 Snowflake가 실행 중인 컨테이너에 자격 증명을 제공하여 컨테이너 코드가 드라이버를 사용하여 Snowflake에 연결하고 SQL을 실행할 수 있도록 합니다(컴퓨터에서 Snowflake에 연결하는 다른 코드와 유사함). 제공된 자격 증명은 서비스 역할로 인증됩니다. Snowflake는 일부 정보를 컨테이너의 환경 변수로 제공합니다.

Snowflake의 모든 오브젝트에는 소유자 역할이 있습니다. 서비스나 작업의 경우 Snowflake에는 서비스 역할 이라는 개념이 있습니다(이 용어는 서비스와 작업에 모두 적용됨). 서비스 역할에 따라 Snowflake와 상호 작용할 때 서비스가 수행할 수 있는 기능이 결정됩니다. 여기에는 SQL 실행, 스테이지 액세스, 서비스 간 네트워킹이 포함됩니다.

참고

현재 구현에서는 서비스 역할이 소유자 역할과 동일합니다.

예를 들어 자습서에 대한 공통 설정 의 일부로 test_role 을 생성합니다. 역할에 필요한 권한을 부여한 다음 서비스와 작업을 생성할 때 해당 역할을 사용합니다. 이 역할은 서비스와 작업의 소유자 역할이자 서비스와 작업의 기능을 결정하는 서비스 역할입니다.

참고

서비스 역할은 ACCOUNTADMIN, SECURITYADMIN, ORGADMIN을 포함한 권한 있는 역할이 될 수 없습니다.

서비스를 생성하면 Snowflake는 해당 서비스와 관련된 “서비스 사용자”도 생성합니다. 서비스는 쿼리를 실행할 때 서비스 사용자로 쿼리를 실행합니다. 서비스 사용자가 할 수 있는 작업은 서비스 역할에 따라 결정됩니다.

Snowflake에 연결하기

Snowflake는 서비스/작업 코드에서 Snowflake 클라이언트를 구성할 수 있도록 다음 환경 변수를 제공합니다.

  • SNOWFLAKE_ACCOUNT: 현재 서비스가 실행 중인 Snowflake 계정의 이름을 제공합니다.

  • SNOWFLAKE_HOST: Snowflake에 연결하는 데 사용되는 호스트 이름을 제공합니다.

Snowflake는 또한 /snowflake/session/token 이라는 파일의 컨테이너에 OAuth 토큰을 제공합니다. 연결을 생성할 때 이 토큰을 커넥터에 제공합니다.

컨테이너에서 Snowflake에 대한 연결을 생성할 때 SNOWFLAKE_HOST, SNOWFLAKE_ACCOUNT 및 OAuth 토큰을 사용해야 합니다. SNOWFLAKE_HOST도 사용해야 OAuth 토큰을 사용할 수 있으며, Snowpark Container Services 외부에서는 OAuth 토큰을 사용할 수 없습니다. 자세한 내용은 OAuth 토큰을 사용하여 SQL 실행하기 섹션을 참조하십시오.

다양한 Snowflake 드라이버를 사용하는 샘플 코드는 Snowflake 연결 샘플 을 참조하십시오.

  • 자습서 2 (main.py 참조)에서 코드는 다음과 같이 환경 변수를 읽습니다.

    SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT')
    SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
    
    Copy

    이 코드는 선택한 Snowflake 클라이언트의 연결 생성 코드에 이러한 변수를 전달합니다. 컨테이너는 이러한 자격 증명을 사용해 서비스 역할을 기본 역할로 하는 새 세션을 생성하여 쿼리를 실행합니다. 다음 예제 코드는 Python에서 Snowflake 연결을 생성하는 데 필요한 최소한의 코드입니다.

    def get_login_token():
      with open('/snowflake/session/token', 'r') as f:
        return f.read()
    
    conn = snowflake.connector.connect(
      host = os.getenv('SNOWFLAKE_HOST'),
      account = os.getenv('SNOWFLAKE_ACCOUNT'),
      token = get_login_token(),
      authenticator = 'oauth'
    )
    
    Copy
  • 기본 호스트를 사용하는 경우(즉, 연결을 생성할 때 host 인자를 포함하지 않음) 다른 인증 형식(예: 사용자 이름 및 비밀번호)을 사용하여 Snowflake에 연결할 수 있습니다. 예를 들어, 다음 연결에서는 인증할 사용자 이름과 비밀번호를 지정합니다.

    conn = snowflake.connector.connect(
      account = os.getenv('SNOWFLAKE_ACCOUNT'),
      user = '<user-name>',
      password = <password>
    )
    
    Copy

    기본 호스트를 사용하려면 서비스에서 계정의 Snowflake 호스트 이름에 대한 액세스를 허용하는 네트워크 규칙을 사용하는 외부 액세스 통합이 필요합니다. 예를 들어, 계정 이름이 MyAccount 인 경우 호스트 이름은 myaccount.snowflakecomputing.com 이 됩니다. 자세한 내용은 네트워크 송신 섹션을 참조하십시오.

    • 계정의 Snowflake API 호스트 이름과 일치하는 네트워크 규칙을 만듭니다.

      CREATE OR REPLACE NETWORK RULE snowflake_egress_access
        MODE = EGRESS
        TYPE = HOST_PORT
        VALUE_LIST = ('myaccount.snowflakecomputing.com');
      
      Copy
    • 이전 네트워크 규칙을 사용하여 통합을 만듭니다.

      CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration
        ALLOWED_NETWORK_RULES = (snowflake_egress_access)
        ENABLED = true;
      
      Copy

SQL 실행을 위한 데이터베이스 및 스키마 컨텍스트 구성하기

이 섹션에서는 다음 두 가지 개념을 설명합니다.

  • Snowflake가 서비스/작업을 생성할 데이터베이스와 스키마를 결정하는 데 사용하는 논리.

  • Snowflake가 이 정보를 컨테이너에 전달하여 컨테이너 코드가 동일한 데이터베이스 및 스키마 컨텍스트에서 SQL을 실행할 수 있도록 지원하는 방법.

Snowflake는 다음 논리를 사용하여 서비스/작업을 생성할 데이터베이스와 스키마를 결정합니다.

  • 서비스의 경우 Snowflake는 CREATE SERVICE 명령에 제공된 서비스 이름을 사용하여 서비스에 대한 데이터베이스 및 스키마 컨텍스트를 결정합니다.

    • 예 1: 다음 CREATE SERVICE 명령은 test_service 를 서비스 이름으로 지정합니다.

      CREATE SERVICE test_service IN COMPUTE POOL ...
      
      Copy

      Snowflake는 이 서비스를 현재 데이터베이스와 스키마에 배치합니다.

    • 예 2: 다음 CREATE SERVICE 명령은 정규화된 서비스 이름을 지정합니다.

      CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ...
      
      Copy

      Snowflake는 현재 스키마에 관계없이 지정된 데이터베이스(test_db)와 스키마(test_schema)에 서비스를 배치합니다.

  • 작업의 경우 EXECUTE SERVICE 명령을 사용하여 작업을 생성할 때 작업 이름을 제공하지 않습니다.

    EXECUTE SERVICE IN COMPUTE POOL ..
    
    Copy

    이 경우 작업을 어디에도 배치할 기회가 없습니다. 따라서 Snowflake는 현재 데이터베이스와 스키마에 작업을 배치합니다. 작업이 다른 스키마에서 SQL 문을 실행하도록 하려면 다른 스키마 컨텍스트를 사용하여 작업을 실행할 수 있습니다. 예:

    USE ROLE test_role;
    USE DATABASE tutorial_db;
    
    USE SCHEMA schema1;
    -- Execute using tutorial_db and schema1
    EXECUTE SERVICE IN COMPUTE POOL ...
    
    USE SCHEMA schema2;
    -- execute service again, using schema2
    EXECUTE SERVICE IN COMPUTE POOL ...
    
    Copy

Snowflake는 서비스/작업을 시작할 때 다음 환경 변수를 사용하여 실행 중인 컨테이너에 데이터베이스 및 스키마 정보를 제공합니다.

  • SNOWFLAKE_DATABASE

  • SNOWFLAKE_SCHEMA

컨테이너 코드는 다음 예제와 같이 연결 코드에 환경 변수를 사용하여 사용할 데이터베이스와 스키마를 결정할 수 있습니다.

conn = snowflake.connector.connect(
  host = os.getenv('SNOWFLAKE_HOST'),
  account = os.getenv('SNOWFLAKE_ACCOUNT'),
  token = get_login_token(),
  authenticator = 'oauth',
  database = os.getenv('SNOWFLAKE_DATABASE'),
  schema = os.getenv('SNOWFLAKE_SCHEMA')
)
Copy

자습서 2 에서는 Snowflake와 연결하고 SQL 문을 실행하는 Snowflake 작업을 만듭니다. 다음 단계에서는 자습서 코드가 환경 변수를 사용하는 방법을 요약합니다.

  1. 공통 설정(공통 설정 섹션 참조)에서는 데이터베이스와 스키마를 포함한 리소스를 만듭니다. 또한 세션에 대한 현재 데이터베이스와 스키마를 설정합니다.

    USE DATABASE tutorial_db;
    ...
    USE SCHEMA data_schema;
    
    Copy
  2. 작업을 생성한 후(EXECUTE SERVICE 실행) Snowflake는 컨테이너를 시작하고 컨테이너에서 다음 환경 변수를 세션의 현재 데이터베이스 및 스키마로 설정합니다.

    • SNOWFLAKE_DATABASE가 “TUTORIAL_DB”로 설정됨

    • SNOWFLAKE_SCHEMA가 “DATA_SCHEMA”로 설정됨

  3. 작업 코드(자습서 2의 main.py 참조)는 다음 환경 변수를 읽습니다.

    SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE')
    SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
    
    Copy
  4. 작업 코드는 데이터베이스와 스키마를 SQL 문을 실행할 컨텍스트로 설정합니다(main.pyrun_job() 함수).

    {
       "account": SNOWFLAKE_ACCOUNT,
       "host": SNOWFLAKE_HOST,
       "authenticator": "oauth",
       "token": get_login_token(),
       "warehouse": SNOWFLAKE_WAREHOUSE,
       "database": SNOWFLAKE_DATABASE,
       "schema": SNOWFLAKE_SCHEMA
    }
    ...
    
    Copy

    SNOWFLAKE_ACCOUNT, SNOWFLAKE_HOST, SNOWFLAKE_DATABASE, SNOWFLAKE_SCHEMA는 Snowflake가 애플리케이션 컨테이너에 대해 생성하는 환경 변수이지만 SNOWFLAKE_WAREHOUSE 는 그렇지 않습니다(Snowflake가 웨어하우스 이름을 컨테이너에 전달하지 않으므로 자습서 2 애플리케이션 코드에서 이 변수를 생성함).

컨테이너용 웨어하우스 지정하기

서비스(또는 작업)가 Snowflake에 연결하여 Snowflake 웨어하우스에서 쿼리를 실행하는 경우 웨어하우스를 지정하는 다음 옵션이 있습니다.

  • 애플리케이션 코드에서 웨어하우스를 지정합니다. 코드에서 쿼리를 실행하려면 Snowflake 세션을 시작할 때 연결 구성의 일부로 웨어하우스를 지정하십시오. 예를 보려면 자습서 2 를 참조하십시오.

  • 서비스 생성 시 기본 웨어하우스를 지정합니다. 기본 웨어하우스를 제공하려면 CREATE SERVICE 명령에 선택적 QUERY_WAREHOUSE 매개 변수를 지정하십시오. 애플리케이션 코드가 연결 구성의 일부로 웨어하우스를 제공하지 않는 경우 Snowflake는 기본 웨어하우스를 사용합니다. ALTER SERVICE 명령을 사용하여 기본 웨어하우스를 변경합니다.

두 가지 방법을 모두 사용하여 웨어하우스를 지정하는 경우 애플리케이션 코드에 지정된 웨어하우스가 사용됩니다.

OAuth 토큰을 사용하여 SQL 실행하기

Snowflake에서 제공하는 모든 클라이언트는 인증 방법으로 OAuth를 지원합니다. 서비스/작업 컨테이너는 또한 OAuth 메커니즘을 사용하여 Snowflake로 인증합니다. 예를 들어 컨테이너가 SQL을 실행하려고 하면 컨테이너가 다른 Snowflake 클라이언트와 마찬가지로 Snowflake에 대한 연결을 생성합니다.

def get_login_token():
  with open('/snowflake/session/token', 'r') as f:
    return f.read()

conn = snowflake.connector.connect(
  host = os.getenv('SNOWFLAKE_HOST'),
  account = os.getenv('SNOWFLAKE_ACCOUNT'),
  token = get_login_token(),
  authenticator = 'oauth'
)
Copy

서비스/작업을 생성하면 Snowflake는 컨테이너를 실행하고 컨테이너가 컨테이너 내의 /snowflake/session/token 위치에서 사용할 Oauth 토큰을 제공합니다.

이 OAuth 토큰에 대한 다음 세부 정보를 참고하십시오.

  • 콘텐츠는 10분 후에 만료되고 Snowflake는 몇 분마다 이 파일을 새로 고치므로 사용하기 직전에 /snowflake/session/token 파일의 내용을 읽어야 합니다. 컨테이너가 Snowflake에 올바로 연결되면 사용자가 직접 생성한 세션과 마찬가지로 연결에 만료 시간이 적용되지 않습니다.

  • 이 OAuth 토큰은 특정 Snowflake 서비스/작업 내에서만 유효합니다. OAuth 토큰을 복사하여 서비스/작업 외부에서 사용할 수 없습니다.

  • 컨테이너는 OAuth 토큰을 사용하여 다음과 같이 사용자 및 서비스/작업 역할로 Snowflake와 연결됩니다.

    • 사용자는 서비스/작업을 생성한 사람입니다.

    • 역할은 서비스/작업에 대한 서비스 역할이며 지원되는 유일한 역할입니다. 역할을 변경할 수 없습니다.

  • OAuth 토큰을 사용하여 연결하면 새 세션이 생성됩니다. OAuth 토큰은 기존 SQL 세션과 연결되지 않습니다.

    참고

    저장 프로시저 실행과 서비스/작업 실행의 중요한 차이점은 저장 프로시저가 이들을 실행하는 SQL과 동일한 세션에서 실행된다는 점입니다. 그러나 컨테이너가 새로운 연결을 설정할 때마다 새로운 세션이 생성됩니다.

네트워크 기능 구성하기

다음 섹션에서는 서비스 및 작업에 대한 네트워크 기능(네트워크 수신 및 송신)을 구성하는 방법을 설명합니다.

네트워크 수신

무엇이든 인터넷에서 서비스와 상호 작용할 수 있도록 하려면 서비스 사양 파일에서 서비스가 수신 대기하는 네트워크 포트를 엔드포인트로 선언합니다. 이러한 엔드포인트가 수신을 제어합니다.

기본적으로 서비스 엔드포인트는 비공개입니다. 서비스 함수서비스 간 통신 만 비공개 엔드포인트에 요청할 수 있습니다. 엔드포인트를 공개로 선언하여 인터넷에서 엔드포인트에 대한 요청을 허용할 수 있습니다. (공개 엔드포인트가 있는) 서비스를 생성하는 역할에는 계정에 대한 BIND SERVICE ENDPOINT 권한이 있어야 합니다.

endpoints:
- name: <endpoint name>
  port: <port number>
  protocol : < TCP / HTTP / HTTPS >
  public: true
Copy

예를 보려면 자습서 1 을 참조하십시오.

참고

현재 작업이 아닌 서비스만 네트워크 수신을 지원합니다.

수신 및 웹 앱 보안

공용 엔드포인트 지원(네트워크 수신)을 사용하여 웹 호스팅용 Snowpark Container Services 서비스를 만들 수 있습니다. 보안을 강화하기 위해 Snowflake는 프록시 서비스를 사용하여 클라이언트에서 서비스로 수신되는 요청과 서비스에서 클라이언트로 발신되는 응답을 모니터링합니다. 이 섹션에서는 프록시가 수행하는 작업과 Snowpark Container Services에 배포된 서비스에 미치는 영향을 설명합니다.

참고

로컬에서 서비스를 테스트하는 경우 Snowflake 프록시를 사용하지 않으므로 Snowpark Container Services에 배포할 때와 반대로 로컬에서 서비스를 실행하는 경험 간에 차이가 있습니다. 이 섹션을 검토하고 더 나은 테스트를 위해 로컬 설정을 업데이트하십시오.

예:

  • 요청이 금지된 HTTP 메서드를 사용하는 경우 프록시는 수신되는 HTTP 요청을 전달하지 않습니다.

  • 응답의 Content-Type 헤더가 응답에 실행 파일이 포함되어 있음을 나타내는 경우 프록시는 클라이언트에 403 응답을 보냅니다.

또한 프록시는 컨테이너 및 데이터 보안을 염두에 두고 새 헤더를 삽입하고 요청과 응답에서 기존 헤더를 변경할 수도 있습니다.

예를 들어 요청을 받으면 서비스는 응답으로 HTML, JavaScript, CSS 및 웹 페이지의 기타 콘텐츠를 클라이언트 브라우저에 보낼 수 있습니다. 브라우저의 웹 페이지는 서비스의 일부이며 사용자 인터페이스 역할을 합니다. 보안상의 이유로, 서비스에 제한 사항(예: 다른 사이트에 네트워크로 연결하는 데 대한 제한)이 있는 경우 서비스의 웹 페이지에도 동일한 제한 사항을 적용할 수도 있습니다.

기본적으로 서비스에는 인터넷에 액세스할 권한이 없습니다. 또한 브라우저는 클라이언트 앱이 인터넷에 액세스하고 잠재적으로 데이터를 공유하는 것을 제한해야 합니다. 서비스가 example.com (네트워크 송신 참조)에 액세스할 수 있도록 EAI(External Access Integration)를 설정한 경우 서비스의 웹 페이지도 브라우저를 통해 example.com 에 액세스할 수도 있어야 합니다.

Snowflake 프록시는 응답에 Content-Security-Policy (CSP) 헤더를 추가하여 서비스와 웹 페이지에 동일한 네트워크 제한을 적용합니다. 기본적으로, 프록시는 일반적인 보안 위협으로부터 보호하기 위해 응답에 기준선 CSP를 추가합니다. 또한 서비스가 EAI를 사용하도록 구성된 경우 프록시는 웹 페이지에 대해 EAI에서 CSP까지 동일한 네트워크 규칙을 적용합니다. 이 CSP를 사용하면 브라우저의 웹 페이지에서 서비스가 액세스할 수 있는 것과 동일한 사이트에 액세스할 수 있습니다.

다음 섹션에서는 Snowflake 프록시가 서비스에 대한 수신되는 요청을 처리하고 서비스에서 클라이언트로 발신되는 응답을 수정하는 방법을 설명합니다.

서비스로 수신되는 요청

요청이 도착하면 프록시는 요청을 서비스에 전달하기 전에 다음을 수행합니다.

  • 금지된 HTTP 메서드가 포함된 수신 요청: 수신 HTTP 요청이 다음과 같은 금지된 HTTP 메서드 중 하나를 사용하는 경우 프록시는 해당 요청을 서비스로 전달하지 않습니다.

    • TRACE

    • OPTIONS

    • CONNECT

고객에게 발신되는 응답

Snowflake 프록시는 응답을 클라이언트에 전달하기 전에 서비스에서 보낸 응답에 이러한 수정 사항을 적용합니다.

  • 헤더 스크러빙: Snowflake 프록시는 다음 응답 헤더가 있는 경우 제거합니다.

    • X-XSS-Protection

    • Server

    • X-Powered-By

    • Public-Key-Pins

  • Content-Type 응답 헤더: 서비스 응답에 (실행 파일을 나타내는) 다음 MIME 유형 값을 가진 Content-Type 헤더가 포함된 경우 Snowflake 프록시는 해당 응답을 클라이언트에 전달하지 않습니다. 대신 프록시는 403 Forbidden 응답을 보냅니다.

    • application/x-msdownload: Microsoft 실행 파일.

    • application/exe: 일반 실행 파일.

    • application/x-exe: 또 다른 일반 실행 파일.

    • application/dos-exe: DOS 실행 파일.

    • application/x-winexe: Windows 실행 파일.

    • application/msdos-windows: MS-DOS Windows 실행 파일.

    • application/x-msdos-program: MS-DOS 실행 파일.

    • application/x-sh: Unix 셸 스크립트.

    • application/x-bsh: Bourne 셸 스크립트.

    • application/x-csh: C 셸 스크립트.

    • application/x-tcsh: Tcsh 셸 스크립트.

    • application/batch: Windows 배치 파일.

  • X-Frame-Options 응답 헤더: 클릭재킹 공격을 방지하기 위해 Snowflake 프록시는 이 응답 헤더를 DENY 로 설정하여 다른 웹 페이지가 귀하의 서비스 웹 페이지에 iframe을 사용하지 못하게 합니다.

  • Cross-Origin-Opener-Policy(COOP) 응답 헤더: Snowflake는 교차 원본 윈도우를 참조해 서비스 탭에 액세스하지 못하게 하기 위해 COOP 응답 헤더를 same-origin 으로 설정합니다.

  • Cross-Origin-Resource-Policy(CORP) 응답 헤더: Snowflake는 외부 사이트가 수신 엔드포인트(예: iframe)에 의해 노출된 리소스를 로드하지 못하도록 CORP 헤더를 same-origin 으로 설정합니다.

  • X-Content-Type-Options 응답 헤더: Snowflake 프록시는 이 헤더를 nosniff 로 설정하여 클라이언트가 서비스의 응답에 명시된 MIME 유형을 변경하지 않도록 보장합니다.

  • Cross-Origin-Embedder-Policy(COEP) 응답 헤더: Snowflake 프록시는 COEP 응답 헤더를 credentialless 로 설정하는데, 이는 이미지나 스크립트와 같은 교차 원본 오브젝트를 로드할 때 원격 오브젝트가 Cross-Origin Resource Sharing(CORS) 프로토콜을 지원하지 않는 경우 Snowflake는 오브젝트를 로드할 때 자격 증명을 보내지 않습니다.

  • Content-Security-Policy-Report-Only 응답 헤더: Snowflake 프록시는 이 응답 헤더를 클라이언트가 Snowflake에 CSP 보고서를 보내도록 지시하는 새로운 값으로 바꿉니다.

  • Content-Security-Policy(CSP) 응답 헤더: 기본적으로 Snowflake 프록시는 일반적인 웹 공격으로부터 보호하기 위해 다음 기준선 CSP를 추가합니다.

    default-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: blob: data:; object-src 'none'; connect-src 'self' http: https: wss:; frame-ancestors 'self';
    
    Copy

    다음 두 가지 콘텐츠 보안 정책 고려 사항이 있습니다.

    • 프록시가 추가하는 기준선 콘텐츠 보안 정책 외에도 서비스 자체가 응답에 CSP를 명시적으로 추가할 수 있습니다. 서비스는 더 엄격한 CSP를 추가하여 보안을 강화하도록 선택할 수 있습니다. 예를 들어 서비스는 self 의 스크립트만 허용하도록 다음 CSP를 추가할 수 있습니다.

      script-src 'self'
      
      Copy

      클라이언트에 전송된 결과 응답에는 두 개의 CSP 헤더가 있습니다. 응답을 받으면 클라이언트 브라우저는 각 정책으로 지정된 추가 제한 사항을 포함하는 가장 엄격한 콘텐츠 보안 정책을 적용합니다.

    • 서비스가 외부 사이트(네트워크 송신)에 액세스할 수 있도록 EAI(External Access Integration)를 구성할 경우 Snowflake 프록시는 웹 페이지가 해당 사이트에 액세스할 수 있도록 허용하는 CSP를 생성합니다. 예를 들어, EAI와 연결된 네트워크 규칙에서 example.com 에 대한 서비스 송신 액세스를 허용한다고 가정해 보겠습니다. 그런 다음 Snowflake 프록시가 이 CSP 응답 헤더를 추가합니다.

      default-src 'self' 'unsafe-inline' 'unsafe-eval' http://example.com https://example.com blob: data:; object-src 'none'; connect-src 'self' http://example.com https://example.com wss://example.com; frame-ancestors 'self';
      
      Copy

      브라우저는 응답으로 수신된 콘텐츠 액세스 정책을 준수합니다. 이 예에서 브라우저를 통해 앱이 example.com 에 액세스할 수 있지만 다른 사이트에는 액세스할 수 없습니다.

네트워크 송신

애플리케이션(작업 또는 서비스) 코드에 인터넷 액세스 권한이 필요할 수 있습니다. 기본적으로 애플리케이션 컨테이너에는 인터넷에 액세스할 권한이 없습니다. EAI(External Access Integration) 를 사용하여 인터넷 액세스를 활성화해야 합니다.

일반적으로, 작업과 서비스에서 허용되는 외부 액세스를 관리하려면 계정 관리자가 EAI를 생성해야 합니다. 그러면 계정 관리자는 개발자가 작업이나 서비스를 실행하는 데 사용하는 특정 역할에 EAI 사용 권한을 부여할 수 있습니다.

다음 예에서는 네트워크 규칙을 사용하여 지정된 특정 대상으로의 송신 트래픽을 허용하는 EAI를 생성하는 단계를 간략하게 설명합니다. 그런 다음 작업이나 서비스를 생성할 때 EAI를 참조하여 특정 인터넷 대상에 대한 요청을 허용합니다.

애플리케이션(작업 또는 서비스) 코드가 다음 대상으로 요청을 보내도록 하는 경우를 가정해 보겠습니다.

  • translation.googleapis.com에 대한 HTTPS 요청

  • google.com에 대한 HTTP 및 HTTPS 요청

작업이나 서비스가 인터넷에서 이러한 도메인에 액세스할 수 있도록 하려면 다음 단계를 따르십시오.

  1. EAI(External Access Integration) 만들기 이를 위해서는 적절한 권한이 필요합니다. 예를 들어, ACCOUNTADMIN 역할을 사용하여 EAI를 생성할 수 있습니다. 이는 다음과 같은 2단계 프로세스입니다.

    1. CREATE NETWORK RULE 명령을 사용하여 액세스를 허용하려는 외부 대상을 나열하는 하나 이상의 송신 네트워크 규칙을 만듭니다. 하나의 네트워크 규칙으로 이 예를 수행할 수 있지만, 설명을 위해 다음 두 네트워크 규칙을 만듭니다.

      1. translate_network_rule 이라는 네트워크 규칙을 만듭니다.

        CREATE OR REPLACE NETWORK RULE translate_network_rule
          MODE = EGRESS
          TYPE = HOST_PORT
          VALUE_LIST = ('translation.googleapis.com');
        
        Copy

        이 규칙을 사용해 translation.googleapis.com 대상에 대한 TCP 연결을 허용합니다. VALUE_LIST 속성의 도메인은 선택적 포트 번호를 지정하지 않으므로 기본 포트 443(HTTPS)을 허용합니다. 이를 통해 애플리케이션이 https://translation.googleapis.com/ 으로 시작하는 모든 URL에 연결할 수 있습니다.

      2. google_network_rule 이라는 네트워크 규칙을 만듭니다.

        CREATE OR REPLACE NETWORK RULE google_network_rule
          MODE = EGRESS
          TYPE = HOST_PORT
          VALUE_LIST = ('google.com:80', 'google.com:443');
        
        Copy

        이를 통해 애플리케이션이 http://google.com/ 또는 https://google.com/ 으로 시작하는 모든 URL에 연결할 수 있습니다.

      참고

      VALUE_LIST 매개 변수의 경우 전체 호스트 이름을 제공해야 합니다. 와일드카드(예: *.googleapis.com)는 지원되지 않습니다.

      Snowpark Container Services는 포트 22, 80, 443, 1024 이상을 허용하는 네트워크 규칙만 지원합니다. 참조된 네트워크 규칙이 다른 포트에 대한 액세스를 허용하는 경우 서비스 생성이 실패합니다. 추가 포트를 사용해야 하는 경우 계정 담당자에게 문의하십시오.

      참고

      작업 또는 서비스가 인터넷의 어떤 대상으로든 HTTP 또는 HTTPS 요청을 보내도록 허용하려면 VALUE_LIST 속성에서 “0.0.0.0”을 도메인으로 지정합니다. 다음 네트워크 규칙을 사용하면 인터넷의 어디에서나 “HTTP” 및 “HTTPS” 요청을 모두 보낼 수 있습니다. “0.0.0.0”에서는 포트 80 또는 443만 지원됩니다.

      CREATE NETWORK RULE allow_all_rule
        TYPE = 'HOST_PORT'
        MODE= 'EGRESS'
        VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
      
      Copy
    2. 이전의 두 송신 네트워크 규칙이 허용되도록 지정하는 EAI(외부 액세스 통합)를 생성합니다.

      CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration
        ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule)
        ENABLED = true;
      
      Copy

      이제 계정 관리자는 개발자가 인터넷의 특정 대상에 액세스할 수 있는 작업/서비스를 실행할 수 있도록 통합 사용 권한을 부여할 수 있습니다.

      GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
      
      Copy
  2. 다음 예와 같이 EAI를 제공하여 서비스 또는 작업을 만듭니다. 서비스 또는 작업을 생성하는 역할에는 EAI에 대한 사용 권한과 참조된 시크릿에 대한 읽기 권한이 필요합니다. 서비스나 작업을 생성하는 데 ACCOUNTADMIN 역할을 사용할 수 없습니다.

    • 다음과 같이 서비스를 만듭니다.

      USE ROLE test_role;
      
      CREATE SERVICE eai_service
        IN COMPUTE POOL MYPOOL
        FROM SPECIFICATION
        $$
        spec:
          containers:
            - name: main
              image: /db/data_schema/tutorial_repository/my_echo_service_image:tutorial
              env:
                TEST_FILE_STAGE: source_stage/test_file
              args:
                - read_secret.py
          endpoints:
            - name: read
              port: 8080
        $$
        EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION);
      
      Copy

      이 예시 CREATE SERVICE 요청은 인라인 서비스 사양을 사용하고 EAI를 포함하도록 선택적 EXTERNAL_ACCESS_INTEGRATIONS 속성을 지정합니다. EAI는 서비스에서 특정 대상으로의 송신 트래픽을 허용하는 네트워크 규칙을 지정합니다.

    • 다음과 같이 작업을 만듭니다.

      EXECUTE SERVICE
        IN COMPUTE POOL tt_cp
        FROM SPECIFICATION $$
        spec:
          container:
          - name: curl
            image: /tutorial_db/data_schema/tutorial_repo/alpine-curl:latest
            command:
            - "curl"
            - "http://google.com/"
        $$
        EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION);
      
      Copy

      이 예시 EXECUTE SERVICE 명령은 인라인 사양과 EAI를 포함하도록 선택적 EXTERNAL_ACCESS_INTEGRATIONS 속성을 지정합니다. 이렇게 하면 작업에서 EAI가 허용하는 네트워크 규칙에 지정된 대상으로의 송신 트래픽이 허용됩니다.

컨테이너 간 네트워크 통신

다음 두 가지 고려 사항이 있습니다.

  • 서비스 인스턴스의 컨테이너 간 통신: 서비스 인스턴스가 여러 컨테이너를 실행하는 경우 이러한 컨테이너는 localhost를 통해 서로 통신할 수 있습니다(서비스 사양에서 엔드포인트를 정의할 필요가 없음).

  • 여러 서비스/작업 또는 여러 서비스 인스턴스에 걸친 컨테이너 간 통신: 서로 다른 서비스(또는 동일한 서비스의 다른 인스턴스)에 속한 컨테이너는 사양 파일에 정의된 엔드포인트를 사용하여 통신할 수 있습니다. 자세한 내용은 서비스 간 통신 섹션을 참조하십시오.

Snowflake 시크릿을 사용하여 자격 증명을 컨테이너에 전달하기

서비스 또는 작업이 외부 엔드포인트(Snowflake 외부)와 통신하는 경우 애플리케이션 코드에서 사용할 자격 증명 정보를 컨테이너에 제공해야 합니다. 이렇게 하려면 먼저 Snowflake 시크릿 오브젝트에 자격 증명을 저장하십시오. 다음으로, 서비스 또는 작업 사양 파일에 containers.secrets 필드를 포함하여 이러한 시크릿을 컨테이너에 전달합니다.

이러한 자격 증명을 컨테이너의 환경 변수에 전달하거나 컨테이너의 로컬 파일에서 사용 가능하도록 설정할 수 있습니다. 선택하는 항목에 따라 사양 파일은 다음 섹션에서 설명하는 대로 생성자를 제공합니다.

시크릿을 환경 변수로 전달하기

컨테이너 Snowflake 시크릿을 환경 변수로 전달하려면 containers.secrets 필드를 포함하십시오.

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: <snowflake-secret-name>
    secretKeyRef: <secret-key-reference>
    envVarName: <env-variable-name>
Copy

secretKeyRef: 이 값은 Snowflake 시크릿의 유형에 따라 달라집니다. 가능한 값은 다음과 같습니다.

  • Snowflake 시크릿이 password 유형인 경우 username 또는 password.

  • Snowflake 시크릿이 generic_string 유형인 경우 secret_string.

  • Snowflake 시크릿이 oauth2 유형인 경우 access_token.

참고

서비스(또는 작업)가 생성된 후에는 환경 변수로 전달된 시크릿을 업데이트할 수 없습니다.

예 1: 비밀번호 유형의 시크릿을 환경 변수로 전달하기

이 예에서는 password 유형의 다음 Snowflake 시크릿 오브젝트를 생성합니다.

CREATE SECRET testdb.testschema.my_secret_object
  TYPE = password
  USERNAME = 'snowman'
  PASSWORD = '1234abc';
Copy

이 Snowflake 시크릿 오브젝트를 컨테이너의 환경 변수(예: LOGIN_USERLOGIN_PASSWORD)에 제공하려면 사양 파일에 다음 containers.secrets 필드를 추가하십시오.

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret_object
    secretKeyRef: username
    envVarName: LOGIN_USER
  - snowflakeSecret: testdb.testschema.my_secret_object
    secretKeyRef: password
    envVarName: LOGIN_PASSWORD
Copy

이 예의 containers.secrets 필드는 두 snowflakeSecret 오브젝트의 목록입니다.

  • 첫 번째 오브젝트는 Snowflake 시크릿 오브젝트의 username 을 컨테이너의 LOGIN_USER 환경 변수에 매핑합니다.

  • 두 번째 오브젝트는 Snowflake 시크릿 오브젝트의 password 를 컨테이너의 LOGIN_PASSWORD 환경 변수에 매핑합니다.

예 2: 일반_문자열 유형의 시크릿을 환경 변수로 전달하기

이 예에서는 generic_string 유형의 다음 Snowflake 시크릿 오브젝트를 생성합니다.

CREATE SECRET testdb.testschema.my_secret
  TYPE=generic_string
  SECRET_STRING='
       some_magic: config
  ';
Copy

이 Snowflake 시크릿 오브젝트를 컨테이너의 환경 변수(예: GENERIC_SECRET)에 제공하려면 사양 파일에 다음 containers.secrets 필드를 추가하십시오.

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret
    secretKeyRef: secret_string
    envVarName: GENERIC_SECRET
Copy

oauth2 유형의 시크릿을 환경 변수에 전달하는 방법

OAuth 토큰이 만료되면 새 토큰을 컨테이너에 전달해야 하므로 이는 유용한 시나리오가 아닙니다. 하지만 환경 변수로 전달된 시크릿은 업데이트할 수 없으므로 “oauth2” 유형의 시크릿을 환경 변수로 전달하지 마십시오.

로컬 컨테이너 파일에 시크릿 전달하기

로컬 컨테이너 파일의 애플리케이션 컨테이너에서 Snowflake 시크릿을 사용할 수 있도록 하려면 containers.secrets 필드를 포함하십시오.

containers:
- name: <name>
  image: <url>
  ...
  secrets:
  - snowflakeSecret: <snowflake-secret-name>
    directoryPath: '<local directory path in the container>'
Copy

directoryPath: Snowflake는 지정된 디렉터리의 각 시크릿 키에 대해 하나의 파일을 채우며, secretKeyRef 를 지정할 필요는 없습니다.

참고

서비스(또는 작업)가 생성된 후 Snowflake 시크릿 오브젝트가 업데이트되면 Snowflake가 실행 중인 컨테이너에서 해당 시크릿 파일을 업데이트합니다.

예 1: 로컬 컨테이너 파일에 비밀번호 유형의 시크릿 전달하기

이 예에서는 password 유형의 다음 Snowflake 시크릿 오브젝트를 생성합니다.

CREATE SECRET testdb.testschema.my_secret_object
  TYPE = password
  USERNAME = 'snowman'
  PASSWORD = '1234abc';
Copy

이러한 자격 증명을 로컬 컨테이너 파일에서 사용할 수 있도록 하려면 사양 파일에 다음 containers.secrets 필드를 추가하십시오.

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret_object
    directoryPath: '/usr/local/creds'
Copy

서비스나 작업을 시작하면 Snowflake가 컨테이너 내에 /usr/local/creds/username/usr/local/creds/password 라는 두 파일을 생성합니다. 그러면 애플리케이션 코드에서 이러한 파일을 읽을 수 있습니다.

예 2: 로컬 컨테이너 파일에 oauth2 유형의 시크릿 전달하기

이 예에서는 oauth2 유형의 다음 Snowflake 시크릿 오브젝트를 생성합니다.

CREATE SECRET testdb.testschema.oauth_secret
  TYPE = OAUTH2
  OAUTH_REFRESH_TOKEN = '34n;vods4nQsdg09wee4qnfvadH'
  OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2023-12-31 20:00:00'
  API_AUTHENTICATION = my_integration;
Copy

이러한 자격 증명을 로컬 컨테이너 파일에서 사용할 수 있도록 하려면 사양 파일에 다음 containers.secrets 필드를 추가하십시오.

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.oauth_secret
    directoryPath: '/usr/local/creds'
Copy

Snowflake는 OAuth 시크릿 오브젝트에서 액세스 토큰을 가져오고 컨테이너에 /usr/local/creds/access_token 을 생성합니다.

작업 또는 서비스가 oauth2 유형의 시크릿을 사용하는 경우 서비스 또는 작업은 해당 시크릿을 사용하여 인터넷 대상에 액세스해야 합니다. EAI(External Access Integration) 에서 Oauth 시크릿을 허용해야 하며, 그렇지 않으면 CREATE SERVICE 또는 EXECUTE SERVICE가 실패합니다. 이 추가 EAI 요구 사항은 oauth2 유형의 시크릿에만 적용되며 다른 유형의 시크릿에는 적용되지 않습니다.

요컨대, 이러한 서비스를 생성하는 일반적인 단계는 다음과 같습니다.

  1. (앞서 표시한 대로) oauth2 유형의 시크릿을 만듭니다.

  2. 서비스 또는 작업에서 시크릿을 사용할 수 있도록 EAI를 만듭니다. 예:

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai
      ALLOWED_NETWORK_RULES = (<name>)
      ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret)
      ENABLED = true;
    
    Copy
  3. 사양에 containers.secrets 필드를 포함하는 서비스 또는 작업을 만듭니다. 또한 oauth2 시크릿 사용을 허용하기 위해 EAI를 포함하도록 선택적 EXTERNAL_ACCESS_INTEGRATIONS 속성을 지정합니다.

    예시 CREATE SERVICE(인라인 사양 포함) 명령:

    CREATE SERVICE eai_service
      IN COMPUTE POOL MYPOOL
      FROM SPECIFICATION
      $$
      spec:
        containers:
          - name: main
            image: <url>
            secrets:
            - snowflakeSecret: testdb.testschema.oauth_secret
              directoryPath: '/usr/local/creds'
        endpoints:
          - name: api
            port: 8080
      $$
      EXTERNAL_ACCESS_INTEGRATIONS = (example_eai);
    
    Copy

송신에 대한 자세한 내용은 네트워크 송신 섹션을 참조하십시오.

지침 및 제한 사항

  • 이미지 플랫폼 요구 사항: 현재, Snowpark Container Services에는 linux/amd64 플랫폼 이미지가 필요합니다.

  • 서비스/작업 컨테이너는 권한이 없음: 서비스/작업 컨테이너는 권한이 있는 상태로 실행되지 않으므로 호스트의 하드웨어 구성을 변경할 수 없으며 제한된 OS 구성만 변경할 수 있습니다. 서비스/작업 컨테이너는 일반 사용자(즉, 루트가 필요하지 않은 사용자)가 수행할 수 있는 운영 체제 구성만 수행할 수 있습니다.

  • 데이터베이스 및 스키마 이름 바꾸기:

    • 이미 서비스를 생성한 데이터베이스와 스키마의 이름은 바꾸지 마십시오. 이름을 바꾸면 지원되지 않는 다른 데이터베이스와 스키마로 사실상 서비스가 이동하게 됩니다. 예:

      • 서비스 DNS 이름은 이전 데이터베이스 및 스키마 이름을 계속 반영합니다.

      • Snowflake가 실행 중인 서비스 컨테이너에 제공한 데이터베이스 및 스키마 정보는 계속해서 이전 이름을 참조합니다.

      • 서비스가 이벤트 테이블에서 수집하는 새 로그는 계속해서 이전 데이터베이스 및 스키마 이름을 참조합니다.

      • 서비스 함수는 이전 데이터베이스 및 스키마의 서비스를 계속 참조하므로 서비스 함수를 호출할 때 실패하게 됩니다.

    • 서비스 사양은 Snowflake 스테이지 및 이미지 리포지토리와 같은 오브젝트를 참조할 수 있습니다. 이러한 오브젝트가 있는 데이터베이스 또는 스키마 이름을 바꾸는 경우 서비스 사양에서 참조되는 오브젝트의 데이터베이스 및 스키마 이름을 수동으로 업데이트해야 합니다.

  • 데이터베이스와 스키마 삭제 및 삭제 취소:

    • 상위 데이터베이스 또는 스키마를 삭제하면 서비스가 비동기적으로 삭제됩니다. 이는 내부 프로세스가 서비스를 제거하기 전에 서비스가 일정 시간 동안 계속 실행될 수 있음을 의미합니다.

    • 이전에 삭제한 데이터베이스 또는 스키마를 삭제 취소하려고 시도하는 경우 서비스가 복원될 것이라는 보장은 없습니다.

  • 소유권 이전: 서비스와 작업에 대한 소유권 이전은 지원되지 않습니다.

  • 복제: Snowflake에서 복제를 처리할 때 다음 사항에 유의하십시오.

    • 서비스, 작업, 컴퓨팅 풀, 리포지토리와 같은 Snowpark Container Services 오브젝트는 복제할 수 없습니다.

    • 데이터베이스 내에 리포지토리를 생성하면 전체 데이터베이스를 복제할 수 없습니다. 데이터베이스에 서비스, 작업 또는 컴퓨팅 풀과 같은 다른 리소스가 포함되어 있는 경우 데이터베이스 복제 프로세스는 성공하지만 데이터베이스 내의 이러한 개별 오브젝트는 복제되지 않습니다.

  • 작업 시간 초과: Snowpark Container Services 작업이 동기식으로 실행됩니다. 문 제한 시간이 초과되면 작업이 취소됩니다. 기본 문 제한 시간은 2일입니다. 고객은 ALTER SESSION을 사용하여 매개 변수 STATEMENT_TIMEOUT_IN_SECONDS를 설정하여 시간 제한을 변경할 수 있습니다.

    ALTER SESSION SET statement_timeout_in_seconds=<time>
    
    Copy

    EXECUTE SERVICE 명령을 실행하기 전에 설정하십시오.