容器技术与安全
1. 容器概述
-
定义
容器是 轻量级的操作系统虚拟化技术 可以让应用运行在一个资源隔离的环境中,容器共享宿主机的内核 但是提供用户空间隔离
-
特点
- 资源共享:容器之间共享同一个系统内核,同一个库文件可被多个容器使用
- 逻辑独立:每个容器包含一个独享的完整用户环境空间,不会影响其他容器
- 复用:当需要配置大量具有相同配置的操作系统时,应用程序运行所必需的组件打包成一个镜像可以复用
-
容器与虚拟机有相似的作用,都摆脱了对物理硬件的需求 允许我们更为高效地使用计算资源
从而提升能源效率与成本效益 -
虚拟机环境的特点
-
资源统一分配
虚拟机会将虚拟硬件 、 内核以及用户空间打包在新虚拟机当中,利用 Hypervisor 统一控制所有虚拟机 -
环境独立
每台虚拟机都能够获得唯一的操作系统和负载应用程序
-
隔离能力强
虚拟机先虚拟一个物理环境,然后构建一个完整的操作系统,再搭建一层 Runtime 供应用程序运行
-
-
容器环境的特点
- 不需要安装主机操作系统直接将容器层安装在主机操作系统之上 。
- 容器可以看成一个装好了一组特定应用的虚拟机,它直接利用宿主机的内核抽象层比虚拟机更少,更加轻量化,启动速度极快 。
- 相比虚拟机,实例化规模更小,单个物理机能够承载更多的容器,拥有更高的资源使用效率 。
- 容器易于迁移,但是只能被迁移到具有兼容操作系统内核的其他服务器当中
- 每个容器化应用都会共享相同的操作系统,但每套容器都拥有自己的隔离化用户空间
- 敏捷环境:容器技术最大的优点是创建容器实例比创建虚拟机示例快得多
容器轻量级的脚本可以从性能和大小方面减少开销 。 - 提高生产力:容器通过移除跨服务依赖和冲突提高了开发者的生产力 。 每
个容器都可以看作是一个不同的微服务 可以独立升级 。 - 安全:容器之间的进程是相互隔离的 其中的基础设施亦是如此 。 这样其
中一个容器的升级或者变化不会影响其他容器 - 不能适用所有场景 :一些应用程序并不适合运行在容器当中 。难以解决依赖关系 容器运行在物理操作系统之上 相互之间共享底层的操作系统内核 、 库文件以及二进制文件 这可能会限其可移植性 。
- 较差的隔离性: 共享同一个系统内核以及其他组件 在开始运行之前就已经获得了统一的底层授权 攻击可能进入到底层操作系统或者其它容器
- 复杂性增加 :随着容器及应用数量的增加 管理如此之多的容器是一个极具挑战性的任务 可以使用 Kubernetes 和 Mesos 等工具管理 。
-
Docker容器技术
- 如果只是希望将应用运行的实例进行隔离 容器对于管理应用运行环境 、 启动应用实例以及控制资源开销方面是一个极为高效的工具 。 容器之间共享同一个系统内核 内存的使用效率会得到提升
-
对比
容器 虚拟机 启动应用 启动Guest OS和应用程序 部署的是容器镜像:镜像很小,一般是M级别 部署的是虚拟机镜像:镜像很大,一般是G级别 性能方面,与VM 相比,容器表现更加出色,并且几乎可以秒启动。 启动操作系统以及初始化托管应用会花费几分钟的时间 容器具有Host OS的root权限 Guest OS运行在非根模式 可用性根据业务本身保证 可用性技术已成熟,如快照、克隆、动态迁移、异地双活 -
容器和虚拟机之间的主要区别在于虚拟化层的位置和操作系统资源的使用方式
2. Cgroups
-
定义
Control groups (cgroups) 是 Linux 内核提供的一种可以限制 、记录 、隔离进程组 process groups 所使用物理资源的机制 -
应用:Cgroups 是容器实现虚拟化所使用的资源管理手段,没有 cgroups 就没有容器
-
功能
-
限制进程组可以使用的资源数量
Memory子系统可以为进程组设定内存使用上限 -
进程组的优先级控制
可以使用cpu子系统为某个进程组分配特定cpu share
-
记录进程组使用的资源数量
可以使用cpuacct子系统记录某个进程组使用的cpu时间
-
进程组隔离
使用ns子系统使不同的进程组使用不同的namespace,以达到隔离的目的
-
进程组控制
使用freezer子系统可以将进程组挂起和恢复
-
-
cgroups的概念
- task(任务):指系统中的一个进程
- cgroups(控制族群):按一定标准划分的进程组,是资源分配和控制的单位
- hierarchy(层级):由不同控制族群形成的树状控制层次
- subsytem(子系统):主系统中某部分资源的控制器
-
控制机制
- 每次在系统中构建新层级时 系统中的所有任务都是那个层级的的默认cgroup (root cgroup 即树根 的初始化成员
- cgroup 在创建层级时自动创建 后续在该层创建的 cgroup 都是 root cgroup 的子树
- 一个子系统最多只能附加到一个层级
- 一个层级可以附加多个子系统
- 一个任务可以是多个 cgroup 的成员 但这些 cgroup 须在不同的层级
- 系统中的进程在创建子进程时 该子进程自动成为其父进程所在的 cgroup 成员
-
子系统分类
-
cpu 子系统
使用调度程序提供对 cgroup 中任务 CPU 使用率的限制 即 控制 cgroup 中所有进程,可以使用的 cpu 时间片
-
cpuset 子系统
为 cgroups 中的任务分配单独的 cpu 核心和内存节点
-
cpuacct 子系统
自动统计 cgroup 中任务的 cpu 使用报告
-
memory 子系统
设定 cgroup 中任务的内存使用限制 并自动生成任务所使用的内存资源报告
-
blkio 子系统
为块设备设定输入 输出限制 如 物理设备 磁盘 固态硬盘 USB 等 控
制并监控 cgroup 中的任务对块设备的 I/O 访问 -
devices 子系统
控制任务能够访问的设备资源 允许或者拒绝 cgroup 中的进程访问设备 。 -
freezer 子系统
挂起或者恢复 cgroup 中的进程 -
ns 子系统
使 cgroup 中的任务使用不同的 namespace -
net_cls 子系统
标记 cgroup 中进程的网络数据包 通过 traffic control 对数据包进行控制
-
Namespace
-
定义
Linux Namespace 是 Linux 提供的一种内核级别的环境隔离方法,在容器中用于进程组隔离
-
作用
实现进程隔离,即同一个 namespace 下的进程可以感知彼此的变化而对外界的进程一无所知 -
Namespace的特点
- Namespace 是 Linux chroot 的扩展,提供了对 UTS 、 IPC 、 Mount 、 PID 、 Network 、 User等的隔离 。Chroot 可使得内部的文件系统无法访问外部的内容
- 不同的进程组使用不同的 namespace
- 每个 namespace 里面的资源对其它 namespace 透明
- namespace 展现了系统的不同视图并可以组织为层次结构
- 创建 namespace 时 只需要指定相应的 flag 即可
-
相关概念
- UTS namespace
主机命名空间 独立出主机名和网络信息服务 - FS ( namespace)
挂载命名空间 进程运行时可以将挂载点与系统分离 使用这个功能时 可以达到 chroot 的功能 而在安全性方面比 chroot 更高 - PID namespace
进程命名空间 空间内的 PID 是独立分配 命名空间内的 PID 映射到命名空间外时会使用另外一个 PID - IPC namespace
进程间通信IPC的命名空间 可以将 SystemV 的 IPC 和 POSIX 的消息队列独立出来 - Network namespace
网络命名空间 用于隔离网络资源 ((/proc/net 、 IP 地址 、 网卡 、 路由等) 后台进程可以运行在不同命名空间内的相同端口上 - User namespace
用户命名空间 用户 ID 和组 ID 在命名空间内外是不一样 在不同命名空间内可以存在相同的 ID,或将本地的虚拟 user id 映射到真实的 user id
- UTS namespace
3. 容器安全
- 容器安全增强
- SELinux限制进程访问资源
- 使用quota等技术限制容器磁盘使用量
- 使用Traffic Controller技术对容器的流量进行控制
- 基于内核的容器安全技术
- Cgroups 资源限制
容器本质是是进程 cgroups 应用在容器是为了限制宿主机不同容器的资源使用量,避免单个容器好近宿主机资源而导致其它容器异常 - Namespaces 资源隔离
—为了使容器处于独立环境中 Docker 使用 namespaces 技术隔离容器,使容器与容器之间,容器与宿主机之间相互隔离
—容器目前只对 uts 、 ipc 、 pid 、 network 、 mount 这 5 种 namespace 进行完全
隔离 user namespace 并为全部支持 。 除了上述资源之外 还有很多系统资源未被隔离 如 proc 、 /sys 信息 、 SELinux 、 time 、 syslog 和 dev 设备等均
- Cgroups 资源限制