4.4.2 Kubectl的认证授权
概览
Kubelet的HTTPS端点对外暴露了用于访问不同敏感程序数据的API,并允许您在节点或者容器内执行不同权限级别的操作。
Kubelet认证
默认情况下,所有未被配置的其他身份验证方法拒绝的,对Kubelet的HTTPS端点的请求将被视为匿名请求,并被授予system:anonymous用户名和system:unauthenticated组。
如果要禁用匿名访问并发送401 Unauthorized的未经身份验证的请求的响应:
- 启动kubelet时指定 —anonymous-auth=false标志
如果要对kubelet的HTTPS端点启用X509客户端证书身份验证:
- 启动kubelet时指定 —client-ca-file标志,提供CA bundle以验证客户端证书
- 启动apiserver时指定 —kubelet-client-certificate和 —kubelet-client-key标志
启用API bearer token(包括service account token)用于向kubelet的HTTPS端点进行身份验证:
- 确保在API server中开启了authentication.k8s.io/v1beta1 API组。
- 启动kubelet时指定 —authorization-mode=webhook、—kubeconfig和—require-kubeconfig标志
- kubelet在配置的API Server上调用SubjectAccessReview API,以确定每个请求是否被授权
4.4.4 创建用户认证授权的kubeconfig文件
创建一个devuser用户并将其绑定到dev和test两个namespace为例说明。
创建CA证书和密钥
创建devuser-csr.json文件
{
"CN": "devuser",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "k8s",
"OU": "System"
}
]
}
我们再在Master节点上为devuser创建证书和密钥,在/etc/kubernetes/ssl目录下执行如下命令:
执行该命令前请先确保该目录下已经包含如下文件:
ca-key.pem ca.pem ca-config.json devuser-csr.json
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes devuser-csr.json|cfssljson -bare devuser
这将生成如下文件:
devuser.csr devuser-key.pem devuser.pem
创建kubeconfig文件
#设置集群参数
export KUBE_APISERVER="https://172.20.0.113:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=devuser.kubeconfig
#设置客户端认证参数
kubectl config set-credentials devuser \
--client-certificate=/etc/kubernetes/ssl/devuser.pem \
--client-key=/etc/kubernetes/ssl/devuser-key.pem \
--embed-certs=true \
--kubeconfig=devuser.kubeconfig
#设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=devuser \
--namespace=dev \
--kubeconfig=devuser.kubeconfig
#设置默认上下文
kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig
替换默认为的context配置:
cp -f ./devuser.kubeconfig /root/.kube/config
RoleBinding
使用RBAC创建角色绑定以将该用户的行为限制在某个或某几个namespace空间范围内,例如:
kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev
kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=test
这样devuser用户对dev和test两个namespace具有完全访问权限。
4.4.5 IP伪装代理
创建ip-masq-agent
使用如下命令创建ip-masq-agent:
kubectl create -f https://raw.githubusercontent.com/kubernetes-inclubator/ip-masq-agent/master/ip-masq-agent.yaml
为了仅允许ip-masq-agent考虑10.0.0.0/8,可以在名为config的文件中创建以下ConfigMap。
nonMasqueradeCIDRs:
- 10.0.0.0/8
resyncInternal: 60s
运行如下命令将ConfigMap添加到集群中:
kubectl create configmap ip-masq-agent --from-file=config --namespace=kube-system
这将会更新/etc/config/ip-masq-agent文件,并每隔resyncInterval时间段检查一遍文件,将配置应用到集群的节点中。
要让ip-masq-agent忽略本地链路,可以在ConfigMap中将masqLinkLocal设置为true。
nonMasqueradeCIDRs:
- 10.0.0.0/8
resyncInterval: 60s
masqLinkLocal: true
4.4.6 使用kubeconfig或token进行用户身份认证
使用kubeconfig(即证书)和token两种认证方式是最简单的认证方式。
以示例讲解两种认证方式:
- 为brand命名空间下的brand用户创建kubeconfig文件
- 为集群的管理员(拥有所有命名空间的admin权限)创建token
使用kubeconfig
生成token
需要创建一个admin用户并授予admin角色绑定,使用下面的yaml文件创建admin用户并赋予他管理员权限,然后可以通过token访问kubernetes。
生成kubernetes集群最高权限admin用户的token
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
执行命令创建serviceaccount和角色绑定:
kubectl create -f admin-role.yaml
4.4.7 Kubernetes中的用户与身份认证授权
认识Kubernetes中的用户
Kubernetes集群中包含两类用户:一类是由Kubernetes管理的service account,另一类是普通用户。
普通用户被假定为外部独立服务管理。管理员分发私钥,用户存储,甚至包含用户名和密码列表的文件。
Kubernetes中没有代表普通用户账户的对象,无法通过API调用的方式向集群中添加普通用户。
serviceaccount是由Kubernetes API管理的账户。它们都绑定了特定的namespace,并由API server自动创建,或者通过API调用手动创建。Service Account关联了一套凭证,存储在secret,这些凭证同时被挂载到pod中,从而允许pod与kubernetes API之间的调用。
API请求被绑定到普通用户或service account上,或者作为匿名请求对待。意味着集群内部或外部的每个进程,无论从在工作站上输入kubectl 的人类用户到节点上的kubelet,到控制平面的成员,都必须在向API Server发出请求时进行身份验证,或者被视为匿名用户。
认证策略
Kubernetes使用客户端证书、bearer token、身份验证代理或者HTTP 基本身份验证等身份认证插件来对API请求进行身份验证。当有HTTP请求发送到API Server时,插件会尝试将以下属性关联到请求上:
- 用户名:标识最终用户的字符串。常用值可能是kube-admin或者jane@example.com
- UID:标识最终用户的字符串,比用户名更加一致且唯一。
- 组:一组将用户和常规用户组相关联的字符串。
- 额外字段:包含其他有用认证信息的字符串列表的映射。
当启用了多个认证模式时,第一个认证模块成功认证后将短路请求,不会进行第二个模块的认证。API server不会保证认证的顺序。
system:authenticated 组包含在所有已验证用户的组列表中。
X509客户端证书
使用openssl命令工具生成用于签名认证请求的证书:
openssl req -new -key jbeda.pem -out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2"
静态Token文件
当在命令行上指定—token-auth-file=SOMEFILE选项时,API Server从文件读取bearer token。目前,token会无限期的持续下去,并且不重启API Server的话就无法更改令牌列表。
token文件是一个csv文件,每行至少包含三列:token、用户名、用户uid,其次是可选的组名。
如果有多个组,则该列必须使用双引号。
token,user,uid,"group1,group2,group3"
Service Account Token
Service Account是一个自动启用的验证器,它使用签名的bearer token来验证请求。该插件包括两个可选的标志:
- —service-account-key-file : 一个包含签名bearer token的PEM编码文件。如果未指定,将使用API Server的TLS密钥。
- —service-account-looup:如果启用,从API中删除掉的token将被撤销;
Service Account通常由API Server自动创建,并通过ServiceAccount注入控制器关联到集群中运行的Pod上。
Bearer token挂载到pod中众所周知的位置,并允许集群进程与API Server通信。
账户可以使用PodSpec的serviceAccountName字段显式的与Pod关联。
注意:ServiceAccountName通常被省略,因为这会自动生成。
apiVersion: apps/v1beata2
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
spec:
replicas: 3
template:
metadata:
# ...
spec:
containers:
- name: nginx
image: nginx:1.7.9
serviceAccountName: bob-the-bot
Service account bearer token 在集群外使用也是完全有效的,并且可以用于为希望与Kubernetes通信的长期运行作业创建身份。要手动创建service account,只需要使用kubectl create serviceaccount(NAME)命令。这将在当前的namespace和相关联的secret中创建一个service account。
注意:所有值是基于base64编码的,因为secret总是基于base64编码。
经过签名的JWT可以用作bearer token 与给定的service account进行身份验证。
通常情况下,这些secret被挂在到Pod中,以便对集群内的API Server进行访问,但也可以从集群外访问。
Service account验证时用户名system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT),被指定到组system:serviceaccounts和system:serviceaccounts:(NAMESPACE)。
注意:由于service account的token存储在secret中,所以具有对这些secret的读取权限的任何用户都可以作为Service Account进行身份验证。授予Service account权限和读取secret功能时要谨慎。
4.4.8 Kubernetes集群安全性配置最佳实践
端口
注意管理好如下端口:
端口 | 进程 | 描述 |
---|---|---|
4149/TCP | kubelet | 用于查询容器监控指标的cAdvisor端口 |
10250/TCP | kubelet | 访问节点的API端口 |
10255/TCP | kubelet | 未认证的只读端口,允许访问节点状态 |
10256/TCP | kube-proxy | kube-proxy的健康检查服务端口 |
9099/TCP | calico-felix | calico的健康检查服务端口(如果使用calico/canal) |
6443/TCP | kube-apiserver | Kubernetes API端口 |