大规模 Kubernetes 集群安全实战:如何应对未授权访问、容器逃逸与恶意镜像?
未授权访问:权限管理是第一道防线
容器逃逸:限制容器能力是关键
恶意镜像:镜像安全扫描不可或缺
作为一名 Kubernetes 管理员,我深知在生产环境中维护大型微服务集群安全的重要性。Kubernetes 本身虽然提供了许多安全机制,但默认配置往往不足以应对复杂的安全威胁。在实际工作中,我踩过不少坑,也积累了一些经验,今天就来分享一下我是如何通过配置网络策略、RBAC 权限控制、镜像安全扫描等手段,来解决 Kubernetes 安全挑战的。希望我的经验能帮助你更好地保护你的 Kubernetes 集群。
未授权访问:权限管理是第一道防线
Kubernetes 的 RBAC(Role-Based Access Control,基于角色的访问控制)是控制集群访问权限的关键。如果 RBAC 配置不当,就可能导致未授权用户访问敏感资源,甚至控制整个集群。我见过一些团队,为了方便开发,直接给所有用户授予 cluster-admin
权限,这简直就是把集群的钥匙拱手让人!
案例:权限膨胀导致的事故
曾经有个开发人员,因为需要频繁调试线上服务,就被授予了 cluster-admin
权限。后来,这位开发人员离职了,但他的账号却没有及时回收。结果,几个月后,有人利用这个账号,删除了生产环境的几个关键 Deployment,导致服务中断了好几个小时。事后调查发现,攻击者就是通过扫描 GitHub 找到这个泄露的 Kubernetes 配置文件,从而获得了集群的控制权。
如何避免权限膨胀?
最小权限原则: 只授予用户完成工作所需的最小权限。例如,只允许开发人员查看特定命名空间的 Pod 日志,不允许他们修改 Deployment。可以使用 Kubernetes 内置的
view
、edit
等角色,也可以自定义角色,以满足更精细的权限控制需求。权限分级: 将用户分为不同的角色,例如管理员、开发人员、测试人员等,并为每个角色分配不同的权限。可以使用 Kubernetes 的
Role
和ClusterRole
对象来定义角色,并使用RoleBinding
和ClusterRoleBinding
对象将角色绑定到用户或组。定期审查: 定期审查 RBAC 配置,确保权限设置仍然合理。可以使用
kubectl get rolebindings --all-namespaces -o yaml
和kubectl get clusterrolebindings -o yaml
命令来查看 RBAC 配置,并手动检查是否存在不合理的权限授予。使用 OIDC 集成: 将 Kubernetes 集群与 OIDC(OpenID Connect)身份提供商集成,例如 Google Identity Platform、Azure Active Directory 等。这样,用户就可以使用自己的组织账号登录 Kubernetes 集群,而无需创建额外的 Kubernetes 用户。OIDC 集成还可以实现更精细的权限控制,例如基于用户组的权限控制。
使用 Kubernetes Admission Controller: 使用 Kubernetes Admission Controller 来强制执行 RBAC 策略。Admission Controller 是 Kubernetes 的一个扩展点,可以在对象被创建、更新或删除之前,对对象进行验证和修改。可以使用 Gatekeeper、Kyverno 等工具来配置 Admission Controller,以强制执行 RBAC 策略,例如禁止创建具有
cluster-admin
权限的 RoleBinding。
示例:使用 Kyverno 强制执行 RBAC 策略
以下是一个使用 Kyverno 禁止创建具有 cluster-admin
权限的 RoleBinding 的策略:
apiVersion: kyverno.io/v1 kind: Policy metadata: name: disallow-cluster-admin annotations: policies.kyverno.io/title: Disallow Cluster Admin policies.kyverno.io/category: RBAC policies.kyverno.io/severity: medium policies.kyverno.io/subject: RoleBinding policies.kyverno.io/description: >- Prevents the creation of RoleBindings which grant the cluster-admin ClusterRole to any subject. spec: validationFailureAction: enforce background: true rules: - name: check-cluster-admin match: any: - resources: kinds: - RoleBinding validate: message: >- Assigning the cluster-admin role is not allowed. Refer to internal security guidelines for details. deny: conditions: all: - key: "{{ request.object.roleRef.name }}" operator: Equals value: cluster-admin
这个策略会拦截所有尝试创建将 cluster-admin
角色绑定到任何用户的 RoleBinding 请求,并拒绝该请求。
容器逃逸:限制容器能力是关键
容器逃逸是指攻击者从容器内部突破容器的隔离,获得宿主机的控制权。容器逃逸的危害非常大,攻击者可以利用宿主机的控制权,窃取敏感数据、破坏系统,甚至攻击其他容器。
案例:利用 Docker Socket 逃逸
我曾经遇到过一个案例,攻击者利用一个存在漏洞的 Web 应用,获得了容器的执行权限。然后,攻击者通过挂载宿主机的 Docker Socket,获得了宿主机的控制权。Docker Socket 是 Docker 守护进程的 Unix 域套接字,用于与 Docker 守护进程进行通信。如果容器可以访问 Docker Socket,就可以执行 Docker 命令,从而控制宿主机。
如何防止容器逃逸?
限制容器能力: 使用 Kubernetes 的 SecurityContext 对象来限制容器的能力。可以禁止容器执行特权操作、挂载敏感目录等。例如,可以设置
allowPrivilegeEscalation: false
来禁止容器提升权限,设置readOnlyRootFilesystem: true
来将容器的根文件系统设置为只读。使用 AppArmor 或 SELinux: 使用 AppArmor 或 SELinux 来限制容器的系统调用。AppArmor 和 SELinux 是 Linux 内核的安全模块,可以限制进程的系统调用,从而防止容器执行恶意操作。可以使用 Kubernetes 的
container.apparmor.security.beta.kubernetes.io
注解或container.security.alpha.kubernetes.io/seccomp профиль
注解来配置 AppArmor 或 SELinux。定期扫描容器镜像: 定期扫描容器镜像,发现潜在的安全漏洞。可以使用 Aqua Security、Trivy 等工具来扫描容器镜像,并及时修复发现的漏洞。
使用 Kubernetes Pod Security Admission: 使用 Kubernetes Pod Security Admission 来强制执行 Pod 安全策略。Pod Security Admission 是 Kubernetes 的一个内置特性,可以根据预定义的策略,限制 Pod 的配置。可以使用 Pod Security Admission 来禁止创建具有特权权限的 Pod,或者限制 Pod 的能力。
示例:使用 Pod Security Admission 限制 Pod 权限
以下是一个使用 Pod Security Admission 限制 Pod 权限的示例:
apiVersion: v1 kind: Namespace metadata: name: restricted-namespace labels: pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/warn: restricted
这个配置会将 restricted-namespace
命名空间的 Pod 安全级别设置为 restricted
。restricted
级别是最严格的 Pod 安全级别,会禁止创建具有特权权限的 Pod,或者限制 Pod 的能力。
恶意镜像:镜像安全扫描不可或缺
容器镜像的安全问题日益突出,恶意镜像可能会包含病毒、木马、后门等恶意代码,一旦被部署到 Kubernetes 集群中,就会对整个集群造成威胁。
案例:Docker Hub 上的恶意镜像
我曾经在 Docker Hub 上发现过一些恶意镜像,这些镜像伪装成流行的软件,例如 Nginx、Redis 等,但实际上却包含了恶意代码。如果用户不小心下载并使用了这些镜像,就可能会被植入木马,导致数据泄露或系统被控制。
如何防范恶意镜像?
使用可信的镜像仓库: 尽量使用官方的镜像仓库,例如 Docker Hub 官方镜像、Google Container Registry 等。这些镜像仓库通常会对镜像进行安全扫描,并及时修复发现的漏洞。
验证镜像签名: 使用 Docker Content Trust 来验证镜像的签名。Docker Content Trust 可以确保镜像的完整性和来源,防止恶意用户篡改镜像。
定期扫描镜像: 定期扫描容器镜像,发现潜在的安全漏洞。可以使用 Aqua Security、Trivy 等工具来扫描容器镜像,并及时修复发现的漏洞。
构建自己的镜像: 尽量自己构建镜像,避免使用未经授权的第三方镜像。在构建镜像时,要遵循最佳实践,例如使用最小镜像、避免安装不必要的软件等。
使用 Kubernetes ImagePolicyWebhook: 使用 Kubernetes ImagePolicyWebhook 来强制执行镜像安全策略。ImagePolicyWebhook 是 Kubernetes 的一个扩展点,可以在镜像被拉取之前,对镜像进行验证。可以使用 ImagePolicyWebhook 来禁止拉取未经授权的镜像,或者强制拉取具有特定标签的镜像。
示例:使用 ImagePolicyWebhook 强制执行镜像安全策略
以下是一个使用 ImagePolicyWebhook 强制执行镜像安全策略的示例:
配置 ImagePolicyWebhook:
首先,需要配置 Kubernetes 集群的 kube-apiserver,启用 ImagePolicyWebhook。需要在 kube-apiserver 的配置文件中添加以下配置:
admission-control: plugin-names: - ImagePolicyWebhook imagePolicyWebhook: kubeconfig: /etc/kubernetes/imagepolicywebhook/config timeout: 30s 其中,
/etc/kubernetes/imagepolicywebhook/config
是 ImagePolicyWebhook 的配置文件,需要根据实际情况进行修改。实现 ImagePolicyWebhook 服务:
需要实现一个 ImagePolicyWebhook 服务,用于对镜像进行验证。该服务需要实现一个 HTTP endpoint,接收 Kubernetes 集群发送的镜像验证请求,并返回验证结果。验证结果可以是允许拉取镜像,也可以是拒绝拉取镜像。
以下是一个简单的 ImagePolicyWebhook 服务示例:
from flask import Flask, request, jsonify app = Flask(__name__) @app.route("/validate", methods=["POST"]) def validate_image(): request_json = request.get_json() image = request_json["request"]["object"]["spec"]["containers"][0]["image"] # 在这里进行镜像验证 if image.startswith("my-registry.example.com/"): # 允许拉取来自 my-registry.example.com 的镜像 return jsonify({"apiVersion": "admission.k8s.io/v1", "kind": "AdmissionReview", "response": {"uid": request_json["request"]["uid"], "allowed": True}}) else: # 拒绝拉取其他镜像 return jsonify({"apiVersion": "admission.k8s.io/v1", "kind": "AdmissionReview", "response": {"uid": request_json["request"]["uid"], "allowed": False, "status": {"reason": "Image not allowed"}}}) if __name__ == "__main__": app.run(host="0.0.0.0", port=8080) 这个示例服务会验证镜像是否来自
my-registry.example.com
,如果不是,则拒绝拉取镜像。配置 ImagePolicyWebhook 策略:
需要在 Kubernetes 集群中配置 ImagePolicyWebhook 策略,指定使用哪个 ImagePolicyWebhook 服务进行镜像验证。可以使用
kubectl create
命令创建一个MutatingWebhookConfiguration
或ValidatingWebhookConfiguration
对象,指定 ImagePolicyWebhook 服务的地址。
总结:安全是持续的过程
Kubernetes 安全是一个持续的过程,需要不断地学习、实践和改进。我今天分享的只是一些基本的安全措施,还有很多其他的安全技术和方法可以应用到 Kubernetes 集群中。希望我的经验能帮助你更好地保护你的 Kubernetes 集群,让你的应用安全可靠地运行。
最后,我想强调几点:
- 安全意识是第一位的。 只有所有人都意识到安全的重要性,才能真正做好 Kubernetes 安全。
- 自动化安全策略。 使用工具来自动化安全策略的实施,可以减少人为错误,提高安全效率。
- 持续监控和审计。 定期监控和审计 Kubernetes 集群的安全状态,及时发现和解决安全问题。
希望这些经验对你有所帮助!