前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker进阶与实战上

Docker进阶与实战上

作者头像
Jack Chen
发布2021-12-08 14:28:31
3440
发布2021-12-08 14:28:31
举报
文章被收录于专栏:ccylovehs

华为Docker实践小组集大成之作,此文主要是摘录笔记,分为上下两部分,陆续更新,欢迎交流

简介

概念澄清

DockerLXC基础上做了什么工作

LXC含义

  • LXC用户态工具
  • Linux Container内核容器技术简称

通常指第二种,其特性为

  • 跨主机部署
  • 以应用为中心
  • 自动构建
  • 版本管理
  • 组件重用
  • 共享
  • 工具生态链

Docker容器与虚拟机

  • 虚拟机:是用来进行硬件资源划分的完美解决方案,利用硬件虚拟化技术,通过一个hypervisor层来实现对资源的彻底隔离;
  • 容器:是操作系统级别的虚拟化,利用内核的CgroupNamespace特性,通过软件实现虚拟化,仅仅是进程本身就可以与其他进程隔离开,不需要任何辅助

对比虚拟机的总结

特性

容器

虚拟机

启动

秒级

分钟级

硬盘使用

一般为MB

一般为GB

性能

接近原生

弱于

系统支持量

单机支持上千个容器

一般几十个

关于容器技术

容器技术的前世今生

关于容器技术

容器技术主要包括CgroupNamespace

  • Namespace 又称命名空间,主要做访问隔离。其原理是针对一类资源进行抽象,并将其封装在一起提供给一个容器使用,对这类资源每个容器都有自己的抽象并且彼此不可见,所以就可以做到访问隔离。
  • Cgroupcontrol group 的简称,又称为控制组,主要是做资源控制。其原理是将一组进程放在一个控制组里,通过给这个控制组分配指定的可用资源,达到控制这一组进程可用资源的目的。

一分钟理解容器

容器的组成

容器 = cgroup + namespace + rootfs + 容器引擎(用户态工具)

  • Cgroup:资源控制
  • Namespace: 访问隔离
  • rootfs: 文件系统
  • 容器引擎:生命周期控制

容器的创建原理

代码一:

代码语言:javascript
复制
pid = clone(fun, stack, flags, clone_arg);
(flags: CLONE_NEWPID | CLONE_NEWNS |
CLONE_NEWUSER | CLONE_NEWNET |
CLONE_NEWIPC | CLONE_NEWUTS |
...)

通过clone系统调用,并传入各个Namespace对应的clone flag,创建了一个新的子进程,该进程拥有自己的pidmountusernetipcuts namespace

代码二:

代码语言:javascript
复制
echo $pid > /sys/fs/cgroup/cpu/tasks
echo $pid > /sys/fs/cgroup/cpuset/tasks
echo $pid > /sys/fs/cgroup/blkio/tasks
echo $pid > /sys/fs/cgroup/memory/tasks
echo $pid > /sys/fs/cgroup/devices/tasks
echo $pid > /sys/fs/cgroup/freezer/tasks

将代码一中产生的进程pid写入各个Cgroup子系统中,这样该进程就可以受到相应的Cgroup子系统的控制

代码三:

代码语言:javascript
复制
fun()
{
  ...
  pivot_root("path_of_rootfs/", path);
  ...
  exec("/bin/bash");
  ...
}

fun函数由上面生成的新进程执行,在fun函数中,通过pivot_root系统调用,使进程进入一个新的rootfs,之后通过exec系统调用,在新的NamespaceCgrouprootfs中执行"/bin/bash"程序

Cgroup介绍

Cgroup是什么

Cgroupcontrol group的简写,属于Linux内核提供的一个特性,用于限制和隔离一组进程对系统资源的使用,也就是做资源的Qos,这些资源主要包括CPU、内存、block I/O和网络带宽。

Cgroup中实现的子系统及其作用如下:

  • devices:设备权限控制
  • cpuset:分配指定的CPU和内存节点
  • cpu:控制CPU占用率
  • cpuacct:统计CPU使用情况
  • memory:限制内存的使用上限
  • freezer:冻结(暂停)Cgroup中的进程
  • net_cls:配合tctraffic controller)限制网络带宽
  • net_piro:设置进程的网络流量优先级
  • huge_tlb:限制HugeTLB的使用
  • perf_event:允许Perf工具基于Cgroup分组做性能监测

