【Kubernetes学习之连接集群】利用 kubeconfig 或 secret Token 连接 k8s 集群

参考

  • 通过kubeconfig文件生成证书,用curl访问Kubernetes API server_网络飞鸥的博客-CSDN博客
  • k8s用ServiceAccount Token的方式访问apiserver_kubenetes api 访问token-CSDN博客
  • k8s serviceaccount创建后没有生成对应的secret - SoulChild随笔记
  • 参考 | Kubernetes
  • Kubernetes API Reference Docs

1 | 用ServiceAccount Token的方式访问apiserver

在kubernetes集群,可以登陆到master集群,可以使用私钥证书的方式访问。证书路径:master的/etc/kubernetes/pki/(ca.crt / apiserver.crt / apiserver.key) 下面。

# server是apiserver公网访问地址
$ curl --cacert ca.crt --cert apiserver.crt --key apiserver.key https://$server/api

这里再介绍一下使用ServiceAccount Token的方式访问集群。
serviceaccount的权限由集群中对应的rolebinding决定,官方文档:
https://kubernetes.io/docs/reference/access-authn-authz/rbac

# 请选择对应权限的ServiceAccount来获取token,这边选择的是admin ServiceAccount
$ kubectl get sa admin -n kube-system -o yaml
 
# 查看对应的clusterrolebinding:
$ kubectl get clusterrolebinding admin -o yaml
 
# 查看admin sa绑定的clusterrole和对应的权限。命令:
$ kubectl get clusterrole admin -o yaml
 
# 获取对应sa的secret从中获取token。并进行base64解码。
$ kubectl get secret admin-token-5tctj -n kube-system -o jsonpath={".data.token"} | base64 -d

最后使用该token访问apiserver:

最后使用公网slb地址访问。

# 如 curl -k -H 'Authorization: Bearer token' https://10.182.101.255:6443/api/v1/namespaces
curl -k -H 'Authorization: Bearer token' https://111.111.111.111:6443/path(api接口) 

例如:

$ curl -k -H 'Authorization: Bearer hbGciOiJSUzI1NiIsImtpZCI6Ilg3RHRVOEZZdW0zVmZLV0JZeGlfVjJSTG1TQ1A3LWRPX0w1SUVvdldEWkkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXBycjJsIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIxN2U3NjAxMi1lYTE5LTRkNDktODM1NS0zMmQ4OGIzY2Y2YWEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.dLNfDTlxoEAMw115yT4NPsOgRcN1rOp9rCZYj9mAzbfKX3L1LNzLlCAYgcBjWdro5u-8NncOyWp9--vAyADq7yaa0T-tBfVALg8dESuwSQpSN-I5YOh7G8ua81HFjWFWX6dvq1GW2fbHPeXCJDlkBnJAbTGLb-487lbK0VWkSdLl1tsT435eZS5e6rRNIWAJJizVBrxDliND_7IXE6zILOR5u-A3z3wk3ngCv4e2FLNOR6z4qr2l-xyQG3pLXH2YQt_TjCkaR9kg57CRQRpwSiN6DfMfeq_qwI7d_iCawNSbLEBWRPEjA3j4juE64CcrA1fr58LIFxEr_ga949XgWw' https://10.182.101.255:6443/api/v1/namespaces
 
$ curl -k -H 'Authorization: Bearer hbGciOiJSUzI1NiIsImtpZCI6Ilg3RHRVOEZZdW0zVmZLV0JZeGlfVjJSTG1TQ1A3LWRPX0w1SUVvdldEWkkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXBycjJsIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIxN2U3NjAxMi1lYTE5LTRkNDktODM1NS0zMmQ4OGIzY2Y2YWEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.dLNfDTlxoEAMw115yT4NPsOgRcN1rOp9rCZYj9mAzbfKX3L1LNzLlCAYgcBjWdro5u-8NncOyWp9--vAyADq7yaa0T-tBfVALg8dESuwSQpSN-I5YOh7G8ua81HFjWFWX6dvq1GW2fbHPeXCJDlkBnJAbTGLb-487lbK0VWkSdLl1tsT435eZS5e6rRNIWAJJizVBrxDliND_7IXE6zILOR5u-A3z3wk3ngCv4e2FLNOR6z4qr2l-xyQG3pLXH2YQt_TjCkaR9kg57CRQRpwSiN6DfMfeq_qwI7d_iCawNSbLEBWRPEjA3j4juE64CcrA1fr58LIFxEr_ga949XgWw' https://10.182.101.255:6443/api
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "172.20.8.14:6443"
    }
  ]
}

2 | 个人测试使用 创建 token

在 Kubernetes 中,admincluster-admin 是两个不同的角色,它们在权限层级上有所不同。

  1. admin 角色:
    • admin 角色通常是指拥有特定命名空间(namespace)的管理员权限的用户或服务账户。这个角色允许用户执行一些与特定命名空间相关的管理任务,如创建、删除资源对象,以及查看和修改特定命名空间内的资源。
    • admin 角色没有集群范围的管理权限,只能对某个命名空间内的资源进行操作。该角色通常用于限定用户的权限,使其只能管理特定的资源。
  2. cluster-admin 角色:
    • cluster-admin 角色是 Kubernetes 中的超级管理员角色,具有对整个集群的完全控制权限。拥有 cluster-admin 角色的用户或服务账户可以对所有命名空间中的任何资源进行任意操作,包括创建、删除、修改以及访问集群级别的信息。
    • cluster-admin 角色通常用于赋予用户对整个集群的高级管理权限,比如执行集群范围的配置更改、安装插件或进行集群级别的监控。

总的来说,admin 角色是针对某个命名空间的管理员权限,而 cluster-admin 角色是对整个集群的超级管理员权限。在实践中,为了最小化权限并遵循最小权责原则,应该尽可能使用 admin 角色,只在必要时才授予用户或服务账户 cluster-admin 角色。

$ kubectl get clusterrole | grep admin
admin                                                                  2023-11-16T07:21:29Z
cluster-admin                                                          2023-11-16T07:21:29Z
system:aggregate-to-admin                                              2023-11-16T07:21:29Z
system:kubelet-api-admin                                               2023-11-16T07:21:29Z

# 可以看出 cluster-admin 具有所有资源的所有权限
$ kubectl describe clusterrole cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]
             [*]                []              [*]

# 可以看出 admin 具有所有资源的部分权限(下面没有粘贴上全部内容,请自行查看自己的集群)
$ kubectl describe clusterrole admin
Name:         admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources                                       Non-Resource URLs  Resource Names  Verbs
  ---------                                       -----------------  --------------  -----
 pods/attach                                     []                 []              [get list watch create delete deletecollection patch update]
  pods/exec                                       []                 []              [get list watch create delete deletecollection patch update]
  pods/portforward                                []                 []              [get list watch create delete deletecollection patch update]
  pods/proxy                                      []                 []              [get list watch create delete deletecollection patch update]
  secrets                                         []                 []              [get list watch create delete deletecollection patch update]
  services/proxy                                  []                 []              [get list watch create delete deletecollection patch update]
  bindings                                        []                 []              [get list watch]
  endpoints                                       []                 []              [get list watch]
  limitranges                                     []                 []              [get list watch]
  namespaces/status                               []                 []              [get list watch]
  namespaces                                      []                 []              [get list watch]
  persistentvolumeclaims/status                   []                 []              [get list watch]
  pods/log                                        []                 []              [get list watch]

2.1 | 个人测试使用 cluster-admin 角色

# 1. 创建 ServiceAccount
$ kubectl create sa cluster-admin-test -n kube-system
 
# 2. 创建 ClusterRoleBinding
$ kubectl create clusterrolebinding cluster-admin-test-crb --clusterrole=cluster-admin --serviceaccount=kube-system:cluster-admin-test

# 3. 由于现在 创建 sa 不自动生成 secret,因此创建个 secret 保持永久有效的 token, 使用 kubectl 执行下面内容
apiVersion: v1
kind: Secret
metadata:
  name: cluster-admin-test-secret
  namespace: kube-system
  annotations:
    kubernetes.io/service-account.name: "cluster-admin-test"   # 这里填写serviceAccountName
type: kubernetes.io/service-account-token
 
# 4. 获取对应sa的secret从中获取token。并进行base64解码。
$ kubectl get secret cluster-admin-test-secret -n kube-system -o jsonpath={".data.token"} | base64 -d
# 注意要去掉后面的 % 号
eyJ....7X6Vd5sdVViZEr3Cv2xiGa2gzWRDgVXxZc1yJ64OKBOYHkEtay5t9bTulof1x4D-HefAPNGd5hdw% # 错误
eyJ....7X6Vd5sdVViZEr3Cv2xiGa2gzWRDgVXxZc1yJ64OKBOYHkEtay5t9bTulof1x4D-HefAPNGd5hdw  # 正确

2.2 | k8s serviceaccount 创建后没有生成对应的 secret

果然两天不看就跟不上了,我的集群版本是 1.25.3,今天需要用 token 来做些事情,创建 serviceAccount 的时候发现没有生成 secret,查了一下发现从 1.24 开始就不会自动生成 secret 了,chanagelog 在这里.

内容如下 LegacyServiceAccountTokenNoAutoGeneration 功能门是测试版,默认启用。启用后,不再为每个 ServiceAccount 自动生成包含服务帐户令牌的 Secret API 对象。使用 TokenRequest API 获取服务帐户令牌,或者如果需要未过期的令牌,请按照本指南为令牌控制器创建一个 Secret API 对象以填充服务帐户令牌

pr: https://github.com/kubernetes/kubernetes/pull/108309

在上面提到的两种方式要怎么用呢

