Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

kubectlでやってることをcurlでやりたい

概要

kubernetesを運用する際に、アドオン的な感じで動的にPod(Kubernetes Resource)を生成するというユースケースを知った。そのため例えばPod内から新たにPodを生成するなどといった場合が考えられ、その際にkubectlをPod内から使用するケースやcurlなどの汎用的なツールを簡易的に使えるかを確認したくなった。

下記では、kubectl proxyを用いて、kubernetesクラスタ外からKubernetes APIをcurlを通して実行することで同様のことを確認した。Pod内から同様のことを行う際は、Kubernetes APIを実行するためのトークン 取得方法が異なっているので注意が必要。

Kubernetes APIとは

Kubernetes内のコンポーネント間の通信や捜査はすべてAPIを通して行われており、REST形式のAPIとなっています。

kubectlを用いることで大半の操作は行うことができますし、直接REST APIをcurlで叩くことでも同様の操作を行うことができます。

https://kubernetes.io/docs/reference/using-api/api-overview/

直接Kubernetes API叩いてみる

kubectl proxyなしの場合

なければクラスタ起動

kind create cluster

クラスタ一覧確認

kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'

アクセスするクラスタ名を選択(自分の場合は、kindを使用しているのでこのクラスタ名を選択)

export CLUSTER_NAME="kind-kind"

クラスタ名からアクセス先取得

APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")

アクセストークン 取得

TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode)

kubernetes APIを実行

curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "172.17.0.2:6443"
    }
  ]
}

kubectl proxyありの場合

kubectl proxyを起動

8001番ポートで動作していることを確認

kubectl proxy
Starting to serve on 127.0.0.1:8001

Kubernetes APIを叩いてみると、先ほどと同様の結果を取得できる

curl -X GET 127.0.0.1:8001/api 
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "172.17.0.2:6443"
    }
  ]
}

試しにnginxのPodを動作させてみてから、Kubernetes APIでPodを確認してみる

k run nginx --image=nginx --restart=Never --dry-run -oyaml > nginx.yaml

k apply -f nginx.yaml 

k get po
NAME    READY   STATUS              RESTARTS   AGE
nginx   0/1     ContainerCreating   0          1s

curlでPod一覧取得してみるとjson形式で同様の情報が取得できる