Namespace 介绍

Namespace是什么

Namespace是将内核的全局资源做封装,使得每个Namespace都有一份独立的资源,因此不同的进程在各自的Namespace内对同一资源的使用不会互相干扰

目前Linux内核总共实现了6种Namespace

  • IPC:隔离System V IPCPOSIX消息队列
  • Network:隔离网络资源
  • Mount:隔离文件挂在系统
  • PID:隔离进程ID
  • UTS:隔离主机名和域名
  • User:隔离用户ID和组ID

理解Docker镜像

Docker image概念介绍

Docker image是用来启动容器的只读模板,是容器启动所需要的rootfs,类似于虚拟机所使用的镜像。

Docker镜像的表示方法 Remote-dockerhub.com/namespace/bar:latest

  • Remote-dockerhub.com: Remote image hub,集中存储镜像的Web服务器地址(若缺少,则使用默认的镜像库,即Docker官方镜像库)
  • namespace: Namespace,类似于Github中的命名空间,是一个用户或组织中所有镜像的集合
  • bar: Repository,类似于Github仓库,一个仓库可以有很多个镜像,不同镜像通过tag来区分
  • latest: Tag,类似于Git仓库中的tag,一般用来区分同一镜像的不同版本
  • Layer:镜像有一系列层组成,每层都用64位的十六进制,类似于Git仓库中的commit
  • Image ID:镜像最上层的layer ID就是该镜像的IDRepo:tag提供了易于人类识别的名字,而ID便于脚本处理、操作镜像

使用Docker镜像

Docker内嵌了一系列命令制作、管理、上传、下载镜像,可以调用REST APIDocker daemon发送相关命令,也可以使用client端提供CLI命令完成操作。

列出本机的镜像

docker images

Build:创建镜像

  • 直接下载 docker pull busybox
  • 导入镜像
    • docker save -o busybox.tar busybox 导出busyboxbusybox.tar
    • docker load -i busybox.tar 导入该镜像
  • 制作新镜像 docker import 用于导入根文件系统的归档,并将之变成Docker镜像。常用于制作Docker基础镜像,与此相比,docker export则是把一个镜像导出为根文件系统的归档

Ship:传输一个镜像

镜像传输是连接开发和部署的桥梁。可以使用Docker镜像仓库做中转传输,还可以使用docker export/docker save生成的tar包来实现,或者使用Docker镜像的模板文件Dockerfile做间接传输。

Run:以image为模板启动一个容器

启动容器时,使用docker run命令

  • 命令间逻辑不一致,docker ps列出容器,docker images列出镜像
  • docker inspect 查看容器和镜像的详细信息

Docker image的组织结构

Docker image包含着数据及必要的元数据。数据由一层层的image layer组成,元数据则是一些JSON文件,用来描述数据(image layer)之间的关系以及容器的一些配置信息。

写时复制

当父进程fork子进程时,内核并没有为子进程分配内存(当然基本的进程控制块、堆栈还是需要的),而是让父子进程共享内存。当两者之一修改共享内存时,会触发一次缺页异常导致真正的内存分配。这样既加速了子进程的创建速度,又减少了内存的消耗。

仓库

什么是仓库

仓库(repository)是用来集中存储Docker镜像,支持镜像分发和更新

仓库的组成

仓库的名字通常是由两部分组成,中间以斜线分开,斜线之前是用户名,斜线之后是镜像名。

仓库镜像

仓库下面包含一组镜像,镜像之间用标签(tag)区分,一个完整的镜像路径通常由服务器地址、仓库名称和标签组成

registry.hub.docker.com/official/ubuntu:14.04

它代表Docker Hub上的Ubuntu官方镜像,发行版本是14.04

  • docker push localhost:5000/official/ubuntu:14.04 向本地私有仓库上传镜像,如果不写服务器地址默认上传到官方Docker Hub
  • docker pull ubuntu:14.04 下载镜像,不写服务器地址默认从官方Docker Hub下载
  • docker search localhost:5000/ubuntu 查询镜像

再看Docker Hub

