0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【コツコツAWS】SageMaker用の閉域pip環境を作成

0
Last updated at Posted at 2026-08-15

VPC only(閉域環境)のSageMakerドメインから、CodeArtifact経由でPythonパッケージをインストールする構成を実装しました。
(カスタムイメージではなく、指定したパッケージやバージョンを必要に応じてインストールできる仕組みが欲しかった)

以下の手順で実装しています。

  1. 個人用のCodeArtifact作成
  2. VPC関連のリソース作成
  3. SagaMakerのドメイン作成
  4. パッケージの登録
  5. 動作確認

各項目について詳細を記載します。

1. 個人用のCodeArtifact作成

最初にPythonパッケージを入れるリポジトリを作成します。(後でもいい)
CodeArtifactは、まずパッケージのデータを格納するドメインを作成し、その後でパッケージを登録するリポジトリを作成します。
コンソールでの作成手順は特に困る部分もなかったので、説明は省略します。好きな名前で作成して完了です。ドメインにはKMSキーを設定できます。(今回はAWSマネージドを利用)

作成したドメインの詳細を見ると、S3バケットARNがあります。(パッケージのデータ保存用)
S3のコンソールからは見られず、CodeArtifactやAWS CLI経由での操作となるようです。

2. VPC関連のリソース作成

VPC onlyのSageMakerドメインを作成するため、各種リソースを作成します。

VPC

VPC onlyでIPv4 CIDRを10.0.0.0/16、テナンシーをデフォルトにして作成。 (作成後にVPCの設定を開き、DNS解決とDNSホスト名を有効化)

サブネット, ルートテーブル

SageMakerのドメインをVPC onlyで作成する場合、2つ以上のサブネットが推奨されるため、2つ作成します。(IPv4 CIDRは10.0.1.0/2410.0.2.0/24で設定)
またルートテーブルについては、2つのサブネットが同じVPC Endpointを利用することになるので、1つのルートテーブルに2つのサブネットを関連付けるようにします。

最初のVPC作成時にサブネットやルートテーブルをまとめて作ると、サブネットごとのルートテーブルができるので、修正が必要。

セキュリティグループ

SageMaker Studio用のセキュリティグループ
インバウンド:NFS (TCP/2049)およびカスタムTCP (TCP/8192~65535)を許可し、ソースにはStudio用のセキュリティグループ(自分自身)を指定

アウトバウンド:HTTPS (TCP/443)を許可し、宛先にEndpoints用のセキュリティグループを指定

Endpoint用のセキュリティグループ
インバウンド:HTTPS (TCP/443)を許可し、ソースは自分自身のセキュリティグループを指定

アウトバウンド:指定なし

Endpoint作成

閉域環境でのSageMakerの利用を可能にするため、下記サービスのEndpointを作成。(S3はルートテーブル、その他は2つのサブネットとEndpoint用のセキュリティグループを関連付けして作成)

  • com.amazonaws.ap-northeast-1.s3(Gateway)
  • com.amazonaws.ap-northeast-1.sagemaker.api
  • com.amazonaws.ap-northeast-1.sagemaker.runtime
  • com.amazonaws.ap-northeast-1.servicecatalog
  • com.amazonaws.ap-northeast-1.codeartifact.api
  • com.amazonaws.ap-northeast-1.codeartifact.repositories
  • com.amazonaws.ap-northeast-1.sts
  • com.amazonaws.ap-northeast-1.ecr.api
  • com.amazonaws.ap-northeast-1.ecr.dkr
  • com.amazonaws.ap-northeast-1.logs

3. SagaMakerのドメイン作成

インターネット接続のない、VPC onlyのドメインを作成します。

  • ロールは既存のものがあればそれを利用、なければ新規ロールを作成し、CodeArtifactを利用するための下記ポリシーを追記
  • アプリケーションやインターフェイスはお好み (今回はJupyterLabとCodeEditorを使えるよう設定)
  • ネットワーク設定で「VPCのみ」を選び、作成したVPCと2つのサブネット、Studio用のセキュリティグループを設定
ポリシー例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CodeArtifactReadForPip",
            "Effect": "Allow",
            "Action": [
                "codeartifact:GetAuthorizationToken",
                "codeartifact:GetRepositoryEndpoint",
                "codeartifact:ReadFromRepository"
            ],
            "Resource": "*"
        },
        {
            "Sid": "STSServiceBearerTokenForCodeArtifact",
            "Effect": "Allow",
            "Action": "sts:GetServiceBearerToken",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "sts:AWSServiceName": "codeartifact.amazonaws.com"
                }
            }
        }
    ]
}

4. パッケージの登録

1で作成したリポジトリにパッケージを登録します。
今回はCodeCommitのリポジトリに登録したpyproject.tomluv.lockを入力とし、CodeBuildでwheelを集めてCodeArtifactに投入する形を取りました。

まずCodeCommitにリポジトリを作成し、以下のファイルを置きます。

  • pyproject.toml
  • uv.lock
  • buildspec.yml

buildspec.ymlの中身は以下の通り。

buildspec.yml
version: 0.2

