- 1. 虚拟化和容器技术
- 2. 容器化的基础
- 3. Docker架构
- 4. Docker安装
- https://github.com/prometheus/node_exporter#disabled-by-default">参考 https://github.com/prometheus/node_exporter#disabled-by-default
- sysctls for k8s node config
- Do not accept source routing
- Promote secondary addresses when the primary address is removed
- Enable hard and soft link protection
- https://help.aliyun.com/knowledge_detail/39428.html">see details in https://help.aliyun.com/knowledge_detail/39428.html
- https://help.aliyun.com/knowledge_detail/41334.html">see details in https://help.aliyun.com/knowledge_detail/41334.html
- 5. Docker相关进程
1. 虚拟化和容器技术
- 虚拟化技术
Type1: 不安装宿主机操作系统,而直接在硬件基础上安装虚拟化管理软件
Type2: 安装宿主机操作系统,在宿主机操作系统之上安装虚拟化管理软件
- 容器技术
Container 是在宿主机操作系统上使用Cgroups,Namespaceses技术创建出来具有边界的特殊进程。
- 区别
虚拟化技术会虚拟出多个内核,每个虚拟机拥有一个自己的内核,彼此之间隔离性非常好。并且在创建虚拟机之初就定义好了虚拟机的资源限制,如CPU核心数,内存大小,磁盘大小等。
容器技术是直接运行在宿主机之上的,多个容器共用一个内核,因此隔离效果比较差,但是性能更好。
2. 容器化的基础
2.1. Chroot
如果需要在一个宿主机上运行多个容器,且容器之间相互个离,那么第一个就需要系统库文件的依赖,对于一个容器而言,需要将其需要的系统文件单独复制出来一份,放到指定目录,并且需要让进程认为这就是根目录,而不是去调用宿主机系统上的库文件。Chroot就是一个切换根目录的方式。
2.2. NameSpaces
为了让多个容器以沙盒的方式在宿主机上运行,就需要提前定义好各个容器能看到的边界。由于各个容器都是直接运行在宿主机系统上,因此需要内核对各个容器的上下文进行修改,让他们看上去是一个独立的操作系统。比如,指定PID为1的进程,指定网卡设备,指定文件系统挂载,指定用户等等。
Linux操作系统内核从底层实现了为各个进程创建独立用户空间的功能,不同用户空间似于一个个独立的虚拟机系统,用户空间内部进程不能感知到其它用户空间中的进程状态。内核提供了六种Namespaces:
UTS | hostname and domainname | 主机名和域名隔离 | 内核版本:2.6.19 |
---|---|---|---|
User | 用户隔离。运行进程的用户和组 | 内核版本:3.8.x | |
Mount | 挂载点隔离。即挂载点隔离,主要指根目录 | 内核版本:2.4.19 | |
IPC | Inter-process-connection | 进程间通信隔离。消息队列、共享内存、信号量 | 内核版本:2.6.19 |
Pid | Process ID | PID隔离 | 内核版本:2.6.24 |
Net | Network | 网络隔离。网络设备、协议栈、端口 | 内核版本:2.6.29 |
2.3. Cgroups
Namespaceses通过障眼法实现了用户空间的隔离,但是没办法对硬件资源进行限制,当一个容器进行CPU密集型操作时,会消耗掉整个宿主机的CPU资源,进而影响了其它容器的正常运行。
因此在Namespaceses之上,还需要对各个容器实现硬件资源限制,比如CPU,Memory,diskio等等。
Cgroups技术针对进程而言的,在centos7系统上,可以通过以下方式来实现对进程的资源限制:
[root@centos-82 ~]# while :;do :;done &
[1] 2136
[root@centos-82 ~]# pidstat -u -p 2136 2 ## 未加cgroups限制下,跑满单个CPU核心
11:09:54 AM UID PID %usr %system %guest %CPU CPU Command
11:09:56 AM 0 2136 99.50 0.00 0.00 99.50 4 bash
11:09:58 AM 0 2136 100.00 0.00 0.00 100.00 4 bash
11:10:00 AM 0 2136 100.00 0.00 0.00 100.00 4 bash
[root@centos-82 ~]# mount -t cgroup ## 查看当前cgroups路径
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
[root@centos-82 ~]# mkdir /sys/fs/cgroup/cpu/loop
[root@centos-82 ~]# cat /sys/fs/cgroup/cpu/loop/cpu.cfs_quota_us
-1
[root@centos-82 ~]# cat /sys/fs/cgroup/cpu/loop/cpu.cfs_period_us
100000
[root@centos-82 ~]# echo 10000 >/sys/fs/cgroup/cpu/loop/cpu.cfs_quota_us ## CPU时间片限制在10%
[root@centos-82 ~]# echo 2136 > /sys/fs/cgroup/cpu/loop/tasks ## 指定限制的进程PID
[root@centos-82 ~]# pidstat -u -p 2136 2
Linux 3.10.0-862.el7.x86_64 (centos-82) 03/02/2019 _x86_64_ (8 CPU)
11:16:37 AM UID PID %usr %system %guest %CPU CPU Command
11:16:39 AM 0 2136 10.50 0.00 0.00 10.50 4 bash
11:16:41 AM 0 2136 10.00 0.00 0.00 10.00 4 bash
11:16:43 AM 0 2136 9.50 0.00 0.00 9.50 4 bash
11:16:45 AM 0 2136 9.95 0.00 0.00 9.95 4 bash
3. Docker架构
3.1. Docker组件
Docker服务有三个部分组成,分别是Client,Docker Host,Registry。当创建新的容器时,会向Docker Daemon发送指令,Docker Daemon通过本地镜像文件创建容器,当本地不存在镜像时,将从Registry下载镜像。
Registry由两个部分组成:
- Repostitory
- 由特定的docker镜像的所有迭代版本组成一个镜像仓库
- 一个Registry可以包括多个Repostitory
- Repostitory包含顶层仓库和用户仓库
- 顶层仓库: 仓库名:标签, nginx:latest
- 用户仓库: 用户名/仓库名:标签, heyang/nginx:1.4.2
- 一个镜像可以有多个标签,如最新版的nginx,可以是nginx:latest,nginx:1.4.2
- Index
- 提供用户认证、镜像检索功能
3.2. Docker镜像和容器
3.2.1. Docker镜像
镜像(Image)是一堆只读层(read-only layer)的统一视角。如下图所示:
左边的是多个只读层,他们相互堆叠在一起。除了最下层之外,其它每一层都会有一个指针指向下一层。这些层是Docker内部的实现细节,并且能够在宿主机的文件系统上访问到。
统一文件系统(union file system,aufs)技术(新版用overlay2)能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。我们可以在图片的右边看到这个视角的形式。
每一层都包含了当前层的ID,Metadata,Pointer(指向上一层)三层,最底层不包含Pointer。3.2.2. Docker容器
Docker容器包含静止状态和运行状态两种,这两种状态下的层级不一样。
静态状态的容器仅仅是在镜像状态下增加一个可读写的层级,运行状态中的容器包含了进程和对应的进程空间:
- 提供用户认证、镜像检索功能
4. Docker安装
4.1. Docker安装配置
Docker在2017年以前时使用大版本号+小版本号来名,在2017年之后,采用YY.MM.N-xx格式,如 19.03.1-ce表示2019年3月份的第2个ce版本。
4.1.1. CentOS 7安装docker-ce
4.1.1.1. 内核升级(可选)
CentOS 7 默认的 3.10 版本内核是可以安装 docker-ce 的,但是如果是后续安装 kubernetes ,推荐升级内核到最新的稳定版本。
12-9-软件管理
4.1.1.2. 安装docker-ce
[root@centos-7-51 ~]# uname -r # 确认内核版本,要求大于3.8
5.4.144-1.el7.elrepo.x86_64
[root@centos-7-51 ~]# wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@centos-7-51 ~]# yum repolist
[root@centos-7-51 ~]# yum list docker-ce* --showduplicates # 通常不安装最新的版本
[root@centos-7-51 ~]# yum install -y docker-ce-19.03.15-3.el7 docker-ce-cli-19.03.15-3.el7
[root@centos-7-51 ~]# cat /etc/docker/daemon.json
{
"graph": "/data/docker",
"oom-score-adjust": -1000,
"log-driver": "json-file",
"log-opts": {
"max-size": "32m",
"max-file": "3"
},
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 10,
"bip": "172.24.20.1/24",
"registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
"insecure-registries": ["harbor.ddn.com"],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
4.1.2. ubuntu 1804 安装docker-ce
root@ubuntu-1804-120:~# apt autoremove --purge docker docker-engine docker.io containerd runc
root@ubuntu-1804-120:~# apt update
root@ubuntu-1804-120:~# apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
root@ubuntu-1804-120:~# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
root@ubuntu-1804-120:~# add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
root@ubuntu-1804-120:~# apt install -y docker-ce=5:19.03.15~3-0~ubuntu-bionic docker-ce-cli=5:19.03.15~3-0~ubuntu-bionic
root@ubuntu-1804-120:~# vim /etc/docker/daemon.json
{
"graph": "/data/docker",
"storage-driver": "overlay2",
"insecure-registries": ["harbor.ddn.com"],
"registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
"bip": "172.24.20.1/24",
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": true,
"log-opts": {"max-size":"32M", "max-file":"2"}
}
root@ubuntu-1804-120:~# systemctl restart docker
root@ubuntu-1804-120:~# docker info
......
WARNING: No swap limit support
解决上述 docker info 中警告 WARNING: No swap limit support
,可以参考docker官方文档
root@ubuntu-1804-120:~# vim /etc/default/grub # 对GRUB_CMDLINE_LINUX启用swap分区cgroup限制功能
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
root@ubuntu-1804-120:~# update-grub
root@ubuntu-1804-120:~# reboot
4.2. 优化
以下优化参数是从 rancher 官方文档获取
4.2.1. 节点
- 内核参数 ``` [root@centos-7-51 ~]# vim /etc/sysctl.conf net.bridge.bridge-nf-call-ip6tables=1 net.bridge.bridge-nf-call-iptables=1 net.ipv4.ip_forward=1 net.ipv4.conf.all.forwarding=1 net.ipv4.neigh.default.gc_thresh1=4096 net.ipv4.neigh.default.gc_thresh2=6144 net.ipv4.neigh.default.gc_thresh3=8192 net.ipv4.neigh.default.gc_interval=60 net.ipv4.neigh.default.gc_stale_time=120
参考 https://github.com/prometheus/node_exporter#disabled-by-default
kernel.perf_event_paranoid=-1
sysctls for k8s node config
net.ipv4.tcp_slow_start_after_idle=0 net.core.rmem_max=16777216 fs.inotify.max_user_watches=524288 kernel.softlockup_all_cpu_backtrace=1
kernel.softlockup_panic=0
kernel.watchdog_thresh=30 fs.file-max=2097152 fs.inotify.max_user_instances=8192 fs.inotify.max_queued_events=16384 vm.max_map_count=262144 fs.may_detach_mounts=1 net.core.netdev_max_backlog=16384 net.ipv4.tcp_wmem=4096 12582912 16777216 net.core.wmem_max=16777216 net.core.somaxconn=32768 net.ipv4.ip_forward=1 net.ipv4.tcp_max_syn_backlog=8096 net.ipv4.tcp_rmem=4096 12582912 16777216
net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.default.disable_ipv6=1 net.ipv6.conf.lo.disable_ipv6=1
kernel.yama.ptrace_scope=0 vm.swappiness=0
Do not accept source routing
net.ipv4.conf.default.accept_source_route=0 net.ipv4.conf.all.accept_source_route=0
Promote secondary addresses when the primary address is removed
net.ipv4.conf.default.promote_secondaries=1 net.ipv4.conf.all.promote_secondaries=1
Enable hard and soft link protection
fs.protected_hardlinks=1 fs.protected_symlinks=1
see details in https://help.aliyun.com/knowledge_detail/39428.html
net.ipv4.conf.all.rp_filter=0 net.ipv4.conf.default.rp_filter=0 net.ipv4.conf.default.arp_announce = 2 net.ipv4.conf.lo.arp_announce=2 net.ipv4.conf.all.arp_announce=2
see details in https://help.aliyun.com/knowledge_detail/41334.html
net.ipv4.tcp_max_tw_buckets=5000 net.ipv4.tcp_syncookies=1 net.ipv4.tcp_fin_timeout=30 net.ipv4.tcp_synack_retries=2 kernel.sysrq=1
[root@centos-7-51 ~]# sysctl -p
- 打开的文件句柄数
[root@centos-7-51 ~]# vim /etc/security/limits.conf
- soft nofile 65535
- hard nofile 65535
``` [root@centos-7-51 ~]# vim /etc/systemd/system.conf # 修改默认打开的文件数 DefaultLimitNOFILE=65535 [root@centos-7-51 ~]# systemctl daemon-reexec
4.2.2. docker
[root@centos-7-51 ~]# cat /etc/docker/daemon.json { "graph": "/data/docker", "oom-score-adjust": -1000, "log-driver": "json-file", "log-opts": { "max-size": "32m", "max-file": "3" }, "max-concurrent-downloads": 10, "max-concurrent-uploads": 10, "bip": "172.24.20.1/24", "registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"], "insecure-registries": ["harbor.ddn.com"], "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } [root@centos-7-51 ~]# systemctl restart docker
[root@centos-7-51 ~]# vim /usr/lib/systemd/system/docker.service # 在[Service]块增加以下两个配置 OOMScoreAdjust=-1000 ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT [root@centos-7-51 ~]# systemctl daemon-reload && systemctl restart docker
5. Docker相关进程
本章讨论 docker 安装时涉及的软件包,以及启动后涉及的进程。以 CentOS 7 安装 docker-ce 为例。
5.1. 软件包
安装中涉及到的软件包有三个:
- docker-ce-cli
docker-ce-cli 是客户端工具,主要提供了 docker 命令,用来连接本地或者远程的 docker 服务端。
[root@centos-7-51 ~]# rpm -ql docker-ce-cli | grep -v man
/usr/bin/docker
/usr/libexec/docker/cli-plugins/docker-app
/usr/libexec/docker/cli-plugins/docker-buildx
/usr/share/bash-completion/completions/docker
- docker-ce
docker-ce 提供了三个二进制文件和两个 systemd unit 文件:
[root@centos-7-51 ~]# rpm -ql docker-ce
/usr/bin/docker-init
/usr/bin/docker-proxy
/usr/bin/dockerd
/usr/lib/systemd/system/docker.service
/usr/lib/systemd/system/docker.socket
- 二进制文件
dockerd : 创建 docker 守护进程的
docker-proxy
- /usr/lib/systemd/system/docker.service
从service文件能看到,docker.service 强依赖于 docker.socket 和 containerd.service,并且在开机时会在 firewalld 和 containerd 服务之后启动.
docker.service 是通过 dockered二进制文件启动,并且指定了 containerd 的socket 地址
docker.service reload 是通过发送 HUP 到docker.service主进程的
[root@centos-7-51 ~]# cat /usr/lib/systemd/system/docker.service|grep -Ev "#|^$"
[Unit]
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket
[Service]
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT
ExecReload=/bin/kill -s HUP $MAINPID
......
- /usr/lib/systemd/system/docker.socket ``` [root@centos-7-51 ~]# cat /usr/lib/systemd/system/docker.socket [Unit] Description=Docker Socket for the API PartOf=docker.service
[Socket] ListenStream=/var/run/docker.sock SocketMode=0660 SocketUser=root SocketGroup=docker …….
3. containerd.io
containerd.io 配置文件是`config.toml`,并且包含了 `containerd`、`containerd-shim`和`runc`,`ctr`是containerd的客户端管理工具。
[root@centos-7-51 ~]# rpm -ql containerd.io /etc/containerd/config.toml /usr/bin/containerd /usr/bin/containerd-shim /usr/bin/containerd-shim-runc-v1 /usr/bin/containerd-shim-runc-v2 /usr/bin/ctr /usr/bin/runc /usr/lib/systemd/system/containerd.service ……
- /etc/containerd/config.toml
containerd 配置比 docker 要麻烦的多,但是 docker 本身比较臃肿, kubernetes 正在逐渐抛弃 docker,学会配置 containerd 是必要的。<br />使用`containerd config default` 获取默认配置,相关配置可以参考containerd[官方文档](https://github.com/containerd/cri/blob/master/docs/config.md)。
- 二进制位文件
runc 直接管理容器生命周期的程序,最底层的容器运行时<br />containerd 是containerd服务的守护进程程序,containerd 服务通过 containerd-shim 调用 runc 管理容器生命周期。<br />ctr 是 containerd 的客户端工具
- containerd.service
[Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target local-fs.target [Service] ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/bin/containerd Type=notify Delegate=yes KillMode=process Restart=always RestartSec=5 LimitNPROC=infinity LimitCORE=infinity LimitNOFILE=1048576 TasksMax=infinity OOMScoreAdjust=-999 [Install] WantedBy=multi-user.target
<a name="K4jpp"></a>
## 5.2. 进程之间关系
启动两个 docker 容器,并映射端口和存储卷:
[root@centos-7-51 ~]# docker run -d —rm -p 8080:80 -v /tmp/aa:/tmp nginx:latest [root@centos-7-51 ~]# docker run -d —rm -p 8081:80 -v /tmp/bb:/tmp nginx:latest [root@centos-7-51 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2792284fc6e7 nginx:latest “/docker-entrypoint.…” 10 seconds ago Up 9 seconds 0.0.0.0:8081->80/tcp dreamy_leavitt 0b0a76475750 nginx:latest “/docker-entrypoint.…” 18 seconds ago Up 17 seconds 0.0.0.0:8080->80/tcp cool_roentgen
使用 `ps`命令查看进程之间的拓扑关系:<br />在启动容器后,dockerd 服务会启动 docker-proxy 进行端口映射管理,每个需要NAT映射的容器启动一个 docker-proxy<br />每启动一个容器,containerd 服务会创建 containerd-shim 创建容器,containerd-shim会指定使用runc创建容器(/var/run/docker/runtime-runc)
[root@centos-7-51 ~]# ps axf PID TTY STAT TIME COMMAND 11902 ? Ssl 1:18 /usr/bin/dockerd -H fd:// —containerd=/run/containerd/containerd.sock 77366 ? Sl 0:00 _ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.24.20.2 -container-port 80 77460 ? Sl 0:00 _ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8081 -container-ip 172.24.20.3 -container-port 80
1596 ? Ssl 6:32 /usr/bin/containerd 77371 ? Sl 0:00 _ containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/0b0a76475750c44a6b30c8dbcc72265164b13e384e843a1126e9cce4c23 77385 ? Ss 0:00 | _ nginx: master process nginx -g daemon off; 77435 ? S 0:00 | _ nginx: worker process 77465 ? Sl 0:00 _ containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/2792284fc6e77f49a48b41e6dc40986fc0897824a5ba397176436fcc128 77480 ? Ss 0:00 _ nginx: master process nginx -g daemon off; 77530 ? S 0:00 _ nginx: worker process
```
[root@centos-7-51 ~]# ps uax|grep containerd
root 1596 0.1 2.4 1089028 49400 ? Ssl Sep07 6:34 /usr/bin/containerd
root 11902 0.0 5.2 651988 106032 ? Ssl Sep07 1:19 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root 77371 0.0 0.3 709084 7372 ? Sl 08:11 0:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/0b0a76475750c44a6b30c8dbcc72265164b13e384e843a1126e9cce4c2331310 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root 77465 0.0 0.3 709084 7768 ? Sl 08:11 0:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/2792284fc6e77f49a48b41e6dc40986fc0897824a5ba397176436fcc1282e49e -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc