容器技术

在Linux中,容器技术是一种进程隔离的技术。应用可以运行在一个个隔离的容器中,与虚拟机相同的是,可以为这些容器设置计算资源资源限制,挂在存储,连接网络,而与虚拟机不同的是,这些应用运行时共用一个Kernel。

这些技术的基础是Linux的LXC(Linux Container),通过Cgroup的资源管理能力和Linux NameSpace的隔离能力组合在一起。

容器架构图

在这里插入图片描述

容器核心技术

容器 = cgroup + namespace + rootfs + 容器引擎

  • Cgroup: 资源控制
  • namespace: 访问隔离
  • rootfs:文件系统隔离,镜像的本质就是一个rootfs文件
  • 容器引擎:生命周期控制

Cgroup

Cgroup 是 Control group 的简称,是 Linux 内核提供的一个特性,用于限制和隔离一组进程对系统资源的使用。对不同资源的具体管理是由各个子系统分工完成的。
在这里插入图片描述

Cgroup 可以对进程进行任意分组,如何分组由用户自定义。

子系统介绍

cpuset 子系统

cpuset 可以为一组进程分配指定的CPU和内存节点。 cpuset 一开始用在高性能计算上,在 NUMA(non-uniform memory access) 架构的服务器上,通过将进程绑定到固定的 CPU 和内存节点上,来避免进程在运行时因跨节点内存访问而导致的性能下降。
cpuset 的主要接口如下:
cpuset.cpus: 允许进程使用的CPU列表
cpuset.mems: 允许进程使用的内存节点列表

cpu 子系统

cpu 子系统用于限制进程的 CPU 利用率。具体支持三个功能
第一,CPU 比重分配。使用 cpu.shares 接口。
第二,CPU 带宽限制。使用 cpu.cfs_period_us 和 cpu.cfs_quota_us 接口。
第三, 实时进程的 CPU 带宽限制。使用 cpu_rt_period_us 和 cpu_rt_quota_us 接口。

cpuacct 子系统

统计各个 Cgroup 的 CPU 使用情况,有如下接口:
cpuacct.stat: 报告这个 Cgroup 在用户态和内核态消耗的 CPU 时间,单位是 赫兹。
cpuacct.usage: 报告该 Cgroup 消耗的总 CPU 时间。
cpuacct.usage_percpu:报告该 Cgroup 在每个 CPU 上的消耗时间。

memory 子系统

限制 Cgroup 所能使用的内存上限。
memory.limit_in_bytes:设定内存上限,单位字节。
默认情况下,如果使用的内存超过上限,Linux 内核会试图回收内存,如果这样仍无法将内存降到限制的范围内,就会触发 OOM,选择杀死该Cgroup 中的某个进程。
memory.memsw,limit_in_bytes: 设定内存加上交换内存区的总量。
memory.oom_control: 如果设置为0,那么内存超过上限时,不会杀死进程,而是阻塞等待进程释放内存;同时系统会向用户态发送事件通知。
memory.stat: 报告内存使用信息。

blkio

限制 Cgroup 对 阻塞 IO 的使用。

blkio.weight: 设置权值,范围在[100, 1000],属于比重分配,不是绝对带宽。因此只有当不同 Cgroup 争用同一个 阻塞设备时才起作用 blkio.weight_device: 对具体设备设置权值。它会覆盖上面的选项值。 blkio.throttle.read_bps_device: 对具体的设备,设置每秒读磁盘的带宽上限。 blkio.throttle.write_bps_device: 对具体的设备,设置每秒写磁盘的带宽上限。 blkio.throttle.read_iops_device: 对具体的设备,设置每秒读磁盘的IOPS带宽上限。 blkio.throttle.write_iops_device: 对具体的设备,设置每秒写磁盘的IOPS带宽上限。

devices 子系统

控制 Cgroup 的进程对哪些设备有访问权限
devices.list: 只读文件,显示目前允许被访问的设备列表,文件格式为
类型[a|b|c] 设备号[major:minor] 权限[r/w/m 的组合]
a/b/c 表示 所有设备、块设备和字符设备。
devices.allow: 只写文件,以上述格式描述允许相应设备的访问列表。
devices.deny: 只写文件,以上述格式描述禁止相应设备的访问列表。

