想通过证书来访问和控制kubernete的api, 网上找了一圈, 也没一个比较好的, 找了一些文章, 整理在一块的了, 有点乱, 但思路基本是清晰, 有启发就拿去。
API Server kube-apiserver 是 Kubernetes 最重要的核心组件之一,主要提供以下的功能
提供集群管理的 REST API 接口,包括认证授权、数据校验以及集群状态变更等
提供其他模块之间的数据交互和通信的枢纽(其他模块通过 API Server 查询或修改数据,只有 API Server 才直接操作 etcd)
REST API kube-apiserver 支持同时提供 https(默认监听在 6443 端口)和 http API(默认监听在 127.0.0.1 的 8080 端口),其中 http API 是非安全接口,不做任何认证授权机制,不建议生产环境启用。两个接口提供的 REST API 格式相同,参考 Kubernetes API Reference 查看所有 API 的调用格式。
本地端口 该端口用于接收HTTP请求; 该端口默认值为8080,可以通过API Server的启动参数–insecure-port的值来修改默认值; 默认的IP地址为localhost,可以通过启动参数–insecure-bind-address的值来修改该IP地址; 非认证或授权的HTTP请求通过该端口访问API Server; 安全端口 该端口默认值为6443,可通过启动参数–secure-port的值来修改默认值; 默认IP地址为非本地localhost网络端口,通过启动参数–bind-address设置该值; 该端口用于接收HTTPS请求; 用于基于Token文件或客户端证书及HTTP Base的认证; 用于基于策略的授权; 默认不启动HTTPS安全访问控制; 打开本地不认证的调试端口
1
kubectl proxy --port=8080 &
example:
1
2
3
4
5
6
7
8
9
curl localhost:8080/api
curl localhost:8080/api/v1/pods
curl localhost:8080/api/v1/nodes/
curl localhost:8080/api/v1/services
curl localhost:8080/api/v1/replicationcontrollers
curl localhost:8080/api/v1/proxy/namespaces/kube-system/pods/coredns-565d847f94-fhmwh
curl localhost:8080/api/v1/proxy/namespaces/{namespace}/pods/{name}
Node相关接口 关于Node相关的接口的REST路径为:/api/v1/proxy/nodes/{name},其中{name}为节点的名称或IP地址。
1
2
3
/api/v1/proxy/nodes/{name}/pods/ #列出指定节点内所有Pod的信息
/api/v1/proxy/nodes/{name}/stats/ #列出指定节点内物理资源的统计信息
/api/v1/prxoy/nodes/{name}/spec/ #列出指定节点的概要信息
这里获取的Pod信息来自Node而非etcd数据库,两者时间点可能存在偏差。如果在kubelet进程启动时加–enable-debugging-handles=true参数,那么kubernetes Proxy API还会增加以下接口:
1
2
3
4
5
6
7
/api/v1/proxy/nodes/{name}/run #在节点上运行某个容器
/api/v1/proxy/nodes/{name}/exec #在节点上的某个容器中运行某条命令
/api/v1/proxy/nodes/{name}/attach #在节点上attach某个容器
/api/v1/proxy/nodes/{name}/portForward #实现节点上的Pod端口转发
/api/v1/proxy/nodes/{name}/logs #列出节点的各类日志信息
/api/v1/proxy/nodes/{name}/metrics #列出和该节点相关的Metrics信息
/api/v1/proxy/nodes/{name}/runningpods #列出节点内运行中的Pod信息
Pod相关接口 1
2
/api/v1/proxy/namespaces/{namespace}/pods/{name}/{path:*} #访问pod的某个服务接口
/api/v1/proxy/namespaces/{namespace}/pods/{name} #访问Pod
可通过 kubectl api-versions 和 kubectl api-resources 查询 Kubernetes API 支持的 API 版本以及资源对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl get nodes -o yaml
kubectl describe nodes silas-thinkpad-l460 -o yaml
# Describe a node
kubectl describe nodes kubernetes-node-emt8.c.myproject.internal
# Describe a pod
kubectl describe pods/nginx
kubectl get pods -n <namespace> <pod-name>
## out pod info to yaml
kubectl get pods -n kube-system coredns-565d847f94-fhmwh -o yaml
hostIP is the pod machine ip.
1
2
3
4
5
6
7
8
9
10
11
12
spec:
nodeName: silas-thinkpad-l460
status:
containerStatuses:
- containerID: containerd://aa0fa0870010a7758eb41b4b47b9e7251e500a905812c72259ca232ec2737ba0
image: registry.k8s.io/coredns/coredns:v1.9.3
hostIP: 192.168.255.6
phase: Running
podIP: 10.88.0.7
podIPs:
- ip: 10.88.0.7
- ip: 2001:4860:4860::7
How to get Kubernetes API host and port 打开本地不认证的调试端口
kubectl proxy –port=8080 &
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ kubectl cluster-info
Kubernetes control plane is running at https://192.168.58.2:8443
kubectl config view
curl --cacert /etc/kubernetes/pki/ca.crt $KUBE_API/version
# Get pod info by http curl token
$ JWT_TOKEN_DEFAULT_DEFAULT=$(kubectl create token default)
curl $KUBE_API/api/v1/namespaces/kube-system/pods/coredns-565d847f94-fhmwh \
--cacert /etc/kubernetes/pki/ca.crt \
--header "Authorization: Bearer $JWT_TOKEN_DEFAULT_DEFAULT" \
# Get pod info by http curl ssl
curl $KUBE_API/api/v1/namespaces/kube-system/pods/coredns-565d847f94-fhmwh \
--cacert /etc/kubernetes/pki/ca.crt \
--cert /etc/kubernetes/pki/apiserver-kubelet-client.crt \
--key /etc/kubernetes/pki/apiserver-kubelet-client.key
kubectl get --raw /api/v1/namespaces/kube-system/pods/coredns-565d847f94-fhmwh
Create auth tls secret kubectl create secret tls tls-secret –cert=path/to/tls.cert –key=path/to/tls.key
1
2
3
$ kubectl create secret tls my-tls-secret \
--key ca.key \
--cert ca.crt
检查签名 1
2
cat /etc/kubernetes/pki/ca.crt | openssl x509 -text
cat client.crt | openssl x509 -text
1. Generate the CA Key and Certificate 1
$ openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 356 -nodes -subj '/CN=Fern Cert Authority'
2. Generate the Server Key, and Certificate and Sign with the CA Certificate 1
2
$ openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=meow.com'
$ openssl x509 -req -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
3. Generate the Client Key, and Certificate and Sign with the CA Certificate 1
2
3
$ openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Tiabao'
$ openssl x509 -req -sha256 -days 365 -in client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -set_serial 02 -out client.crt
4. create ssl secret 1
2
3
kubectl create secret tls tls-secret --cert=client.crt --key=client.key
kubectl get secrets
5. curl calling example 1
2
3
4
5
6
7
8
9
curl $KUBE_API/api/v1/nodes/ \
--cacert /etc/kubernetes/pki/ca.crt \
--cert /home/silas/Documents/haiwen/k8s/cmworker/k8s_proxy/temp/client.crt \
--key /home/silas/Documents/haiwen/k8s/cmworker/k8s_proxy/temp/client.key
curl $KUBE_API/api/v1/namespaces/kube-system/pods/coredns-565d847f94-fhmwh \
--cacert /etc/kubernetes/pki/ca.crt \
--cert /home/silas/Documents/haiwen/k8s/cmworker/k8s_proxy/temp/client.crt \
--key /home/silas/Documents/haiwen/k8s/cmworker/k8s_proxy/temp/client.key
extral:
1
2
kubectl describe secrets/db-user-pass
kubectl describe secrets/tls-secret
kubectl get clusterrolebinding
kubectl get serviceaccount
Grant ClusterRole to user kubectl get clusterrolebinding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tian-admin-bind
subjects:
- kind: User
name: tian-admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat << EOF | kubectl delete -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tian-admin-bind
subjects:
- kind: User
name: tian-admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
EOF
对于一般的应用系统来说,用户提供用户名和密码,服务端收到过后会在数据库中进行检查是否存在并有效,如果有就表示鉴权成功,反之失败。
那对于 Kubernetes 来说,是如何实现的呢?
尽管无法通过 API 调用来添加普通用户,Kubernetes 巧妙的通过证书来进行用户认证。也就是说,不管任何用户,只要能提供有效的证书就能通过 Kubernetes 用户认证。
通过用户认证过后,Kubernetes 会把证书中的 CN 作为用户名(比如证书中”/CN=joker“,则用户名就是 Joker),把 Organization 作为用户组,然后由用户名和用户组绑定的 Role 来决定用户的权限。