curl -X GET http://127.0.0.1:8001/api/v1/namespaces/default/pods
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/default/pods",
    "resourceVersion": "5973"
  },
  "items": [
    {
      "metadata": {
        "name": "nginx",
        "namespace": "default",
        "selfLink": "/api/v1/namespaces/default/pods/nginx",
        "uid": "119f6219-5ff3-4542-b785-e7532301a972",
        "resourceVersion": "5891",
        "creationTimestamp": "2020-03-21T06:08:56Z",
        "labels": {
          "run": "nginx"
        },
        "annotations": {
          "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"labels\":{\"run\":\"nginx\"},\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx\",\"name\":\"nginx\",\"resources\":{}}],\"dnsPolicy\":\"ClusterFirst\",\"restartPolicy\":\"Never\"},\"status\":{}}\n"
        }
      },
      "spec": {
        "volumes": [
          {
            "name": "default-token-lh646",
            "secret": {
              "secretName": "default-token-lh646",
              "defaultMode": 420
            }
          }
        ],
        "containers": [
          {
            "name": "nginx",
            "image": "nginx",
            "resources": {

            },
~中略~
      }
    }
  ]
}

jsonだとkubectlの結果より見づらいのは仕方ないが、下記のようなツールでjson結果もある程度扱いやすくできる。

Macの場合下記のコマンドで導入できる。

brew install jid

curl -X GET http://127.0.0.1:8001/api/v1/namespaces/default/pods | jid

下記のように対話的にjsonファイルを深掘りできる。

jid.png

curlでPodの作成を試してみる

エンドポイントについてはKubernetes APIから確認することができる

kubernetesAPI_pod.png

Hwllo Worldとだけ出力するPodを作成する

curl -X POST -H 'Content-Type: application/yaml'  -d '
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  containers:
  - name: ubuntu
    image: ubuntu:trusty
    command: ["echo"]
    args: ["Hello World"]
  restartPolicy: Never
'  http://127.0.0.1:8001/api/v1/namespaces/default/pods 

実行結果

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "pod-example",
    "namespace": "default",
    "selfLink": "/api/v1/namespaces/default/pods/pod-example",
    "uid": "4ac7cf5c-69b7-40f9-806d-582cafebd590",
    "resourceVersion": "8977",
    "creationTimestamp": "2020-03-21T06:50:46Z"
  },
  "spec": {
    "volumes": [
      {
        "name": "default-token-lh646",
        "secret": {
          "secretName": "default-token-lh646",
          "defaultMode": 420
        }
      }
    ],
    "containers": [
      {
        "name": "ubuntu",
        "image": "ubuntu:trusty",
        "command": [
          "echo"
        ],
        "args": [
          "Hello World"
        ],
        "resources": {

        },
~中略~
}

Podが作成されていることを確認
pod-example.png

先ほど作成したnginxのpodに加えて、

ログにHello Worldが出力されていることも確認できる

k logs pod-example 
Hello World

Pod内からKubernetes APIを叩く方法

必要な権限を持ったSeriveAccountを作成(ついでにnamespaceなども作成)

k apply -f api.yaml 

Namespace切り替え

kubensは別途install必要(https://github.com/ahmetb/kubectx)

kubens mynamespace

Curlを叩くためのPodのyamlを生成

k run fedora --image=fedora --restart=Never --dry-run -oyaml -- /sbin/init  > fedora.yaml

出力したyamlに一部追記(tty, stdin, serviceAccountName)

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: fedora
  name: fedora
spec:
  containers:
  - args:
    - /sbin/init
    image: fedora
    name: fedora
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Never
  tty: true
  stdin: true
  serviceAccountName: mysa
status: {}

Podをデプロイ

k apply -f fedora.yaml

Pod内にアクセス

k exec -it fedora bash

トークン を取得して、Kubernetes APIを実行

下記は、このコマンドを実行しているPod情報を取得する

KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
NAMESPACE=mynamespace
curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" \
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/$NAMESPACE/pods/$HOSTNAME

jsonで取得するためぱっと見わかるづらいが、k get po と同様の内容を取得できている。

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "fedora",
    "namespace": "mynamespace",
    "selfLink": "/api/v1/namespaces/mynamespace/pods/fedora",
    "uid": "7c918fc0-f194-4729-896a-f52167c4a803",
    "resourceVersion": "17841",
    "creationTimestamp": "2020-03-21T08:51:57Z",
    "labels": {
      "run": "fedora"
    },
    "annotations": {
      "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"labels\":{\"run\":\"fedora\"},\"name\":\"fedora\",\"namespace\":\"mynamespace\"},\"spec\":{\"containers\":[{\"args\":[\"/sbin/init\"],\"image\":\"fedora\",\"name\":\"fedora\",\"resources\":{},\"stdin\":true,\"tty\":true}],\"dnsPolicy\":\"ClusterFirst\",\"restartPolicy\":\"Never\",\"serviceAccountName\":\"mysa\"},\"status\":{}}\n"
    }
  },
  "spec": {
    "volumes": [
      {
        "name": "mysa-token-lt4gh",
        "secret": {
          "secretName": "mysa-token-lt4gh",
          "defaultMode": 420
        }
      }
    ],
    "containers": [
      {
        "name": "fedora",
        "image": "fedora",
        "args": [
          "/sbin/init"
        ],
        "resources": {

        },
~中略~
}

まとめ

Kubernetes APIを知ることでkubectlでやっていることをcurlでも同様に行えることを確認した。
新たにPodなどを作る処理はPod内でもかけるため、動的に増加するリソースを制御・監視する方法を検討したい。

iaoiui
SIerでDocker, Kubernetes使って遊んでる人
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away