Kubernetes 作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Server 是集群内部各个组件通信的中介,也是外部控制的入口。所以 Kubernetes 的安全机制基本就是围绕保护 API Server 来设计的。Kubernetes 使用了认证(Authentication)、鉴权(Authorization)、准入控制(AdmissionControl)三步来保证API Server的安全。
当用户或者pod访问apiserver的时候来镜像身份的识别,这就是认证。
HTTP Token 认证:通过一个 Token 来识别合法用户(或者理解为通过一个字符串识别合法用户)
HTTP Token 的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串 - Token 来表达客户的一种方式。Token 是一个很长的很复杂的字符串,每一个 Token 对应一个用户名存储在 API Server 能访问的文件中(这种存储方式不是存储在etcd上面,而是一个文件当中,安全性可想而知)。当客户端发起 API 调用请求时,需要在 HTTP Header 里放入 Token。
HTTP Base 认证:通过用户名+密码的方式认证
用户名+:+密码用 BASE64 算法进行编码后的字符串放在 HTTP Request 中的 Heather Authorization 域里发送给服务端,服务端收到后进行解码,获取用户名及密码。这样服务器就知道用户名密码,然后进行判定。
上面两种都不太安全,都是服务器去验证客户端的机会,但是客户端没有认证服务器。也就是服务器可以认证客户端是否是一个合理的合法的。但是客户端不知道这个服务是不是真的,万一是一个假的也不是不可能。上面的一种放在文件当中不安全,第二种用户名密码方式太费劲。
最严格的 HTTPS 证书认证:基于 CA 根证书签名的客户端身份认证方式
在整个K8s域当中签署一个CA根证书,所有节点的证书都是以这个根证书签发出来的子证书,并且实现的是https的双向认证。
[root@k8s-master ~]# ls /etc/kubernetes/pki/ | grep ca
ca.crt
ca.key
I、HTTPS 证书认证:
II、需要认证的节点
对于认证来说白了就是用户或者pod访问apiserver的时候来进行身份的识别,集群的组件etcd controller manager等需要访问apiserver。那么也需要有双向认证的证书存在
两种类型
安全性说明
证书颁发
III、kubeconfig
kubeconfig文件包含集群参数(CA证书、API Server地址),客户端参数(上面生成的证书和私钥),集群context信息(集群名称、用户名)。Kubenetes 组件通过启动时指定不同的kubeconfig文件可以切换到不同的集群
IV、ServiceAccount
Pod中的容器访问API Server。因为Pod的创建、销毁是动态的,所以要为它手动生成证书就不可行了。Kubenetes使用了Service Account解决Pod 访问API Server的认证问题
(为什么不使用组件之间的双向认证呢,如果使用双向认证就会几百个证书,因为有几百个pod,并且pod会销毁,所以证书就相当于没用了,同时创建证书对集群会造成压力)
V、Secret 与 SA 的关系
Kubernetes 设计了一种资源对象叫做 Secret,分为两类,一种是用于 ServiceAccount 的 service-account-token,另一种是用于保存用户自定义保密信息的 Opaque。ServiceAccount 中用到包含三个部分:Token、ca.crt、namespace
root@nginx-6799fc88d8-drb2s:/run/secrets/kubernetes.io/serviceaccount# pwd
/run/secrets/kubernetes.io/serviceaccount
root@nginx-6799fc88d8-drb2s:/run/secrets/kubernetes.io/serviceaccount# ls
ca.crt namespace token
Json web token(JWT),是为了在网络应用环境间传递声明而执行的一种基于 Json 的开放标准((Rrc 7519】)该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(sso)场景。jwt的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声面明德患,该 token 也可直接被用于认证,也可被加密
默认情况下,每个 namespace 都会有一个 ServiceAccount,如果 Pod 在创建时没有指定 ServiceAccount,就会使用 Pod 所属的 namespace 的 ServiceAccount,默认挂载目录/run/secrets/kubernetes.io/serviceaccount
这个serviceaccount会生成一个token保存在secret里面,serviceaccount和secret是有关联的,用sercert保存token的 (Kubernetes 自身也有一些内置的 Secret,主要用来保存访问 APIServer 的 service account token)
[root@k8s-master ~]# kubectl get serviceaccount
NAME SECRETS AGE
default 1 65d
[root@k8s-master ~]# kubectl describe sa default
Name: default
Namespace: default
Labels:
Annotations:
Image pull secrets:
Mountable secrets: default-token-j9294
Tokens: default-token-j9294
Events:
[root@k8s-master ~]# kubectl get secret default-token-j9294
NAME TYPE DATA AGE
default-token-j9294 kubernetes.io/service-account-token 3 65d
#这里保存的是token信息
[root@k8s-master ~]# kubectl describe secret default-token-j9294
Name: default-token-j9294
Namespace: default
Labels:
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 3b6f6ac8-fb89-42e0-9a45-d14680ee6157
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1066 bytes
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6InR0cTRHNDNQUGFMeUZ5Rnp1azZnSUEyRVU0WEY1dWdEMEYwd056ZnNkWWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tajkyOTQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjNiNmY2YWM4LWZiODktNDJlMC05YTQ1LWQxNDY4MGVlNjE1NyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.cbHTMxahgVgImt2ll-cN4pJIbtN_gMks9Wg-Aqc3hvntktpmPFN0TRk9eT362HoYFpf6RB5pJvH4Xg-eACoZ9IfOcIqDK8ky14jk1z5TolgXrLv1OqacxI8PlRJBDvmjIEX8iLIxcFE63gJQpBoDscCOHMMs-i1cuygdRr2vEq47XX_ykxPg49pw1hRaG4DSLjfCTA7kAG3R-9NnhGCpexruryDd4ftqaKKf12BTmT8xgydcvNWzzkgnYMnoF-o8cfaLqd9c_-TOr3h1VGyoop925CCrTXqHxBU6VPEnSRozegIfDbLwbyhp4Wq3CTDyBAc4YSm8WbqRPyikNRa-ow
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-6799fc88d8-wp9kx 1/1 Running 0 50m
#指定了sa,也就是k8s在创建pod的时候会将创建的sa会注入到pod当中,里面程序带着
[root@k8s-master ~]# kubectl exec -it nginx-6799fc88d8-wp9kx sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /run/secrets/kubernetes.io/
# ls
serviceaccount
# cd serviceaccount
# ls
ca.crt namespace token
# cat token
eyJhbGciOiJSUzI1NiIsImtpZCI6InR0cTRHNDNQUGFMeUZ5Rnp1azZnSUEyRVU0WEY1dWdEMEYwd056ZnNkWWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tajkyOTQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjNiNmY2YWM4LWZiODktNDJlMC05YTQ1LWQxNDY4MGVlNjE1NyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.cbHTMxahgVgImt2ll-cN4pJIbtN_gMks9Wg-Aqc3hvntktpmPFN0TRk9eT362HoYFpf6RB5pJvH4Xg-eACoZ9IfOcIqDK8ky14jk1z5TolgXrLv1OqacxI8PlRJBDvmjIEX8iLIxcFE63gJQpBoDscCOHMMs-i1cuygdRr2vEq47XX_ykxPg49pw1hRaG4DSLjfCTA7kAG3R-9NnhGCpexruryDd4ftqaKKf12BTmT8xgydcvNWzzkgnYMnoF-o8cfaLqd9c_-TOr3h1VGyoop925CCrTXqHxBU6VPEnSRozegIfDbLwbyhp4Wq3CTDyBAc4YSm8WbqRPyikNRa-ow
对于整个k8s集群来说使用的是https认证,是一个双向认证的方式,如果是系统的组件想要访问k8s apiserver分为两种
如果是pod想要访问就要使用sa