Namespcae

Namespace 是将内核的全局资源做封装,使得每个namespace都有一份独立的资源,因此不同的进程在各自的namespace内对同一种资源的使用互不干扰。举个例子,执行sethostname这个系统调用会改变主机名,这个主机名就是全局资源,内核通过UTS Namespace可以将不同的进程分隔在不同的 UTS Namespace 中,在某个 Namespace 修改主机名时,另一个Namespace 的主机名保持不变。

目前,Linux 内核实现了6种 Namespace:
在这里插入图片描述

与命名空间相关的三个系统调用:

clone创建全新的Namespace,由clone创建的新进程就位于这个新的namespace里。创建时传入 flags参数,可选值有 CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWUSER, 分别对应上面六种namespace。

unshare为已有进程创建新的namespace。
setns把某个进程放在已有的某个namespace里。

=========================== 6种命名空间 ======================

UTS namespace

UTS namespace 对主机名和域名进行隔离。为什么要隔离主机名?因为主机名可以代替IP来访问。如果不隔离,同名访问会出冲突。

IPC namespace

Linux 提供很多种进程通信机制,IPC namespace 针对 System V 和 POSIX 消息队列,这些 IPC 机制会使用标识符来区别不同的消息队列,然后两个进程通过标识符找到对应的消息队列。
IPC namespace 使得 相同的标识符在两个 namespace 代表不同的消息队列,因此两个namespace 中的进程不能通过 IPC 来通信。

PID namespace

隔离进程号,不同namespace 的进程可以使用相同的进程号。
当创建一个 PID namespace 时,第一个进程的PID 是1,即 init 进程。它负责回收所有孤儿进程的资源,所有发给 init 进程的信号都会被屏蔽。

Mount namespace

隔离文件挂载点,每个进程能看到的文件系统都记录在/proc/$$/mounts里。在一个 namespace 里挂载、卸载的动作不会影响到其他 namespace。

Network namespace

隔离网络资源。每个 namespace 都有自己的网络设备、IP、路由表、/proc/net 目录、端口号等。网络隔离可以保证独立使用网络资源,比如开发两个web 应用可以使用80端口。
新创建的 Network namespace 只有 loopback 一个网络设备,需要手动添加网络设备。

User namespace

隔离用户和用户组。它的厉害之处在于,可以让宿主机上的一个普通用户在 namespace 里成为 0 号用户,也就是 root 用户。这样普通用户可以在容器内“随心所欲”,但是影响也仅限在容器内。最后,回到 Docker 上,经过上述讨论,namespace 和 cgroup 的使用很灵活,需要注意的地方也很多。 Docker 通过 Libcontainer 来做这些脏活累活。用户只需要使用 Docker API 就可以优雅地创建一个容器。docker exec 的底层实现就是上面提过的 setns 。

Docker

什么是Docker

Docker 是一个开源的、轻量级的容器引擎,主要运行于 Linux 和 Windows,用于创建、管理和编排容器。
和 VMware 虚拟机相比,Docker 使用容器承载应用程序,而不使用操作系统,所以它的开销很少,性能很高。但是,Docker 对应用程序的隔离不如虚拟机彻底,所以它并不能完全取代 VMware。

Docker VS VM

下面的图片比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

在这里插入图片描述
在这里插入图片描述

Docker CLI

在这里插入图片描述

#####################Docker安装############################################
wget  http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
 yum install docker-ce docker-ce-cli containerd.io
 sudo systemctl start docker
 
#####Docker 镜像加速
[root@host201 docker]# pwd
/etc/docker
[root@host201 docker]# cat daemon.json 
{"registry-mirrors":["https://reg-mirror.qiniu.com/"]}
sudo systemctl daemon-reload
sudo systemctl restart docker
		 Registry Mirrors:
		  https://reg-mirror.qiniu.com/
		 Live Restore Enabled: false

#####Docker中关于镜像的基本操作
###Docker 三部曲####
	#Build
	#ship
	#Run

[root@host201 ~]# docker search centos 
  216  docker search centos
  217  docker pull ansible/centos7-ansible
  218  docker images
  219  docker run -it ansible/centos7-ansible /bin/bash
  220  docker ps -a
  
  
  ###启动容器
  315  docker start 9473140c024f 
  316  docker ps -a
  317  docker exec -it 9473140c024f /bin/bash