Docker Hub优点

  • 为开发者提供海量的Docker镜像,供免费下载学习和使用
  • 拥有完善的账户管理系统,为用户提供付费扩容
  • 服务器采用分布式部署,支持负载均衡
  • 支持镜像上传、下载、查询、删除及属性设置等多种操作
  • 支持在线编译镜像
  • 后端采用分布式存储,可容灾备份
  • 其核心是Docker distribution,在开源社区上设计维护,会不断更新和完善
  • 提供企业版Docker Hub,为企业级用户提供一站式解决方案

账户管理系统

  • 用户可以编辑自己的注册信息,如密码邮箱等
  • 创建和删除用户下的镜像
  • 收费用户可以创建和设置私有镜像
  • 创建和维护组织,添加组员
  • 用户之间可以互相关注

仓库服务

Registry功能和架构

Registry旨在实现镜像的创建、存储、分发和更新等功能

  • 镜像存储 镜像数据存储在Registry后端,与本地镜像存储方式类似,它也分隔成多个镜像层,放置在各自的目录中,保存成tar格式。还保留了清单文件(manifest)和镜像签名文件(signature)等
  • 镜像创建、分发和更新 本地用户和Registry之间通过Registry API传输镜像。Registry API 即一系列HTTP/HTTPS请求,用来发送用户请求到Registry,并接收Registry响应,请求响应中包含了镜像数据的交互

Registry特点

  • 快速上传和下载镜像
  • 设计方案新颖且高性能
  • 部署方便
  • 有详细完整的Registry API说明文档
  • 后端支持多种分布式云存储方案(s3、azure)和本地文件系统等,接口以插件方式存在,易于配置
  • 清单文件(Manifest)作为元数据完整的记录镜像信息
  • Webhook方式实现通知系统
  • 实现了本地的TLS,支持HTTPS安全访问
  • 有可配置的认证模块
  • 有健康检查模块
  • 管理镜像的清单文件和摘要文件格式清晰,更清楚地为镜像打标签
  • 拥有完善的镜像缓存机制,镜像下载更加快捷

Registry API

API描述:Registry API遵循REST设计标准,用于RegistryDocker Engine之间的通信,实现Registry镜像分发,是Docker Registry的重要组成部分

