1.实现并总结容器跨主机的通信过程
1.1 修改docker默认子网实现跨主机通信
首先,需要准备2
台机器,以下环境系统为Ubuntu 20.04.6 LTS
初始化安装,安装的docker为最新24.0.2
规划默认IP地址范围如下
主机名 | 主机IP | docker的IP地址范围 |
---|---|---|
harbor1 | 10.0.0.231 | 10.10.0.1/24 |
harbor2 | 10.0.0.232 | 10.20.0.1/24 |
思路如下:
-
修改docker的默认地址范围
-
在两台主机添加静态路由
-
iptables
规则配置允许响应报文转发,记得需要看Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
这里面的规则是拒绝还是允许,以下环境演示的是ACCEPT
开始操作
# 第一台主机操作->10.0.0.231
[root@harbor1 ~]$ sed -i 's/containerd\.sock$/& --bip=10.10.0.1\/24/' /lib/systemd/system/docker.service
[root@harbor1 ~]$ systemctl daemon-reload && systemctl restart docker
[root@harbor1 ~]$ ip a |grep docker0 -A 4
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:8c:8e:46:6e brd ff:ff:ff:ff:ff:ff
inet 10.10.0.1/24 brd 10.10.0.255 scope global docker0
valid_lft forever preferred_lft forever
# route命令是需要安装net-tools包的,没有的话需要先安装
[root@harbor1 ~]$ apt install net-tools
# 添加静态路由
[root@harbor1 ~]$ route add -net 10.20.0.0/24 gw 10.0.0.232 #此处是临时添加,重启失效
# 永久添加方式是在网卡配置文件添加静态路由
[root@harbor1 ~]$ vim /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
ethernets:
ens33:
addresses:
- 10.0.0.232/24
gateway4: 10.0.0.2
nameservers:
addresses:
- 223.5.5.5
search: []
routes: # 添加这3行
- to: 10.20.0.0/24
via: 10.0.0.232
version: 2
[root@harbor1 ~]$ netplan apply # 重启网卡生效
# 10.20.0.0 是添加的静态路由
[root@harbor1 ~]$ route -F
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default _gateway 0.0.0.0 UG 0 0 0 ens33
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33
10.10.0.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
10.20.0.0 10.0.0.232 255.255.255.0 UG 0 0 0 ens33
# 添加IPtable规则
[root@harbor1 ~]$ iptables -A FORWARD -s 10.0.0.232 -j ACCEPT
## 如果有多台主机需要打通建议直接加网段 10.0.0.0/21
# 第二台主机操作->10.0.0.232
[root@harbor1 ~]$ sed -i 's/containerd\.sock$/& --bip=10.20.0.1\/24/' /lib/systemd/system/docker.service
[root@harbor1 ~]$ systemctl daemon-reload && systemctl restart docker
[root@harbor1 ~]$ ip a |grep docker0 -A 4
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:8c:8e:46:6e brd ff:ff:ff:ff:ff:ff
inet 10.20.0.1/24 brd 10.10.0.255 scope global docker0
valid_lft forever preferred_lft forever
# route命令是需要安装net-tools包的,没有的话需要先安装
[root@harbor1 ~]$ apt install net-tools
# 添加静态路由
[root@harbor1 ~]$ route add -net 10.10.0.0/24 gw 10.0.0.231
# 10.10.0.0 是添加的静态路由
[root@harbor2 /data]$ route -F
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default _gateway 0.0.0.0 UG 0 0 0 ens33
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33
10.10.0.0 10.0.0.231 255.255.255.0 UG 0 0 0 ens33
10.20.0.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
# 添加IPtable规则
[root@harbor2 ~]$ iptables -A FORWARD -s 10.0.0.231 -j ACCEPT
## 如果有多台主机需要打通建议直接加网段 10.0.0.0/21
验证两台主机的容器相互通信
# 拉取busybox镜像,里面包含各种工具,足够这次验证
[root@harbor1 ~]$ docker pull busybox
# 10.0.0.231主机启动镜像
[root@harbor1 ~]$ docker run -it busybox sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:0a:0a:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.10.0.2/24 brd 10.10.0.255 scope global eth0
valid_lft forever preferred_lft forever
# 10.0.0.232主机启动镜像
[root@harbor2 /data]$ docker run -it busybox sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:0a:14:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.20.0.2/24 brd 10.20.0.255 scope global eth0
valid_lft forever preferred_lft forever
# 10.0.0.231主机去ping10.0.0.232的主机,能ping通即可
/ # ping 10.20.0.2
PING 10.20.0.2 (10.20.0.2): 56 data bytes
64 bytes from 10.20.0.2: seq=0 ttl=62 time=0.442 ms
64 bytes from 10.20.0.2: seq=1 ttl=62 time=0.618 ms
64 bytes from 10.20.0.2: seq=2 ttl=62 time=0.315 ms
64 bytes from 10.20.0.2: seq=3 ttl=62 time=0.471 ms
^C
--- 10.20.0.2 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.315/0.461/0.618 ms
1.2 实现原理
1.2.1结论
-
源容器发出请求报文到网关docker0
-
docker0收到后判断目的IP,如果是本机直接转发,不是就转发给宿主机eth0
-
源宿主机收到报文后查看路由表,将源地址替换为eth0的IP发送给目的主机
-
目的主机收到请求报文,查看目的IP和端口,将报文转发给docker0
-
docker0查看IP和MAC地址,转发给容器。
1.2.2 实现过程
主机地址及MAC地址如下
主机名 | 主机IP(mac地址) | docker0地址(mac地址) | 容器地址(mac地址) |
---|---|---|---|
node1 | 10.0.0.231(00:0c:29:7a:44:fb) | 10.10.0.1(02:42:42:b4:c0:3f) | 10.20.0.2(02:42:0a:0a:00:02) |
node2 | 10.0.0.232(00:0c:29:a3:90:fc) | 10.20.0.1(02:42:ad:20:5c:94) | 10.20.0.2(02:42:0a:14:00:02) |
基于上面的地址规划,分别在两台node主机上的ens33
网口,docker0
网卡,容器
网卡上抓包
该场景是在node1上运行一个容器去访问node2上的nginx的80端口抓包,具体实现参照上边运行容器,这里不再给出,给出对应的抓包命令:
# node1上
tcpdump -nn -vvv -i veth38ab290 -vvv -nn ! port 22 and ! arp and ! port 53 -w 231-veth38ab290.pacp
tcpdump -nn -vvv -i docker0 -vvv -nn ! port 22 and ! arp and ! port 53 -w 231-docker0.pacp
tcpdump -nn -vvv -i ens33 -vvv -nn ! port 22 and ! arp and ! port 53 and ! port 1900 -w 231-ens33.pacp
# node2上
tcpdump -nn -vvv -i vethc374c59 -vvv -nn ! port 22 and ! arp and ! port 53 -w 232-vethc374c59.pacp
tcpdump -nn -vvv -i docker0 -vvv -nn ! port 22 and ! arp and ! port 53 -w 232-docker0.pacp
tcpdump -nn -vvv -i ens33 -vvv -nn ! port 22 and ! arp and ! port 53 -w 232-ens33.pacp
抓包分析报文原理画成如下图所示,并标注了颜色,感兴趣的小伙伴可以自行抓包查看
2.总结Dockerfile的常见指令
2.1dockerfile文件常见命令
详细参考:
FROM:指定基础镜像,构建新镜像的起点。
RUN:在容器中执行命令,用于安装软件包、运行脚本等。
COPY:复制文件或目录到容器中。
ADD:类似于 COPY,但支持更复杂的操作,如自动解压缩文件。不支持zip
WORKDIR:设置工作目录,后续的指令将在该目录下执行。
ENV:设置环境变量,供后续的指令和应用程序使用。
EXPOSE:声明容器运行时的监听端口。
CMD:指定容器启动时要执行的默认命令或程序。
ENTRYPOINT:与 CMD 类似,但指定的命令不会被 Dockerfile 中的 CMD 覆盖。
VOLUME:声明匿名卷或挂载点。
ARG:定义构建时传递给构建器的变量。
MAINTAINER:构建镜像的作者信息(已弃用,推荐使用 LABEL)。
LABEL:为镜像添加元数据,如版本号、描述等。
USER:设置运行容器时的用户名或 UID。
HEALTHCHECK:定义容器的健康检查命令。
SHELL:指定用于执行后续指令的默认 shell。
举个例子:基于alpine
构建nginx
镜像
# 指定基础镜像
FROM alpine:3.14
# 指定作者
LABEL author="nat_su"
# RUN相当于平时在shell里面执行的命令,非常常用
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.14/main/" > /etc/apk/repositories \
&& apk update \
&& apk upgrade \
&& apk add --no-cache tzdata build-base pcre pcre-dev openssl openssl-dev zlib zlib-dev gcc \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& rm -rf /var/cache/apk/*
# 运行命令
RUN adduser -s /sbin/nologin -D nginx \
&& mkdir -p /usr/local/src \
&& mkdir -p /apps/nginx
# 拷贝宿主机文件,并自动解压,不支持zip,非常常用
ADD nginx-1.24.0.tar.gz /usr/local/src
# 运行命令
RUN cd /usr/local/src/nginx-1.24.0 \
&& ./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
&& make && make install \
&& chown -R nginx.nginx /apps/nginx
# 设置环境变量
ENV PATH $PATH:/apps/nginx/sbin
# nginx 启动命令
ENTRYPOINT ["nginx", "-g", "daemon off;"]
dockerfile打包命令
# 打包镜像
docker build -t='alpine-nginx:1.0' .
# 整合成脚本-打tag及上传镜像
cat bulid.sh
#!/bin/bash
docker build -t harbor.rootnat.com/baseimage/$1 .
docker push harbor.rootnat.com/baseimage/$1
# 启动镜像,访问映射的80端口即可成功访问
docker run -it -p 80:80 -d alpine-nginx:1.0
3.基于Dockerfile Nginx镜像并验证可以启动为容器
基于alpine编译nginx
[root@docker /data/nginx]$ vim dockerfile
# 指定基础镜像
FROM alpine:3.14
# 指定作者
LABEL author="nat_su"
# RUN相当于平时在shell里面执行的命令,非常常用
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.14/main/" > /etc/apk/repositories \
&& apk update \
&& apk upgrade \
&& apk add --no-cache tzdata build-base pcre pcre-dev openssl openssl-dev zlib zlib-dev gcc \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& rm -rf /var/cache/apk/*
# 运行命令
RUN adduser -s /sbin/nologin -D nginx \
&& mkdir -p /usr/local/src \
&& mkdir -p /apps/nginx
# 拷贝宿主机文件,并自动解压,不支持zip,非常常用
ADD nginx-1.24.0.tar.gz /usr/local/src
# 运行命令
RUN cd /usr/local/src/nginx-1.24.0 \
&& ./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
&& make && make install \
&& chown -R nginx.nginx /apps/nginx
# 设置环境变量
ENV PATH $PATH:/apps/nginx/sbin
# nginx 启动命令
ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@docker /data/nginx]$ wget https://nginx.org/download/nginx-1.24.0.tar.gz
[root@docker /data/nginx]$ docker build -t apline-nginx:v1 .
[root@docker /data/nginx]$ docker run -it -p 80:80 -d alpine-nginx:1.0
# 验证
[root@docker /data/nginx]$ curl 10.0.0.231
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
4.部署单机harbor并实现镜像的上传与下载
# 部署 先安装docker,docker-compose此处省略
[root@harbor1 /data/harbor]$ ls
harbor-offline-installer-v2.8.2.tgz
[root@harbor1 /data/harbor]$ tar xf harbor-offline-installer-v2.8.2.tgz
[root@harbor1 /data/harbor]$ cd harbor/
[root@harbor1 /data/harbor/harbor]$ cp harbor.yml.tmpl harbor.yml
# harbor的http配置只需改域名、注释掉https、以及密码,详细按照下图配置
[root@harbor1 /data/harbor/harbor]$ vim harbor.yml
# 开始安装
[root@harbor1 /data/harbor/harbor]$ bash install.sh
[Step 0]: checking if docker is installed ...
Note: docker version: 24.0.2
[Step 1]: checking docker-compose is installed ...
Note: docker-compose version: 1.28.6
[Step 2]: loading Harbor images ...
...
[Step 5]: starting Harbor ...
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating registryctl ... done
Creating harbor-db ... done
Creating registry ... done
Creating redis ... done
Creating harbor-portal ... done
Creating harbor-core ... done
Creating harbor-jobservice ... done
Creating nginx ... done
✔ ----Harbor has been installed and started successfully.----
# 这样代表harbor安装成功了
4.1 linux主机推送上传镜像需要配置:
1.添加一条hosts
解析记录,指向harbor.rootnat.com
2.配置/etc/docker/daemon.json
增加一行配置 "insecure-registries": ["harbor.rootnat.com"]
并重启docker
3.登录docker
镜像仓库
4.配置web页面,加对应仓库
# 1.添加hosts记录
[root@k8s /data]$ echo "10.0.0.231 harbor.rootnat.com" >> /etc/hosts
[root@k8s /data]$ ping harbor.rootnat.com
PING harbor.rootnat.com (10.0.0.231) 56(84) bytes of data.
64 bytes from harbor.rootnat.com (10.0.0.231): icmp_seq=1 ttl=64 time=0.392 ms
^C
--- harbor.rootnat.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.392/0.392/0.392/0.000 ms
# 2.配置insecure-registries,并重启docker
[root@k8s /data]$ vim /etc/docker/daemon.json
{
"data-root": "/var/lib/docker",
"storage-driver": "overlay2",
"insecure-registries": ["harbor.rootnat.com"], # http的这里要配置该地址
"registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": false,
"log-opts": {
"max-file": "5",
"max-size": "100m"
}
}
[root@k8s /data]$ systemctl restart docker
# 3.登录docker仓库
root@k8s:/data# docker login harbor.rootnat.com
Username: admin # 输入用户名
Password: # 输入密码
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded # 提示成功即可
# 4. 镜像仓库配置具体看下图
# 5. 打一个基于apline的基础镜像
[root@k8s /data/baseimages]$ cat dockerfile
FROM alpine:3.14
# 指定作者
LABEL author="nat_su"
# RUN相当于平时在shell里面执行的命令,非常常用
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.14/main/" > /etc/apk/repositories \
&& apk update \
&& apk upgrade \
&& apk add --no-cache tzdata build-base pcre pcre-dev openssl openssl-dev zlib zlib-dev gcc \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& rm -rf /var/cache/apk/*
# 6. 推送脚本
[root@k8s /data/baseimages]$ cat build.sh
#!/bin/bash
docker build -t harbor.rootnat.com/baseimage/$1 .
docker push harbor.rootnat.com/baseimage/$1
# 7.执行推送脚本
[root@k8s /data/baseimages]$ bash build.sh alpine_base:3.14
4.2下载镜像
# 1.查看当前镜像
[root@k8s /data/baseimages]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine 3.14 0a97eee8041e 20 months ago 5.61MB
# 2.拉取镜像
[root@k8s /data/baseimages]$ docker pull harbor.rootnat.com/baseimage/alpine_base:v3.14
v3.14: Pulling from baseimage/alpine_base
97518928ae5f: Already exists
dca61add5ae0: Pull complete
Digest: sha256:c184899b2326a49c5438215226b435c0ce6a7aef101dd76c222ef35e1399538d
Status: Downloaded newer image for harbor.rootnat.com/baseimage/alpine_base:v3.14
harbor.rootnat.com/baseimage/alpine_base:v3.14
# 3.再次查看镜像
[root@k8s /data/baseimages]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
harbor.rootnat.com/baseimage/alpine_base v3.14 941ef8881e5d 4 minutes ago 212MB
alpine 3.14 0a97eee8041e 20 months ago 5.61MB
5.基于systemd实现容器的CPU及内存的使用限制
默认情况下,容器没有资源限制,可以使用主机内核调度程序允许的尽可能多的给定资源,Docker提供了控制容器可以限制容器使用多少内存或CPU的方法,运行docker run
命令创建容器的时候可以进行资源限制。
要实现容器资源限制,需要满足:
- 改
docker
的配置文件/etc/docker/daemon.json
配置"exec-opts": ["native.cgroupdriver=systemd"]
- 使用
docker info
命令检查下内核是否有WARNING
警告,参考官方文档解决相关警告
可以使用lorel/docker-stress-ng
镜像测试
5.1 CPU资源限制
# cpu限制参数
--cpus=<value> #指定容器可以使用多少可用CPU资源。例如,如果主机有两个CPU,那么可分配的数量就为2,可以设置为1.5。写法有2种方式,一种是--cpus="1.5",另一种是--cpu-quota="150000"。
--cpu-period=<value> # 指定CPU CFS计划程序周期,默认值为100000微秒(100毫秒),一般不会调整改值
--cpu-quota=<value> # 对容器施加CPU CFS配额。容器在被限制之前的微秒数。一般也很少用
--cpuset-cpus #限制容器可以使用的特定CPU或内核。如果您有多个CPU,容器可以使用的CPU的逗号分隔列表或连字符分隔范围。第一个CPU编号为0。有效值可能是(使用第一、第二、第三和第四CPU)或(使用第二和第四CPU)。可以理解成nginx的cpu绑定
--cpu-shares #将此标志设置为大于或小于默认值1024的值,以增加或减少容器的重量,并给予它访问主机CPU周期的更大或更小比例。只有当CPU周期受到限制时才强制执行此操作。当有大量的CPU周期可用时,所有的容器都会使用它们所需的CPU。这是一个软限制。并不阻止集装箱以群模式调度。它为可用的CPU周期划分容器CPU资源的优先级。它不保证或保留任何特定的CPU访问。
举个例子:
1.如果主机有一个cpu
那么有2
种方式是可以保证容器每秒最多使用50%的CPU
# 第一种方式
[root@k8s /data/baseimages]$ docker run -it --cpus=".5" ubuntu /bin/bash
# 第二种方式
[root@k8s /data/baseimages]$ docker run -it --cpu-period=100000 --cpu-quota=50000 ubuntu /bin/bash
2.给容器分配最多两核宿主机CPU利用率
# 宿主机有4核CPU
[root@harbor2 ~]$ lscpu |grep "CPU(s): "
CPU(s): 4
NUMA node0 CPU(s): 0-3
# 给容器分配最多2核宿主机的CPU使用
[root@harbor2 ~]$ docker run -it --rm --name rootnat-c1 --cpus 2 lorel/docker-stress-ng --cpu 4 --vm 4
# 验证 top命令可以看到占用了4核cpu,每个核心大概50%
top - 11:38:57 up 5:54, 2 users, load average: 0.36, 0.20, 0.07
Tasks: 235 total, 10 running, 225 sleeping, 0 stopped, 0 zombie
%Cpu0 : 51.2 us, 0.0 sy, 0.0 ni, 48.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 50.0 us, 0.3 sy, 0.0 ni, 49.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 50.3 us, 0.0 sy, 0.0 ni, 49.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 49.0 us, 0.0 sy, 0.0 ni, 51.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 7915.1 total, 5782.8 free, 1450.2 used, 682.0 buff/cache
MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 6207.5 avail Mem
5.2 内存资源限制
# 物理内存限制参数
-m or --memory #限制容器可以使用的最大内存量,如果设置此选项,最小存值为4m(4兆字节)
--memory-swap #容器可以使用的交换分区大小,必须要在设置了物理内存限制的前提才能设置交换分区的限制
--memory-swappiness #设置容器使用交换分区的倾向性,值越高表示越倾向于使用swap分区,范围为0-100,0为能不用就不用,100为能用就用
--kernel-memory #容器可以使用的最大内核内存量,最小为4m,由于内核内存与用户空间内存隔离,因此无法与用户空间内存直接交换,因此内核内存不足的容器可能会阻塞宿主主机资源,这会对主机和其他容器或者其他服务进程产生影响,因此不要设置内核内存大小
--memory-reservation #允许指定小于--memory的软限制,当Docker检测到主机上的争用或内存不足时会激活该限制,如果使用-- memory-reservation,则必须将其设置为低于--memory才能使其优先。 因为它是软限制,所以不能保证容器不超过限制。
--oom-kill-disable #默认情况下,发生OOM时,kernel会杀死容器内进程,但是可以使用--oom-kill-disable参数,可以禁止oom发生在指定的容器上,即 仅在已设置-m / - memory选项的容器上禁用OOM,如果-m 参数未配置,产生OOM时,主机为了释放内存还会杀死系统进程。
# 交换分区限制参数
--memory-swap #只有在设置了 --memory 后才会有意义。使用Swap,可以让容器将超出限制部分的内存置换到磁盘上,WARNING:经常将内存交换到磁盘的应用程序会降低性能。不同的--memory-swap设置会产生不同的效果:
--memory-swap #值为正数, 那么--memory和--memory-swap都必须要设置,--memory-swap表示你能使用的内存和swap分区大小的总和,例如: --memory=300m, --memory-swap=1g, 那么该容器能够使用 300m 内存和 700m swap,即--memory是实际物理内存大小值不变,而swap的实际大小计算方式为(--memory-swap)-(--memory)=容器可用swap。
--memory-swap #如果设置为0,则忽略该设置,并将该值视为未设置,即未设置交换分区。
--memory-swap #如果等于--memory的值,并且--memory设置为正整数,容器无权访问swap即也没有设置交换分区。
--memory-swap #如果设置为unset,如果宿主机开启了swap,则实际容器的swap值为2x( --memory),即两倍于物理内存
大小,但是并不准确(在容器中使用free命令所看到的swap空间并不精确,毕竟每个容器都可以看到具体大小,但是宿主机的
swap是有上限而且不是所有容器看到的累计大小)。
--memory-swap #如果设置为-1,如果宿主机开启了swap,则容器可以使用主机上swap的最大空间。
宿主机内存为8G,限制内存为256m,压测两个进程,每个进程512M
# 限制内存为256m,压测两个进程,每个进程512M
[root@harbor2 ~]$ docker run --rm --name rootnat-1 -m 256m lorel/docker-stress-ng --vm 2 --vm-bytes 512M
# 验证
[root@harbor2 ~]$ docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
89ea7451b711 rootnat-1 168.69% 255.9MiB / 256MiB 99.98% 806B / 0B 227MB / 0B 5
5.3 容器资源限制验证
[root@harbor2 ~]$ docker run --rm --name rootnat-3 --cpus 1 -m 512M lorel/docker-stress-ng --cpu 2 --vm 2 --vm-bytes 512M
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 cpu, 2 vm
# 过滤出pid为17971
[root@harbor2 /]$ ps -ef|grep vm
root 284 2 0 00:33 ? 00:00:07 [irq/16-vmwgfx]
root 747 1 0 00:34 ? 00:00:38 /usr/bin/vmtoolsd
root 17915 2137 0 10:31 pts/0 00:00:00 docker run --rm --name rootnat-3 --cpus 1 -m 512M lorel/docker-stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 17971 17944 0 10:31 ? 00:00:00 /usr/bin/stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 17993 17971 25 10:31 ? 00:00:05 /usr/bin/stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 17994 17971 0 10:31 ? 00:00:00 /usr/bin/stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 17995 17971 25 10:31 ? 00:00:05 /usr/bin/stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 17996 17971 0 10:31 ? 00:00:00 /usr/bin/stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 17997 17996 24 10:31 ? 00:00:05 /usr/bin/stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 18007 17994 29 10:31 ? 00:00:01 /usr/bin/stress-ng --cpu 2 --vm 2 --vm-bytes 512M
root 18010 2334 0 10:31 pts/1 00:00:00 grep --color=auto vm
[root@harbor2 /]$ cat /proc/17971/cpuset
/system.slice/docker-5aaa2729aae0bc9ac9117f3943b696c1040c1939c9671cec020b544a23cc06a8.scope
# cpu限制
[root@harbor2 /]$ cat /sys/fs/cgroup/cpu/system.slice/docker-5aaa2729aae0bc9ac9117f3943b696c1040c1939c9671cec020b544a23cc06a8.scope/cpu.cfs_quota_us
100000
# 内存限制
[root@harbor2 /]$ cat /sys/fs/cgroup/memory/system.slice/docker-5aaa2729aae0bc9ac9117f3943b696c1040c1939c9671cec020b544a23cc06a8.scope/memory.limit_in_bytes
536870912
标签:00,--,0.0,nginx,第二周,docker,root
From: https://www.cnblogs.com/rootnat/p/hw2.html