Trending keywords: security, cloud, container,

Kubernetes API の概要

SHARE:

Kubernetes は、Kubernetes API をベースに構築されています。この Kubernetes API のおかげで、Kubernetes クラスターとやり取りしたり、Kubernetes クラスターを調査、管理したりすることができます。kubectl kubeadm などのツールを使用している場合でも、各ツールが Kubernetes API とやり取りして変更を適用させることができます。Kubernetes API はクラスター管理にとって重要なコンポーネントであるため、この API の内容や機能を知っておくことが不可欠です。この記事では、Kubernetes API の概要とその仕組みについて説明します。 

まず、Kubernetes API の内容と、この API Kubernetes の全体的な戦略の中で果たしている役割を見てみましょう。次に、Kubernetes API でできることと、この API でアプリケーションをデプロイおよび管理する方法について説明します。また、さまざまな API コマンドを取り上げ、Kubernetes 環境での使用例をご覧いただきます。それでは始めましょう。

Kubernetes API が使用される理由

Kubernetes API は、Kubernetes のコントロールプレーンの基盤です。この API のおかげで、Kubernetes クラスター内のプリミティブ要素を作成、変更、削除することができます。また、この API によって、クラスター内のさまざまなコンポーネント間のやり取りが可能にし、外部のコンポーネントとのやり取りが容易になります。kubectl または kubeadm を使用していた場合は、これらのコマンドラインツールから API を間接的に呼び出していました。REST 呼び出しを使用すれば API に直接アクセスすることもできます。

Kubernetes API のドキュメントは、Kubernetes Web サイトで簡単に入手できます。また、最新バージョンの API を探して、より具体的な情報を得ることもできます。(現時点で、この API の最新版はバージョン 1.23.0 です)。さらに詳しい情報を知りたい場合は、Kubernetes GitHub リポジトリで最新の API 仕様を直接確認するか、Swagger/OpenAPI 形式でダウンロードしてください。 

Kubernetes クラスターは、異なる API パスで応答する複数の API バージョンをサポートできます。クラスターがサポートする API バージョンは、次の kubectl コマンドで判断できます: 

$ kubectl api-versions

前述のとおり、Kubernetes API サーバー(kube-apiserver)は、etcdkube-schedulerkube-controller-manager、および cloud-controller-manager とともに、コントロールプレーン内に存在します。このコントロールプレーンは通常、他のコンテナが一切デプロイされていないノードに存在します。Kubernetes kube-apiserver を水平方向にスケールするため、デプロイするインスタンスをクラスターの要求に応じて増やすことができます。API サーバーへのリクエストによってクラスターの望ましい状態が変わると、コントロールプレーンはその変更を管理し、クラスターの実際の状態を望ましい状態に合わせて調整します。

Kubernetes API とのやり取り

ほとんどの Kubernetes ユーザーは、kubectl などのツールを使用してクラスターとやり取りします。このコマンドラインツールのインストールと構成が完了すれば、クラスター上でアクションをテスト、実行するためのコマンドを使用できるようになります。このツールでは、コマンドの後にタイプを入力し、名前やさまざまなフラグを(必要に応じて)含めることができます。いくつかの一般的なコマンドを使って、クラスターに関するどのような情報が得られるのか見てみましょう。

$ kubectl get nodes
NAME           STATUS   ROLES                  AGE    VERSION
kube-master    Ready    control-plane,master   22h    v1.23.4
kube-worker1   Ready    <none>                 151m   v1.23.4
kube-worker2   Ready    <none>                 136m   v1.23.4
kube-worker3   Ready    <none>                 67m    v1.23.4Code language: HTML, XML (xml)

このコマンドは、nodes タイプを取得する get アクションを実行します。また、kubectl を使用して、createdescribedelete などその他のアクションを実行できます。先の出力結果で確認できるように、コントロールプレーンを実行するマスターノードを構成するクラスターが 1 つ存在します。また、使用可能なワーカーノードが 3 つ存在します。単一のノードを調べるには、そのノードの名前を含めます。ここでは、get アクションと type ノードを使用して、マスターノードを調べてみましょう。

