NTNX>日記

個人的な趣味による Nutanix Community Edition 日記。Japanese のみですみません。

NAI 2.4 の推論エンドポイントむけデモ アプリを NKP のカタログに登録してみる。

NAI 2.4 の推論エンドポイントむけに作成したデモ アプリを、Nutanix  Kubernetes Platform(NKP)のカタログに、カスタム アプリケーションとして登録してみます。

今回の内容です。

 

今回のアプリについて

以前に作成した、AI チャットのデモ アプリを使用します。

このデモ アプリは、コンテナ イメージ化してあり、OCI アーティファクト形式の Helm Chart を用意してあります。

 

1. nkp CLI のインストール

NKP では、アプリケーション管理でも nkp CLI を使用します。そこで、作業用の Linux マシンに nkp CLI をインストールしておきます。NKP の Kubernetes クラスタ作成時に使用した nkp コマンド実行マシンがある場合は、そこでも作業できます。

 

作業用ユーザーは、PATH 環境変数に $HOME/bin ディレクトリを追加してあります。Nutanix Support & Insight Portal から、nkp CLI の tar.gz ファイルをダウンロードして、Linux マシンに配置しておきます。

$ ls -l nkp_v2.16.0_linux_amd64.tar.gz
-rw-rw-r-- 1 gowatana gowatana 138587302 Oct 17 10:41 nkp_v2.16.0_linux_amd64.tar.gz

ファイルを展開して、nkp コマンドをインストールします。

$ tar zxvf nkp_v2.16.0_linux_amd64.tar.gz nkp
$ install nkp $HOME/bin/

不要になったファイルは削除しておきます。

$ rm nkp
$ rm nkp_v2.16.0_linux_amd64.tar.gz

今回の nkp CLI のバージョンは、v2.16.0 です。

$ nkp version
catalog: v0.7.0
diagnose: v0.12.0
imagebuilder: v2.16.0
kommander: v2.16.0
konvoy: v2.16.0
mindthegap: v1.22.1
nkp: v2.16.0

 

2. NKP カタログ バンドルの準備

NKP のカタログ リポジトリを作成して、それを tar アーカイブしたカタログ バンドルを作成します。

2-1. NKP カタログ リポジトリの作成

NKP カタログ リポジトリのディレクトリを作成します。このディレクトリ名はこの後作成する OCI リポジトリのパスにも使用されます。

$ mkdir nkp-repo

 

nkp generate catalog-repository で、カタログ リポジトリの雛形となるファイル一式を作成します。「--apps」で指定している「nai-demo=0.0.1」は、リポジトリに含める Helm Chart のアプリ バージョンではなく、NKP カタログ リポジトリで管理するアプリ バージョンです。そのため、カタログ リポジトリ自体の設定を変更する場合は、Helm Chart とは別バージョンとは分離して管理できます。

$ nkp generate catalog-repository --apps nai-demo=0.0.1 --repo-dir ./nkp-repo/
Successfully initialized application layout for nai-demo-0.0.1
Catalog layout generated at /home/gowatana/nkp-repo

 

下記のようにリポジトリが生成されます。隠しファイルがあるので、tree コマンドに「-a」オプションを追加しています。

$ tree ./nkp-repo/ --charset=ascii -a
./nkp-repo/
|-- .bloodhound.yml
`-- applications
    `-- nai-demo
        `-- 0.0.1
            |-- helmrelease
            |   |-- cm.yaml
            |   |-- helmrelease.yaml
            |   `-- kustomization.yaml
            |-- helmrelease.yaml
            |-- kustomization.yaml
            `-- metadata.yaml

5 directories, 7 files

 

リポジトリ(nkp-repo ディレクトリ)直下の .bloodhound.yml ファイルは、ひとまずデフォルトのままにしてあります。

./nkp-repo/.bloodhound.yml

gist.github.com

 

metadata.yaml ファイルは、バンドル作成時のエラー解消のため「supportLink」のみ編集してあります。

./nkp-repo/applications/nai-demo/0.0.1/metadata.yaml

  • L14:supportLink を、とりあえず私の X/Twitter アカウントに変更

gist.github.com

 

helmrelease.yaml ファイルは、OCI アーティファクトの URL のみ変更します。

./nkp-repo/applications/nai-demo/0.0.1/helmrelease/helmrelease.yaml

  • L9:OCI アーティファクト イメージのタグ(0.0.1)
  • L10:OCI リポジトリを指定
    url: oci://<registry>/<org-name>/<repo-name>

    url: oci://ghcr.io/gowatana/nai-demo-repo/nai-demo

gist.github.com

 

2-2. NKP カタログ バンドルの作成

nkp create catalog-bundle で、カタログ バンドルを作成します。今回は、nai-demo-0.0.1.tar ファイルが作成されます。

$ nkp create catalog-bundle --repo-dir ./nkp-repo/
Bundling 1 application(s) (airgapped : false)
 ✓ Validating metadata.yaml for nai-demo/0.0.1
 ✓ Building OCI artifact nkp-repo/nai-demo:0.0.1
Processing application nai-demo/0.0.1
 ✓ K8s v1.33.0: parsing resources
 ✓ K8s v1.33.0: validating
 ✓ Pulling requested images [====================================>1/1] (time elapsed 00s)
 ✓ Saving application bundle to /home/gowatana/nai-demo-0.0.1.tar

Run the following to push the artifact to your registry:

        nkp push bundle --bundle /home/gowatana/nai-demo-0.0.1.tar --to-registry 


Run the following command to create catalog artifact(s) after pushing them:

        nkp create catalog-application --url oci:///nkp-repo/nai-demo --tag 0.0.1 --workspace kommander-workspace

$

 

3. OCI リポジトリの準備

NKP カタログ バンドルを OCI レジストリに Push して、OC リポジトリとして公開します。

今回の OCI レジストリは、コンテナ イメージと同様に GitHub Container Registry(ghcr.io)を使用します。

 

3-1. OCI レジストリへのログイン

docker login の認証情報がそのまま利用できます。パスワードには、あらかじめ GitHub の Tokens (classic) ページ(GitHub アカウントで要ログイン)で生成しておいたトークン(ghp_~ といった文字列)を入力します。

$ docker login ghcr.io
Username: gowatana
Password:

WARNING! Your credentials are stored unencrypted in '/home/gowatana/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

 

3-2. OCI レジストリへのカタログ バンドルの Push

下記のコマンドで OCI レジストリに Push します。今回している「ghcr.io/gowatana」は、私の GitHub リポジトリです。

nkp push bundle \
--bundle ./nai-demo-0.0.1.tar \
--to-registry ghcr.io/gowatana

 

実際に実行すると、下記のようになります。

$ nkp push bundle \
--bundle ./nai-demo-0.0.1.tar \
--to-registry ghcr.io/gowatana
 ✓ Creating temporary directory
 ✓ Extracting bundle configs from "./nai-demo-0.0.1.tar"
 ✓ Parsing image bundle config
 ✓ Starting temporary Docker registry
 ✓ Pushing bundled images [====================================>1/1] (time elapsed 02s)

 

これで、Github Container Registry のリポジトリに、NKP カタログ バンドルのパッケージがアップロードされ、OCI アーティファクトとして扱えるようになりました。

 

3-3. OCI リポジトリの公開

OCI リポジトリから、認証なしでアーティファクトをダウンロードできるようにしておきます。パッケージの Visibility を Public に変更しておきます。

 

コンテナ イメージのページにある、「Package settings」を開きます。

 

画面下方にある、「Change visibility」をクリックします。

 

「Public」を選択し、リポジトリの名前(今回は nkp-repo/nai-demo)を入力して、「I understand the consequences, change package visibility」をクリックします。

 

これで、コンテナ イメージの Visibility が「Public」になり、GitHub の認証なしで Pull できるようになりました。

 

4. NKP カタログ アプリケーションの登録

NKP のカタログ アプリケーションを、NKP の管理クラスタに登録します。

 

4-1. NKP 管理クラスタのコンテキスト作成

NKP の管理クラスタに接続するためのコンテキスト作成を、NKP Dashboard から実施します。すでに管理クラスタの kubeconfig ファイルがある場合は、この手順を省略して「--kubeconfig」オプションで管理クラスタに接続できます。

 

NKP Dashboard にログインして、画面上部で「Global」を選択して、画面右上のユーザー名 →「Ganarate Token」をクリックします。ちなみに、「admin」はビルトインではなく、手動作成したユーザーです。

 

「Main」を選択します。

 

ログイン画面が表示されたら、NKP の管理ユーザー(NKP Dashboard と同じユーザー)でログインします。

 

コードが表示されるので、上から順に、kubectl を実行するターミナルにコピー & ペーストして実行します。

 

これで、管理クラスタに接続できるコンテキスト(今回は admin-172.22.5.201)が作成されます。

$ kubectl config get-contexts
CURRENT   NAME                  CLUSTER              AUTHINFO             NAMESPACE
          admin-172.22.5.201    admin-172.22.5.201   admin-172.22.5.201
*         nkpw02-admin@nkpw02   nkpw02               nkpw02-admin

 

管理クラスタのコンテキストを切り替えます。

$ kubectl config use-context admin-172.22.5.201
Switched to context "admin-172.22.5.201".

 

管理クラスタ(nkpm01)に接続できることを確認しておきます。

$ kubectl get nodes
NAME                            STATUS   ROLES           AGE   VERSION
nkpm01-8x785-c2phw              Ready    control-plane   15d   v1.33.2
nkpm01-8x785-k29gq              Ready    control-plane   15d   v1.33.2
nkpm01-8x785-nrlvp              Ready    control-plane   15d   v1.33.2
nkpm01-md-0-rnvvs-qdkdq-lrmlr   Ready    <none>          15d   v1.33.2
nkpm01-md-0-rnvvs-qdkdq-m4jmn   Ready    <none>          15d   v1.33.2
nkpm01-md-0-rnvvs-qdkdq-ncnzj   Ready    <none>          15d   v1.33.2

 

カタログ アプリケーションを追加する NKP Workspace の Namespace を確認しておきます。この NKP では、「ws-01」Workspaceを作成してありますが、これは Kubernetes の「ws-01-4vp9g-d4xvq」Namespace に紐づけられています。アプリケーションをインストールするワークロード クラスタは、ws-01 Workspace に配置してあります。

$ kubectl get workspaces.workspaces.kommander.mesosphere.io
NAME                  DISPLAY NAME                   WORKSPACE NAMESPACE           AGE
default-workspace     Default Workspace              kommander-default-workspace   15d
kommander-workspace   Management Cluster Workspace   kommander                     15d
ws-01-4vp9g           ws-01                          ws-01-4vp9g-d4xvq             15d

 

なお、このコンテキストは一定時間経過すると期限切れになります。管理クラスタ(ワークロード クラスタも)に接続できなくなった場合は、あらためてこの手順でコンテキストを再作成します。

 

4-2. カタログ アプリケーションの追加

ws-01 Workspace(ws-01-4vp9g-d4xvq Namespace)に、カタログを追加します。

nkp create catalog-application \
--url oci://ghcr.io/gowatana/nkp-repo/nai-demo  \
--tag 0.0.1 \
--workspace ws-01-4vp9g \
--skip-oci-registry-patches

 

コマンドを実行すると、下記のようになります。

$ nkp create catalog-application \
--url oci://ghcr.io/gowatana/nkp-repo/nai-demo  \
--tag 0.0.1 \
--workspace ws-01-4vp9g \
--skip-oci-registry-patches
Catalog application nkp-repo-nai-demo created. Use 'nkp edit ocirepository -n ws-01-4vp9g-d4xvq nkp-repo-nai-demo' to change its configuration if needed.

Note that the OCIRepository is not patched by NKP with credentials due to custom configuration. Make sure to configure the url and credentials according to your cluster networking capabilities.

 

4-3. カタログ アプリケーション追加後の様子(管理クラスタ)

管理クラスタに、OCIRepository リソースが作成されました。

$ kubectl get ocirepository -n ws-01-4vp9g-d4xvq nkp-repo-nai-demo
NAME                URL                                        READY   STATUS                                                                                                       AGE
nkp-repo-nai-demo   oci://ghcr.io/gowatana/nkp-repo/nai-demo   True    stored artifact for digest '0.0.1@sha256:851b60d0de193dae2ec7d5a3be791f80e5e86c46ec9aaf13462d1a8b955fb96d'   27s

 

OCIRepository リソースの情報です。

$ kubectl get ocirepository -n ws-01-4vp9g-d4xvq nkp-repo-nai-demo -o yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
  annotations:
    nkp.nutanix.com/skip-oci-registry-patches: "true"
  creationTimestamp: "2025-10-23T12:51:04Z"
  finalizers:
  - finalizers.fluxcd.io
  generation: 1
  labels:
    catalog.nkp.nutanix.com/catalog-source-artifact: "true"
  name: nkp-repo-nai-demo
  namespace: ws-01-4vp9g-d4xvq
  resourceVersion: "43883061"
  uid: 75527318-acd8-4979-9c36-9ab173885b45
spec:
  interval: 6h0m0s
  provider: generic
  ref:
    tag: 0.0.1
  timeout: 1m0s
  url: oci://ghcr.io/gowatana/nkp-repo/nai-demo
status:
  artifact:
    digest: sha256:9bd003a9d734a9a2ed482fd23f7f14923da58f19e288612c390174010e0c7000
    lastUpdateTime: "2025-10-23T12:51:06Z"
    metadata:
      com.nutanix.nkp.catalog.application-name: nai-demo
      com.nutanix.nkp.catalog.application-version: 0.0.1
      com.nutanix.nkp.catalog.artifact-type: catalog-application
      org.opencontainers.image.created: "2025-10-23T04:35:33Z"
      org.opencontainers.image.ref.name: nai-demo:0.0.1
      org.opencontainers.image.source: nai-demo:0.0.1
    path: ocirepository/ws-01-4vp9g-d4xvq/nkp-repo-nai-demo/sha256:851b60d0de193dae2ec7d5a3be791f80e5e86c46ec9aaf13462d1a8b955fb96d.tar.gz
    revision: 0.0.1@sha256:851b60d0de193dae2ec7d5a3be791f80e5e86c46ec9aaf13462d1a8b955fb96d
    size: 883
    url: http://source-controller.kommander-flux.svc.cluster.local./ocirepository/ws-01-4vp9g-d4xvq/nkp-repo-nai-demo/sha256:851b60d0de193dae2ec7d5a3be791f80e5e86c46ec9aaf13462d1a8b955fb96d.tar.gz
  conditions:
  - lastTransitionTime: "2025-10-23T12:51:06Z"
    message: stored artifact for digest '0.0.1@sha256:851b60d0de193dae2ec7d5a3be791f80e5e86c46ec9aaf13462d1a8b955fb96d'
    observedGeneration: 1
    reason: Succeeded
    status: "True"
    type: Ready
  - lastTransitionTime: "2025-10-23T12:51:06Z"
    message: stored artifact for digest '0.0.1@sha256:851b60d0de193dae2ec7d5a3be791f80e5e86c46ec9aaf13462d1a8b955fb96d'
    observedGeneration: 1
    reason: Succeeded
    status: "True"
    type: ArtifactInStorage
  observedGeneration: 1
  url: http://source-controller.kommander-flux.svc.cluster.local./ocirepository/ws-01-4vp9g-d4xvq/nkp-repo-nai-demo/latest.tar.gz

 

App リソースも作成されました。

$ kubectl get apps -n ws-01-4vp9g-d4xvq nai-demo-0.0.1
NAME             APP ID     APP VERSION   SOURCE              AGE
nai-demo-0.0.1   nai-demo   0.0.1         nkp-repo-nai-demo   93s

 

App リソースの情報です。

$ kubectl get apps.apps.kommander.d2iq.io -n ws-01-4vp9g-d4xvq nai-demo-0.0.1 -o yaml
apiVersion: apps.kommander.d2iq.io/v1alpha3
kind: App
metadata:
  annotations:
    apps.kommander.d2iq.io/allow-multiple-instances: "true"
    apps.kommander.d2iq.io/category: general
    apps.kommander.d2iq.io/display-name: nai-demo
    apps.kommander.d2iq.io/licensing-tiers: pro,ultimate
    apps.kommander.d2iq.io/scope: project
    apps.kommander.d2iq.io/support-link: https://x.com/gowatana
    apps.kommander.d2iq.io/type: custom
  creationTimestamp: "2025-10-23T12:51:06Z"
  generation: 1
  name: nai-demo-0.0.1
  namespace: ws-01-4vp9g-d4xvq
  resourceVersion: "43883064"
  uid: 49147775-353d-41fa-a2f1-da7955eb295e
spec:
  appId: nai-demo
  sourceRef:
    kind: OCIRepository
    name: nkp-repo-nai-demo
    namespace: ws-01-4vp9g-d4xvq
  version: 0.0.1

 

NKP Dashboard で、「ws-01」ワークスペースの「Application」画面を表示すると、カタログにデモ アプリ「nai-demo」が追加されています。

 

5. NKP でのアプリケーション インストール

NKP Dashboard から、デモ アプリ「nai-demo」をインストールします。

「ws-01」Workspace →「Application」を開き、「nai-demo」パネル右下のボタン →「Enable」をクリックします。

 

パラメータを入力して、「Enable」をクリックします。

  • ID:nai-demo-1
  • Selected Cluster:nkpw02(ワークロード クラスタ)
  • Workplace Configuration:Helm Chart の values.yaml と同じパラメータ(下記)を入力
config:
  NAI_ENDPOINT_NAME: "gemma-ep-01"
  NAI_ENDPOINT_URL: "https://10.1.7.122/api/v1/chat/completions"

secret:
  NAI_API_KEY: "d8cb366b-d68d-4f9e-8a65-7075e137977e"

 

 

これで、アプリがインストールされました。

 

ワークロード クラスタでは、ws-01 Workspace に対応した Namespace に、Service が作成されているので、EXTERNAL-IP を確認します。

$ kubectl get svc --context nkpw02-admin@nkpw02 -n ws-01-4vp9g-d4xvq -l app=nai-demo
NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE
ws-01-4vp9g-d4xvq-nai-demo-1   LoadBalancer   10.101.202.0   172.22.5.212   80:31096/TCP   5m

 

Service の EXTERNAL-IP(例では 172.22.5.212)に Web ブラウザからアクセスすると、デモ アプリの AI チャットが表示されます。

 

5-2. インストールされたカスタム アプリの様子(管理クラスタ)

NKP の管理クラスタでは、AppDeployment リソースが作成されました。

$ kubectl get appdeployments.apps.kommander.d2iq.io -n ws-01-4vp9g-d4xvq nai-demo-1
NAME         APP              AGE
nai-demo-1   nai-demo-0.0.1   23s

 

AppDeployment の情報です。

$ kubectl get appdeployments.apps.kommander.d2iq.io -n ws-01-4vp9g-d4xvq nai-demo-1 -o yaml
apiVersion: apps.kommander.d2iq.io/v1alpha3
kind: AppDeployment
metadata:
  creationTimestamp: "2025-10-23T12:54:52Z"
  finalizers:
  - kommander.mesosphere.io/appdeployment
  generation: 1
  name: nai-demo-1
  namespace: ws-01-4vp9g-d4xvq
  resourceVersion: "43890749"
  uid: af3fd0e5-d49c-4761-9342-8080d838c26f
spec:
  appRef:
    kind: App
    name: nai-demo-0.0.1
  clusterSelector:
    matchExpressions:
    - key: kommander.d2iq.io/cluster-name
      operator: In
      values:
      - nkpw02
  configOverrides:
    name: nai-demo-1-config-overrides
status:
  clusters:
  - conditions:
    - status: "True"
      type: AppDeploymentEnabled
    name: nkpw02
  observedGeneration: 1

 

5-3. インストールされたカスタム アプリの様子(ワークロード クラスタ)

アプリをインストールしたワークロード クラスタに、コンテキストを切り替えます。

$ kubectl config use-context nkpw02-admin@nkpw02
Switched to context "nkpw02-admin@nkpw02".

 

コンテキストがワークロード クラスタに切り替わりました。

$ kubectl config get-contexts
CURRENT   NAME                  CLUSTER              AUTHINFO             NAMESPACE
          admin-172.22.5.201    admin-172.22.5.201   admin-172.22.5.201
*         nkpw02-admin@nkpw02   nkpw02               nkpw02-admin

 

ワークロード クラスタに接続できることを確認しておきます。

$ kubectl get nodes
NAME                            STATUS   ROLES           AGE   VERSION
nkpw02-5jkcf-wx4bc              Ready    control-plane   15d   v1.33.2
nkpw02-md-0-9xs7f-nhlcz-dbdwd   Ready    <none>          15d   v1.33.2

 

 ws-01 Workspace に対応した Namespace で、アプリに関連するリソースが作成されています。

$ kubectl get all -n ws-01-4vp9g-d4xvq -l app=nai-demo
NAME                                                READY   STATUS    RESTARTS   AGE
pod/ws-01-4vp9g-d4xvq-nai-demo-1-5965c56985-fx662   1/1     Running   0          109s

NAME                                   TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE
service/ws-01-4vp9g-d4xvq-nai-demo-1   LoadBalancer   10.101.202.0   172.22.5.212   80:31096/TCP   109s

NAME                                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ws-01-4vp9g-d4xvq-nai-demo-1   1/1     1            1           109s

NAME                                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/ws-01-4vp9g-d4xvq-nai-demo-1-5965c56985   1         1         1       109s

 

Pod「ws-01-4vp9g-d4xvq-nai-demo-1-~」も起動されています。

$ kubectl get pods -n ws-01-4vp9g-d4xvq
NAME                                                        READY   STATUS      RESTARTS   AGE
alertmanager-kube-prometheus-stack-alertmanager-0           2/2     Running     0          14d
etcd-metrics-proxy-hlxtq                                    1/1     Running     0          14d
gatekeeper-audit-7c7c7d5f49-5dfg6                           1/1     Running     0          15d
gatekeeper-controller-manager-774b66c7c4-hvgt8              1/1     Running     0          15d
gatekeeper-controller-manager-774b66c7c4-v8szr              1/1     Running     0          15d
kommander-traefik-c5bd74457-52jrt                           1/1     Running     0          14d
kommander-traefik-c5bd74457-s2jf6                           1/1     Running     0          14d
kube-oidc-proxy-77974fb489-7zq8t                            1/1     Running     0          14d
kube-prometheus-stack-grafana-86d746f479-x4kcg              2/2     Running     0          14d
kube-prometheus-stack-kube-state-metrics-58b99f6dc7-n6xwr   1/1     Running     0          14d
kube-prometheus-stack-operator-57f998d8d7-d9qhf             1/1     Running     0          14d
kube-prometheus-stack-prometheus-node-exporter-rb7bw        2/2     Running     0          14d
kube-prometheus-stack-prometheus-node-exporter-rr8h4        2/2     Running     0          14d
kubecost-cost-analyzer-67f74b5864-wq2kc                     1/1     Running     0          14d
kubecost-pre-install-hc8zx                                  0/1     Completed   0          14d
kubecost-prometheus-alertmanager-6bc8fc8977-zhcpl           2/2     Running     0          14d
kubecost-prometheus-server-7c57b45f5f-8wncj                 2/2     Running     0          14d
kubernetes-dashboard-api-c59dc7996-ntxfb                    1/1     Running     0          14d
kubernetes-dashboard-auth-dd9b69cfb-lj9nt                   1/1     Running     0          14d
kubernetes-dashboard-kong-5d8d8bc7b8-29dqf                  1/1     Running     0          14d
kubernetes-dashboard-metrics-scraper-7fbb77f87f-xd5t6       1/1     Running     0          14d
kubernetes-dashboard-web-697769cddd-r4lq7                   1/1     Running     0          14d
prometheus-adapter-d8f96c654-cz9sj                          1/1     Running     0          14d
prometheus-kube-prometheus-stack-prometheus-0               3/3     Running     0          14d
traefik-forward-auth-567694d49d-lr9ch                       1/1     Running     0          14d
ws-01-4vp9g-d4xvq-nai-demo-1-5965c56985-fx662               1/1     Running     0          80s
ws-01-4vp9g-d4xvq-reloader-reloader-5ddb54d499-8hkbg        1/1     Running     0          14d

 

今回登録したアプリを削除するには、下記のような手順を実施します。

 

以上。

 

©2025 gowatana
クリエイティブ・コモンズ・ライセンスこの 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。