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の細かい説明はないみたい。
-
api-versions
-
説明
- Print the supported API versions on the server, in the form of "group/version".
- 和訳
- サーバー上でサポートされている API バージョンを「グループ/バージョン」の形式で出力します。
-
api-resources
-
説明
- Print the supported API resources on the server.
- 和訳
- サーバー上でサポートされている API リソースを出力します。
リソースの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が表示される際には、優先バージョン(最新)が使われる。