Kubernetes

KubernetesオブジェクトのapiVersionについて

api-resources と api-versions で表示されるautoscalingのversionが違うことに疑問を持ち調べてみた。

api-versions とapi-resources のAPIVERSIONが違う

api-versions のautoscalingでは、v1、v2がサーバ上でサポートされていることが分かるが、
kubectl api-resources のAPIVERSIONでは、autoscaling/v2しか表示されない。
この違いが気になった。

  • kubectl api-versions
    $ kubectl api-versions| grep autoscaling
    autoscaling/v1
    autoscaling/v2
    $
  • kubectl api-resources
    $ kubectl api-resources | grep autoscaling
    NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
    horizontalpodautoscalers          hpa          autoscaling/v2                         true         HorizontalPodAutoscaler
    $

api-versions とapi-resources のコマンドをドキュメントで確認してみる

Kubernetesコマンドのドキュメントを調べてみるが、APIVERSIONの細かい説明はないみたい。

リソースのAPIVERSIONは登録時にどうなっているのか?

以下ドキュメントを読むと、オブジェクトとしてはAPIバージョンは登録しておらず、
サーバが使用できるAPIであればバージョンは関係なく呼び出しできるみたい。

  • The Kubernetes API > API groups and versioning

  • 英語

    API resources are distinguished by their API group, resource type, namespace (for namespaced resources), and name. The API server handles the conversion between API versions transparently: all the different versions are actually representations of the same persisted data. The API server may serve the same underlying data through multiple API versions.

    API resources are distinguished by their API group, resource type, namespace (for namespaced resources), and name. The API server handles the conversion between API versions transparently: all the different versions are actually representations of the same persisted data. The API server may serve the same underlying data through multiple API versions.

  • 和訳

    APIリソースは、APIグループ、リソースタイプ、ネームスペース(namespacedリソースのための)、
    名前によって区別されます。
    APIサーバーは、APIバージョン間の変換を透過的に処理します。
    すべてのバージョンの違いは、実際のところ同じ永続データとして表現されます。
    APIサーバーは、同じ基本的なデータを複数のAPIバージョンで提供することができます。

    例えば、同じリソースでv1とv1beta1の2つのバージョンが有ることを考えてみます。
    v1beta1バージョンのAPIを利用しオブジェクトを最初に作成したとして、
    v1beta1バージョンが非推奨となり削除されるまで、v1beta1もしくはv1どちらのAPIバージョンを
    利用してもオブジェクトのread、update、deleteができます。
    その時点では、v1 APIを使用してオブジェクトの修正やアクセスを継続することが可能です。

試験環境

ドキュメントの内容を検証するために、試験環境を作成します
実行環境は以下です。

  • 作業環境のバージョン

    $ kubectl version
    Client Version: v1.28.1
    Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
    Server Version: v1.27.4
    
    $ minikube version
    minikube version: v1.31.2
    commit: fd7ecd9c4599bef9f04c0986c4a0187f98a4396e
    $

試験用リソースの作成

バージョンが2つあるhorizontalpodautoscalers で確認するので以下でリソースを作成します

  • deployment をnginxで作成

    #デプロイ用Yamlの作成
    $kubectl create deployment --image=nginx nginx --dry-run=client -o yaml > nginx_test.yaml
    
    $ cat nginx_test.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
      name: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      strategy: {}
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: nginx
        spec:
          containers:
          - image: nginx
            name: nginx
            resources: {}
    status: {}
    $
    
    #デプロイ
    $ kubectl apply -f nginx_test.yaml
  • horizontalpodautoscalersの設定を追加する
    ※設定参考はここ

    #Yaml形式で出力
    $ kubectl autoscale deployment nginx --cpu-percent=50 --min=1 --max=10 --dry-run=client -o yaml
    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      creationTimestamp: null
      name: nginx
    spec:
      maxReplicas: 10
      minReplicas: 1
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: nginx
      targetCPUUtilizationPercentage: 50
    status:
      currentReplicas: **0**
      desiredReplicas: 0
    $
    
    #Yamlファイルに設定を追加
    $ vi nginx_test.yaml
    
    $ cat nginx_test.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: nginx
      name: nginx
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      strategy: {}
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - image: nginx
            name: nginx
            resources: {}
    status: {}
    
    ---
    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      name: nginx
    spec:
      maxReplicas: 10
      minReplicas: 1
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: nginx
      targetCPUUtilizationPercentage: 50
    status:
      currentReplicas: 0
      desiredReplicas: 0
    $
    
    #デプロイ
    $ kubectl apply -f test.yaml
    
    #確認
    #※TARGETS がunknownだけど今回の検証に関係ないのでこのまま
    $ kubectl get hpa
    NAME    REFERENCE          TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
    nginx   Deployment/nginx   <unknown>/50%   1         10        3          2m56s
    $
    $ kubectl get deployments.apps
    NAME    READY   UP-TO-DATE   AVAILABLE   AGE
    nginx   3/3     3            3           2m58s
    $