方式 1 使用 TokenRequest API 来生成 token,获取方式如下

  • 使用 client-go 或者其他 api 调用工具来获取某个 serviceaccount 的 token
  • 创建 yaml,使用 kubectl apply -f
  • 使用 kubectl create token -n xxx 来获取一个临时的 token, 默认 1 小时

方式 2 创建 secret token,创建后从 secret 的 token 字段拿就可以了

apiVersion: v1
kind: Secret
metadata:
  name: secret-sa-sample
  annotations:
    kubernetes.io/service-account.name: "sa-name"   # 这里填写serviceAccountName
type: kubernetes.io/service-account-token

3 | 理解 ~/.kube/config 文件

在 Kubernetes 的 kubeconfig 文件中,以下三个字段用于配置客户端认证:

  1. client-certificate-data
    • 该字段包含了 Base64 编码的客户端证书数据(PEM 格式)。客户端证书用于验证客户端身份。
  2. client-key-data
    • 该字段包含了 Base64 编码的客户端私钥数据(PEM 格式)。客户端私钥用于与客户端证书进行配对,以进行身份验证。
  3. certificate-authority-data
    • 该字段包含了 Base64 编码的证书颁发机构(CA)的根证书数据(PEM 格式)。CA 证书用于验证服务器端证书的有效性。

这些字段是客户端认证的一部分,通常与 users 部分的某个具体用户配置关联。以下是一个示例 kubeconfig 文件片段,演示了如何配置客户端认证:

apiVersion: v1
clusters:
- cluster:
    server: https://-api-server>
    certificate-authority-data: -encoded-ca-cert>
  name: my-cluster
contexts:
- context:
    cluster: my-cluster
    user: my-user
  name: my-context
current-context: my-context
kind: Config
preferences: {}
users:
- name: my-user
  user:
    client-certificate-data: -encoded-client-cert>
    client-key-data: -encoded-client-key>
    
---- 
# 实际环境信息
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTi......NG1DN1NqeUJDNUkKKzZFPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://127.0.0.1:63522
  name: kind-12403-k8s-cluster
contexts:
- context:
    cluster: kind-12403-k8s-cluster
    user: kind-12403-k8s-cluster
  name: kind-12403-k8s-cluster
current-context: kind-12403-k8s-cluster
kind: Config
preferences: {}
users:
- name: kind-12403-k8s-cluster
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ......RVJUSUZJQ0FURS0tLS0tCg==
    client-key-data: LS0tLS1CRUdJTi......NzBIWUg1Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==

请注意, 分别是 Base64 编码的 CA 证书、客户端证书和客户端私钥数据。这些字段的值可以通过将相应的 PEM 格式文件内容进行 Base64 编码获得。

4 | 使用 kubeconfig 文件访问集群

Kubernetes是一个完全基于API的系统。使用curl或Postman等简单工具,在构建应用程序之前获取API信息更方便。

1、从查看 kubectl 的配置文件开始,需要:三个证书和 API server 的地址

# cat /root/.kube/config 

2、我们将会把证书设为环境变量,在设置时候请检查每一个参数。我们从 client-certificate-data 开始。

export clientcert=$(grep client-cert ~/.kube/config |cut -d" " -f 6)  
echo $clientcert

3、使用类似的命令将 client-key-data 保存为环境变量

export clientkey=$(grep client-key-data ~/.kube/config |cut -d" " -f 6)  
echo $clientkey

4、然后是 certificate-authority-data

export certauth=$(grep certificate-authority-data ~/.kube/config |cut -d" " -f 6)  
echo $certauth

5、加密这些变量,供 curl 使用:

[root@master k8s-cert\]# echo $clientcert | base64 -d > ./client.pem  
[root@master k8s-cert\]# echo $clientkey | base64 -d > ./client-key.pem  
[root@master k8s-cert\]# echo $certauth | base64 -d > ./ca.pem

6、从配置文件中读取 server 地址:

$ kubectl config view |grep server  
server: https://10.182.101.255:6443

7、使用 curl 和刚刚加密的密钥文件来访问 API server:

curl --cert ./client.pem --key ./client-key.pem --cacert ./ca.pem https://10.182.101.255:6443/api/v1/pods
curl --cert ./client.pem --key ./client-key.pem --cacert ./ca.pem https://10.182.101.255:6443/api/v1/namespace

4.1 | 命令小结

export clientcert=$(grep client-cert ~/.kube/config |cut -d" " -f 6)
export clientkey=$(grep client-key-data ~/.kube/config |cut -d" " -f 6)
export certauth=$(grep certificate-authority-data ~/.kube/config |cut -d" " -f 6)
echo $clientcert | base64 -d > ./client.pem
echo $clientkey | base64 -d > ./client-key.pem
echo $certauth | base64 -d > ./ca.pem
 
curl --cert ./client.pem --key ./client-key.pem --cacert ./ca.pem https://10.182.101.255:6443/api/v1/pods

你可能感兴趣的:(Kubernetes学习笔记,kubernetes,学习,容器)