PodからKubernetes APIにアクセスする

このガイドでは、Pod内からKubernetes APIにアクセスする方法を示します。

始める前に

Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:

Pod内からAPIへのアクセス

Podの中からAPIにアクセスする時、APIサーバーの場所の検出と認証は、外部クライアントの場合とは若干異なります。

PodからKubernetes APIを使用する最も簡単な方法は、公式のクライアントライブラリを使用することです。 これらのライブラリは自動的にAPIサーバーを検出して認証できます。

公式クライアントライブラリの使用

Podの中からKubernetes APIに接続する推奨された方法として次のものがあります:

いずれの場合も、APIサーバーと安全に通信するために、Podのサービスアカウントの資格情報が使用されます。

REST APIによる直接アクセス

コンテナは、Pod内での実行中に環境変数KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT_HTTPSを取得することで、Kubernetes APIサーバーのHTTPSのURLを作成することができます。 APIサーバーのクラスター内アドレスは、PodがローカルAPIサーバーのDNS名としてkubernetes.default.svcを参照できるように、default Namespaceのkubernetesという名前のServiceにも公開されます。

APIサーバーに対して認証を行う推奨された方法は、サービスアカウントの資格情報を使用することです。 既定では、Podはサービスアカウントと関連づけられており、そのサービスアカウントに対する資格情報(トークン)が、そのPod内の各コンテナのファイルシステムツリーの/var/run/secrets/kubernetes.io/serviceaccount/token内に配置されます。

利用可能であれば、証明書バンドルが各コンテナのファイルシステムツリーの/var/run/secrets/kubernetes.io/serviceaccount/ca.crtに配置され、APIサーバーが提供する証明書を検証するために使用されます。

最後に、NamespaceスコープのAPIの操作に対して使用される既定のNamespaceは、各コンテナの/var/run/secrets/kubernetes.io/serviceaccount/namespaceにあるファイルに記載されます。

kubectl proxyの使用

公式のクライアントライブラリを使用せずにAPIを呼び出したい場合は、Pod内の新しいサイドカーコンテナのコマンドとしてkubectl proxyを実行することができます。 こうすることで、kubectl proxyがAPIを認証してPodのlocalhostインターフェースに公開するため、Pod内の他のコンテナが直接使用することができます。

プロキシを使用しない方法

認証トークンを直接APIサーバーに渡すことで、kubectl proxyの使用を避けることも可能です。 内部の証明書によって接続を保護します。

# 内部のAPIサーバーのホスト名の指定
APISERVER=https://kubernetes.default.svc

# ServiceAccountトークンのパス
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount

# PodのNamespaceの読み込み
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)

# ServiceAccountのBearerトークンを取得
TOKEN=$(cat ${SERVICEACCOUNT}/token)

# 内部の認証局(CA)の参照
CACERT=${SERVICEACCOUNT}/ca.crt

# トークンを用いてAPIの探索
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api

次のような出力になります:

{
  "kind": "APIVersions",
  "versions": ["v1"],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}