kubernetes之使用http rest api訪問叢集

周國通發表於2019-06-27

系列目錄

在Kubernetes叢集中,API Server是叢集管理API的入口,由執行在Master節點上的一個名為kube-apiserver的程式提供的服務。 使用者進入API可以通過kubectl、客戶端庫或者http rest,User 或者 Service Account可以被授權進入API。當一個請求到達API時, 往往要經過幾個階段的安全控制,在一個典型的應用叢集中,API Server通常會使用自簽名的證書提供HTTPS服務,同時開啟認證與授權等安全機制。

通常,在Kubernetes叢集搭建之後,除了使用官方的kubectl工具與API Server進行互動,我們還可以使用Postman或者curl了,有些時候直接使用curl功能更強大, 與API Server互動通常需要首先建立一個有正確許可權的ServiceAccount,這個ServiceAccount通過ClusterRole/Role、ClusterRoleBinding/RoleBinding等給其賦予相關資源的操作許可權, 而Service Account對應的Token則用於API Server進行基本的認證。與API Server的互動是基於TLS,所以請求的時候還需要自簽名的證書,當然也可以非安全方式連線API Server, 但是不推薦。

建立ServiceAccount

前面我們講到過ServiceAccount,它類似於傳統登陸裡的使用者.建立一個ServiceAccount以後,會自動為它建立一個關聯的secret(金鑰)

我們建立一個名為apiviewer的ServiceAccount

[centos@k8s-master ~]$ kubectl create sa apiviewer
serviceaccount/apiviewer created

我們可以檢視這個sa對應的secret的名字

[centos@k8s-master ~]$ kubectl get sa apiviewer  -ojson
{
    "apiVersion": "v1",
    "kind": "ServiceAccount",
    "metadata": {
        "creationTimestamp": "2019-05-27T08:09:56Z",
        "name": "apiviewer",
        "namespace": "default",
        "resourceVersion": "16750207",
        "selfLink": "/api/v1/namespaces/default/serviceaccounts/apiviewer",
        "uid": "d078f034-8056-11e9-99bc-0050568417a2"
    },
    "secrets": [
        {
            "name": "apiviewer-token-z5bpq"
        }
    ]
}

我們可以使用secretes裡的name去檢視這個secretes的值

apiviewer-token-z5bpq[centos@k8s-master ~]$ kubectl describe secret apiviewer-token-z5bpq
Name:         apiviewer-token-z5bpq
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: apiviewer
              kubernetes.io/service-account.uid: d078f034-8056-11e9-99bc-0050568417a2

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFwaXZpZXdlci10b2tlbi16NWJwcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcGl2aWV3ZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMDc4ZjAzNC04MDU2LTExZTktOTliYy0wMDUwNTY4NDE3YTIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDphcGl2aWV3ZXIifQ.GUd7uCwTntMXhwXEGFvo62tJBTVdI_SNATDIbuxINmbmBI2bjHuQ-whRE5183AXqWiifoM0HjOGoams11f_R2Dtak3fRxPLNRGGFTMyUN1uHmwedPmsAK0GTW0xPgInyIy4SF-uI7lghrpsRzBQ4AmA2AuctwCGdXUC3YuqrZPEnla3HeF6Tz72KpddlgiA3N1T5yvoOHPL4AgQRDPGKJ6L-nEdXumg3BlTWR0ENBNgzAz2eh6RZLRSsKlG0zQ8vhApkMGru7k5a_PKkU3Z3b0ZhKBKmE_LsMJ7bAunr9J9bbG--Id4rnuPpcj1DoJ0ZlJ3G1IP3xTUVncxO_gV4VQ

我們熟練了可以使用一條命令

