17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-03-21

概要

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で叩くことでも同様の操作を行うことができます。

直接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内でもかけるため、動的に増加するリソースを制御・監視する方法を検討したい。

17
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?