$ kubectl get node kube-master
NAME           STATUS   ROLES                  AGE    VERSION
kube-master    Ready    control-plane,master   22h    v1.23.4Code language: JavaScript (javascript)

コマンドを実行できるその他のリソースには、Service、Pod、Deployment などがあります。クラスター内で利用できるすべてのリソースの完全なリストを表示するには、kubectl api-resources を実行してください。kubectl は便利ですが(また、API とやり取りする手段の 1 つでもあります)、この記事は kubect について学ぶためのものではないため、kubect を最大限に活用されたい方は、優れたリソースである Kubernetes のドキュメントをお読みください。

Kubernetes API と直接やり取りするには、2 つの方法があります。1 つ目のアプローチは kubectl proxy を使用すること、2 つ目は認証トークンを生成し、各リクエストでヘッダーとして渡すことです。そこで、各アプローチを実行する方法と、それぞれのアプローチを選択する理由について説明しましょう。

プロキシは、kubectl ツール内に格納されている apiserver の場所と自己署名証明書を使用します。これにより、クラスターに接続するプロセスが驚くほど簡単になります。  Kubernetes では、中間者攻撃を回避するため、クラスターへのアクセスにプロキシアクセスを使用することを推奨しています。プロキシアクセスを設定するには、次の kubectl コマンドを使用します: 

$ kubectl proxy --port=8080 &
[1] 747

$ Starting to serve on 127.0.0.1:8080
これで、プロキシがローカルワークステーションで実行されます。プロキシが実行されると、ブラウザ、curl、wget などのツールを使用して、API へのアクセスや API の調査ができるようになります。上の例では、これらのコマンドをローカルプロキシアドレス(127.0.0.1:8080 など)に対して実行しています。kubectl はクラスターとのやり取りを安全に管理しています。 
127.0.0.18080api
2 つ目のアプローチでは、認証トークンを渡すことで API に直接アクセスできます。この手法は中間者攻撃に対して脆弱で、安全性がきわめて低くなりますが、検討する価値はあります。 

最初のステップは、リクエストでヘッダーとして渡すことができるトークンの生成です。その際、リクエストの管理を容易にするために、一連の環境変数を設定します。この最初のステップでは、アクセスしたいクラスターの名前を特定します。この名前は、kubectl で使用されている config ファイルで確認するか、次のコマンドを使用して kubectl に直接リストを問い合わせます。
$ kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'

Cluster name    Server
kubernetes      https://kube-master:6443Code language: JavaScript (javascript)

K8S_NAME. と呼ばれる変数にクラスターの名前を保存しましょう。

$ export K8S_NAME=”kubernetes”Code language: JavaScript (javascript)

次に、クラスターの API サーバー(名前は K8S_API)のアドレスを使用して変数を作成します。この情報は、最初のリクエストから取得するか、K8S_NAME を使って次のコマンドをコピーアンドペーストして作成します。

$ K8S_API=$(kubectl config view -o 
jsonpath="{.clusters[?(@.name==\"$K8S_NAME\")].cluster.server}")Code language: JavaScript (javascript)

 次のステップは、トークンを保持するシークレットの作成です。ここでも、kubectl コマンドを使用します。

$ kubectl apply -f - <<EOF
> apiVersion: v1
> kind: Secret
> metadata:
>   name: default-token
>   annotations:
>     kubernetes.io/service-account.name: default
> type: kubernetes.io/service-account-token
> EOF

secret/default-token createdCode language: JavaScript (javascript)

トークンコントローラがシークレットにトークンを入力するまで待機する、小さなルーチンが必要です。

$ while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do
>   echo "waiting for token..." >&2
>   sleep 1
> doneCode language: JavaScript (javascript)