作成したhorizontalpodautoscalersをcurlでバージョンを指定して確認してみる

以下ドキュメントのHTTP Requestで必要なパスを確認する。

必要なパスは各バージョンで以下ですね。

  • V1
    • GET /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}
  • v2
    • GET /apis/autoscaling/v2/namespaces/{namespace}/horizontalpodautoscalers/{name}

kubectl proxyを使って実際に呼び出しを試してみましょう。

※ curlでAPIを呼び出す方法の詳細は、以前書いた記事の
ここを参照してください。

$ kubectl proxy
Starting to serve on 127.0.0.1:8001
  • V1 での呼び出し
    $ curl http://127.0.0.1:8001/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/nginx
    {
    "kind": "HorizontalPodAutoscaler",
    "apiVersion": "autoscaling/v1",
    "metadata": {
    "name": "nginx",
    "namespace": "default",
    "uid": "15c67a8f-292b-455c-83c3-ca3714ff7912",
    "resourceVersion": "265033",
    "creationTimestamp": "2023-11-04T08:44:37Z",
    "annotations": {
      "autoscaling.alpha.kubernetes.io/conditions": "[{\"type\":\"AbleToScale\",\"status\":\"True\",\"lastTransitionTime\":\"2023-11-04T08:44:52Z\",\"reason\":\"SucceededGetScale\",\"message\":\"the HPA controller was able to get the target's current scale\"},{\"type\":\"ScalingActive\",\"status\":\"False\",\"lastTransitionTime\":\"2023-11-04T08:44:52Z\",\"reason\":\"FailedGetResourceMetric\",\"message\":\"the HPA was unable to compute the replica count: failed to get cpu utilization: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server could not find the requested resource (get pods.metrics.k8s.io)\"}]",
      "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"autoscaling/v1\",\"kind\":\"HorizontalPodAutoscaler\",\"metadata\":{\"annotations\":{},\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"maxReplicas\":10,\"minReplicas\":1,\"scaleTargetRef\":{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"name\":\"nginx\"},\"targetCPUUtilizationPercentage\":50},\"status\":{\"currentReplicas\":0,\"desiredReplicas\":0}}\n"
    },
    "managedFields": [
      {
        "manager": "kubectl-client-side-apply",
        "operation": "Update",
        "apiVersion": "autoscaling/v1",
        "time": "2023-11-04T08:44:37Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {
          "f:metadata": {
            "f:annotations": {
              ".": {},
              "f:kubectl.kubernetes.io/last-applied-configuration": {}
            }
          },
          "f:spec": {
            "f:maxReplicas": {},
            "f:minReplicas": {},
            "f:scaleTargetRef": {},
            "f:targetCPUUtilizationPercentage": {}
          }
        }
      },
      {
        "manager": "kube-controller-manager",
        "operation": "Update",
        "apiVersion": "autoscaling/v2",
        "time": "2023-11-04T08:44:52Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {
          "f:status": {
            "f:conditions": {
              ".": {},
              "k:{\"type\":\"AbleToScale\"}": {
                ".": {},
                "f:lastTransitionTime": {},
                "f:message": {},
                "f:reason": {},
                "f:status": {},
                "f:type": {}
              },
              "k:{\"type\":\"ScalingActive\"}": {
                ".": {},
                "f:lastTransitionTime": {},
                "f:message": {},
                "f:reason": {},
                "f:status": {},
                "f:type": {}
              }
            },
            "f:currentReplicas": {}
          }
        },
        "subresource": "status"
      }
    ]
    },
    "spec": {
    "scaleTargetRef": {
      "kind": "Deployment",
      "name": "nginx",
      "apiVersion": "apps/v1"
    },
    "minReplicas": 1,
    "maxReplicas": 10,
    "targetCPUUtilizationPercentage": 50
    },
    "status": {
    "currentReplicas": 3,
    "desiredReplicas": 0
    }
    }$

* V2 での呼び出し

