Kubernetes_认证授权_静态Pod网关apiserver底层都是restful接口(UserAccount三种访问方式和打开外网)
静态Pod网关apiserver底层都是restful接口
系列文章目录
前言
一个k8s集群每个node节点上都有 kubelet服务、kube-proxy容器、calico容器,主节点上有 kube-apiserver、kube-proxy、kube-controller-manager、kube-scheduler,这四个被称为静态Pod,其次,主节点上还有 kube-dns/coredns 域名解析 和 etcd 配置中心。
本文讲解 kube-apiserver,直译为网关,所有的发送给 k8s 集群的请求会从 kube-apiserver 经过,类似写 spring 服务端程序的拦截器。对于 kube-apiserver 静态Pod,与工程开发相关,有四个方面需要学习:所有的kubectl底层都是http请求、rbac 权限机制、audit 审计日志。
本文介绍两点:
第一,kubectl底层都是https请求,三种访问方式:匿名访问、bearer Token访问、x509客户端证书访问;
第二,k8s打开外网,然后集群外通过 x509客户端证书 连接上。
API Server的验证环节支持多种身份校验方式:CA 证书认证、Token 认证、Base 认证
一、所有的kubectl底层都是https请求
1.1 所有的kubectl底层都是https请求
对于k8s集群而言,kubectl、kubelet、kubeadm是版本是一致的,kubectl是操作命令,kubeadm是安装工具(安装kubeadm init,重置kubeadm reset),kubelet是linux服务(systemctl status kubelet查看)。
kubectl作为命令操作工具,其实每一条kubectl命令底层本质都是restful风格的https请求。
注意:所有对于k8s的都是https请求,没有http请求。
以 kubectl get ns 为例,如下:

使用Postman发送请求也可以使用相同的效果,如下:
先查询到对应的 url,如下

然后使用Postman发送请求,如下:
GET /api/v1/namespaces


现在就验证了,所有的kubectl底层都是https请求,对于k8s api而言,这里提供三个官方链接,可方便日常使用,如下:
restful接口:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/
kubectl命令:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#patch
swagger:https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json
1.2 从集群外使用https访问k8s集群(打开匿名权限)
在提供https访问的时候,常见的问题是:User “system:anonymous” cannot list resource “configmaps”
https://192.168.100.155:6443/api/v1/namespaces

因为是Get请求,在chrome浏览器中也可以尝试,如下:
最简单的解决方式是去掉鉴权,主节点上执行:kubectl create clusterrolebinding test:anonymous --clusterrole=cluster-admin --user=system:anonymous
然后,Postman这边关闭SSL,就可以发送成功了。

1.3 从集群外使用https访问k8s集群(使用bearer token)
第二种方法,手动新建一个sa账号,给这个sa账号binding足够的role权限,然后这个sa账号一定会以secret的方式保存,取出secret中的三个属性(cr.crt namespace token)中的token属性(base64解密之后的),然后放到postman中作为header请求头中的Authorizaion中的bearer,带密钥发送https请求,如下:
步骤1:先获得token
步骤2:使用token访问
步骤1:先获得token
1.创建一个k8s-admin.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard-admin
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: dashboard-admin
subjects:
- kind: ServiceAccount
name: dashboard-admin
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
在RBAC权限中,能够与 role/clusterrole 绑定的只有三种资源,分别是:kind: User、kind: Group、kind: ServiceAccount ,所以,这里ServiceAccount绑定ClusterRole,很正常
注意:从来没有一种 kind: UserAcccount 的资源
2.应用k8s-admin.yaml配置
kubectl apply -f k8s-admin.yaml
3.获取admin-token名字
kubectl get secret -n kube-system|grep admin
4.Describe查询token内容
kubectl describe secret dashboard-admin-token-slc8x -n kube-system

步骤2:使用token访问


请求头上增加 bearer 具体token

篇外知识:无论是默认的名为default的serviceAccount,还是kubectl命令新建的serviceAccount,创建出来之后,都会带有一个secret,这secret里面存放数据data包含三个东西,加密的namespace、加密的token、加密的ca.crt,如下:


1.4 从集群外使用https访问k8s集群(三个证书)
步骤1:关闭匿名权限
开始,去掉匿名权限,尝试让Postman使用三个证书访问k8s集群

先在master节点上使用curl测试,成功之后再到 Postman 上测试。
步骤2:在master节点上使用curl测试
先不使用三个证书,curl https://127.0.0.1:6443/api/v1/namespaces,一定会报错,如下:

这个报错信息是 https 请求缺乏SSL证书,要解决这个错误,要么加上证书,要么加上 -k 或者 --insecure,要么直接curl http,发送http请求,但是这种k8s内部接口,服务端只能处理 https 请求,会报错 send http request to https server.
然后加上三个证书,curl --cert /etc/kubernetes/pki/client.crt --key /etc/kubernetes/pki/client.key --cacert /etc/kubernetes/pki/ca.crt https://127.0.0.1:6443/api/v1/namespaces
还是错误,但是错误日志发生了改变
最后发现,使用 127.0.0.1:6443 错误,但是,使用 192.168.100.155:6443 正确,因为三个证书是通过ip为 192.168.100.155 生成的。
curl --cert /etc/kubernetes/pki/client.crt --key /etc/kubernetes/pki/client.key --cacert /etc/kubernetes/pki/ca.crt https://192.168.100.155:6443/api/v1/namespaces
成功了。
另外,如果只使用 curl https://192.168.100.155:6443/api/v1/namespaces 也是会出现缺少 – cacert 证书的错误,如下:

小结:需要三个证书,而且对应的IP正确。
特别注意1:curl命令中,三个证书一定要使用绝对路径,一定不能使用相对路径
正确:curl --cert /etc/kubernetes/pki/client.crt --key /etc/kubernetes/pki/client.key --cacert /etc/kubernetes/pki/ca.crt https://192.168.100.155:6443/api/v1/namespaces
错误:cd /etc/kubernetes/pki
curl --cert client.crt --key client.key --cacert ca.crt https://192.168.100.155:6443/api/v1/namespaces
特别注意2:curl命令中,一定要写 宿主机内网ip/外网ip ,一定不能写 127.0.0.1,因为三个证书是通过ip生成的
正确:curl --cert /etc/kubernetes/pki/client.crt --key /etc/kubernetes/pki/client.key --cacert /etc/kubernetes/pki/ca.crt https://192.168.100.155:6443/api/v1/namespaces
错误:curl --cert /etc/kubernetes/pki/client.crt --key /etc/kubernetes/pki/client.key --cacert /etc/kubernetes/pki/ca.crt https://127.0.0.1:6443/api/v1/namespaces
常用的base64命令
base64 xxx.txt # 对文件内容加密
echo “xxx” | base64 # 对字符串xxx加密
echo “xxx” | base64 --decode # 对字符串xxx加密
步骤3:在postman上带证书发出https请求给K8S集群
接下来,postman如何带证书发出https请求,关闭了匿名认证之后,直接发送一定是 403 forbidden,如下:
(1) 在集群上生成三个pem文件
# .key 转换成 .pem:
openssl rsa -in client.key -out client_key.pem
# .crt 转换成 .pem:
openssl x509 -in client.crt -out client_crt.pem
# .crt 转换成 .pem:
openssl x509 -in ca.crt -out ca.pem
生成三个pem文件中,需要注意如下:
.key 和 .crt 文件中,前后两行不能去掉,否则无法使用 openssl 命令,从 .key/.crt 生成 .pem 文件,报错信息如下:

(2) Postman访问
Postman配置三个证书,就是因为 postman 必须使用 pem 文件,所有才需要生成三个 pem 文件。

配置三个证书之后,成功发送,注意Postman上的URL,一定要加上https,postman即使你配置了证书,也不会自动切https,需要你在url中明确表示。

打开SSL也是可以发送成功
二、打开外网
2.1 理论: 打开外网的需求
搭建 k8s 集群使用的是kubeadm init命令,这个命令要求使用的是内网ip,使用外网ip/公网ip是无法搭建成功的。所以默认的集群,各个node节点的内网ip写入到了k8s集群的密钥里面去,但是公网ip没有写入到密钥里面去的。
我现在直接搭建的是在vmware上的,因为 windows 和 vmware 在同一局域网里面,所以因为在 windows 直接使用内网ip 192.168.100.155 ,所以在 windows 的 Postman 可以访问到。
如果是使用 云服务器搭建的话,使用公网ip在Postman调用,是无法成功的,所以需要手动打开外网,将外网ip添加到密钥里面去。
2.2 实践: 打开外网的操作
本质就是到 /etc/kubernetes/pki 目录下,重新生成 apiserver.key apiserver.crt 这两个证书。
步骤1:查看当前允许哪些通过哪些ip操作k8s集群 (默认只允许 内网ip:6443 操作k8s集群,不允许外网ip:6443 操作k8s集群)
cd /etc/kubernetes/pki
openssl x509 -noout -text -in apiserver.crt |grep IP

步骤2:移走 apiserver.key apiserver.crt 两个证书
mkdir -pv /opt/cert
mv apiserver.* /opt/cert (这里必须移走,否则生成报错,不是可选操作)
注意:这里必须移走,否则生成报错,不是可选操作
步骤3:重新生成 apiserver.key apiserver.crt 这两个证书
kubeadm init phase certs apiserver \
--apiserver-advertise-address 内网ip \
--apiserver-cert-extra-sans apiserver.xxx域名 或者 本机外网ip 或者 代理机外网ip
这里有两个参数:
–apiserver-advertise-address 后面接内网ip
–apiserver-cert-extra-sans 后面接apiserver.xxx域名 或者 本机外网ip 或者 代理机外网ip
步骤4:重启主节点上的kubelet服务 (各个从节点上的kubelet服务不需要重启)
systemctl restart kubelet.service
我是使用vmware虚拟机,没有外网ip,所以这里无法截图演示了。没有云服务器,穷。
总结
本文介绍所有的kubectl底层都是https请求,并且k8s打开外网,然后集群外访问到。
天天打码,天天进步!
更多推荐



所有评论(0)