容器技术的发展越来越成熟和趋于标准化,本文主要介绍容器技术的相关概念,包括Docker的一些技术点,加深对容器技术领域的理解和掌握。
容器是对服务器CPU和内存等资源分割和调度的基本单位,在容器出现之前在操作系统通过进程来实现,但是计算资源的隔离和灵活调度不满足发展需要。容器是为开发者和系统管理员设计的,用于构建、发布和运行分布式应用的平台。
在操作系统中一个进程和操作系统构成完整环境,不同进程共享操作系统,对于容器来说一个容器和对应的主机构成完整环境。容器中提供应用程序完整的运行时环境,包括:,
容器化则是一种应用程序或系统分发方法,将应用程序或系统及其依赖项与底层基础设施隔离开来。无论底层基础设施什么硬件,什么样的操作系统,只要系统支持容器。容器可以看成是操作系统级虚拟化,允许用户在容器中部署和运行分布式应用程序或系统。
虚拟机和容器都是资源隔离的一种方式
传统意义上的容器指代docker的概念已经发生了变化,在当前的容器环境下,原来docker环境下的dockershim逐渐演变为通过CRI插件来和containered交互,再由containered管理多个container。这个也成为主流和标准的方式,整个流程上更加的简洁。
1)镜像的种类
2)镜像标签
用户可以创建一个本地仓库供内部使用,可以使用官方提供的工具docker-registry,并获取官方registry镜像来运行。仓库会被创建在容器的/var/lib/registry目录:
docker run --name registry -d -p 5000:5000 --restart=always –v /opt/data/registry:/var/lib/registry registry
$ sudo docker run -i -t ubuntu /bin/bash
以上为例运行ubuntu镜像,按照顺序,Docker执行以下流程
对Docker项目来说,它最核心的原理实际上就是为待创建的用户进程:
Rootfs保证了容器的一致性,使得容器无论是在本地、物理机、云服务器上都处于同样的运行环境
容器技术主要包括Cgroup和Namespace这两个内核特性:Namespace用于隔离资源、Cgroup用于限制资源。参看“容器云系列之Docker数据卷管理和资源限制”部分有关资源限制介绍。
1)Namespace
2)Cgroup:为每种可以控制的资源定义了子系统,限制进程组能够使用cpu、内存、磁盘、带宽等资源的上限
例:查看子系统/sys/fs/cgroup/
[root@tango-01 cgroup]# cd /sys/fs/cgroup/
[root@tango-01 cgroup]# ll
total 0
drwxr-xr-x 6 root root 0 Apr 16 15:38 blkio
lrwxrwxrwx 1 root root 11 Apr 16 15:38 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Apr 16 15:38 cpuacct -> cpu,cpuacct
drwxr-xr-x 6 root root 0 Apr 16 15:38 cpu,cpuacct
drwxr-xr-x 3 root root 0 Apr 16 15:38 cpuset
drwxr-xr-x 6 root root 0 Apr 16 15:38 devices
drwxr-xr-x 3 root root 0 Apr 16 15:38 freezer
drwxr-xr-x 3 root root 0 Apr 16 15:38 hugetlb
drwxr-xr-x 6 root root 0 Apr 16 15:38 memory
lrwxrwxrwx 1 root root 16 Apr 16 15:38 net_cls -> net_cls,net_prio
drwxr-xr-x 3 root root 0 Apr 16 15:38 net_cls,net_prio
lrwxrwxrwx 1 root root 16 Apr 16 15:38 net_prio -> net_cls,net_prio
drwxr-xr-x 3 root root 0 Apr 16 15:38 perf_event
drwxr-xr-x 6 root root 0 Apr 16 15:38 pids
drwxr-xr-x 6 root root 0 Apr 16 15:38 systemd
3)Cgroups组织
4)Cgroup实战
[root@tango-01 cpu]# mkdir /sys/fs/cgroup/cpu/mycgroup
[root@tango-01 cpu]# ls -l mycgroup
total 0
-rw-r--r-- 1 root root 0 Apr 16 16:45 cgroup.clone_children
--w--w--w- 1 root root 0 Apr 16 16:45 cgroup.event_control
-rw-r--r-- 1 root root 0 Apr 16 16:45 cgroup.procs
-r--r--r-- 1 root root 0 Apr 16 16:45 cpuacct.stat
-rw-r--r-- 1 root root 0 Apr 16 16:45 cpuacct.usage
-r--r--r-- 1 root root 0 Apr 16 16:45 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 Apr 16 16:45 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Apr 16 16:45 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Apr 16 16:45 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Apr 16 16:45 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Apr 16 16:45 cpu.shares
-r--r--r-- 1 root root 0 Apr 16 16:45 cpu.stat
-rw-r--r-- 1 root root 0 Apr 16 16:45 notify_on_release
-rw-r--r-- 1 root root 0 Apr 16 16:45 tasks
模拟高CPU占用 cat /dev/urandom | gzip -9 > /dev/null
[root@tango-01 cpu]# cat /dev/urandom | gzip -9 > /dev/null
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13536 root 20 0 4624 612 396 R 40.7 0.0 0:11.78 gzip
限制CPU,占用率不超过20%
[root@tango-01 mycgroup]# echo 10000 > cpu.cfs_quota_us
[root@tango-01 mycgroup]# echo 50000 > cpu.cfs_period_us
[root@tango-01 mycgroup]# echo 13536 > tasks
查看CPU使用
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13536 root 20 0 4624 612 396 R 8.0 0.0 1:50.98 gzip
启动容器时挂载整个“/”根目录
Docker 在镜像的设计中,引入了层(layer)的概念。也就是说,用户制作镜像的每一步操作,都会生成一个层,也就是一个增量 rootfs
参考“容器云系列之Docker镜像和仓库管理”关于镜像分层结构的介绍。
创建Docker容器时,可以用–net选项指定容器的网络模式。Docker有以下4种网络模式:
参看“容器云系列之Docker网络管理及容器互联”有关容器网络的详细介绍。
[root@tango-01 ~]# docker run -p 18080:80 nginx
[root@tango-01 mycgroup]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2eca44029685 nginx "/docker-entrypoint.…" 49 seconds ago Up 44 seconds 0.0.0.0:18080->80/tcp cranky_mirzakhani
当Docker进程启动时,会创建为docker0的虚拟网桥
从docker0 子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关
Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0,另一端放在主机中,以veth*这样类似的名字命名,并将这个网络设备加入到docker0 网桥中。通过brctl show 命令查看
[root@tango-01 ~]# brctl show
bridge name bridge id STP enabled interfaces
br-1d93f41271b4 8000.0242a3d69c1c no
br-d9ffb1af87f2 8000.024262f9a631 no veth70da614
veth78ca7c6
vethb281fb7
vethfb847e9
docker0 8000.02421ad85f66 no
使用docker run -p时,docker实际是在iptables 做了DNAT规则,可以使用iptables -t nat -nL查看
[root@tango-01 mycgroup]# iptables -t nat -nL
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.19.0.3:8052
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:18080 to:172.17.0.2:80
容器之间的连接有两种方式:link连接网络和自定义网络
[root@tango-01 ~]# docker network create -d bridge my-net
f702ac3515d65156d5c7494cedf41cd984f82b0b2af02cd424e1ce03f64122ca
[root@tango-01 ~]# docker run -it --rm --name busybox1 --network my-net busybox sh
[root@tango-01 ~]# docker run -it --rm --name busybox1 --network my-net busybox sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:14:00:02
inet addr:172.20.0.2 Bcast:172.20.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:19 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2230 (2.1 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ping 172.20.0.3
PING 172.20.0.3 (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.183 ms
64 bytes from 172.20.0.3: seq=1 ttl=64 time=0.069 ms
^C
--- 172.20.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.069/0.126/0.183 ms
运行另外一个
[root@tango-01 ~]# docker run -it --rm --name busybox2 --network my-net busybox sh
/ #
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:14:00:03
inet addr:172.20.0.3 Bcast:172.20.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:516 (516.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
[root@tango-01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7a1329f43d63 ansible/awx:latest "/usr/bin/tini -- /u…" 17 months ago Up 5 minutes 8052/tcp awx_task
docker ps –a查看该容器处于退出状态,但是容器没有真正销毁
[root@tango-01 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f88d934e7197 busybox "echo hello world" 36 seconds ago Exited (0) 14 seconds ago stoic_kepler
[root@tango-01 ~]# docker pull training/webapp
[root@tango-01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
oceanbase/obce-mini latest 1a5ca6d233a7 8 months ago 690MB
[root@tango-01 dockerfile]# docker build -t alpine:v1.0 .
[root@tango-01 ~]# docker run busybox echo hello world
hello world
[root@tango-01 ~]# docker start dc2a72625341
dc2a72625341
[root@tango-01 ~]# docker exec -it influxdb /bin/bash
[root@tango-01 ~]# docker logs -f c39cf512b3f9
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
export/import:备份和恢复容器文件到tar文件,但是如果有tempfs卷则无法使用,因为不能备份内存信息。
docker rm:删除容器
[root@tango-01 ~]# docker rm e7330d407e32
e7330d407e32
[root@tango-01 ~]# docker run -t -i busybox /bin/sh
/ # cd /tmp
/tmp # ls / > root.txt
/tmp # ls -l
total 4
-rw-r--r-- 1 root root 43 Apr 16 07:59 root.txt
[root@tango-01 ~]# docker commit a80287c1f2da my_busybox
sha256:b7b85aec55e5474911987979012ca45640f7f7ccf04340573cbc26e638f65b08
通过diff命令可以查看修改的历史记录
[root@tango-01 ~]# docker diff a80287c1f2da
C /tmp
A /tmp/root.txt
C /root
A /root/.ash_history
[root@tango-01 ~]#
创建Dockerfile镜像文件:
[root@tango-01 dockerfile]# vi Dockerfile
FROM alpine
ADD root.txt /tmp
使用docker build命令构建
[root@tango-01 dockerfile]# docker build -t alpine:v1.0 .
Sending build context to Docker daemon 1.06MB
Step 1/2 : FROM alpine
---> c059bfaa849c
Step 2/2 : ADD root.txt /tmp
---> d0b7c4e5849f
Successfully built d0b7c4e5849f
Successfully tagged alpine:v1.0
运行docker
[root@tango-01 dockerfile]# docker run -t -i alpine:v1.0 /bin/sh
/ # ls /tmp
root.txt
Dockerfile使用经验
定义和运行多容器的应用程序工具,定义若干个容器作为整体运行。通过docker-compose.yml文件定义,包含version、services和networks三部分。
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid
&& bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
通过命令docker-compose up运行
Podman是Redhat公司推出的容器管理工具,开发、管理、运行OCI容器,起初是CRI-O的一部分,后来单独分离出来叫做libpod后来改成Podman。Podman的命令几乎同docker类似,在结构上与Docker不同,Podman不使用daemon的方式去创建容器,而是直接调用OCI runtime,比如runc。Podman由两部分组成:Podman CLI方便用户交互和conmon负责container runtime,主要包括监控、日志、TTY分配等,是所有容器进程的父进程。
以上是最近参加的容器技术培训有关容器这一块的基本概念和技术点,全文基于张建锋老师的培训材料整理。容器技术这几年发展迅猛,技术迭代更新很快,逐渐也形成一套行业标准,从Docker到K8S、Rancher以及Podman,开源和商业化产品的碰撞,行业内的产品和工具不断涌现,整个生态也是欣欣向荣。
参考资料:
转载请注明原文地址:https://blog.csdn.net/solihawk/article/details/124288506
文章会同步在公众号“牧羊人的方向”更新,感兴趣的可以关注公众号,谢谢!