我想用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文件进行对话式深挖如下所示。
尝试使用curl命令创建Pod
你可以从Kubernetes API中确认有关终端节点的信息。
创建一个仅输出 “你好世界” 的 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": {
},
~中略~
}
除了之前创建的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等操作,因此希望探讨一种动态控制和监视增加资源的方法。