Skip to content

Files

Latest commit

0279954 · Dec 27, 2021

History

History
262 lines (188 loc) · 22.6 KB

File metadata and controls

262 lines (188 loc) · 22.6 KB

六、保护集群组件

在前面的章节中,我们研究了 Kubernetes 集群的架构。Kubernetes 集群由主组件(包括kube-apiserveretcdkube-scheduler、CoreDNS、kube-controller-managercloud-controller-manager)和节点组件(包括kubeletkube-proxycontainer-runtime组成。主组件负责集群管理。它们构成了集群的控制平面。另一方面,节点组件负责节点上的容器和容器的功能。

第 3 章威胁建模中,我们简要讨论了 Kubernetes 集群中的组件需要进行配置以确保集群的安全性。任何集群组件的泄露都可能导致数据泄露。环境配置不当是传统或微服务环境中数据泄露的主要原因之一。了解每个组件的配置以及每个设置如何打开新的攻击面非常重要。因此,集群管理员了解不同的配置非常重要。

在本章中,我们将详细介绍如何保护集群中的每个组件。在许多情况下,不可能遵循所有的安全最佳实践,但是如果攻击者试图利用易受攻击的配置,突出风险并制定缓解策略是很重要的。

对于每个主组件和节点组件,我们简要讨论 Kubernetes 集群中具有安全相关配置的组件的功能,并详细查看每个配置。我们查看这些配置的可能设置,并强调推荐的做法。最后,我们介绍kube-bench并介绍如何使用它来评估集群的安全状况。

在本章中,我们将涵盖以下主题:

  • 保护 kube-apiserver
  • 保护 kubelet
  • 固定 etcd
  • 保护 kube 调度程序
  • 保护 kube-控制器-管理器
  • 保护 coreens
  • 对集群的安全配置进行基准测试

保护 kube-apiserver

kube-apiserver是你集群的入口。它实现了一个表示状态转移 ( REST ) 应用编程接口 ( API )来授权和验证对对象的请求。它是在 Kubernetes 集群内通信和管理其他组件的中央网关。它执行三个主要功能:

  • API 管理 : kube-apiserver公开用于集群管理的 API。开发者和集群管理员使用这些 API 来修改集群的状态。
  • 请求处理:对对象管理和集群管理的请求进行验证和处理。
  • 内部消息传递:API 服务器与集群中的其他组件进行交互,确保集群正常运行。

对应用编程接口服务器的请求在处理前要经过以下步骤:

  1. 认证 : kube-apiserver首先验证请求的来源。kube-apiserver支持多种认证模式,包括客户端证书、承载令牌、超文本传输协议 ( HTTP )认证。
  2. 授权:一旦验证了起源的身份,API 服务器验证允许起源执行请求。kube-apiserver默认支持基于属性的访问控制 ( ABAC )、基于角色的访问控制 ( RBAC )、节点授权、网络钩子进行授权。RBAC 是推荐的授权方式。
  3. 准入控制器:一旦kube-apiserver认证并授权该请求,准入控制器解析该请求,以检查集群内是否允许该请求。如果该请求被任何接纳控制器拒绝,则该请求被丢弃。

kube-apiserver是集群的大脑。API 服务器的泄露会导致集群泄露,因此 API 服务器的安全至关重要。Kubernetes 提供了无数的设置来配置 API 服务器。接下来让我们看看一些与安全相关的配置。

要保护应用编程接口服务器,您应该执行以下操作:

  • 禁用匿名认证:使用anonymous-auth=false标志将匿名认证设置为false。这确保了被所有身份验证模块拒绝的请求不会被视为匿名请求而被丢弃。
  • 禁用基础认证:基础认证在kube-apiserver中为了方便支持,不宜使用。基本身份验证密码无限期保留。kube-apiserver使用--basic-auth-file参数启用基本身份验证。请确保不使用此参数。
  • 禁用令牌身份验证 : --token-auth-file为您的集群启用基于令牌的身份验证。不建议使用基于令牌的身份验证。静态令牌永远存在,需要重启应用编程接口服务器才能更新。客户端证书应该用于身份验证。
  • 使用 HTTPS 确保与库贝莱的连接:默认情况下,--kubelet-https设置为true。确保该参数没有设置为kube-apiserverfalse
  • 禁用分析:使用--profiling启用分析会暴露不必要的系统和程序细节。除非您遇到性能问题,否则通过设置--profiling=false禁用性能分析。
  • 禁用 alwaysacclave:--enable-admission-plugins可用于启用默认未启用的准入控制插件。AlwaysAdmit接受请求。确保插件不在--enabled-admission-plugins列表中。
  • 使用 AlwaysPullImages :准入控制确保节点上的映像在没有正确凭证的情况下无法使用。这可以防止恶意 pods 为节点上已经存在的映像创建容器。
  • 使用安全上下文拒绝:如果PodSecurityPolicy未启用,应使用该准入控制器。SecurityContextDeny确保 Pod 不能修改SecurityContext升级权限。
  • 启用审核:审核默认在kube-apiserver中启用。确保--audit-log-path设置为安全位置的文件。此外,确保审核的maxagemaxsizemaxbackup参数设置符合合规性预期。
  • 禁用 AlwaysAllow 授权:授权模式确保来自拥有正确权限的用户的请求被 API 服务器解析。不要将AlwaysAllow--authorization-mode一起使用。
  • 启用 RBAC 授权 : RBAC 是 API 服务器推荐的授权模式。ABAC 很难使用和管理。RBAC 角色和角色绑定的易用性和易更新性使 RBAC 适合经常扩展的环境。
  • 确保对 kubelet 的请求使用有效证书:默认情况下,kube-apiserverkubelet的请求使用 HTTPS。启用--kubelet-certificate-authority--kubelet-client-key--kubelet-client-key可确保通信使用有效的 HTTPS 证书。
  • 启用服务账户查找:除了确保服务账户令牌有效,kube-apiserver还应验证令牌存在于etcd中。确保--service-account-lookup未设置为false
  • 启用 PodSecurityPolicy 策略 : --enable-admission-plugins可用于启用PodSecurityPolicy。正如我们在第 5 章中看到的,配置 Kubernetes 安全边界PodSecurityPolicy用于定义 pod 的安全敏感标准。我们将在 第 8 章中深入探讨如何创建 pod 安全策略来保护 Kubernetes pod ** 使用服务帐户密钥文件:使用--service-account-key-file可以旋转服务帐户的密钥。如果未指定,则kube-apiserver使用来自传输层安全性 ( TLS )证书的私钥来签署服务帐户令牌。* 启用授权请求 etcd : --etcd-certfile--etcd-keyfile可用于识别对etcd的请求。这确保了任何未识别的请求都可以被etcd拒绝。* 不要禁用服务账户准入控制:该准入控制自动服务账户。启用ServiceAccount确保具有受限权限的自定义ServiceAccount可以用于不同的 Kubernetes 对象。* 不要使用自签名证书请求:如果kube-apiserver启用了 HTTPS,则应提供一个--tls-cert-file和一个--tls-private-key-file,以确保不使用自签名证书。* 到 etcd 的安全连接:设置--etcd-cafile允许kube-apiserver使用证书文件通过安全套接字层 ( SSL )向etcd验证自身。* 使用安全的 TLS 连接:仅将--tls-cipher-suites设置为强密码。--tls-min-version用于设置最低支持的 TLS 版本。TLS 1.2 是推荐的最低版本。* 启用高级审核:将--feature-gates设置为AdvancedAuditing=false可以禁用高级审核。确保该字段存在并设置为true。高级审计有助于在发生违规时进行调查。*

*在 Minikube 上,kube-apiserver配置如下:

$ps aux | grep kube-api
root      4016  6.1 17.2 495148 342896 ?       Ssl  01:03   0:16 kube-apiserver --advertise-address=192.168.99.100 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/var/lib/minikube/certs/ca.crt --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota --enable-bootstrap-token-auth=true --etcd-cafile=/var/lib/minikube/certs/etcd/ca.crt --etcd-certfile=/var/lib/minikube/certs/apiserver-etcd-client.crt --etcd-keyfile=/var/lib/minikube/certs/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/var/lib/minikube/certs/apiserver-kubelet-client.crt --kubelet-client-key=/var/lib/minikube/certs/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/var/lib/minikube/certs/front-proxy-client.crt --proxy-client-key-file=/var/lib/minikube/certs/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=8443 --service-account-key-file=/var/lib/minikube/certs/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/var/lib/minikube/certs/apiserver.crt --tls-private-key-file=/var/lib/minikube/certs/apiserver.key

如您所见,默认情况下,在 Minikube 上,kube-apiserver并没有遵循所有的安全最佳实践。例如:默认不启用PodSecurityPolicy,默认不设置强密码套件和tls最低版本。集群管理员有责任确保应用编程接口服务器配置安全。

保护库布雷

kubelet是 Kubernetes 的节点代理。它管理 Kubernetes 集群内对象的生命周期,确保对象在节点上处于健康状态。

要保护kubelet,您应该执行以下操作:

  • 禁用匿名身份验证:如果启用匿名身份验证,则被其他身份验证方法拒绝的请求将被视为匿名。确保为kubelet的每个实例设置--anonymous-auth=false
  • 设置授权模式:使用配置文件设置kubelet的授权模式。使用--config参数指定配置文件。确保授权模式列表中没有AlwaysAllow
  • 旋转库伯莱证书 : kubelet证书可以使用kubelet配置文件中的RotateCertificates配置进行旋转。这应该与RotateKubeletServerCertificate一起使用,以自动请求服务器证书的轮换。
  • 提供证书颁发机构(CA)捆绑包:CA 捆绑包由kubelet用来验证客户端证书。这可以使用配置文件中的ClientCAFile参数进行设置。
  • 禁用只读端口:默认为kubelet启用只读端口,应该禁用。只读端口没有身份验证或授权。
  • 启用节点限制准入控制器:准入控制器NodeRestriction只允许kubelet修改其绑定到的节点上的节点和 pod 对象。
  • 限制对库布雷应用编程接口的访问:只有kube-apiserver组件与kubelet应用编程接口交互。如果尝试与节点上的kubelet API 通信,则是禁止的。这是通过将 RBAC 用于kubelet来保证的。

在 Minikube 上,kubelet配置如下:

root      4286  2.6  4.6 1345544 92420 ?       Ssl  01:03   0:18 /var/lib/minikube/binaries/v1.17.3/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=docker --fail-swap-on=false --hostname-override=minikube --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.99.100 --pod-manifest-path=/etc/kubernetes/manifests

与应用编程接口服务器类似,并非所有安全配置都默认用于kubelet—例如,禁用只读端口。接下来,我们将讨论集群管理员如何保护etcd

固定 etcd

etcd是 Kubernetes 用于数据存储的键值存储。它存储 Kubernetes 集群的状态、配置和机密。只有kube-apiserver可以访问etcdetcd的妥协会导致集群妥协。

要保护etcd,您应该执行以下操作:

  • 限制节点访问:使用 Linux 防火墙,确保只允许需要访问etcd的节点访问。
  • 确保 API 服务器使用 TLS:--cert-file``--key-file确保对etcd的请求是安全的。
  • 使用有效证书 : --client-cert-auth确保来自客户端的通信是使用有效证书进行的,将--auto-tls设置为false确保不使用自签名证书。
  • 静态加密数据 : --encryption-provider-config传递给 API 服务器,确保数据在etcd中静态加密。

在 Minikube 上,etcd配置如下:

$ ps aux | grep etcd
root      3992  1.9  2.4 10612080 48680 ?      Ssl  01:03   0:18 etcd --advertise-client-urls=https://192.168.99.100:2379 --cert-file=/var/lib/minikube/certs/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/minikube/etcd --initial-advertise-peer-urls=https://192.168.99.100:2380 --initial-cluster=minikube=https://192.168.99.100:2380 --key-file=/var/lib/minikube/certs/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.99.100:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.99.100:2380 --name=minikube --peer-cert-file=/var/lib/minikube/certs/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/var/lib/minikube/certs/etcd/peer.key --peer-trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt --snapshot-count=10000 --trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt

etcd存储 Kubernetes 集群的敏感数据,如私钥和机密。etcd的妥协是api-server成分的妥协。集群管理员在设置etcd时要特别注意。

保护 kube 调度程序

接下来,我们来看看kube-scheduler。正如我们在 第 1 章中已经讨论过的,Kubernetes 架构kube-scheduler负责将一个节点分配给一个 pod。一旦 Pod 被分配给一个节点,kubelet执行 Pod 。kube-scheduler首先对 pod 可以运行的节点集进行过滤,然后根据每个节点的评分,将 pod 分配给过滤后得分最高的节点。kube-scheduler组件的折衷会影响集群中 Pod 的性能和可用性。

要保护kube-scheduler,您应该执行以下操作:

  • 禁用剖析:剖析kube-scheduler暴露系统细节。将--profiling设置为false会减少的攻击面。
  • 禁用与 kube-scheduler 的外部连接:应禁用kube-scheduler的外部连接。AllowExtTrafficLocalEndpoints设置为true,启用与kube-scheduler的外部连接。确保使用--feature-gates禁用该功能。
  • 启用设备:默认情况下,kube-scheduler启用AppArmor。确保kube-scheduler没有禁用AppArmor

在 Minikube 上,kube-scheduler配置如下:

$ps aux | grep kube-scheduler
root      3939  0.5  2.0 144308 41640 ?        Ssl  01:03   0:02 kube-scheduler --authentication-kubeconfig=/etc/kubernetes/scheduler.conf --authorization-kubeconfig=/etc/kubernetes/scheduler.conf --bind-address=0.0.0.0 --kubeconfig=/etc/kubernetes/scheduler.conf --leader-elect=true

kube-apiserver类似,调度程序也没有遵循所有的安全最佳实践,例如禁用概要分析。

保护库比-控制器-管理器

kube-controller-manager管理集群的控制回路。它通过应用编程接口服务器监控集群的变化,旨在将集群从当前状态移动到所需状态。默认情况下,kube-controller-manager附带多个控制器管理器,例如复制控制器和名称空间控制器。kube-controller-manager的妥协可能导致对集群的更新被拒绝。

要保护kube-controller-manager,您应该使用- -use-service-account-credentials,当与 RBAC 一起使用时,确保控制回路以最低权限运行。

在 Minikube 上,kube-controller-manager配置如下:

$ps aux | grep kube-controller-manager
root      3927  1.8  4.5 209520 90072 ?        Ssl  01:03   0:11 kube-controller-manager --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf --bind-address=0.0.0.0 --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-signing-cert-file=/var/lib/minikube/certs/ca.crt --cluster-signing-key-file=/var/lib/minikube/certs/ca.key --controllers=*,bootstrapsigner,tokencleaner --kubeconfig=/etc/kubernetes/controller-manager.conf --leader-elect=true --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --root-ca-file=/var/lib/minikube/certs/ca.crt --service-account-private-key-file=/var/lib/minikube/certs/sa.key --use-service-account-credentials=true

接下来,让我们谈谈保护 CoreDNS。

保护核心域名

kube-dns是 Kubernetes 集群的默认域名系统 ( 域名系统)服务器。DNS 服务器帮助内部对象(如服务、容器和容器)相互定位。kube-dns由三个容器组成,详细如下:

  • kube-dns:这个容器使用 SkyDNS 来执行 DNS 解析服务。
  • dnsmasq:轻量级 DNS 解析器。它缓存来自 SkyDNS 的响应。
  • sidecar:监控的运行状况,并处理域名系统的指标报告。

kube-dns从 1.11 版本开始就被取代了,因为 dnsmasq 的安全漏洞和 SkyDNS 的性能问题。CoreDNS 是提供kube-dns所有功能的单一容器。

要编辑 CoreDNS 的配置文件,可以使用kubectl,如下所示:

$ kubectl -n kube-system edit configmap coredns

默认情况下,Minikube 上的 CoreDNS 配置文件如下所示:

# Please edit the object below. Lines beginning with a '#' 
# will be ignored, and an empty file will abort the edit. 
# If an error occurs while saving this file will be
# reopened with the relevant failures.
apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }

要保护 CoreDNS,请执行以下操作:

  • 确保健康插件没有被禁用:health插件监控核心域名系统的状态。它用于确认 CoreDNS 是否已启动并运行。通过在Corefile的待启用插件列表中添加health来启用。

  • 为 CoreDNS 启用 istio:istio是一个服务网格,Kubernetes 使用它来提供服务发现、负载平衡和身份验证。默认情况下,它在 Kubernetes 中不可用,需要作为外部依赖项添加。您可以通过启动istio服务并将istio服务的代理添加到配置文件中来将istio添加到您的集群中,如下所示:

    global:53 {
             errors
             proxy . {cluster IP of this istio-core-dns service}
        }
    

现在我们已经了解了集群组件的不同配置,重要的是要认识到,随着组件变得更加复杂,将会添加更多的配置参数。集群管理员不可能记住这些配置。因此,接下来,我们讨论一种工具,它可以帮助集群管理员监控集群组件的安全状态。

对集群的安全配置进行基准测试

互联网安全中心 ( CIS )发布了 Kubernetes 的基准,集群管理员可以使用该基准来确保集群遵循推荐的安全配置。发布的 Kubernetes 基准测试超过 200 页。

kube-bench是一个用 Go 编写并由 Aqua Security 发布的自动化工具,运行 CIS 基准测试中记录的测试。测试用 YAML 非标记语言 ( YAML )编写,很容易进化。