###Dockerfile
[root@host201 ~]# vi Dockerfile
[root@host201 ~]# docker build -t test/centos7   .
#-t :指定要创建的目标镜像名
#. :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径

####共享母机的 /sysadmin/manager/ 文件到docker的/mnt/webapp 上
docker run -d -it --name web -v /sysadmin/manager/:/mnt/webapp  ansible/centos7-ansible

Dockerfile

####使用 Dockerfile 定制镜像
FROM 指定基础镜像
RUN 执行命令(shell 格式和exec 格式两种)

Docker 实践

#####################Docker安装############################################
wget  http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
 yum install docker-ce docker-ce-cli containerd.io
 sudo systemctl start docker


 docker version
 [root@host201 ~]# docker version
Client: Docker Engine - Community
 Version:           20.10.12
 API version:       1.41
 Go version:        go1.16.12
 Git commit:        e91ed57
 Built:             Mon Dec 13 11:45:41 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.12
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.12
  Git commit:       459d0df
  Built:            Mon Dec 13 11:44:05 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.12
  GitCommit:        7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
 

############################### docker --help#################################
 [root@host201 ~]#  docker --help

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker
                           context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  app*        Docker App (Docker Inc., v0.9.1-beta3)
  builder     Manage builds
  buildx*     Docker Buildx (Docker Inc., v0.7.1-docker)
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  image       Manage images
  manifest    Manage Docker image manifests and manifest lists
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  scan*       Docker Scan (Docker Inc., v0.12.0)
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.

To get more help with docker, check out our guides at https://docs.docker.com/go/guides/

#####Docker中关于镜像的基本操作
[root@host201 ~]# docker search centos
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                            The official build of CentOS.                   6928      [OK]       
ansible/centos7-ansible           Ansible on Centos7                              135                  [OK]
consol/centos-xfce-vnc            Centos container with "headless" VNC session??  132                  [OK]
jdeathe/centos-ssh                OpenSSH / Supervisor / EPEL/IUS/SCL Repos - ??  121                  [OK]
centos/systemd                    systemd enabled base container.                 105                  [OK]
centos/mysql-57-centos7           MySQL 5.7 SQL database server                   92                   
imagine10255/centos6-lnmp-php56   centos6-lnmp-php56                              58                   [OK]
tutum/centos                      Simple CentOS docker image with SSH access      48                   
centos/postgresql-96-centos7      PostgreSQL is an advanced Object-Relational ??  45                   
jdeathe/centos-ssh-apache-php     Apache PHP - CentOS.                            31                   [OK]
kinogmt/centos-ssh                CentOS with SSH                                 29                   [OK]
guyton/centos6                    From official centos6 container with full up??  10                   [OK]
nathonfowlie/centos-jre           Latest CentOS image with the JRE pre-install??  8                    [OK]
centos/tools                      Docker image that has systems administration??  7                    [OK]
drecom/centos-ruby                centos ruby                                     6                    [OK]
roboxes/centos8                   A generic CentOS 8 base image.                  4                    
darksheer/centos                  Base Centos Image -- Updated hourly             3                    [OK]
mamohr/centos-java                Oracle Java 8 Docker image based on Centos 7    3                    [OK]
miko2u/centos6                    CentOS6 ?ユ....                                  2                    [OK]
dokken/centos-7                   CentOS 7 image for kitchen-dokken               2                    
amd64/centos                      The official build of CentOS.                   2                    
mcnaughton/centos-base            centos base image                               1                    [OK]
blacklabelops/centos              CentOS Base Image! Built and Updates Daily!     1                    [OK]
smartentry/centos                 centos with smartentry                          0                    [OK]
starlabio/centos-native-build     Our CentOS image for native builds              0                    [OK]


docker search centos
docker pull centos
docker images
  
  
  

参考资料

华为云云原生黄金课程02:容器技术基础介绍
【Docker&VM】docker容器与虚拟机有什么区别?
Docker教程:Docker入门实践(精讲版)
只要一小时,零基础入门Docker
Docker — 从入门到实践
容器核心技术 :Cgroup 与 Namespace

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