API传输的对象主要包括镜像layer的块数据(blob)和表单(Manifests

ManifestJSON格式的文件,记录镜像的元数据信息,并兼容V1版本镜像信息

代码语言:javascript
复制
{
  "name": <name>,
  "tag": <tag>,
  "fsLayers": [
    {
	  "blobSum": <tarsum>
	},
	...
  ],
  "history": [...],
  "signatures": [...]
}

鉴权机制

鉴权机制是Registry V2版本之后新增的功能,目的是校验用户请求权限。校验和控制访问权限的任务是由Docker EngineRegistryAuth Service 协作完成

部署私有仓库

运行私有仓库

Docker私有服务(private registry)用来建设私有仓库、管理私有Docker镜像。 部署私有服务的有点:

  • 可独立开发和运维私有仓库
  • 节省带宽资源
  • 有独立的账户管理系统
  • 增加了定制化功能

搭建私有仓库的前提是部署Docker Private Registry。命令如下 docker run -d --hostname localhost --name registry-v2 -v /opt/data/distribution:/var/lib/registry/docker/registry/v2 -p 5000:5000 registry:2.0

构建反向代理

在实际使用中,暴露主机端口的方法是不安全的,如果Registry没有配置访问代理,任何用户都可以直接通过端口访问,因此,设计时需要为其加上HTTPS反向代理。 该方式会用代理服务器来接受用户的HTTPS请求,然后将请求转发给内部网络上的Registry服务器,并将Registry响应结果返回给用户。

Index及仓库高级功能

Index作用和组成

Index作用:

  • 管理Docker Private Hub注册用户,认证用户访问权限
  • 保存记录和更新用户信息,以及token等校验信息
  • Docker元数据(metadata)存储
  • 记录用户操作镜像的历史数据
  • 提供操作界面Web UI,用户可以方便的访问和更新资源

Index主要由控制单元、鉴权模块、数据库、健康检查和日志系统组成

Docker网络

Docker网络现状

Libnetwork提出新的容器网络模型(Container Network Model,简称CNM),定义了标准的API用于为容器配置网络,其底层可以适配各种网络驱动。 CNM三个重要概念

  • 沙盒 是一个隔离的网络运行环境,保存了容器网络栈的配置,包括了对网络接口、路由表和DNS配置的管理。
  • Endpoint 将沙盒加入一个网络,Endpoint的实现可以是一对veth pair或者OVS内部端口,当前的Libnetwork使用的是veth pair
  • 网络 网络包括一组能互相通信的Endpoint。网络实现可以是Linux bridgevlan

CNM的概念角度讲,Libnetwork的出现使得Docker具备了跨主机多子网的能力,同一个子网内的不同容器可以运行在不同主机上

Libnetwork五种驱动(driver

  • bridge Docker默认的容器网络驱动
  • host 容器于主机共享同一Network Namespace,共享同一套网络协议栈、路由表及iptables规则等,容器和主机看到的是相同的网络视图
  • null 容器内网络配置为空,需要用户手动为容器配置网络接口及路由等
  • remote Docker网络插件的实现,Remote driver 使得Libnetwork可以通过HTTP RESTful API对接第三方的网络方案, 类似SocketPlaneSDN方案只要实现了约定的HTTP URL处理函数及底层的网络接口配置方法,就可以替换Docker原生的网络实现
  • overlay Docker原生的跨主机多子网网络方案

基本网络配置

Docker网络初探

Docker五种容器网络模式

  • none 不为容器配置任何网络功能
  • container 与另一个运行中的容器共享Network Namespace,共享相同的网络视图
  • host 与主机共享Root Network Namespace,容器有完整的权限可以操纵主机的协议栈、路由表和防火墙等,所以被认为是不安全的
  • bridge Docker设计的NAT网络模型
  • overlay Docker原生的跨主机多子网模型

网络解决方案进阶

  • Weave
  • Flannel
  • SocketPlane

容器卷管理

Docker卷管理基础

增加新数据卷

docker run -d -v /tmp/data --name busyboxtest busybox 其中-v参数会在容器的/tmp/data目录下创建一个新的数据卷,用户可以通过docker inspect 命令查看数据卷所在主机中的位置

将主机目录挂载为数据卷

-v参数除了可以用于创建数据卷外,还可以用来将Docker daemon所在主机上的文件或文件夹挂载在容器中 docker run -d -v /host/data:/data --name busyboxtest busybox 上述命令是将主机的/host/data目录挂载在容器的/data目录

还可以只读的方式挂载

docker run -d -v /host/data:/data:ro --name busyboxtest busybox

如果容器中的/data路径已经存在,Docker会使用/host/data的内容覆盖该目录,与mount命令行为一致

数据卷的备份、转储和迁移

使用如下命令将数据卷中的数据打包,并将打包后的文件拷贝到主机当前目录中 docker run --rm --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf

上述命令创建了一个容器,该容器挂载了dbdata数据卷,并将主机的当前目录挂载到容器的/backup目录中;然后在容器中使用tar命令将dbdata数据卷中的内容打包存放到/backup目录的backup.tar文件中。 待容器执行结束后,备份文件就出现在主机的当前目录。之后可以将备份文件恢复到当前容器或者新创建的容器中,完成数据的备份和迁移工作

Docker卷管理的问题

  • 只支持本地数据卷
  • 缺乏对数据卷生命周期的有效管理

使用卷插件

卷插件简介

开发者可以根据自己的需要开发卷插件,可以更方便、更灵活地将本机或远端的存储卷挂载到本机的容器中,提供比Docker自身的卷管理更丰富的功能(如快照、备份等)

已有的卷插件

  • Convoy 一种基于本地存储的单机版插件
  • Flocker 支持多种后台存储驱动

Docker API

关于Docker API

REST简介

REST Representational State Transfer 一般来说只要一个架构设计满足REST,就可以称之为RESTful架构

Docker安全

深入理解Docker的安全

Docker的安全性

Docker安全性主要体现如下几个方面

  • Docker容器的安全性:这是指容器是否会危害到host或其他容器
  • 镜像的安全性:用户如何确保下载下来的镜像是可信的、未被篡改的
  • Docker daemon的安全性:如何确保发送给daemon的命令是可信用户发起的。

Docker容器的安全性

安全策略

Cgroup

Docker如何使用Cgroup

  • 限制CPU
  • 限制内存
  • 限制块设备 I/O

ulimit

Linux系统中有一个ulimit指令,可以对一些类型的资源起到限制作用,包括core dump文件的大小、进程数据段的大小、可创建文件的大小、常驻内存集的大小、打开文件数量、进程栈的大小、CPU时间、单个用户的最大线程数、进程的最大虚拟内存等

容器组网

在接入容器隔离不足的情况下,将受信任的和不受信任的容器组网在不同的网络中,可以减少危险

容器+全虚拟化

如果将容器运行在全虚拟化环境中(例如在虚拟机中运行容器),这样就算容器被攻破,也有虚拟机的保护作用

镜像签名

当发布者将镜像push到远程仓库时,Docker会对镜像用私钥进行签名,之后其他人pull镜像时,Docker就会用发布者的公钥来校验该镜像是否和发布者所发布的镜像一致,是否被篡改,是否是最新版

日志审计

目前支持的类型nonejson-filesysloggelffluentd,默认为json-file

监控

在使用容器时,应该注意监控容器的信息,若发现异常,就能采取措施及时补救

文件系统级防护

Docker可以设置容器的根文件系统为只读模式,只读模式的好处是即使容器与host使用的是同一文件系统,也不用担心会影响甚至破坏host的根文件系统

capability

打破了Linux操作系统中超级用户/普通用户的概念,让普通用户也可以做只有超级用户才能完成的工作

SELinux

Security-Enhanced Linux 美国国家安全局对于强制访问控制的实现,在这种访问控制体系下,进程只能访问那些在它的任务中所需要的文件

AppArmor

其主要作用是设置某个可执行程序的访问控制权限

Seccomp

Seccompsecure computing mode)是一种Linux内核提供的安全特性,可以实现应用程序的沙盒机制,以白名单或黑名单的方式限制进程进行系统调用

grsecurity

可以用来控制资源访问权限

几个与Docker安全相关的项目

  • Notary 保证serverclient之间的交互使用可信任的连接
  • docker-bench-security 检测用户的生产环境是否符合Docker的安全实践

安全加固

主机逃逸

利用虚拟机软件或虚拟机中运行的软件漏洞进行攻击,以达到攻击或控制虚拟机宿主操作系统的目的

后记

若文中有错误欢迎大家评论指出

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
    • 概念澄清
      • Docker在LXC基础上做了什么工作
      • Docker容器与虚拟机
  • 关于容器技术
    • 容器技术的前世今生
      • 关于容器技术
    • 一分钟理解容器
      • 容器的组成
      • 容器的创建原理
    • Cgroup介绍
      • Cgroup是什么
    • Namespace 介绍
      • Namespace是什么
  • 理解Docker镜像
    • Docker image概念介绍
      • 使用Docker镜像
        • 列出本机的镜像
        • Build:创建镜像
        • Ship:传输一个镜像
        • Run:以image为模板启动一个容器
      • Docker image的组织结构
        • 写时复制
    • 仓库
      • 什么是仓库
        • 仓库的组成
        • 仓库镜像
      • 再看Docker Hub
        • Docker Hub优点
        • 账户管理系统
      • 仓库服务
        • Registry功能和架构
        • Registry API
        • 鉴权机制
      • 部署私有仓库
        • 运行私有仓库
        • 构建反向代理
      • Index及仓库高级功能
        • Index作用和组成
    • Docker网络
      • Docker网络现状
        • 基本网络配置
          • Docker网络初探
        • 网络解决方案进阶
        • 容器卷管理
          • Docker卷管理基础
            • 增加新数据卷
            • 将主机目录挂载为数据卷
            • 数据卷的备份、转储和迁移
            • Docker卷管理的问题
          • 使用卷插件
            • 卷插件简介
          • 已有的卷插件
          • Docker API
            • 关于Docker API
              • REST简介
          • Docker安全
            • 深入理解Docker的安全
              • Docker的安全性
              • Docker容器的安全性
            • 安全策略
              • Cgroup
              • ulimit
              • 容器组网
              • 容器+全虚拟化
              • 镜像签名
              • 日志审计
              • 监控
              • 文件系统级防护
              • capability
              • SELinux
              • AppArmor
              • Seccomp
              • grsecurity
              • 几个与Docker安全相关的项目
            • 安全加固
              • 主机逃逸
          • 后记
          相关产品与服务
          容器镜像服务
          容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档