kube-bench可以直接使用kube-bench二进制在节点上运行,如下所示:

$kube-bench node --benchmark cis-1.4

对于在gkeeksaks上托管的集群,kube-bench作为一个 pod 运行。一旦 pod 完成运行,您可以查看日志以查看结果,如以下代码块所示:

$ kubectl apply -f job-gke.yaml
$ kubectl get pods
NAME               READY   STATUS      RESTARTS   AGE
kube-bench-2plpm   0/1     Completed   0          5m20s
$ kubectl logs kube-bench-2plpm
[INFO] 4 Worker Node Security Configuration
[INFO] 4.1 Worker Node Configuration Files
[WARN] 4.1.1 Ensure that the kubelet service file permissions are set to 644 or more restrictive (Not Scored)
[WARN] 4.1.2 Ensure that the kubelet service file ownership is set to root:root (Not Scored)
[PASS] 4.1.3 Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)
[PASS] 4.1.4 Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)
[WARN] 4.1.5 Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Not Scored)
[WARN] 4.1.6 Ensure that the kubelet.conf file ownership is set to root:root (Not Scored)
[WARN] 4.1.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Not Scored)
......
== Summary ==
0 checks PASS
0 checks FAIL
37 checks WARN
0 checks INFO

调查状态为FAIL的支票非常重要。你的目标应该是零检查失败。如果由于任何原因这是不可能的,您应该为失败的检查制定一个风险缓解计划。