$ curl http://127.0.0.1:8001/apis/autoscaling/v2/namespaces/default/horizontalpodautoscalers/nginx
{
  "kind": "HorizontalPodAutoscaler",
  "apiVersion": "autoscaling/v2",
  "metadata": {
    "name": "nginx",
    "namespace": "default",
    "uid": "15c67a8f-292b-455c-83c3-ca3714ff7912",
    "resourceVersion": "265033",
    "creationTimestamp": "2023-11-04T08:44:37Z",
    "annotations": {
      "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"autoscaling/v1\",\"kind\":\"HorizontalPodAutoscaler\",\"metadata\":{\"annotations\":{},\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"maxReplicas\":10,\"minReplicas\":1,\"scaleTargetRef\":{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"name\":\"nginx\"},\"targetCPUUtilizationPercentage\":50},\"status\":{\"currentReplicas\":0,\"desiredReplicas\":0}}\n"
    },
    "managedFields": [
      {
        "manager": "kubectl-client-side-apply",
        "operation": "Update",
        "apiVersion": "autoscaling/v1",
        "time": "2023-11-04T08:44:37Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {
          "f:metadata": {
            "f:annotations": {
              ".": {},
              "f:kubectl.kubernetes.io/last-applied-configuration": {}
            }
          },
          "f:spec": {
            "f:maxReplicas": {},
            "f:minReplicas": {},
            "f:scaleTargetRef": {},
            "f:targetCPUUtilizationPercentage": {}
          }
        }
      },
      {
        "manager": "kube-controller-manager",
        "operation": "Update",
        "apiVersion": "autoscaling/v2",
        "time": "2023-11-04T08:44:52Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {
          "f:status": {
            "f:conditions": {
              ".": {},
              "k:{\"type\":\"AbleToScale\"}": {
                ".": {},
                "f:lastTransitionTime": {},
                "f:message": {},
                "f:reason": {},
                "f:status": {},
                "f:type": {}
              },
              "k:{\"type\":\"ScalingActive\"}": {
                ".": {},
                "f:lastTransitionTime": {},
                "f:message": {},
                "f:reason": {},
                "f:status": {},
                "f:type": {}
              }
            },
            "f:currentReplicas": {}
          }
        },
        "subresource": "status"
      }
    ]
  },
  "spec": {
    "scaleTargetRef": {
      "kind": "Deployment",
      "name": "nginx",
      "apiVersion": "apps/v1"
    },
    "minReplicas": 1,
    "maxReplicas": 10,
    "metrics": [
      {
        "type": "Resource",
        "resource": {
          "name": "cpu",
          "target": {
            "type": "Utilization",
            "averageUtilization": 50
          }
        }
      }
    ]
  },
  "status": {
    "currentReplicas": 3,
    "desiredReplicas": 0,
    "currentMetrics": null,
    "conditions": [
      {
        "type": "AbleToScale",
        "status": "True",
        "lastTransitionTime": "2023-11-04T08:44:52Z",
        "reason": "SucceededGetScale",
        "message": "the HPA controller was able to get the target's current scale"
      },
      {
        "type": "ScalingActive",
        "status": "False",
        "lastTransitionTime": "2023-11-04T08:44:52Z",
        "reason": "FailedGetResourceMetric",
        "message": "the HPA was unable to compute the replica count: failed to get cpu utilization: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server could not find the requested resource (get pods.metrics.k8s.io)"
      }
    ]
  }
}$

今回、horizontalpodautoscalersをautoscaling/v1で作成しました。

V1、V2で呼び出したcurlの差分を見てみると呼び出しているAPIのバージョンにより、
レスポンスのapiVersionが変わっています。

ドキュメント通りに呼び出したAPIのバージョンによりapiVersionが決まるみたいですね。

curl http://127.0.0.1:8001/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/nginx > v1.ttx
curl http://127.0.0.1:8001/apis/autoscaling/v2/namespaces/default/horizontalpodautoscalers/nginx > v2.ttx

$ sdiff -s v1.ttx v2.ttx
  "apiVersion": "autoscaling/v1",                             |   "apiVersion": "autoscaling/v2",
      "autoscaling.alpha.kubernetes.io/conditions": "[{\"type <
    "targetCPUUtilizationPercentage": 50                      |     "metrics": [
                                                              >       {
                                                              >         "type": "Resource",
                                                              >         "resource": {
                                                              >           "name": "cpu",
                                                              >           "target": {
                                                              >             "type": "Utilization",
                                                              >             "averageUtilization": 50
                                                              >           }
                                                              >         }
                                                              >       }
                                                              >     ]
    "desiredReplicas": 0                                      |     "desiredReplicas": 0,
                                                              >     "currentMetrics": null,
                                                              >     "conditions": [
                                                              >       {
                                                              >         "type": "AbleToScale",
                                                              >         "status": "True",
                                                              >         "lastTransitionTime": "2023-11-04T08:44:52Z",
                                                              >         "reason": "SucceededGetScale",
                                                              >         "message": "the HPA controller was able to get the ta
                                                              >       },
                                                              >       {
                                                              >         "type": "ScalingActive",
                                                              >         "status": "False",
                                                              >         "lastTransitionTime": "2023-11-04T08:44:52Z",
                                                              >         "reason": "FailedGetResourceMetric",
                                                              >         "message": "the HPA was unable to compute the replica
                                                              >       }
                                                              >     ]
