Kubernetes安全
安全永远是一个重大的话题,特别是云计算平台,更需要设计出一套完善的安全方案,以应对复杂的场景。 Kubernetes主要使用Docker作为应用承载环境,Kubernetes首先设计出一套API和敏感信息处理方案,当然也基于Docker提供容器安全控制。以下是Kubernetes的安全设计原则:
1. 保证容器与其运行的宿主机之间有明确的隔离
2. 限制容器对基础设施或者其它容器造成不良影响的能力
3. 最小特权原则——限定每个组件只被赋予了执行操作所必需的最小特权,由此确保可能产生的损失达到最小
4. 允许系统用户明确区别于管理员
5. 允许赋予管理权限给用户
6. 允许应用能够从公开数据中提取敏感信息(keys, certs, passwords)
一、Kubernetes API Server访问控制
Kubernetes API Server通过一个名为kube-apiserver的进程提供服务,该进程运行在Master节点上。在默认情况下,kube-apiserver进程在本机的8080端口(–insecure-port)提供REST服务。我们可以同时启动HTTPS安全端口(–secure=6443)来启动安全机制,加强REST API访问的安全性。
1、REST调用
通常我们使用kubectl来与Kubernetes API Server交互,它们之间的接口是REST调用。也可以使用curl命令行工具进行快速验证。
2、编程的方式调用
另外是通过编程的方式调用Kubernetes API Server 具体又细分为以下两种场景:
1. 运行在POD里的进程调用Server API. Pod中的进程如何指定API Server的访问地址呢?答案很简单,因为Kubernetes API Server本身也是一个Service,它的名字是“kubernetes”,IP地址是ClusterIP地址池里面的第一个地址。服务端口是HTTPS端口443.
2. 开发基于Kubernetes的管理平台,比如调用Kubernetes API来完成Pod,Service,RC等资源对象的图形化创建和管理界面。可采用社区中相关的Client Library.
正常情况下,为了确保Kubernetes集群的安全,API Server都会对客户端进行身份认证,认证失败则无法调用API。此外,Pod中访问Kubernetes API Server服务的时候,是以Service方式访问服务名为kubernetes的这个服务,而kubernetes服务又只在HTTPS 443上提供服务,那么如何进行身份认证呢? 答案是 Service Account Token.
API的请求会经过多个阶段的访问控制才会被接受处理,其中包含认证、授权以及准入控制(Admission Control)等。如下图所示:
需要注意:认证授权过程只存在HTTPS形式的API中。也就是说,如果客户端使用HTTP连接到kube-apiserver,是不会进行认证授权的。所以说,可以这么设置,在集群内部组件间通信使用HTTP,集群外部就使用HTTPS,这样既增加了安全性,也不至于太复杂。
Kubernetes集群中所有资源的访问和变更都是通过Kubernetes API Server的REST API来实现的,所以集群安全的关键点在于识别认证客户端身份(Authentication)以及访问权限的授权(Authorization)。
- 认证Authentication
支持Client certificate authentication 、Token authentication 、Basic authentication集中方式。 - 授权Authorization
在Authentication的基础上,Authorization可以对HTTP请求设置AlwaysDeny、AlwaysAllow、ABAC三种模式模式,其中ABAC可以设置不同用户的访问权限。
二、API Server的 认证Authentication
当TLS建立时,HTTP请求会进行身份认证步骤,如图中步骤1,集群管理器将apiserver配置为运行一个或多个认证器模块。
认证模块包含客户端证书,密码、Plain Tokens、Bootstrap Tokens、JWT Tokens(used for service accounts)。
我们可以指定多个认证模块,每个认证模块都会按顺序进行,直到其中一个成功。(在GCE上,客户端证书、密码、Plain Tokens和JWT Tokens都会启用。)
API Server认证 Authentication提供管理三种级别的客户端身份认证方式:
- 最严格的HTTPS证书认证:基于CA根证书签名的双向数字证书认证方式;
- HTTP Token认证:通过一个Token来识别合法用户;
- HTTP Base认证:通过用户名+密码的方式认证;
1、HTTPS证书认证:
- HTTPS通信双方的务器端向CA机构申请证书,CA机构是可信的第三方机构,它可以是一个公认的权威的企业,也可以是企业自身。企业内部系统一般都使用企业自身的认证系统。CA机构下发根证书、服务端证书及私钥给申请者;
- HTTPS通信双方的客户端向CA机构申请证书,CA机构下发根证书、客户端证书及私钥个申请者;
- 客户端向服务器端发起请求,服务端下发服务端证书给客户端。客户端接收到证书后,通过私钥解密证书,并利用服务器端证书中的公钥认证证书信息比较证书里的消息,例如域名和公钥与服务器刚刚发送的相关消息是否一致,如果一致,则客户端认为这个服务器的合法身份;
- 客户端发送客户端证书给服务器端,服务端接收到证书后,通过私钥解密证书,获得客户端的证书公钥,并用该公钥认证证书信息,确认客户端是否合法;
- 客户端通过随机秘钥加密信息,并发送加密后的信息给服务端。服务器端和客户端协商好加密方案后,客户端会产生一个随机的秘钥,客户端通过协商好的加密方案,加密该随机秘钥,并发送该随机秘钥到服务器端。服务器端接收这个秘钥后,双方通信的所有内容都都通过该随机秘钥加密;
CA认证流程图:
上述是双向SSL协议的具体通信过程,这种情况要求服务器和用户双方都有证书。单向认证SSL协议不需要客户拥有CA证书,对应上面的步骤,只需将服务器端验证客户端证书的过程去掉,以及在协商对称密码方案和对称通话秘钥时,服务器端发送给客户端的是没有加过密的(这并不影响SSL过程的安全性)密码方案。
2、HTTP Token原理:
HTTP Token的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串——Token来表明客户身份的一种方式。在通常情况下,Token是一个复杂的字符串,比如我们用私钥签名一个字符串的数据就可以作为一个Token,此外每个Token对应一个用户名,存储在API Server能访问的一个文件中。当客户端发起API调用请求时,需要在HTTP Header里放入Token,这样一来API Server就能够识别合法用户和非法用户了。
3、HTTP Base:
常见的客户端账号登录程序,这种认证方式是把“用户名+冒号+密码”用BASE64算法进行编码后的字符串放在HTTP REQUEST中的Header Authorization域里发送给服务端,服务端收到后进行解码,获取用户名及密码,然后进行用户身份的鉴权过程。
现在使用Basic authentication + ABAC model设置API server,
首先配置Basic authentication,设置用户密码,格式为每行password, user name, user id,
basic_auth.csv:
admin_passwd,admin,admin
test_passwd,test,test
然后配置ABAC访问策略, 设置admin具有任何权限,test用户只能访问pods,
policy_file.jsonl:
{"user":"admin"}
{"user":"test", "resource": "pods", "readonly": true}
访问策略配置详情参考:
https://github.com/kubernetes/ … rithm
然后启动API Server:
$kube-apiserver
...
--basic-auth-file=basic_auth.csv --authorization-mode=ABAC --authorization-policy-file=policy_file.jsonl
访问API,可以看到test用户无法访问Pod之外的资源:
$ curl --basic -u admin:admin_passwd https://192.168.3.146:6443/api/v1/pods -k
[
...
]
$ curl --basic -u test:test_passwd https://192.168.3.146:6443/api/v1/pods -k
[
...
]
$ curl --basic -u test:test_passwd https://192.168.3.146:6443/api/v1/nodes -k
Forbidden: "/api/v1/nodes"
三、API Server授权Authorization
认证之后的请求是授权模块:如图中步骤2
对合法用户进行授权(Authorization)并且随后在用户访问时进行鉴权,是权限与安全系统的重要一环。授权就是授予不同用户不同访问权限:
API Server 目前支持以下几种授权策略 (通过 API Server 的启动参数 --authorization-mode
设置)
- AlwaysDeny:标识拒绝所有的请求,一般用于测试
- AlwaysAllow:允许接受所有请求,如果集群不需要授权流程,则可以采用该策略
- ABAC:(Attribute-Base Access Control)基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制,淘汰
- Webbook:通过调用外部 REST 服务对用户进行授权
- RBAC:基于角色的访问控制,现行默认规则,常用
ABAC授权模式:
为了简化授权的复杂度,对于ABAC模式的授权策略,Kubernetes仅有下面四个基本属性:
- 用户名(代表一个已经被认证的用户的字符型用户名)
- 是否是只读请求(REST的GET操作是只读的)
- 被访问的是哪一类资源,例如Pod资源/api/v1/namespaces/default/pods
- 被访问对象所属的Namespace
当API Server启用ABAC模式时,需要指定授权文件的路径和名字(–authorization_policy_file=SOME_FILENAME),授权策略文件里的每一行都是一个Map类型的JOSN对象,被称为访问策略对象,我们可以通过设置“访问策略对象”中的如下属性来确定具体的授权行为:
- user:字符串类型,来源于Token文件或基本认证文件中的用户名字段的值;
- readonly:true时表示该策略允许GET请求通过;
- resource:来自于URL的资源,例如“Pod”;
- namespace:表明该策略允许访问某个namespace的资源;
eg:
- {“user”:”alice”}
- {“user”:”kubelet”,”resource”:”Pods”,”readonly”:true}
- {“user”:”kubelet”,”resource”:”events”}
- {“user”:”bob”,”resource”:”Pods”,”readonly”:true,”ns”:”myNamespace”}
RBAC 授权模式
RBAC 基于角色的访问控制,在 kubernetes1.5 中引入,现行版本成为默认标准。相对其他访问控制方式,拥有以下优势:
- 对集群中的资源和非资源拥有完整的覆盖
- 整个 RBAC 完全由几个API 对象完成。同其他 API 对象一样,可以用 kubectl 或 API 进行操作。
- 可以在运行时进行调整,无需重启 API Server。
RBAC 的 API 资源对象说明
RBAC 引入了 4个新的顶级资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding、4种对象类型均可以通过 kubectl 与 API 操作。
Role:普通角色 | ClusterRole:集群角色
Rolebinding:普通角色绑定 ClusterRoleBinding:集群角色绑定
三、准入控制Admission Controllers
在认证和授权之外,Admission Controller也可以对Kubernetes API Server的访问控制,任何请求在访问API Server时需要经过一系列的验证,任何一环拒绝了请求,则会返回错误。
实际上Admission Controller是作为Kubernetes API Serve的一部分,并以插件代码的形式存在,在API Server启动的时候,可以配置需要哪些Admission Controller,以及它们的顺序,如:
--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota
Admission Controller支持的插件如下:
- AlwaysAdmit:允许所有请求;
- AlwaysPullmages:在启动容器之前总去下载镜像,相当于在每个容器的配置项imagePullPolicy=Always
- AlwaysDeny:禁止所有请求,一般用于测试;
- DenyExecOnPrivileged:它会拦截所有想在Privileged Container上执行命令的请求,如果你的集群支持Privileged Container,你又希望限制用户在这些Privileged Container上执行命令,强烈推荐你使用它;
- Service Account:这个plug-in将ServiceAccount实现了自动化,默认启用,如果你想使用ServiceAccount对象,那么强烈你推荐使用它;
- SecurityContextDeny:这个插件将使用SecurityContext的Pod中的定义全部失效。SecurityContext在Container中定义了操作系统级别的安全设定(uid,gid,capabilityes,SELinux等)
- ResourceQuota:用于配额管理目的,作用于namespace上,它会观察所有请求,确保在namespace上的配额不会超标。推荐在Admission Control参数列表中这个插件排最后一个;
- LimitRanger:用于配额管理,作用于Pod与Container,确保Pod与Container上的配额不会超标;
- NamespaceExists(已过时):对所有请求校验namespace是否已存在,如果不存在则拒绝请求,已合并至NamespaceLifecycle。
- NamespaceAutoProvision(已过时):对所有请求校验namespace,如果不存在则自动创建该namespace,推荐使用NamespaceLifecycle。
- NamespaceLifecycle:如果尝试在一个不存在的namespace中创建资源对象,则该创建请求将被拒绝。当删除一个namespace时,系统将会删除该namespace中所有对象,保存Pod,Service等。
在API Server上设置–admission-control参数,即可定制我们需要的准入控制链,如果启用多种准入控制选项,则建议的设置如下:
- –admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota
下面着重介绍三个准入控制器:
SecurityContextDeny
Security Context时运用于容器的操作系统安全设置(uid、gid、capabilities、SELinux role等),Admission Control的SecurityContextDeny插件的作用是,禁止创建设置了Security Context的Pod,例如包含以下配置项的Pod:
- spec.containers.securityContext.seLinuxOptions
- spec.containers.securityContext.runAsUser
ResourceQuota
ResourceQuota不仅能够限制某个Namespace中创建资源的数量,而且能够限制某个namespace中被Pod所请求的资源总量。该准入控制器和资源对象ResourceQuota一起实现了资源的配额管理;
LimitRanger
准入控制器LimitRanger的作用类似于上面的ResourceQuota控制器,这对Namespace资源的每个个体的资源配额。该插件和资源对象LimitRange一起实现资源限制管理。
四、ServiceAccount
4.1、什么是service account?
什么是service account? 顾名思义,相对于user account(比如:kubectl访问APIServer时用的就是user account),service account就是Pod中的Process用于访问Kubernetes API的account,它为Pod中的Process提供了一种身份标识。相比于user account的全局性权限,service account更适合一些轻量级的task,更聚焦于授权给某些特定Pod中的Process所使用。
Service Account概念的引入是基于这样的使用场景:运行在pod里的进程需要调用Kubernetes API以及非Kubernetes API的其它服务(如image repository/被mount到pod上的NFS volumes中的file等)。我们使用Service Account来为pod提供id。
Service Account和User account可能会带来一定程度上的混淆,User account可以认为是与Kubernetes交互的个体,通常可以认为是human, 目前并不作为一个代码中的类型单独出现,比如第一节中配置的用户,它们的区别如下。
Kubernetes有User Account和Service Account两套独立的账号系统:
1.User Account是给人用的,Service Account 是给Pod 里的进程使用的,面向的对象不同。
2.User Account是全局性的,即跨namespace使用。 Service Account 是属于某个具体的Namespace,即仅在所属的namespace下使用。
3.User Account是与后端的用户数据库同步的。创建一个新的user account通常需要较高的特权并且需要经过比较复杂的business process(即对于集群的访问权限的创建),而service account则不然。
如果kubernetes开启了ServiceAccount(–admission_control=…,ServiceAccount,… )那么会在每个namespace下面都会创建一个默认的default的ServiceAccount。即service account作为一种resource存在于Kubernetes cluster中,我们可以通过kubectl获取
1、当前cluster中的service acount列表:
kubectl get serviceaccount –all-namespaces
2、service account的详细信息
我们查看一下kube-system namespace下名为”default”的service account的详细信息:
kubectl describe serviceaccount/default -n kube-system
我们看到service account并不复杂,只是关联了一个secret资源作为token,该token也叫service-account-token,该token才是真正在API Server验证(authentication)环节起作用的。
3、查看系统的secret 的token列表:
[root@k8s-master k8s-kube-scheduler]# kubectl get secret -n kube-system
NAME TYPE DATA AGE
coredns-token-cdn9x kubernetes.io/service-account-token 2 1h
default-token-lht2v kubernetes.io/service-account-token 2 1h
[root@k8s-master k8s-kube-scheduler]# kubectl get secret
NAME TYPE DATA AGE
db-user-pass Opaque 0 18d
default-token-k7jfg kubernetes.io/service-account-token 2 1h
registry-key-secret kubernetes.io/dockerconfigjson 1 18d
4、查看系统的secret 详细:
我们看到这个类型为service-account-token的secret资源包含的数据有三部分:namespace和token。
- namespace:这个就是Secret所在namespace的值的base64编码:# echo -n “kube-system”|base64 => “a3ViZS1zeXN0ZW0=”
- token:这是一段用API Server私钥签发(sign)的bearer tokens的base64编码,在API Server authenticating环节,它将派上用场。
5、获取原始token:
获取对应sa的secret从中获取token。并进行base64解码。
kubectl get secret default-token-lht2v -n kube-system -o jsonpath={“.data.token”} | base64 -d
6、使用token 请求apiserver:
获取对应sa的secret从中获取token。并进行base64解码。
curl -k -H ‘Authorization: Bearer token’ https://111.111.111.111:6443
curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLWxodDJ2Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2MDg2MmMxMS04ZTgzLTExZTktYjY2YS0wMDUwNTZiMTIzYjEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.SCn9sq6i4t4fLPW7kuTe3VfoQUO_iXY6M6vKjR40wqPDFJll5-F9n92iY0DqpBAs-vTWeZDmUuevjSJYeRzJlQmMzw5tZj4CIXZ_LHdiiW4kwmAWiproDE-nAXjF4vKHKkWsGLwpeHOQ2F2pCMIibQkk60ZudlJb_qszoTQvt2NgkUmh-DxwEy6uj6pc-j14s--qNSrValkPIoZV7u2zmPEXzC9sFjADKnqUJ4GCtSS3VIVfqUZvSecWB95f-VIBnQwKJAcOvN7Nspk8Vjp0zW3CAWTmiPm_1AHqIuM0daxl6JLpUBZvfQnCAm_s928DbSyyNrTR9V3ra0M3pHcPdw' https://192.168.10.50:6443/api
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "192.168.10.50:6443"
},
{
"clientCIDR": "192.168.0.0/16",
"serverAddress": "192.168.0.1:443"
}
]
}
4.2、默认的service account
1、开启ServiceAccount
如果K8S apiserver的启动参数中添加–admission_control=ServiceAccount
apiserver在启动的时候会自己创建一个key和crt(见/var/run/kubernetes/apiserver.crt和apiserver.key)
然后在启动./kube-controller-manager 时添加flag:
–service_account_private_key_file=/var/run/kubernetes/apiserver.key
那么k8s会在每个namespace下面都会创建一个默认的service account资源,并命名为”default”:
kubectl get serviceaccount –all-namespaces
如果Pod中没有显式指定spec.serviceAccount字段值,那么Kubernetes会将该namespace下的”default” service account自动mount到在这个namespace中创建的Pod里。
2、查看pod的service account资源,
当用户在namespace下创建pod时会默认使用默认的service account资源,。
我们以namespace “default”为例,我们查看一下其中的一个Pod的信息:
kubectl describe pod/webapp-nl754
可以看到,secret:default-token-k7jfg就是我们default这个serviceaccount下的secret。它被装载到容器内部mountPath: /var/run/secrets/kubernetes.io/serviceaccount
目录中
Pod创建成功后,可以查询Pod的容器挂载/var/run/secrets/kubernetes.io/serviceaccount,实际上这个目录是ServiceAccount的Secret,里面包含了一个token,应用通过使用这个token便可以去访问Kubernetes API:
# kubectl exec webapp-62xws ls /var/run/secrets/kubernetes.io/serviceaccount
namespace
token
3、查看pod的token的内容:
# kubectl exec webapp-62xws cat /var/run/secrets/kubernetes.io/serviceaccount/token
也可以深入容器内部,查看mount的serviceaccount路径下的结构:
# docker exec 3d11ee06e0f8 ls /var/run/secrets/kubernetes.io/serviceaccount
namespace
token
这token文件与上面提到的service account的token中的数据是一一对应的。
4.3、API Server的service account token原理
1、开启ServiceAccount
kubernetes apiserver开启了ServiceAccount(–admission_control=…,ServiceAccount,… )那么会在每个namespace下面都会创建一个默认的default的ServiceAccount。即service account作为一种resource存在于Kubernetes cluster中。
每个ServiceAccount下面都会拥有一个加密过的secret作为Token. 该token也叫service-account-token
2、apiserver启动的时候,每个ServiceAccount自动生成token。
该token是APIServer在创建service account时用API server启动参数:–service-account-key-file的值签署(sign)生成的。如果–service-account-key-file未传入任何值,那么将默认使用–tls-private-key-file的值,即API Server的私钥(server.key)。
3、pod发起请求http请求携带signed bearer token
在HTTP Header中传递了一个Token字符串,这类似于之前提到的HTTP Token认证方式
类似这样:curl -k -H ‘Authorization: Bearer token’ https://192.168.10.50:6443/api
即pod的Token是在指定路径下的一个文件(/run/secrets/kubernetes.io/serviceaccount/token),这token是动态生成的,确切的说,是由KubernetesController进程用API Server的私钥(–service-account-private-key-file指定的私钥)签名生成的一个JWT Secret。
4、apiserver验证token
apiserver的authenticating环节支持多种身份校验方式:client cert、bearer token、static password auth等。
apiserver发现client发起的request使用的是service account token的方式,apiserver就会自动采用signed bearer token方式进行身份校验。而request就会使用携带的service account token参与验证。
apiserver收到这个Token以后,采用自己的私钥(实际是使用参数service-account-key-file)指定的私钥,如果此参数没有设置,则默认采用tls-private-key-file指定的参数,即自己的私钥,对token进行合法性验证。
5、通过authenticating后
API Server将根据Pod username所在的group:system:serviceaccounts和system:serviceaccounts:(NAMESPACE)的权限对其进行authority 和admission control两个环节的处理。在这两个环节中,cluster管理员可以对service account的权限进行细化设置。
五、Secrets
Kubernetes提供了Secret来处理敏感信息,目前Secret的类型有3种:
- Opaque(default): 任意字符串
- kubernetes.io/service-account-token: 作用于ServiceAccount
- kubernetes.io/dockercfg: 作用于Docker registry
开发者可以任意定义Secret的格式和内容,现在创建一个假设Opaque Secret,比如应用要使用账号密码:
username: value-1
password: value-2
首先创建Secret,
secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmFsdWUtMg0K
username: dmFsdWUtMQ0K
注意:其中password和username的值是通过base64 加密。
$ kubectl create -f secret.yaml
$ kubectl describe secrets mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
password: 9 bytes username: 9 bytes
现在创建一个Pod使用该Secret
red-pod.json:
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "mypod"
},
"spec": {
"containers": [{
"name": "mypod",
"image": "redis",
"volumeMounts": [{
"name": "foo",
"mountPath": "/etc/foo",
"readOnly": true
}]
}],
"volumes": [{
"name": "foo",
"secret": {
"secretName": "mysecret"
}
}]
}
}
这里将Secret作为一个Volume挂载到Po中容器的/etc/foo下,实际上Secret中的值都会以文件生成到/etc/foo下(文件名是key,文件内容是value),待Pod运行后查看:
$ kubectl exec mypod ls /etc/foo
password
username
$ kubectl exec mypod cat /etc/foo/password
value-2
$ kubectl exec mypod cat /etc/foo/username
value-1
Secret用于 Docker Registry的安全认证,参考:
https://github.com/GoogleCloud … a-pod
六、Security context
Security context是用以对容器进行限制,使得不同的运行容器之前能够实现较为明晰的隔离,以及降低其影响宿主机和其它容器的可能性。通俗而言,容器中的security context用于表征在创建及运行容器时,它能够使用及访问的资源参数。
securityContext目前只实现了capabilities和privileged ,
etcd-discovery-controller.yaml:
kind: ReplicationController
apiVersion: v1
metadata:
name: etcd-discovery
creationTimestamp:
spec:
strategy:
type: Recreate
resources: {}
triggers:
- type: ConfigChange
replicas: 1
selector:
name: etcd-discovery
template:
metadata:
creationTimestamp:
labels:
name: etcd-discovery
spec:
containers:
- name: discovery
image: openshift/etcd-20-centos7
args:
- etcd-discovery.sh
ports:
- containerPort: 2379
protocol: TCP
resources: {}
terminationMessagePath: "/dev/termination-log"
imagePullPolicy: IfNotPresent
capabilities: {}
securityContext:
capabilities: {}
privileged: false
restartPolicy: Always
dnsPolicy: ClusterFirst
serviceAccount: ''
status: {}
问题
kube-controller-manager日志出现:
E0711 18:59:01.092033 18548 leaderelection.go:234] error retrieving resource lock kube-system/kube-controller-manager: Get https://k8s-master:6443/api/v1/namespaces/kube-system/endpoints/kube-controller-manager: x509: certificate is valid for kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local, not k8s-master
说明masterssl.cnf没有指定域名k8s-master
Kubernetes 解决/var/run/secret/kubernetes.io/serviceaccount/token no such file or directory问题
kubectl get serviceaccount
NAME SECRETS
default 0
如果没有则需要添加
在apiserver的启动参数中添加:
–admission_control=ServiceAccount
apiserver在启动的时候会自己创建一个key和crt(见/var/run/kubernetes/apiserver.crt和apiserver.key)
然后在启动./kube-controller-manager 时添加flag:
–service_account_private_key_file=/var/run/kubernetes/apiserver.key
kubectl get serviceaccount
NAME SECRETS
default 1