env:
  variables:
    AWS_REGION: ap-northeast-1
    DOMAIN: <作成したArtifactのDomain名>
    DOMAIN_OWNER: "<アカウントID>"
    DEST_REPO: <作成したArtifactのリポジトリ名>

phases:
  install:
    runtime-versions:
      python: 3.12
    commands:
      # venv作成・ツール導入(uv/twine)
      - |
          set -eu
          python3 --version
          python3 -m venv venv
          . venv/bin/activate
          pip install -U pip wheel twine uv
          uv --version

  build:
    commands:
      # uv.lock → requirements.txt → wheel収集 → CodeArtifact投入
      - |
          set -eu
          . venv/bin/activate

          # wheel格納場所
          mkdir -p wheelhouse

          # uv.lockを元に固定requirementsを生成
          uv export --format requirements.txt --output-file requirements.txt
          head -n 50 requirements.txt

          # requirements.txtを元にwheel収集(依存込み)
          pip download -d wheelhouse --only-binary=:all: -r requirements.txt

          # CodeArtifactへupload
          export AWS_STS_REGIONAL_ENDPOINTS=regional

          CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \
            --domain "$DOMAIN" --domain-owner "$DOMAIN_OWNER" \
            --query authorizationToken --output text --region "$AWS_REGION")

          REPO_URL=$(aws codeartifact get-repository-endpoint \
            --domain "$DOMAIN" --domain-owner "$DOMAIN_OWNER" \
            --repository "$DEST_REPO" --format pypi \
            --query repositoryEndpoint --output text --region "$AWS_REGION")

          # 誤爆防止(空なら失敗させる)
          test -n "$REPO_URL"

          twine upload --repository-url "$REPO_URL" -u aws -p "$CODEARTIFACT_AUTH_TOKEN" wheelhouse/*

CodeCommitのリポジトリに上記3つのファイルを追加できたら、CodeBuildでプロジェクトを作成します。

  • ソースプロバイダにCodeCommitを選択し、↑で作成したリポジトリを設定
  • 環境はデフォルトのものを選択 (本来はversion等を固定すべき?)
  • ロールは下記ポリシーを持つものを選択
  • Buildspecは「buildspecファイルを使用する」を選択
CodeBuild Policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CodeCommitGitPull",
            "Effect": "Allow",
            "Action": "codecommit:GitPull",
            "Resource": "arn:aws:codecommit:ap-northeast-1:<アカウントID>:<リポジトリ名>"
        },
        {
            "Sid": "CloudWatchLogsForCodeBuild",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        },
        {
            "Sid": "CodeArtifactPublish",
            "Effect": "Allow",
            "Action": [
                "codeartifact:GetAuthorizationToken",
                "codeartifact:GetRepositoryEndpoint",
                "codeartifact:PublishPackageVersion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "STSServiceBearerTokenForCodeArtifact",
            "Effect": "Allow",
            "Action": "sts:GetServiceBearerToken",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "sts:AWSServiceName": "codeartifact.amazonaws.com"
                }
            }
        }
    ]
}

プロジェクトが作成できたら、「ビルドを開始」してCodeCommitの内容を元にCodeArtifactへの登録が行われるのを確認。
無事に登録ができていれば、Artifactのリポジトリの中にpyproject.tomluv.lockに記載していたパッケージが入っていることが確認できます。

5. 動作確認

Artifactへの登録が完了したら、SageMakerでインストールができるかを確認します。
3で作成したドメインからStudioを開き、スペースを作成してJupyterLabを起動します。
起動できたらターミナルを開き、CodeArtifactにログイン (pipの参照先を固定)します。

Artifactへのログイン
export AWS_REGION=ap-northeast-1
export AWS_STS_REGIONAL_ENDPOINTS=regional

aws codeartifact login \
  --tool pip \
  --domain <作成したArtifactのDomain名> \
  --domain-owner <アカウントID> \
  --repository <作成したArtifactのリポジトリ名> \
  --region $AWS_REGION

ログインできたら、まず以下のコマンドでPyPIへの通信が失敗することを確認します。(Privateサブネットなので、PyPIにはアクセスできない)

curl -I https://pypi.org/ -m 5
# curl: (28) Connection timed out after 5001 milliseconds

そして、Artifactに登録したパッケージがインストールできるか確認します。

pip install ***
# Looking in indexes: https://aws:****@my-domain-...
# Collecting ***
# ...

Looking in indexes...で作成したCodeArtifactを参照し、installが進んでいます。無事にPrivate環境からArtifactに登録したパッケージだけをインストールできる環境ができました。

まとめ

閉域環境のSageMakerドメインから、CodeArtifact経由でPythonパッケージをインストールする構成を実装しました。
これで解析環境を閉域にしつつ、指定したパッケージや自作パッケージを必要に応じてインストールすることができます。

今回はbuildspec側でPythonのversionを固定してますが、SageMaker側のpythonのversionに合わせて、pyproject.tomlやbuildspec.ymlのpythonのversionも追従する仕組みがあると、より便利かもしれません。
他にもCodeCommitのリポジトリの変更をトリガーとしたパッケージ更新の自動化も考えられますが、そこは運用の仕方にもよると思うので、今回は割愛します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?