最後に、トークンの値を取得して、K8S_TOKEN と呼ばれる変数に代入します。なお、このトークンは Web アプリケーションでよく使用される標準的な Javascript Web TokenJWT)です。

$ K8S_TOKEN=$(kubectl get secret default-token -o 
jsonpath='{.data.token}' | base64 --decode)Code language: JavaScript (javascript)

このトークンを使用すると、マスターノード上の kubeapi-server に対して直接 API 呼び出しを実行できます。その際、-insecure フラグを使用して SSL 証明書の検証を回避します。

$ curl -X GET $K8S_API/api --header "Authorization: Bearer $K8S_TOKEN" --insecure

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   183  100   183    0     0   5382      0 --:--:-- --:--:-- --:--:--  5545

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "172.16.10.8:6443"
    }
  ]
}Code language: PHP (php)

最初に述べたように、Kubernetes API はクラスターに関する詳細情報を取得したり、Deployment の追加や操作、Service の追加、アプリケーションのスケールアップやスケールダウンを通じてクラスターを管理したりするための基盤です。この API の真の価値は、プログラムでやり取りできることにあります。この機能を支援するために、Kubernetes GoPythonJavadotnetJavascriptHaskell といったよく使われる言語向けのクライアントライブラリを提供し、サポートしています。

Kubernetes の API Watch について

API の用途の 1 つは、クラスターで実行されているアプリケーションやリソースの現在の状態を把握することです。不安定な動作やその他の問題のトラブルシューティングを行っている場合は、API リクエストを実行して状況を監視できます。とはいえ、API コマンドを繰り返し実行して応答の変化を確認する作業は、退屈なばかりか、現実的ではなく、あまり意味がありません。Kubernetes API は、API 呼び出し上に特定のリソースの経時的な状態変化を監視することを設定できる、Watch と呼ばれる概念もサポートしています。

そこで、kubectl による Watch の実行について見てみましょう(Watch は API 自体で直接実行することもできます)。ここでは、クラスター上で Deployment を作成してスケールアップします。この Deployment のために、nginx イメージのバージョン 1 を使用します。

$ kubectl create deployment nginx --image=nginx:1

deployment.apps/nginx created

$ kubectl autoscale deployment nginx --min=5 --max=10

horizontalpodautoscaler.autoscaling/nginx autoscaled

このクラスターには、nginx アプリケーションを実行する 5 つの pod が必要です。ここでは、その Deployment で使用するイメージをバージョン 1.21 に更新します。その後、get pods アクションとリソースを使用して、更新中の Pod の状態を確認します。

$ kubectl set image deployment/nginx nginx=nginx:1.21

deployment.apps/nginx image updated

$ kubectl get pods
NAME                     READY   STATUS              RESTARTS   AGE
nginx-65895c4c4f-8x7z2   1/1     Terminating         0          6m39s
nginx-65895c4c4f-fqmhp   1/1     Running             0          6m30s
nginx-65895c4c4f-n8kf6   1/1     Running             0          6m30s
nginx-65895c4c4f-nbgng   1/1     Running             0          6m29s
nginx-65895c4c4f-qc4fh   1/1     Running             0          6m30s
nginx-f594cdf46-49k7d    0/1     ContainerCreating   0          3s
nginx-f594cdf46-7rtw4    0/1     ContainerCreating   0          2s
nginx-f594cdf46-lv2kk    0/1     ContainerCreating   0          3sCode language: JavaScript (javascript)

実行、停止、作成など、Pod のさまざまな状態を監視できます。Kubernetes では、アプリケーションへのアクセスを維持しながら更新を実行できます。ただし、Deployment の状況を監視するには、kubectl get pods コマンドを繰り返し実行して、経時的な変化を確認する必要があります。そこで、最新の Deployment をロールバックして Watch を設定し、同じコマンドを繰り返し実行しなくてもリアルタイムで状況を監視できるようにしましょう。まず、この Deployment のロールアウト履歴をチェックします。

$ kubectl rollout history deployment/nginx