apiviewer-token-z5bpq[centos@k8s-master ~]$ kubectl describe secret `kubectl get sa apiviewer -ojsonpath='{.secrets[0].name}'`
Name:         apiviewer-token-z5bpq
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: apiviewer
              kubernetes.io/service-account.uid: d078f034-8056-11e9-99bc-0050568417a2

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFwaXZpZXdlci10b2tlbi16NWJwcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcGl2aWV3ZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMDc4ZjAzNC04MDU2LTExZTktOTliYy0wMDUwNTY4NDE3YTIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDphcGl2aWV3ZXIifQ.GUd7uCwTntMXhwXEGFvo62tJBTVdI_SNATDIbuxINmbmBI2bjHuQ-whRE5183AXqWiifoM0HjOGoams11f_R2Dtak3fRxPLNRGGFTMyUN1uHmwedPmsAK0GTW0xPgInyIy4SF-uI7lghrpsRzBQ4AmA2AuctwCGdXUC3YuqrZPEnla3HeF6Tz72KpddlgiA3N1T5yvoOHPL4AgQRDPGKJ6L-nEdXumg3BlTWR0ENBNgzAz2eh6RZLRSsKlG0zQ8vhApkMGru7k5a_PKkU3Z3b0ZhKBKmE_LsMJ7bAunr9J9bbG--Id4rnuPpcj1DoJ0ZlJ3G1IP3xTUVncxO_gV4VQ

當然,也可以使用jq工具

[centos@k8s-master ~]$ kubectl describe secret `kubectl get sa apiviewer -ojson|jq -r  .secrets[].name`
Name:         apiviewer-token-z5bpq
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: apiviewer
              kubernetes.io/service-account.uid: d078f034-8056-11e9-99bc-0050568417a2

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFwaXZpZXdlci10b2tlbi16NWJwcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcGl2aWV3ZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMDc4ZjAzNC04MDU2LTExZTktOTliYy0wMDUwNTY4NDE3YTIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDphcGl2aWV3ZXIifQ.GUd7uCwTntMXhwXEGFvo62tJBTVdI_SNATDIbuxINmbmBI2bjHuQ-whRE5183AXqWiifoM0HjOGoams11f_R2Dtak3fRxPLNRGGFTMyUN1uHmwedPmsAK0GTW0xPgInyIy4SF-uI7lghrpsRzBQ4AmA2AuctwCGdXUC3YuqrZPEnla3HeF6Tz72KpddlgiA3N1T5yvoOHPL4AgQRDPGKJ6L-nEdXumg3BlTWR0ENBNgzAz2eh6RZLRSsKlG0zQ8vhApkMGru7k5a_PKkU3Z3b0ZhKBKmE_LsMJ7bAunr9J9bbG--Id4rnuPpcj1DoJ0ZlJ3G1IP3xTUVncxO_gV4VQ

建立ClusterRole、RoleBinding

我們可以從頭建立一個ClusterRole,但是k8s叢集裡預設也是有若干個ClusterRole的,我們可以通過kubectl get clusterrole來檢視都有哪些clusterrole,這裡我們使用一個名為cluster-admin,把剛建立的ServiceAccount與它繫結

建立RoleBinding的命令如下

[centos@k8s-master ~]$  kubectl create rolebinding apiadmin --clusterrole cluster-admin --serviceaccount default:apiviewer
rolebinding.rbac.authorization.k8s.io/apiadmin created

獲取Bearer Token、Certificate、API Server URL

[centos@k8s-master ~]$ SECRET=$(kubectl get serviceaccount ${SERVICE_ACCOUNT} -ojsonpath='{.secrets[0].name}')

這條命令用於獲取SECRET的名稱,上面我們已經講到過.

然後我們就可以用secret的名稱來獲取token了,前面也是講到過的

TOKEN=$(kubectl get secret ${SECRET} -ojsonpath='{.data.token}'|base64 -d)

使用jsonpath時,我們需要預先知道json的結構,比較笨但是往往非常有效的辦法是先把整個json全部輸出出來,然後再根據結構擷取.

由於token是經過base64編碼過的,因此需要base64解碼

下面從secret裡把證書提取出來

 kubectl get secret ${SECRET} -o jsonpath="{.data['ca\.crt']}" | base64 -d > /tmp/ca.crt

獲取API Server URL,如果API Server部署在多臺Master上,只需訪問其中一臺即可。
APISERVER=https://$(kubectl -n default get endpoints kubernetes --no-headers | awk '{ print $2 }' | cut -d "," -f 1)

通過jq -r提取所有的Pod名字

curl -s $APISERVER/api/v1/namespaces/default/pods/ --header "Authorization: Bearer $TOKEN" \
> --cacert /tmp/ca.crt  | jq -r '.items[].metadata.name'

由於這裡不是kubectl命令,無法再直接通過jsonpath過濾結果,這裡我們使用jq工具來過濾.關於jq工具本章節前面部分也有介紹.想詳細瞭解的童鞋可以參考一下.

相關文章