1.什么是容器
首先介绍几个基本概念:
- 容器进行时runtime:容器真正运行的地方(就好比java运行在JVM上)。低阶运行时(low-level runtime)关注如何与操作系统交互,创建并运行容器,常见的低阶运行时有runc、rkt等。高阶运行时(high-level runtime)关注于将容器镜像解压并传递到低阶运行时中,常见的高阶运行时有:docker、containerd、rkt。
- 容器引擎:主要是准备运行容器的资源以及管理容器的声明周期,docker使用docker engine作为管理docker的引擎,kubernetes为了兼容多种容器,引入CRI来调用容器引擎(通信协议是gRPC)。
- 容器仓库:统一存放镜像的地方,常见的有docker hub,私人搭建的harbor仓库。
2.安装运行容器
安装docker脚本:
#!/bin/sh
echo "Remove Old Docker..."
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
echo "Start install docker..."
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl start docker
sudo systemctl enable docker
3.docker镜像
base镜像:一种是不依赖其他镜像,从scratch构建;一种是各种Linux发行版的镜像。
为什么容器镜像会比虚拟镜像小:linux刚启动时会加载内核空间的bootfs文件系统,之后将其卸载掉,而容器镜像只需要准备用户空间的rootfs文件系统即可。rootfs只需要包括最基本的命令、工具和程序库就可以了。也就是说容器使用的是宿主机的内核。
3.1 构建镜像
一种方式是将运行时的容器通过docker commit保存为镜像
一种方式是通过编写Dockerfile构造镜像(也是通过docker commit一层一层构建镜像的)
3.2 Dockerfile
- From 指定base镜像
- MANITAINER 镜像作者
- COPY 将文件复制到镜像层
- ADD 与COPY的不同点在于归档文件会自动解压
- ENV 设置环境变量
- EXPOSE 暴露端口
- VOLUME 设置存储卷
- WORKDIE 设置镜像当前的工作目录
- RUN 在容器中运行指定命令,常用来安装应用和软件包
- CMD 指定容器的默认执行命令,可以被docker run后面的命令行参数替换
- ENTRYPOINT 让容器以服务的形式运行,不会被忽略,一定会执行
4.docker技术栈
docker底层使用了namespace做视图隔离,cgroup做资源限制。
4.1 namespace
一共有六种:PID namespace, net namespace, IPC namespace, Mount namespace, UTS namespace, USR namespace. 提供了不同视图视角。
4.2 Cgroups
对CPU、内存、磁盘IO等进程所需要资源进行管控 可配额:cpu、memory
4.3 Union FS生成文件系统
常用的有AUFS,overlayFS等
写特性:Copy-on-write
5. docker实验
5.1 network namespace
fork一个net namespace并进入这个namespace查看ip
$ unshare -fn sleep 120 # unshare 启动了一个新的网络namespace的子进程
NS TYPE NPROCS PID USER NETNSID NSFS COMMAND
4026537700 net 2 2698215 root unassigned unshare
$ nsenter -t <pid> -n ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5.2 cgroup限制cpu资源
我们设置一个busyloop的死循环go程序
$ vi busyloop.go
package main
func main() {
go func() {
for {
}
}()
for {
}
}
$ go build busyloop.go
我们设置开启一个限制busyloop的cgroup树
cd /sys/fs/cgroup/cpu
mkdir cpudemo
首先运行该程序,并查看cpu占用情况
$ ./busyloop
$ top # cpu占用率为197%,因为我这里是两个cpu
$ echo 2830119 > cgroup.procs # 将要管理的进程ID写如cgroup.procs中
$ echo 100000 > cpu.cfs_quota_us # 将分配的时间片设置为一个CPU的大小,发现CPU占用率变为100%
$ echo 10000 > cpu.cfs_quota_us # cpu占用率变为10%左右,说明限制了进程的资源
tips
推荐几个常见的开源容器监控工具:Weave Scope,cAdvisor,Prometheus 日志管理工具:ELK:Elasticsearch、logstash、Kibana