我想用curl来做kubectl的工作

简而言之

当了解到在管理Kubernetes时,可以通过类似插件的方式动态生成Pod(Kubernetes资源),因此可以考虑在Pod内部生成新的Pod等情况。于是想要确认在这种情况下是否可以从Pod内部使用kubectl这样的工具,或者是否可以简便地使用通用工具如curl进行检查。

通过使用kubectl proxy,我确认了可以通过curl从kubernetes集群外部执行Kubernetes API的相同操作。但是,需要注意的是,当从Pod内部执行相同操作时,获取用于执行Kubernetes API的令牌的方法有所不同。

Kubernetes API 是什么?

所有Kubernetes内的组件之间的通信和探索都是通过API进行的,而且是以REST形式的API进行的。

使用kubectl命令可以完成大部分操作,并且也可以通过curl直接调用REST API来实现相同的操作。

试着直接调用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代理的情况下

启动kubectl代理

确认正在运行在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": {

            },
~中略~
      }
    }
  ]
}

尽管对于kubectl命令的结果来说,以JSON格式来表示可能会显得有些难以理解,但使用下面的工具,可以在一定程度上让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

创建一个仅输出 “你好世界” 的 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-example.png

除了之前创建的nginx pod之外,

在日志中也可以确认到输出了”Hello World”这句话。

k logs pod-example 
Hello World

从Pod内部调用Kubernetes API的方法

创建一个拥有所需权限的SeriveAccount(同时创建命名空间等)。

k apply -f api.yaml 

切换命名空间

kubens需要单独安装,安装方法见(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,可以确定可以使用curl执行与kubectl相同的操作。
由于可以在Pod内运行创建新的Pod等操作,因此希望探讨一种动态控制和监视增加资源的方法。

广告
将在 10 秒后关闭
bannerAds