从pod访问K8s API

从pod内部访问K8s的API比外部访问简单些,访问的话有两种方式:

  1. 使用官方的client库 , 可以自动发现API server并进行认证

  2. 直接访问REST API

使用官方client库

地址: https://github.com/kubernetes-client/python/

config.load_incluster_config() 函数用于处理API server发现与认证

python代码示例:https://github.com/kubernetes-client/python/blob/master/examples/in_cluster_config.py

步骤如下。先创建一个python pod:

kubectl run python --image=python -i --tty -- sh

在python pod中,安装k8s client:

pip install kubernetes

创建一个api.py文件:

cat > api.py << EOL
from kubernetes import client, config


def main():
    config.load_incluster_config()

    v1 = client.CoreV1Api()
    print("Listing pods with their IPs:")
    ret = v1.list_pod_for_all_namespaces(watch=False)
    for i in ret.items:
        print("%s\t%s\t%s" %
              (i.status.pod_ip, i.metadata.namespace, i.metadata.name))


if __name__ == '__main__':
    main()
EOL

执行python api.py此时并没有像预期一样返回pod列表,而是报错:

image-20230726193620715

这是因为默认的service account没有list权限,参考文档 ( The default service accounts in each namespace get no permissions by default )

所以需要为这个service account添加权限,新打开一个控制台,执行:

$ cat > roles.yaml << EOL
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pods-list
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["list"]

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pods-list
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
roleRef:
  kind: ClusterRole
  name: pods-list
  apiGroup: rbac.authorization.k8s.io
EOL

$ kubectl apply -f roles.yaml

此时再回到python pod中运行api.py,可以成功输出pod列表:

# python api.py
Listing pods with their IPs:
10.10.49.31     default busybox
10.10.43.203    default mycurlpod
10.10.35.210    default mycurlpod2
10.10.53.89     default mycurlpod3
10.10.13.165    default mycurlpod4
10.10.2.145     default python
10.10.58.85     default rebel-base-7bdbfb9c9d-lng8k
10.10.8.194     default rebel-base-7bdbfb9c9d-xxslz
10.10.16.140    default x-wing-d9fccdb9b-hh7j5
10.10.41.198    default x-wing-d9fccdb9b-rb92s
10.10.33.30     kube-system     cilium-hdm8z
10.10.33.30     kube-system     cilium-node-init-m5wlf
10.10.1.150     kube-system     cilium-node-init-vd5f4
10.10.33.30     kube-system     cilium-operator-656567b78d-j6djz
10.10.1.150     kube-system     cilium-qz7rf
10.10.59.68     kube-system     coredns-857b668457-bx27n

使用REST API访问

访问kubernetes.default.svc 服务,可以获取API server的信息。原理也是使用service account的token信息,这个信息保存在: /var/run/secrets/kubernetes.io/serviceaccount/token

在上面的python pod里执行访问测试:

# Point to the internal API server hostname
APISERVER=https://kubernetes.default.svc

# Path to ServiceAccount token
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount

# Read this Pod's namespace
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)

# Read the ServiceAccount bearer token
TOKEN=$(cat ${SERVICEACCOUNT}/token)

# Reference the internal certificate authority (CA)
CACERT=${SERVICEACCOUNT}/ca.crt

# Explore the API with TOKEN
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api

结果如下:

image-20230726195114791


参考:https://kubernetes.io/docs/tasks/run-application/access-api-from-pod/