deployment.apps/nginx
REVISION  CHANGE-CAUSE
1         <none>
2         <none>Code language: HTML, XML (xml)

この Deployment を直前のバージョンにロールバックして Watch を設定し、状況を監視できるようにしましょう。Watch フラグの -w status パラメーターの後に追加して、Deployment が完了するまでリアルタイムで監視します。

$ kubectl rollout undo deployment/nginx --to-revision=1

deployment.apps/nginx rolled back

$ kubectl rollout status -w deployment/nginx
Waiting for deployment "nginx" rollout to finish: 3 out of 5 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 5 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 5 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 5 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 5 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 4 out of 5 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 4 out of 5 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 2 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 4 of 5 updated replicas are available...
deployment "nginx" successfully rolled outCode language: JavaScript (javascript)

kubectl がロールアウトを確認すると、インサイトを提供します。ただし、kubectl 出力が十分な情報を提供しない場合や、この情報を別のツールに表示したい場合は、API を使って生の情報を取得できます。

先に設定したプロキシを使用すると、追加または停止された各 Pod に関するデータを大量に収集できます。API を使用するもう 1 つのメリットは、渡したパラメーターに基づいて Watch が情報を継続的に提供してくれることです。このアプリケーションに対して、別のターミナルから curl http://localhost:8080/api/v1/namespaces/default/pods?watch=1&app=nginx を実行すれば、起こっている変化を確認したり、その情報を別のツールに取り込んで詳しい分析を行ったりできます。

$ curl http: //localhost:8080/api/v1/namespaces/default/pods?watch=1&app=nginx
  [1] 1236
  % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0--: --: -- --: --: -- --: --: --0

$ {
  "type": "ADDED",
  "object": {
    "kind": "Pod",
    "apiVersion": "v1",
    "metadata": {
      "name": "nginx-f594cdf46-b8rmz",
      "generateName": "nginx-f594cdf46-",
      "namespace": "default",
      "uid": "a2315438-4e70-485b-8de1-12d9a2f4cee0",
      "resourceVersion": "115953",
      "creationTimestamp": "2022-03-16T08:44:34Z",
      "labels": {
        "app": "nginx",
        "pod-template-hash": "f594cdf46"
      },
      "annotations": {
        "cni.projectcalico.org/containerID": "ad6ec053a52ede11a94e832afbc9f0dc4a3e2f801cdf28393b8ac70fd54cfb3e",
        "cni.projectcalico.org/podIP": "10.10.130.137/32",
        "cni.projectcalico.org/podIPs": "10.10.130.137/32"
      },
      "ownerReferences": [{
        "apiVersion": "apps/v1",
        "kind": "ReplicaSet",
        "name": "nginx-f594cdf46",
        "uid": "661d57f3-75ce-494a-8b16-001ccbae090f",
        "controller": true,
        "blockOwnerDeletion": true
      }],
      "managedFields": [{
            "manager": "kube-controller-manager",
            "operation": "Update",
            "apiVersion": "v1",
            "time": "2022-03-16T08:44:34Z",
            "fieldsType": "FieldsV1",
            "fieldsV1": {
              "f:metadata": {
                "f:generateName": {},
                "f:labels": {
                  ".": {},
                  "f:app": {},
                  "f:pod-tem…Code language: JavaScript (javascript)

詳細情報

Kubernetes API は、その名前が示しているように、クラスター内のあらゆるものを管理、制御、監視するためのインターフェイスです。Kubernetes Web サイトは、この API を「Kubernetes の基礎構造」と述べています。kubectl のようなツールはクラスターを管理および表示するための簡単で使いやすい手段ですが、API に直接アクセスすれば、より広く詳しい情報にアクセスできるだけでなく、より細かな制御が可能になります。 


詳細情報やテストに関する情報を知りたい方は、まず Kubernetes のドキュメントをお読みになることをお勧めします。基本的なコンセプトからこの API を最大限に活用する方法まで、あらゆる情報を入手できます。