使用Kubespray进行集群加固(保护Kubespray的安全性!)
首先
在kubespray.io这个看起来像是官方文档页面的网站上,为什么还没有指向相关页面的链接呢(难道还在测试中?)?但是,从Kubespray的Github页面上可以看到,从2022年5月30日起,Kubespray已经添加了一个名为”Cluster Hardening”的页面,用于在CIS Benchmarks方面通过Kubespray进行部署时的配置。这次的目的是介绍这个页面并分享一些小技巧。根据我的观察范围,我没有找到日语解释相关内容的文章…
以下是相关链接:
https://kubespray.io/#/docs/hardening
https://github.com/kubernetes-sigs/kubespray/blob/master/docs/hardening.md
Kubespray到底是什么?
作为创建非托管Kubernetes环境的一种方法之一,它是通过ansible-playbook来进行构建的(参考:Ansible Playbook 是什么)。
它可以用于云环境中准备的虚拟机,也可以用于为家庭Kubernetes群体准备的本地实体机器或虚拟机。
有关ansible的说明和Kubespray本身,请参考先前文章的相关内容。
讲解
暂时的,以下内容是关于“集群加固(Cluster Hardening)”的(截至2022/12/17)。
Kubespray提供了“集群加固”设置集,用于增强安全性。
通过在调用playbook时,使用加固设置覆盖默认配置,以应用这些设置,因此可能需要根据个人环境进行一些微小的更改。
该设置包括启用RBAC和审计、加密密码等,通过仅仅研究相关术语,您将了解Kubernetes中的安全性,并得到一个良好的起点。
硬化.yaml:
# Hardening
---
## kube-apiserver
authorization_modes: ['Node', 'RBAC']
# AppArmor-based OS
# kube_apiserver_feature_gates: ['AppArmor=true']
kube_apiserver_request_timeout: 120s
kube_apiserver_service_account_lookup: true
# enable kubernetes audit
kubernetes_audit: true
audit_log_path: "/var/log/kube-apiserver-log.json"
audit_log_maxage: 30
audit_log_maxbackups: 10
audit_log_maxsize: 100
tls_min_version: VersionTLS12
tls_cipher_suites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
# enable encryption at rest
kube_encrypt_secret_data: true
kube_encryption_resources: [secrets]
kube_encryption_algorithm: "secretbox"
kube_apiserver_enable_admission_plugins:
- EventRateLimit
- AlwaysPullImages
- ServiceAccount
- NamespaceLifecycle
- NodeRestriction
- LimitRanger
- ResourceQuota
- MutatingAdmissionWebhook
- ValidatingAdmissionWebhook
- PodNodeSelector
- PodSecurity
kube_apiserver_admission_control_config_file: true
# EventRateLimit plugin configuration
kube_apiserver_admission_event_rate_limits:
limit_1:
type: Namespace
qps: 50
burst: 100
cache_size: 2000
limit_2:
type: User
qps: 50
burst: 100
kube_profiling: false
## kube-controller-manager
kube_controller_manager_bind_address: 127.0.0.1
kube_controller_terminated_pod_gc_threshold: 50
# AppArmor-based OS
# kube_controller_feature_gates: ["RotateKubeletServerCertificate=true", "AppArmor=true"]
kube_controller_feature_gates: ["RotateKubeletServerCertificate=true"]
## kube-scheduler
kube_scheduler_bind_address: 127.0.0.1
kube_kubeadm_scheduler_extra_args:
profiling: false
# AppArmor-based OS
# kube_scheduler_feature_gates: ["AppArmor=true"]
## etcd
etcd_deployment_type: kubeadm
## kubelet
kubelet_authentication_token_webhook: true
kube_read_only_port: 0
kubelet_rotate_server_certificates: true
kubelet_protect_kernel_defaults: true
kubelet_event_record_qps: 1
kubelet_rotate_certificates: true
kubelet_streaming_connection_idle_timeout: "5m"
kubelet_make_iptables_util_chains: true
kubelet_feature_gates: ["RotateKubeletServerCertificate=true", "SeccompDefault=true"]
kubelet_seccomp_default: true
kubelet_systemd_hardening: true
# In case you have multiple interfaces in your
# control plane nodes and you want to specify the right
# IP addresses, kubelet_secure_addresses allows you
# to specify the IP from which the kubelet
# will receive the packets.
kubelet_secure_addresses: "192.168.10.110 192.168.10.111 192.168.10.112"
# additional configurations
kube_owner: root
kube_cert_group: root
# create a default Pod Security Configuration and deny running of insecure pods
# kube_system namespace is exempted by default
kube_pod_security_use_default: true
kube_pod_security_default_enforce: restricted
适用命令示例:
ansible-playbook -v cluster.yml \
-i inventory.ini \
-b --become-user=root \
--private-key ~/.ssh/id_ecdsa \
-e "@vars.yaml" \
-e "@hardening.yaml"
关于一些小技巧(如在进行“集群硬化”并在Kubernetes上托管“Prometheus”等时的注意事项)。
如上所述,进行”集群加固”将确保最低限度的安全性,并且我建议您考虑这个选项,但需要注意的是:由于配置重点放在提升安全性上,所以一些应用程序可能无法正常工作。例如,Prometheus在配置上与kubelet进行通信以进行抓取,但直接应用上述配置将导致被防火墙阻止而无法运行。为了应对这个情况,我将介绍需要进行修正的位置。
kube-controller-manager的绑定配置
# kube_controller_manager_bind_address: 127.0.0.1
kube_controller_manager_bind_address: 0.0.0.0 # 127.0.0.1の場合、prometheusからのscrapeに失敗するので、変更します。その代わりに別途FWやNetworkPolicy等で保護する必要があるので注意。
kube-scheduler的绑定配置
# kube_scheduler_bind_address: 127.0.0.1
kube_scheduler_bind_address: 0.0.0.0 # 127.0.0.1の場合、prometheusからのscrapeに失敗するので、変更します。その代わりに別途FWやNetworkPolicy等で保護する必要があるので注意。
etcd的绑定配置
如果不添加下面的设置,将会绑定到127.0.0.1(可能为localhost),导致从prometheus进行抓取失败,因此需要进行更改。请注意,需要通过其他方式如防火墙或网络策略来保护。
etcd_extra_vars:
listen-metrics-urls: http://0.0.0.0:2381
关于kubelet的防火墙。
kubelet_secure_addresses是使用systemd和iptables的协作功能,根据连接源IP地址限制可以连接kubelet的应用程序的配置。
如果只需要控制平面连接每个工作节点的kubelet,可以选择不设置并注释掉,kubespray会自动为控制平面设置IP地址。
只有在允许来自控制平面以外的IP地址进行通信时才需要进行设置。
但是,如果在Kubernetes集群内自托管Prometheus时,需要允许Prometheus的Pod与kubelet进行通信,因此需要进行额外的配置以允许此通信。
在kubespray设置阶段,无法预测将分配给Prometheus的Pod的IP地址,因此需要一次性设置用于分配给Pod的CIDR。但仅有这一项配置会降低安全性,因此请注意需要通过其他防火墙或NetworkPolicy进行保护。
在我的情况下,我使用Cilium作为CNI,通过使用CiliumClusterwideNetworkPolicy和NodeSelector的主机策略来进行通信控制(实体等非常方便),除了”集群加固”之外。
kubelet_secure_addresses: "[control-plane1のIP] [control-plane2のIP] [control-plane3のIP] [PodのCIDR]"
总结
我在Kubespray的Kubernetes环境部署中介绍了有关安全性的内容。特别是有关bind和FW设置的提示,如果直接应用”Cluster Hardening”可能会遇到问题,希望能对某些人有所帮助。另外,如果我心情好的话,我也许会解释一下本次同时设置的”CiliumClusterwideNetworkPolicy”的内容。如果有兴趣的人,请不要抱太大期待,耐心等待一下。