$

作成したhorizontalpodautoscalersをkubectl で確認してみる

apiVersion: autoscaling/v1で作成したhorizontalpodautoscalersを
kubectl で確認すると”apiVersion: autoscaling/v2”になりました。

kubectl api-resourcesで確認したapiVersionで呼び出されていますね。

  • 結果
    $ kubectl get hpa nginx -o yaml
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
    annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"autoscaling/v1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"nginx","namespace":"default"},"spec":{"maxReplicas":10,"minReplicas":1,"scaleTargetRef":{"apiVersion":"apps/v1","kind":"Deployment","name":"nginx"},"targetCPUUtilizationPercentage":50},"status":{"currentReplicas":0,"desiredReplicas":0}}
    creationTimestamp: "2023-11-04T08:44:37Z"
    name: nginx
    namespace: default
    resourceVersion: "265033"
    uid: 15c67a8f-292b-455c-83c3-ca3714ff7912
    spec:
    maxReplicas: 10
    metrics:
    - resource:
      name: cpu
      target:
        averageUtilization: 50
        type: Utilization
    type: Resource
    minReplicas: 1
    scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
    status:
    conditions:
    - lastTransitionTime: "2023-11-04T08:44:52Z"
    message: the HPA controller was able to get the target's current scale
    reason: SucceededGetScale
    status: "True"
    type: AbleToScale
    - lastTransitionTime: "2023-11-04T08:44:52Z"
    message: 'the HPA was unable to compute the replica count: failed to get cpu utilization:
      unable to get metrics for resource cpu: unable to fetch metrics from resource
      metrics API: the server could not find the requested resource (get pods.metrics.k8s.io)'
    reason: FailedGetResourceMetric
    status: "False"
    type: ScalingActive
    currentMetrics: null
    currentReplicas: 3
    desiredReplicas: 0
    $
    $ kubectl api-resources | grep autoscaling
    NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
    horizontalpodautoscalers          hpa          autoscaling/v2                         true         HorizontalPodAutoscaler
    $

api-resourcesのAPIVERSIONで表示されているのがautoscaling/v2だけなのは、なぜか?

kubectl proxyを使ってcurでAPIを呼び出しすると、preferredVersion の設定にて
優先バージョンを設定(例だとautoscaling/v2)しているみたいです。

それらしいドキュメントは見つけられませんが、恐らくapi-resourcesのAPIVERSIONは、優先バージョンが
参照されているのでしょう。

$ curl http://127.0.0.1:8001/apis/ | less
    {
      "name": "autoscaling",
      "versions": [
        {
          "groupVersion": "autoscaling/v2",
          "version": "v2"
        },
        {
          "groupVersion": "autoscaling/v1",
          "version": "v1"
        }
      ],
      "preferredVersion": {
        "groupVersion": "autoscaling/v2",
        "version": "v2"
      }
    },

まとめ

  • Kubernetesで登録されているオブジェクトでAPIは登録されていない。
  • kubectl get 等の呼び出し結果のapiVersionは、呼び出したAPIのバージョンが使用される。
  • kubectl get 等で使用されるapiVersionは、api-resourcesで表示されたバージョン使用される。
  • api-resourcesで1つだけAPIが表示される際には、優先バージョン(最新)が使われる。

人気記事

1

Kubernetes kubectl rollout コマンドでdeploymentをロールバックしてみる 概要 kubectl rollout コマンドでデプロイ履歴を確認してロールバックするやり方 ...

2

  terraformのバージョン管理どうすればいいのか? terraformの複数バージョンを簡単に動かしたい terraformのインストール方法が分からない と、疑問を抱えている人の疑 ...

3

本記事では どんな環境にterraformをインストールできるの? terraformのインストールどうしたらいいの? terraformのどのバージョンをインストールすればいいの? と、困っている人 ...

4

Kubernetes kubectl version コマンドでバージョンを調べてみる 概要 kubectl version は、Kubernetes の Client、Serverのバージョンを確認 ...

-Kubernetes