目录
一、Kubernetes API访问控制
1.传输安全(Transport Security)
2.认证(Authentication)
2.1 认证方式
2.2 ServiceAccount和普通用户的区别
2.3 ServiceAccount管理方式
自动ServiceAccount示例
手动ServiceAccount示例
3.鉴权 (Authorization)
3.1鉴权方式
3.2 RBAC
4.准入控制 (Admission Control)
PodSecurity
安全级别
安全实施
配置示例
二、审计 (Auditing)
审计架构
审计策略(Audit Policy)
审计级别
审计策略文件示例
审计日志的存储(Audit Sink)
审计事件结构
三、Secret
四、网络策略(NetworkPolicy)
网络策略的作用
网络策略的工作原理
网络策略示例
Kubernetes(K8s)是一个强大的容器编排平台,安全性至关重要。Kubernetes的安全机制可以分为多个层次,包括集群层、网络层、应用层等。以下是Kubernetes中主要的安全机制:Kubernetes API访问控制、Secret、网络策略(NetworkPolicy) 、审计日志等等。
一、Kubernetes API访问控制
Kubernetes API访问控制是一组机制,确保只有经过授权的用户或服务可以访问和操作集群资源。它涵盖了多个层面,包括传输安全、认证、鉴权、准入控制和审计。以下是这些概念的详细介绍。
1.传输安全(Transport Security)
Kubernetes默认使用HTTPS来确保API通信的安全性,防止数据在传输过程中被窃取或篡改。API服务器会使用TLS(传输层安全协议)对请求进行加密:
客户端与服务器间通信加密:通过使用TLS证书来验证服务器和客户端的身份,从而加密通信。
Kubernetes API server的证书管理:需要为Kubernetes集群中的API服务器配置正确的证书(包括根证书和客户端证书)。
保护内部组件的通信:比如etcd的通信需要加密,并使用适当的证书。
2.认证(Authentication)
2.1 认证方式
所有Kubernetes集群都有两类用户:由Kubernetes管理的服务账户(ServiceAccount)、普通用户。所有API请求都需要经过身份认证,以确保请求来自合法用户或服务,并授予适当的权限。Kubernetes支持多种认证方式,其中比较常见的是基于令牌的身份验证、x509证书、OpenID Connect(OIDC)、服务账户(ServiceAccount)等。
x509证书:用户通过x509证书与API服务器进行通信。这种方式通常用于Kubernetes管理员、集群节点和集群内的一些服务。例如:客户端使用带有用户身份的证书,通过kubectl命令访问API服务器。
Bearer Token:Kubernetes使用令牌(Token)进行身份验证,客户端可以通过将Bearer Token附加到HTTP请求中进行身份验证。
OIDC(OpenID Connect):通过外部身份提供者(如Google、AWS、Keycloak等)验证用户身份。OIDC是一种基于OAuth2.0协议的身份验证协议,适合于与外部认证服务集成。
服务账户(ServiceAccount):服务账户用于集群内的应用程序或Pod来访问API服务器,通常与RBAC(基于角色的访问控制)结合使用。
可以指定多个认证模块,在这种情况下,服务器依次尝试每个验证模块,直到其中一个成功。
2.2 ServiceAccount和普通用户的区别
普通用户通常是指通过kubeconfig文件、证书或OIDC等方式认证的用户,通常是Kubernetes集群的管理员或开发者;Kubernetes不会直接在集群中创建或管理普通用户。
普通用户使用场景:普通用户用于手动管理集群资源(例如 kubectl 命令行工具)或访问Kubernetes API。
ServiceAccount是Kubernetes中的一种特殊类型的账户,用于赋予Pod在集群中运行时的身份。它主要用于集群内的自动化服务,而不是手动用户操作。
ServiceAccount使用场景:ServiceAccount常用于需要与API服务器交互的应用程序,或用于Pod自动管理集群资源。例如CI/CD工具、监控工具、控制器等。
2.3 ServiceAccount管理方式
每个ServiceAccount都与一个JSON Web Token (JWT) 关联,该令牌存储在Pod的文件系统中,位于 /var/run/secrets/kubernetes.io/serviceaccount/token路径下。Pod启动后,会使用这个令牌与Kubernetes API服务器进行通信,API服务器根据该令牌进行身份验证。ServiceAccount通常与RBAC结合,授予Pod访问某些API资源的权限。
ServiceAccount可以通过自动或手动方式使用。默认情况下,每个命名空间Namespace都有一个默认的ServiceAccount,Pod启动时会自动关联这个ServiceAccount。如果需要更高的权限或特殊用途,我们也可以手动创建并指定ServiceAccount。
自动ServiceAccount示例
创建及查看Pod:
#创建Pod
kubectl run my-pod --image=nginx
#查看Pod的ServiceAccount
kubectl get pod my-pod -o yaml
在输出中,会看到以下部分,表示该Pod使用了default
ServiceAccount:
serviceAccount: default
serviceAccountName: default
查看ServiceAccount令牌:
kubectl exec -it my-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
手动ServiceAccount示例
创建ServiceAccount:
#手动创建一个新的ServiceAccount
kubectl create serviceaccount my-service-account
#查看ServiceAccount的详细信息kubectl get serviceaccount my-service-account -o yaml
创建Pod并绑定自定义的ServiceAccount:
apiVersion: v1
kind: Pod
metadata:
name: my-pod-with-sa
spec:
serviceAccountName: my-service-account # 指定使用的ServiceAccount
containers:
- name: my-container
image: nginx
验证Pod是否绑定了自定义ServiceAccount:
#创建Pod
kubectl apply -f pod-with-sa.yaml
#查看该 Pod 的详细信息kubectl get pod my-pod-with-sa -o yaml
输出中会显示:
serviceAccount: my-service-account
serviceAccountName: my-service-account
为ServiceAccount配置权限(可选):
#授予
my-service-account
读取Pod信息的权限。kubectl create role my-role --verb=get,list,watch --resource=pods
kubectl create rolebinding my-role-binding --role=my-role --serviceaccount=default:my-service-account
ServiceAccount 默认没有太多权限,可以使用Role
和RoleBinding
为它配置权限。
关于权限在鉴权 (Authorization)部分说明。
3.鉴权 (Authorization)
3.1鉴权方式
在认证之后,Kubernetes会决定认证通过的用户是否有权限执行特定操作。Kubernetes使用多种授权方式来控制API请求的访问权限。
RBAC (基于角色的访问控制):基于预定义的角色来授予用户或组的权限,通过Role和ClusterRole结合RoleBinding和ClusterRoleBinding来实施访问控制。
ABAC (基于属性的访问控制):通过指定策略文件,根据请求的属性(如用户名、资源类型、动作)决定是否授权。
Webhook模式:将鉴权请求转发到外部服务处理,适合实现自定义的访问控制逻辑。
3.2 RBAC
RBAC(Role-Based Access Control,基于角色的访问控制)是Kubernetes中的一种访问控制机制,用于定义用户或服务账号对 Kubernetes 资源的访问权限。通过 RBAC,集群管理员可以根据角色分配权限,并通过绑定这些角色给用户、组或ServiceAccount来控制访问权限。
RBAC 主要由四个核心组件构成:
- Role:定义某个特定
Namespace
下的权限。它包含了对资源(例如Pods、Services等)的操作规则(如get
、create
、delete
等)。 - ClusterRole:定义集群范围的权限,可以在所有
Namespace
中使用,或直接应用于集群级资源(如节点、PersistentVolumes等)。 - RoleBinding:将
Role
绑定到用户、组或ServiceAccount,使其在指定的Namespace
中拥有相应的权限。 - ClusterRoleBinding:将
ClusterRole
绑定到用户、组或ServiceAccount,使其在整个集群中拥有相应的权限。
Role & RoleBinding示例:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default #作用范围是default命名空间
name: pod-reader
rules:
- apiGroups: [""] #空字符串表示核心API组
resources: ["pods"]
verbs: ["get", "list", "watch"] #授予的操作权限
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects: #绑定的用户或服务账户
- kind: User #可以是User、Group或ServiceAccount
name: "example-user" #用户名
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #绑定的角色类型
name: pod-reader #绑定的角色名称
apiGroup: rbac.authorization.k8s.io
example-user
现在拥有default
命名空间中读取pods
资源的权限。
ClusterRole & ClusterRoleBinding示例:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-pod-reader
rules:
- apiGroups: [""] # 核心API组
resources: ["pods"]
verbs: ["get", "list", "watch"]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-pods-clusterwide
subjects: #绑定的用户或服务账户
- kind: User
name: "example-user" #用户名
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole #绑定ClusterRole
name: cluster-pod-reader #绑定的角色名称
apiGroup: rbac.authorization.k8s.io
ci-service-account
现在可以读取集群中所有命名空间的Pod信息。
4.准入控制 (Admission Control)
准入控制是对经过认证和授权的API请求进行进一步的检查和修改的一个步骤。在请求进入Kubernetes API Server之前,准入控制器可以阻止请求或修改对象。推荐使用的准入控制器默认情况下都处于启用状态。可以使用--enable-admission-plugins来启用默认设置以外的其他准入控制器。
常见的内置准入控制器:例如NamespaceLifecycle、LimitRanger、PodSecurity、RuntimeClass等,用于特定的访问和资源管理。以下介绍PodSecurity概念:
PodSecurity
Pod 安全性标准(Pod Security Standards,PSS)是Kubernetes提供的一套安全标准,用于定义和管理Pod 的安全策略。通过使用Pod安全性标准,Kubernetes集群管理员可以控制和限制 Pod在运行时的行为,从而提高集群的整体安全性。这套标准是通过Kubernetes的内置准入控制器PodSecurity来实现的。
默认情况下,Kubernetes不启用PodSecurity,因此没有默认的安全级别和模式。如果启用PodSecurity准入控制器,默认的安全级别和模式需要手动配置。
安全级别
Pod 安全性标准主要定义了三个安全级别(或模式):
-
特权级别(Privileged)
- 用途:最宽松的安全级别,允许Pod以完全特权运行。适用于那些需要完全控制底层主机的Pod,例如需要执行主机级别操作的系统组件或Pod。
- 特点:
- 允许使用特权模式、HostPath挂载、特权容器、HostNetwork等功能。
- 几乎没有安全约束,风险较高。
-
基线级别(Baseline)
- 用途:旨在允许大多数应用程序正常运行,同时施加基本的安全限制。适合一般的应用程序。
- 特点:
- 拒绝特权模式和特权容器。
- 限制HostPath挂载,防止容器访问主机的敏感文件。
- 限制某些Linux特性,如
CAP_SYS_ADMIN
等高危特权。 - 禁止使用
HostNetwork
和HostPID
。
-
受限级别(Restricted)
- 用途:最严格的安全级别,施加了所有可用的最佳安全实践。适用于高度敏感的应用程序,需要严格限制Pod的行为。
- 特点:
- 禁止一切特权操作,包括HostPath挂载、特权容器、HostNetwork、HostPID、HostIPC等。
- 强制限制容器的用户权限(如不能以root用户身份运行容器)。
- 强制限制进程和文件系统的权限,最大限度减少攻击面。
安全实施
Pod 安全性标准的实施分为以下几种操作模式:
- Enforce(执行):强制执行指定的安全策略,如果Pod不符合要求,则禁止其创建或更新。
- Audit(审计):记录违反安全策略的操作,但不阻止Pod创建或更新。
- Warn(警告):向用户发出警告,通知其违反了安全策略,但不阻止Pod创建或更新。
这些模式允许管理员以递进方式加强安全控制,逐步引导开发人员适应更严格的安全标准。
配置示例
apiVersion: v1
kind: Namespace
metadata:
name: restricted-namespace
labels:
pod-security.kubernetes.io/enforce: "restricted" #强制执行受限级别
pod-security.kubernetes.io/audit: "baseline" #审计基线级别
pod-security.kubernetes.io/warn: "baseline" #警告基线级别
在这个示例中,restricted-namespace
命名空间中,强制执行受限级别的Pod安全策略,并在审计和警告模式下评估基线级别的策略。
apiVersion: v1
kind: Namespace
metadata:
name: baseline-namespace
labels:
pod-security.kubernetes.io/enforce: "baseline" #强制执行基线级别
在这个示例中,baseline-namespace
命名空间中,所有创建的Pod必须符合基线级别的安全标准,否则创建或更新请求将被拒绝。
二、审计 (Auditing)
Kubernetes 审计日志会记录API服务器处理的每一个HTTP请求,它包括从请求的接收到最终的处理结果(允许或拒绝),以及返回的响应。审计的事件按照发生的顺序记录下来,管理员可以根据这些日志了解集群的操作情况。
Kubernetes 默认没有开启审计,需要在kube-apiserver
的配置文件中启用审计功能,并手动配置审计策略文件。API 服务器不默认生成审计日志,也没有预设的审计级别。
审计架构
审计系统由三个主要组件组成:
- Audit Policy:定义审计事件的记录规则,如记录哪些操作、哪些用户的行为等。
- Audit Sink:审计日志的存储位置,可以是文件、标准输出,或通过HTTP Webhook发送到外部服务。
- Audit Event:每个 API 请求会被记录为一个审计事件,包含详细的上下文信息。
审计策略(Audit Policy)
审计策略通过一个策略文件来定义,策略文件控制什么样的API请求会被记录,以及记录的详细程度。
审计级别
每个请求可以按不同的审计级别记录:
- None:不记录任何内容。
- Metadata:仅记录请求的元数据(如用户、操作、时间等),不记录请求和响应的内容。
- Request:记录请求的元数据以及请求体,但不记录响应体。
- RequestResponse:记录请求的元数据、请求体和响应体,包含了所有详细信息。
审计策略文件示例
一个典型的审计策略文件会定义不同资源、不同用户和操作的记录级别。下面是一个示例策略文件:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse # 对于所有的pod操作,记录请求和响应
resources:
- group: ""
resources: ["pods"]
- level: Metadata #对于所有的secrets操作,记录元数据
resources:
- group: ""
resources: ["secrets"]
- level: None #忽略对serviceaccounts的请求
resources:
- group: ""
resources: ["serviceaccounts"]
- level: Request #记录所有的请求操作和元数据
users: ["system:serviceaccount:kube-system:default"]
verbs: ["create", "update", "patch"]
- level: Metadata #默认记录所有其他请求的元数据
omitStages:
- "RequestReceived"
这个策略文件的规则说明如下:
- 对于所有的Pod操作,记录详细的请求和响应。
- 对于 Secret 操作,仅记录元数据(例如操作的时间、用户)。
- 忽略ServiceAccount的所有操作。
- 对特定的服务账户的
create
、update
、patch
请求,记录请求的详细信息。 - 对所有其他请求,默认记录元数据。
审计日志的存储(Audit Sink)
Kubernetes 支持多种审计日志的输出方式,通常包括:
- 文件输出:将审计日志写入文件。
- Webhook 输出:通过HTTP POST请求将审计日志发送到外部服务。
文件输出是一种常见的方式,API服务器可以将审计日志写入到指定文件。 启动kube-apiserver
时,可以通过以下参数配置文件输出:、
kube-apiserver \
--audit-policy-file=/etc/kubernetes/audit-policy.yaml \
--audit-log-path=/var/log/kubernetes/audit.log \
--audit-log-maxage=30 \
--audit-log-maxbackup=10 \
--audit-log-maxsize=100
--audit-policy-file
:指定审计策略文件路径。--audit-log-path
:审计日志文件的存储路径。--audit-log-maxage
:日志文件保存的最大天数。--audit-log-maxbackup
:保留的旧审计日志文件的最大数量。--audit-log-maxsize
:每个日志文件的最大大小(以 MB 为单位)。
审计事件结构
审计日志中的每个事件都包含丰富的上下文信息,在下面的输出示例中,requestObject
和 responseObject
分别记录了请求和响应的详细内容:
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "RequestResponse",
"stage": "ResponseComplete",
"requestURI": "/api/v1/namespaces/default/pods",
"verb": "create",
"user": {
"username": "admin",
"groups": ["system:masters"]
},
"sourceIPs": ["192.168.1.100"],
"objectRef": {
"resource": "pods",
"namespace": "default",
"name": "my-pod"
},
"responseStatus": {
"metadata": {},
"code": 201
},
"requestObject": {
"kind": "Pod",
"metadata": {
"name": "my-pod"
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:latest"
}
]
}
},
"responseObject": {
"kind": "Pod",
"metadata": {
"name": "my-pod"
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:latest"
}
]
}
}
}
三、Secret
Secret API为需要保密的配置值提供基本保护。可以回顾 Kubernetes从零到精通(13-Configmap、Secret)
四、网络策略(NetworkPolicy)
Kubernetes 中的网络策略(NetworkPolicy) 是一种控制Pod间流量和Pod与外部网络流量的安全机制。它允许用户定义哪些流量可以进入和离开Pod,以确保集群的安全性。
网络策略仅会在支持网络策略的网络插件CNI(如 Calico)中生效。Kubernetes 默认的网络实现不支持网络策略。网络插件可以回顾Kubernetes从零到精通(11-CNI网络插件)。
网络策略的作用
NetworkPolicy是通过定义一组规则来允许或拒绝指定Pod的网络流量。这些规则可以基于:
- 命名空间:限制特定命名空间中的 Pod 间的流量。
- Pod 标签:限制带有特定标签的 Pod 间的流量。
- IP Block:限制特定的 IP 地址段的流量。
网络策略的工作原理
Kubernetes 网络策略主要用来定义:
- 入口流量(Ingress):进入Pod的流量。
- 出口流量(Egress):从Pod发送出的流量。
没有配置网络策略时,所有Pod之间的网络流量默认是允许的,一旦定义了网络策略,只有符合规则的流量才会被允许。
网络策略的基本结构
一个网络策略通过以下几部分定义:
- Pod选择器:选择哪些 Pod 应该应用这条策略。
- 策略类型:
Ingress(不是Ingress、Gateway api,只是名称相同)
或Egress
,指定策略是控制入口流量还是出口流量。 - 规则:指定允许哪些流量通过,规则可以基于Pod标签、IP 地址块、命名空间等定义。
网络策略示例
下面的网络策略将阻止所有流向my-pod
的流量,除了带有特定标签的Pod发送的流量:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-specific-pods
namespace: default
spec:
podSelector:
matchLabels:
app: my-pod #应用此策略的Pod
policyTypes:
- Ingress #定义入口流量规则
ingress:
- from:
- podSelector:
matchLabels:
app: allowed-app #允许带有此标签的Pod发送流量
该策略允许来自特定IP地址段(如192.168.0.0/16)的流量,其他流量会被拒绝:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-ip-range
namespace: default
spec:
podSelector:
matchLabels:
app: my-pod #应用此策略的Pod
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 192.168.0.0/16 #允许的IP地址范围
下面的网络策略允许Pod访问外部网络(注意这里只是在策略上允许访问外部网络,底层网络能不能支持该Pod访问外部网络,需要看具体网络情况),但限制对特定命名空间内其他 Pod 的访问:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress
namespace: default
spec:
podSelector:
matchLabels:
app: my-app
policyTypes:
- Egress #定义出口流量规则
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0 #允许Pod访问外部网络
该策略将完全隔离某个Pod的网络流量,既不允许它接收流量,也不允许它发送流量:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: default
spec:
podSelector:
matchLabels:
app: isolated-pod #目标Pod
policyTypes:
- Ingress #不允许任何流量进入
- Egress #不允许任何流量离开