顾名思义, 多租户就是很多人来租用容器平台的资源来实现自己的应用托管运维需求. 有了资源, 那么谁来管理运维分配使用这些资源? 多租户很重要的一点是资源的安全隔离. 即便是专用容器, 也需要考虑相应的安全和业务隔离需求.
从多租户的角度考虑, 租户租用容器云平台的资源来托管, 开发, 部署运维自己的应用, 服务. 容器云平台需要提供, 维护保障租户能正常使用这些资源, 同时给租户托管的应用提供服务注册, 服务发现, 服务配置, 日志, 监控, 预警告警, 弹性伸缩, 负载均衡, 安全等能力. 我们要明白的是租户只是租用这些能力, 他们并不负责维护.
那么谁来管理运维分配使用这些资源? 那么容器云中什么是资源? 资源该由谁来管理? 如何分配? 谁来运维这些资源? 谁来使用这些资源? 这也是我写本篇文章的目的, 本文包含了我对一般多租户安全容器协调器的详细安全考虑. 我会通过具体示例来讲解如何在隔离状态下, 安全的运行第三方代码, 详细介绍请点此.
测试环境的配置
1. 用于运行 Docker 镜像的 API, 使每个进程完全与其他进程隔离;
2. 滥用行为可以立即终止;
3. 代理应该是可自动更新的, 以便在出现安全问题时处理它们;
4. 能够将整个 syscall 接口用于正在运行的进程;
配置性能要求
1. 禁止并删除任何挖矿工具所使用的基础设施及追踪器;
2. 防火墙可以关闭任何现有网络端点;
3. 防火墙可以将运行该进程的容器与它相关联的所有本地链接和任何可访问的内部 IP 隔离开来;
4. 如果一层多租户容器间安全隔离受到破坏, 则另一层隔离需要马上跟上. 如果两层安全隔离同时受到破坏, 那么还会有隔离机制用于保护;
5. 主机操作系统要是安全的;
测试过程
我们要求每个容器按照如下条件运行:
1.Block/io cgroups, 以便磁盘没有噪声干扰. Cgroups 是 control groups 的缩写, 是 Linux 内核提供的一种可以限制, 记录, 隔离进程组 (process groups) 所使用的物理资源 (如: CPU,memory,IO 等等) 的机制. 最初由 google 的工程师提出, 后来被整合进 Linux 内核.
2.CPU 限制;
3. 内存限制;
4. 网络或带宽限制;
5. 有一个与测试主机的其他网络相隔离的网络(bpf 或 iptables);
主机操作系统
主机操作系统应该是一个简化的操作系统, 具备最简单的功能即可, 即尽可能与容器内使用的操作系统共享许多功能. 这是为了将主机环境中的运行漏洞降到最低, 减少攻击面.
这些操作系统的示例包括:
1. 配备 CoreOS 的 Container Linux ;
2. Container Optimized OS;
3.Intel Clear Linux, 英特尔推出 Clear Linux 项目的目标是让用户可以充分利用虚拟机的隔离技术以及容器的部署优势;
4.LinuxKit, linuxkit 这个工具可以理解为是用多个 docker 镜像来组成一个最小化, 定制化的操作系统, 定制化后的系统只有几十兆;
主机操作系统的特征
CoreOS Container Linux 和 Container Optimized OS 都具有以下功能:
1. 验证启动;
2. 只读或 usr:
2.1Container Optimized OS 会将根文件系统 (/) 挂载为只读, 并将其某些部分重新挂载为可写;
2.2/tmp, /run, /media, /mnt/disks 和 /var/lib/cloud 都是使用 tmpfs 挂载的, 虽然它们是可写的, 但它们的内容在重新启动之后是不会保留的;
2.3 目录 / mnt/stateful/partition, /var 和 / home 是从有状态的磁盘分区挂载的, 这意味着这些位置可用于存储在重新引导后持续存在的数据. 例如, Docker 的工作目录 / var / lib / docker 在重新启动时是有状态的;
2.4 在可写位置中, 只有 / var/lib/docker 和 / var/lib/cloud 被挂载为 "可执行", 即没有 noexec 挂载标志;
2.5CoreOS Container Linux 的根文件系统 (/) 挂载为 read_write, 而 / usr 是只读的;
3. 所有操作系统都允许无缝升级以解决安全问题;
容器运行
容器运行时应该是一个管理程序, 以确保 Linux 容器的用户配置不会降低集群的安全性.
如果要允许使用整个系统调用接口, Firecracker 似乎是最合适的. Firecracker 是一种专门用于创建和管理多租户容器和基于函数的服务的虚拟化技术, 使用 Rust 开发, 旨在加快 AWS Lambda 和 AWS Fargate 等服务的速度和效率.
网络要求
默认情况下, 网络应该被锁定, 拒绝所有入口和出口策略. 这将创建一种安全形式, 确保网络环境的绝对安全.
这可以通过 iptables 或直接使用 BPF 来实现.
DNS
不允许任何 inter-cluster DNS, 在主节点和系统节点上没有调度: 确保集群中的主节点和系统节点不能被调度, 这允许将系统进程的重点转移到其他地方.
调度程序
调度程序不应该对 bin 文件进行打包, 在许多使用临时工作载荷的场景中, 当前几个节点耗尽而所有其他节点都没有被使用时, 会出现这种情况. 因为工作载荷不断地完成释放前几个节点上的资源(在批处理作业的情况下).
Kube-batch 目前是 Kubernetes SIGs 旗下的一个孵化项目, 是一个运行在 Kubernetes 上面向机器学习 / 大数据 /HPC 的批调度器(batch scheduler), 它支持以 Pod Group 为单位进行资源调度, 并支持 preempt 和 priority. 对于暂时无法满足资源条件的 Pod, 在 Kubernetes 中会处于 pending 状态, 直到资源释放从而继续执行. Kube-batch 是基于 IBM 多年的 HPC 集群经验构建的, 它更适合批处理作业, 因此如果我们打算长期应用此程序, 就需要对其进行修改.
如果我们在裸机上运行, 我们需要考虑电源管理, BIOS 更新, 硬件故障等等.
资源约束
使用 cgroup 管理资源并设置限制:
1. 磁盘 IO;
2. 网络带宽;
3. 内存;
4.CPU;
避免被挖矿
1. 带有 eBPF 的 CPU 跟踪器会监控 CPU 使用率, 因此如果它没有波动, 则它可能是一个挖矿工具;
2. 二进制跟踪器负责查找具有特定名称的二进制文件或进程;
3. 网络跟踪器负责寻找与已知挖矿工具端点相关的进程;
为什么不用 kubernetes?
kubernetes, 简称 K8s, 是用 8 代替 8 个字符 "ubernete" 而成的缩写. 是一个开源的, 用于管理云平台中多个主机上的容器化的应用, Kubernetes 的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes 提供了应用部署, 规划, 更新, 维护的一种机制.
由于我不希望任何允许任意代码执行的容器只有一层安全保护, 所以我认为 kubernetes 很难满足这个要求.
Kubernetes 的 etcd 集群之间没有隔离, 而且 kubelet 与 apiserver 的通信也不能被隔离. Etcd 是 Kubernetes 集群中的一个十分重要的组件, 用于保存集群所有的网络配置和对象的状态信息.
总而言之, Kubernetes 太复杂了, 有太多的第三方驱动程序. 攻击面太大, 我们不需要其中的大部分 (90%) 功能设置.
默认情况下, Kubernetes 将为每个节点安排最多 110 个 pod. 这是你可以修改的方面, 但同样重要的是要注意 kubernetes 中的默认调度程序是无法识别资源的, 我们必须对其进行修复. 具体的请参阅上面的 "调度程序" 那一节, 由于默认调度程序的逻辑, 集群中的前几个节点会破坏.
甚至谷歌内部也不使用 Kubernetes 来调度虚拟机, Kubernetes 在容器中插入了一些额外的 env 变量, 我们也需要处理这些变量.
如果存在影响隔离的内核零日漏洞, 我们该怎么办?
首先, 更新内核, 但如果内核更新不了, 我们可以使用 ebpf 捕获易受攻击的内核函数, 并删除任何试图利用漏洞的容器.
假设我们已经有了可以持续构建内核和应用补丁的系统, 则可以考虑威胁模型. 大多数情况下, 有人会攻击我们的基础架构, 因此我们应该确保所有这些服务器在网络上与其余堆栈隔离.
另外一个威胁是我们正在运行的用户名和密码在打开容器之后, 黑客会通过 VM 截取它们. 一般来说, 容器运行错误时就会发生这种情况.
来源: http://netsecurity.51cto.com/art/201903/593776.htm