kube-bench是监控遵循安全最佳实践的集群组件的有用工具。建议添加/修改kube-bench规则以适合您的环境。大多数开发人员在启动一个新集群时运行kube-bench,但是定期运行它来监控集群组件是否安全是很重要的。

摘要

在本章中,我们查看了每个主节点和节点组件的不同安全敏感配置:kube-apiserverkube-schedulerkube-controller-managerkubelet、CoreDNS 和etcd。我们学习了如何保护每个组件。默认情况下,组件可能不会遵循所有的安全最佳实践,因此集群管理员有责任确保组件的安全。最后,我们看一下kube-bench,它可以用来了解您运行的集群的安全基线。

理解这些配置并确保组件遵循这些清单以减少妥协的机会非常重要。

在下一章中,我们将研究 Kubernetes 中的身份验证和授权机制。我们在这一章中简要地讨论了一些准入控制者。我们将深入探讨不同的准入控制器,最后讨论如何利用它们来提供更细粒度的访问控制。

问题

  1. 什么是基于令牌的身份验证?
  2. 什么是NodeRestriction入场控制器?
  3. 如何确保数据在etcd静止时加密?
  4. 为什么 CoreDNS 取代了kube-dns
  5. 如何在一个埃拉斯蒂克 Kubernetes 服务 ( EKS )集群上使用kube-bench

进一步阅读

有关本章所涵盖主题的更多信息,您可以参考以下链接: