Kubernetes

KubernetesのAPIをServiceAccountのTOKENを使ってcrulで呼び出してみる

概要

curlコマンドで直接APIに通信する方法は前回試しましたが、「kubectl proxy」を使い
認証を意識していなかったので、今回は認証Tokenを使ったやり方を試してみました。
※前回の記事はここを参照

環境

  • minikube version: v1.32.0
  • Kubernetes v1.28.3
  • Ubuntu 22.04.4 LTS(WSL)

やってみたこと

kubeconfigから全てのCluster名を確認

  • コマンド
    kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'
  • tech-0222@MSI:~$ kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'
    Cluster name    Server
    test    https://127.0.0.1:32784
    tech-0222@MSI:~$

呼び出ししたいCluster名を変数にセット

  • コマンド
    export CLUSTER_NAME="some_server_name"
  • export CLUSTER_NAME="test"
  • 結果
    tech-0222@MSI:~$ export CLUSTER_NAME="test"
    tech-0222@MSI:~$
    tech-0222@MSI:~$ echo $CLUSTER_NAME
    test
    tech-0222@MSI:~$

ClusterのアクセスURLを変数に設定

  • コマンド

    APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")
  • tech-0222@MSI:~$ APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")
    tech-0222@MSI:~$ echo $APISERVER
    https://127.0.0.1:32784
    tech-0222@MSI:~$

    defaultのServiceAccountからTokenを作成

  • コマンド

    TOKEN=$(kubectl create token default)
  • tech-0222@MSI:~$ TOKEN=$(kubectl create token default)
    tech-0222@MSI:~$ echo $TOKEN
    eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzIwMzEwNTQ4LCJpYXQiOjE3MjAzMDY5NDgsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiI1MmVjZWFhMC04ZDJjLTRlN2YtOGFmYS0yZjZjODcyMmM5Y2EifX0sIm5iZiI6MTcyMDMwNjk0OCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.ETGmbjvvLkQ3aF4np5WI1hEuTPudCajnjhBcaiVFE_G0ACLZIPZmZh5bPiLY5Jsy7qefpq15eKXKaHOBIkV98S-Tj-MQrpVdIskDI2FGwzhcHauYPmDV17kH9O8fpcR_xPEdi1Dq2O9FTcToNwwfpHpzGCuCdLm5VJ90KDR4_8kGzmu5Aic_NnYALOJ63Snk9uWvinPvsVa5d4uQpGFu_PY7EMkn5WN5NVe5ahMqxBlFozoIMyc8baxUmoqpMpVEouIBu5AZ72I_pV18etkzOwYEGIL_uoliOnwsRDyJTUC2T9uB64KGZtOmRRvRo0qJU_0l76fOP20ZO1ryIe__EA
    tech-0222@MSI:~$

    curl でAPIを呼び出してみる

リクエストに対して以下例のようにレスポンスが返ってくれば
Tokenによる認証を行いAPIが実行できています。

  • コマンド
    curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
  • tech-0222@MSI:~$ curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
    {
    "kind": "APIVersions",
    "versions": [
    "v1"
    ],
    "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.67.2:8443"
    }
    ]
    }tech-0222@MSI:~$

    ちなみに、API実行のcurl オプションの意味は以下です。

  • 「--insecure」 (-k)は、SSL警告を無視する
  • 「--header」 (-H)は、httpヘッダにリクエストを追加する
  • 「-X」 (--request)はHTTPのメソッドを指定する

補足

Tokenの有効期間

コマンド"kubectl create token XXX"で作成できるTokenは有効期間があるTokenです。
defaultの有効期限が気になりますが、設定や公式ドキュメントでは見つけることができませんでした。

ただ、ここの「--duration」で以下文書があるので、サーバ毎に設定するものと思われます。

発行されたトークンの要求された有効期間。設定されていない場合、または 0 に設定されている場合、
有効期間はサーバーによって自動的に決定されます。サーバーは、より長いまたはより短い有効期間を
持つトークンを返す場合があります。

サーバの有効期限を簡単に確認するには、オプション(--duration)を指定せずにログレベルを変えて
コマンド"kubectl create token "を実行すると簡単に確認できます。

以下例だとResponse Body 内の”"expirationSeconds":3600”が該当箇所になり、
有効期限は3600秒(1時間)みたいですね。

  • tech-0222@MSI:~$ kubectl create token default --v=8
    I0707 17:27:30.419698 1833212 loader.go:395] Config loaded from file:  /home/tech-0222/.kube/config
    I0707 17:27:30.420420 1833212 cert_rotation.go:137] Starting client certificate rotation controller
    I0707 17:27:30.420661 1833212 request.go:1212] Request Body: {"kind":"TokenRequest","apiVersion":"authentication.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{"audiences":null,"expirationSeconds":null,"boundObjectRef":null},"status":{"token":"","expirationTimestamp":null}}
    I0707 17:27:30.420755 1833212 round_trippers.go:463] POST https://127.0.0.1:32784/api/v1/namespaces/default/serviceaccounts/default/token
    I0707 17:27:30.420779 1833212 round_trippers.go:469] Request Headers:
    I0707 17:27:30.420787 1833212 round_trippers.go:473]     Accept: application/json, */*
    I0707 17:27:30.420829 1833212 round_trippers.go:473]     Content-Type: application/json
    I0707 17:27:30.420845 1833212 round_trippers.go:473]     User-Agent: kubectl/v1.28.2 (linux/amd64) kubernetes/89a4ea3
    I0707 17:27:30.429270 1833212 round_trippers.go:574] Response Status: 201 Created in 8 milliseconds
    I0707 17:27:30.429293 1833212 round_trippers.go:577] Response Headers:
    I0707 17:27:30.429298 1833212 round_trippers.go:580]     X-Kubernetes-Pf-Prioritylevel-Uid: e9925eb0-9df8-4d18-8eb2-c2944fbabe8d
    I0707 17:27:30.429310 1833212 round_trippers.go:580]     Content-Length: 1439
    I0707 17:27:30.429319 1833212 round_trippers.go:580]     Date: Sun, 07 Jul 2024 08:27:30 GMT
    I0707 17:27:30.429323 1833212 round_trippers.go:580]     Audit-Id: 3383d33e-e93f-44c5-bf71-8c87996ba6a6
    I0707 17:27:30.429326 1833212 round_trippers.go:580]     Cache-Control: no-cache, private
    I0707 17:27:30.429330 1833212 round_trippers.go:580]     Content-Type: application/json
    I0707 17:27:30.429334 1833212 round_trippers.go:580]     X-Kubernetes-Pf-Flowschema-Uid: f54fb6b1-342b-4e6e-875a-ba24f54cf8f2
    I0707 17:27:30.429373 1833212 request.go:1212] Response Body: {"kind":"TokenRequest","apiVersion":"authentication.k8s.io/v1","metadata":{"name":"default","namespace":"default","creationTimestamp":"2024-07-07T08:27:30Z","managedFields":[{"manager":"kubectl","operation":"Update","apiVersion":"authentication.k8s.io/v1","time":"2024-07-07T08:27:30Z","fieldsType":"FieldsV1","fieldsV1":{"f:spec":{"f:expirationSeconds":{}}},"subresource":"token"}]},"spec":{"audiences":["https://kubernetes.default.svc.cluster.local"],"expirationSeconds":3600,"boundObjectRef":null},"status":{"token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzIwMzQ0NDUwLCJpYXQiOjE3MjAzNDA4NTAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiI1MmVjZWFhMC04ZDJjLTRlN2YtOGFmYS0yZjZjODcyMmM5Y2EifX0sIm5iZiI6MTcyMDM0MDg1MCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50O [truncated 415 chars]
    eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzIwMzQ0NDUwLCJpYXQiOjE3MjAzNDA4NTAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiI1MmVjZWFhMC04ZDJjLTRlN2YtOGFmYS0yZjZjODcyMmM5Y2EifX0sIm5iZiI6MTcyMDM0MDg1MCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.rN0FjTubF5rynUPDqOUMR82QdohiN1nqD7zcR0iLAzmevCbGqIE2p9Rz9THNkIlTcB5QQav1WbLds0jFB9X78xJBc5cLecDdMxyWv8NwogtYBOZF1sVlDrwbd6rgiYwlyn68zLL0DM0AmpgvfS8LQf2ukVre6DyBNau78IB2_XBC92N0Li97DM6AvUhHpMzCrVYiBtC9kSDxSJvcDdwbMowhmohefQ8jyeH6f5-otyU-M5zXff97Z2RZNukkxGthNJRn8SIY4Zz_jpWWHivqTezDSuJnkQkKrms2xAQOpkybCXn73y_iIPzgGlF8BWYoym1ZvjI1H6xOaXEphPGt5A
    tech-0222@MSI:~$

    Tokenの永続化

特別なアノテーションを使用して新しい Secret を作成することでTokenを永続化できるみたいです。
ServiceAccount の長期 API トークンを手動で作成する

  • 実行例
    • デフォルトであるServiceAccountのdefaultのTokenでSecretを作成
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get secrets
No resources found in default namespace.
tech-0222@MSI:~$
tech-0222@MSI:~$ 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 created
tech-0222@MSI:~$ kubectl get secrets
NAME            TYPE                                  DATA   AGE
default-token   kubernetes.io/service-account-token   3      4s
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get secrets -o yaml
apiVersion: v1
items:
- apiVersion: v1
  data:
    ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCakNDQWU2Z0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwdGFXNXAKYTNWaVpVTkJNQjRYRFRJME1ERXdNekF4TXpjeE0xb1hEVE0wTURFd01UQXhNemN4TTFvd0ZURVRNQkVHQTFVRQpBeE1LYldsdWFXdDFZbVZEUVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBT1NvCmZnSjNRSitUNG1jd3ZQMnFPT3VMc2ZweUpBenYrQmNRNUFiRWZvL3BXS3dOMkt3Y1pBUm5kOUY1b3kwcEp4a0gKMDJNbHEycm1nTVNqN1A2cktab0lmZW5VS3NxbXg5dmtGRlVZa1RscFlmRHpCWUt1alhEM1phdTVyL2YyUmwyTQpDMWRzdTlyWXlRTWY2STd1Rm1iWEFuc1VlcGt5U0ptMWczTXVGbDE2QytUTzhyKzNvZ3VBVzZkN2piVlk5S2RECk9icnBySjBEallRS2JRdmNlWFloNXZoZlBwTVpObjdWclpZTDZDTXF1c29UYmJ1eUFqanlXRHdxYW54ZzRvZmgKbTVWRUZMRDRsRWZlNm43TnZHVm0rcy9uZlN6OXpsRjBNVFNpUEhPbCtzdVNpcTFWMTQxbytybGYrMk52UXJnNgpwNkxjZnFhNllqeUR6aDlLTTFjQ0F3RUFBYU5oTUY4d0RnWURWUjBQQVFIL0JBUURBZ0trTUIwR0ExVWRKUVFXCk1CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0RBVEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVcKQkJUa0xCWmlNREpKSXl0aGV5V2NUWVk3YVN3VUtqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFUY2lnMkVKSwpoMTQxaEwyYU0vaXlVdkxWNjJPMjIwN2JzZm01ajNOWk01YXN4VUxxMGJGN09mNEVma2ozTU1Fa005VkVUM0R0Cml0ZW1qeXdHV1EyQlZsZGRJUmU3czUvUng0SlpkK1h5Z2YyeC9QL1drdFhpc3FqZEMraXlwVFFJek5Ib2NnTUwKSCtTR1d5ZjhTTWZXb0J1aXpBYTdENmJqTXVCV25xL1dvUDhoTC9MUHVJdUtwTU1mMjNscXdFMnRUM1R4ZmdJMQpPWGdST29DbDR0dmhnSXZUdDQxSi9ScGt0Skk2QXYwem8yZ1BjZnVEMTFzOEhhL0dMdm05MEd4OFkrTmYyZklBCmg3eUlUR3Y5VGp0bnozdVVhYzVkakEyOUl5V09wcGdiVVlab0NaUmU3elkxaWF2b0haL2xvNU43YW8wSmM5SnQKN2h5QndWL3JlNFgzeFE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    namespace: ZGVmYXVsdA==
    token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklsWkJNVWhEUkMxR0xYaE5aamx3YTE5VFdVRTVhemwzUVVselkweHNNVGRRTFVsWmIzTlZPWGd3VDFVaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbVJsWm1GMWJIUXRkRzlyWlc0aUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sY25acFkyVXRZV05qYjNWdWRDNXVZVzFsSWpvaVpHVm1ZWFZzZENJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExuVnBaQ0k2SWpVeVpXTmxZV0V3TFRoa01tTXROR1UzWmkwNFlXWmhMVEptTm1NNE56SXlZemxqWVNJc0luTjFZaUk2SW5ONWMzUmxiVHB6WlhKMmFXTmxZV05qYjNWdWREcGtaV1poZFd4ME9tUmxabUYxYkhRaWZRLnhXS0hxS0RfckplSWFvdENVeTFjOUpXaEtiQlNGcXpYY3h6V0tLanY1TE1Za0NVcEFDWThGWF8yb2V4UEdtZDllemFaa1NYZFNpTjhaVVVzY2dUVkg3eWcwZjdDbGRoeHo0TGNfQU9NSmtySmlHSlVDNHRLVkZMWGxlSUpVSVU4eksyUUVpY3hqcFEtaW84N25LOW5rZkRoNC1YUFdRNmNxZ0p2Zjg0bW1iRk9KSVVKSU5nNDAyMEVSWmlaZmpkVGFfNjZQOU45bVY2c1dHYWgtbmRwZEtJSWtRSEJidDZtVmlrWHNiNmN3VWVJbUtXSFl3cHdnU0c2bWFPOGVsSVZhMFc1a2F4Mk9ZeHY4cENleEdvZU92VlpyUlpuRDNSMTllazE0Tl9HelktSDlPSUJWMU83dGJ6TDd2SEZZVHlpRnhGQUNyUk1mZWRBSjBadmx2X2lFQQ==
  kind: Secret
  metadata:
    annotations:
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{"kubernetes.io/service-account.name":"default"},"name":"default-token","namespace":"default"},"type":"kubernetes.io/service-account-token"}
      kubernetes.io/service-account.name: default
      kubernetes.io/service-account.uid: 52eceaa0-8d2c-4e7f-8afa-2f6c8722c9ca
    creationTimestamp: "2024-07-07T08:41:41Z"
    name: default-token
    namespace: default
    resourceVersion: "20292"
    uid: 6be44e73-b3bd-4c11-8333-2f6fb2076c15
  type: kubernetes.io/service-account-token
kind: List
metadata:
  resourceVersion: ""
tech-0222@MSI:~$
  • 作成したSecretでのAPIアクセス例
#SecretのTokenをデコードして変数にセット
tech-0222@MSI:~$ TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode)
tech-0222@MSI:~$
tech-0222@MSI:~$ echo $TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjUyZWNlYWEwLThkMmMtNGU3Zi04YWZhLTJmNmM4NzIyYzljYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.xWKHqKD_rJeIaotCUy1c9JWhKbBSFqzXcxzWKKjv5LMYkCUpACY8FX_2oexPGmd9ezaZkSXdSiN8ZUUscgTVH7yg0f7Cldhxz4Lc_AOMJkrJiGJUC4tKVFLXleIJUIU8zK2QEicxjpQ-io87nK9nkfDh4-XPWQ6cqgJvf84mmbFOJIUJINg4020ERZiZfjdTa_66P9N9mV6sWGah-ndpdKIIkQHBbt6mVikXsb6cwUeImKWHYwpwgSG6maO8elIVa0W5kax2OYxv8pCexGoeOvVZrRZnD3R19ek14N_GzY-H9OIBV1O7tbzL7vHFYTyiFxFACrRMfedAJ0Zvlv_iEA
tech-0222@MSI:~$

# API実行
tech-0222@MSI:~$ curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.67.2:8443"
    }
  ]
}tech-0222@MSI:~$

#Token削除するとちゃんとAPIアクセスもエラーになりますね
#
tech-0222@MSI:~$ kubectl delete secrets default-token
secret "default-token" deleted
tech-0222@MSI:~$
tech-0222@MSI:~$ curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}tech-0222@MSI:~$

ただし、ここでは、この方法は非推奨と書かれているので利用する際には注意がいりますね。

参考

人気記事

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