docker使用cgroup控制资源,K8S里面也有limits
Docker通过Cgroup来控制容器使用的资源配额,包括CPU、内存、磁盘三大方面,基本覆盖了常见的资源配额和使用量控制。
Cgroup是Control Groups 的缩写,是Linux 内核提供的。种可以限制、记录、隔离进程组所使用的物理资源(如CPU、内存、磁盘Io等等)的机制
cpu在同一时刻只能给一个进程占用
docker run -itd --cpu-shares 100 centos:stress
--cpu-shares 参数值不能保证可以获得1个vcpu或者多少GHZ的cpu资源,它仅是一个弹性的的加权值。
说明:默认情况下,每个Docker容器的CPU份额都是1024。单独一个容器的份额是没有意义的。只有在同时运行多个容器时,容器的 cPO加权的效果才能体现出来。
docker run -itd --name cpu512 --cpu-shares 512 centos:stress stress -c 10 #容器产生10个子函数进程
docker stats 查看资源使用
docker提供了--cpu-period、--cpu-quota两个参数控制容器可以分配到的cpu时钟周期。
--cpu-period是用来指定容器对cpu的使用要在多长时间内做一次重新分配
--cpu-quota 是用来指定在这个周期内,最多可以有多少时间用来跑这个容器,与--cpu-shares不同的是,这种配置是指定一个绝对值,容器对cpu资源的使用绝对不会超过配置的值。
例如:容器进程需要每1秒使用单个CPU 的0.2 秒时间,可以将cpu-period 设置为1000000 (即1秒),cpu-quota 设置为200000 (0.2秒)。
当然,在多核情况下,如果允许容器进程完全占用两个CPU,则可以将cpu-period 设置为100000 (即0.1 秒),
cpu-quota设置为200000 (0.2 秒)。
docker run -itd --cpu-period 100000 --cpu-quota 200000 centos:stress
cat /sys/fs/cgroup/cpu/cpu.cfs_period_us #查看多长时间周期运行一次
cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us #查看这个周期内运行多长时间
或者docker inspect 容器ID/容器名
**宿主机怎么提供资源、怎么控制docker容器中的应用的:**
CPU --->VCPU--> 以进程的方式体现在workstation环境(docker环境中) ---》 docker表现形式是容器-->Vcpu以进程的方式控制容器--》容器中的应用需要的是服务进程支持--》宿主机内核中cpu可以被cgroup管理(通过分配资源手段) --》linux 内核中的cgroup可以控制管理docker容器中的应用
对多核CPU的服务器,Docker 还可以控制容器运行使用哪些CPU内核,即使用–cpuset-cpus参数。
这对具有多CPU的服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置。
docker run -itd --name cpu1 --cpuset-cpus 0-1 centos:stress
docker exec -it 容器id bash
cat /sys/fs/cgroup/cpuset/cpuset.cpus #查看容器被哪个cpu核心使用
docker exec 容器ID taskset -c -p 1 #容器内部第一个进程号pid为1被绑定到指定cpu上运行
1、创建容器时,直接使用参数指定资源限制
2、创建容器时,指定资源分配。修改宿主机对应容器资源控制的文件 /sys/fs/cgrop/*
通过cpuset-cpus参数指定容器A使用CPU内核0,容器B只是用CPU内核1。
在主机上只有这两个容器使用对应CPU内核的情况,它们各自占用全部的内核资源,cpu-shares没有明显效果。
cpuset-cpus、cpuset-mems参数只在多核、多内存节点上的服务器上有效,并且必须与实际的物理配置匹配,否则也无法达到资源控制的目的。
在系统具有多个cpu内核的情况下,需要通过cpuset-cpus参数为设置容器cpu内核才能方便的进行测试。
docker run -itd --name cpu3 --cpuset-cpus 1 --cpu-shares 512 centos:stress stress -c 1
#将会给系统一个随机负载,产生1个进程,这个进程都反复不停的计算由rand()产生随机数的平方根,知道耗尽资源
与操作系统类似,容器可使用的内存包括两部分:物理内存和Swap
-m或–memory 设置内存的使用限额,例如100M、1024M
–memory-swap 设置内存+swap的使用限额
执行如下命令允许该容器最多使用200M的内存和300M的swap
docker run -it -m 200M --memory-swap=300M centos:stress --vm 1 --vm-bytes 280M
--vm 1 启动1个内存工作线程
--vm-bytes 280M 每个线程分配280M内存
默认情况下,容器可以使用主机上所有空闲内存
与cpu的cgroups配置类似,Docker会自动为容器在目录/sys/fs/cgroup/memory/docker/容器完整的ID中创建响应cgroup配置文件
如果让工作线程分配的内存超过300M,分配的内存超过限额,stress线程报错,容器退出。
默认情况下,所有容器能平等的读写磁盘,可以通过设置–blkio-weight参数来改变容器block IO的优先级。
–blkio-weight与–cpu-shares类似,设置的是相对权重值,默认为500.
在下面的例子中,容器A读写磁盘的带宽是容器B的两倍
docker run -it --name container_A --blkio-weight 600 centos:stress
docker run -it --name container_B --blkio-weight 300 centos:stress
cat /sys/fs/cgroup/blkio/blkio.weight
bps是byte per second,每秒读写的数据量
iops是io per second,每秒IO的次数
可以通过以下参数控制容器的bps和iops
–device-read-bps,限制读某个设备的bps
–device-write-bps,限制写某个设备的bps
–device-read-iops,限制读某个设备的iops
–device-write-iops,限制写某个设备的iops
#下面示例是限制容器写/dev/sda的速率是5MB/s
docker run -it --device-write-bps /dev/sda:5MB centos:stress
dd if=/dev/zero of=test bs=1M count=10 oflag=direct //可以按ctrl+c中断查看
通过dd命令测试在容器中写磁盘的速度。因为容器的文件系统是在host /dev/sda上的,在容器中写文件相当于对host /dev/sda进行写操作。另外,oflag=direct指定用direct IO 方式写文件,这样--device-write-bps才能生效
构建镜像时指定资源限制
–bulid-arg=[] | 设置镜像创建时的变量 |
---|---|
–cpu-shares | 设置cpu使用权重 |
–cpu-period | 限制cpu cfs周期 |
–cpu-quota | 限制cpu cfs配额 |
–cpu-cpus | 指定使用的cpu id |
–cpu-mems | 指定使用的内存id |
–disable-content-trust | 忽略校验,默认开启 |
-f | 指定要使用的Dockerfile路径 |
–force-rm | 设置镜像过程中删除中间容器 |
–isolation | 使用容器隔离技术 |
–label=[] | 设置镜像使用的元数据 |
-m | 设置内存最大值 |
–memory-swap | 设置swap的最大值为内存+swap,“-1”表示不限swap |
–no-cache | 创建镜像的过程不使用缓存 |
–pull | 尝试去更新镜像的新版本 |
–quiet,-q | 安静模式,成功后只输出镜像ID |
–rm | 设置镜像成功后删除中间容器 |
–shm-size | 设置值/dev/shm的大小,默认值64M; |
–ulimit | |
–squash | 将Dockerfile中所有的操作压缩为一层 |
–tag,-t | 镜像的名字及标签,通常name:tag或者name格式;可以在一次构建中为一个镜像设置多个标签 |
–network | 默认default。在构建期间设置run指令的网络模式 |
1、cpu权重shares、quota、cpuset
2、磁盘BPS、TPS限制,指定使用哪个磁盘、磁盘分区
3、内存 -m -swap内存、交换分区
大部分做的是上限的限制
1、bulid构建镜像时,可以指定该镜像的资源限制
2、run将镜像跑为容器的时候,可以指定容器的资源限制。
3、容器启动之后,可以在宿主机对应容器的目录下,修改资源限制,然后重载/sys/fs/cgroup/*(cpu、blk、mem)/docker/容器ID -----》修改对应的资源限制文件参数就可以
1、docker inspect镜像ID/容器ID
2、直接查看宿主机的对应容器ID资源限制文件
docker compose的前身是fig,它是一个定义及运行多个docker容器的工具
使用docker compose不再需要使用shell脚本来启动容器
docker compose非常适合组合使用多个容器进行开发的场景
consul是hashicorp公司推出的开源工具,用于实现分布式系统的服务发现与配置
支持健康检查,允许存储键值对
基于Golong语言,可移植性强
支持ACL访问控制
与docker等轻量级容器可无缝配合
compose:批量构建容器
consul:运行时动态识别、添加新的容器
字段 | 描述 |
---|---|
build dockerfile context | 指定dockerfile文件名构建镜像上下文路径 |
image | 指定镜像 |
command | 执行命令,覆盖默认命令 |
container name | 指定容器名称,由于容器名称是唯一的,如果指定自定义名称,则无法scale |
deploy | 指定部署和运行服务相关配置,只能在Swarm模式使用 |
environment | 添加环境变量 |
networks | 加入网络 |
ports | 暴露容器端口,与-p相同。但端口不能低于60 |
volumes | 挂载宿主机路径或命令卷 |
restart | 重启策略,默认no,always,no-failure,unless-stoped |
hostname | 容器主机名 |
字段 | 描述 |
---|---|
build | 重新构建服务 |
ps | 列出容器 |
up | 创建和启动容器 |
exec | 在容器里面执行命令 |
scale | 指定一个服务容器启动数量 |
top | 显示容器进程 |
logs | 查看容器输出 |
down | 删除容器、网络、数据卷和镜像 |
stop/start/restart | 停止/启动/重启服务 |
192.168.198.128
[root@localhost ~]# curl -L https://github.com/docker/compose/releases/download/1.21.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 633 100 633 0 0 837 0 --:--:-- --:--:-- --:--:-- 837
100 10.3M 100 10.3M 0 0 3338k 0 0:00:03 0:00:03 --:--:-- 5982k
//或者上传docker_compose即可
[root@server ~]# ls
anaconda-ks.cfg docker-compose initial-setup-ks.cfg
[root@server ~]# chmod +x docker-compose //加执行权限
[root@server ~]# cp -p docker-compose /usr/local/bin
[root@server ~]# mkdir /root/compose_nginx
[root@server ~]# cd compose_nginx/
[root@server compose_nginx]# mkdir nginx wwwroot
[root@docker compose_nginx]# cd nginx/ //上传nginx压缩包
[root@docker nginx]# ls
nginx-1.12.2.tar.gz
[root@docker nginx]# vim Dockerfile
FROM centos:7
ADD nginx-1.12.2.tar.gz /mnt
WORKDIR /mnt/nginx-1.12.2
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make &> /dev/null && \
yum clean all && \
sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && \
./configure --prefix=/usr/local/nginx &> /dev/null && \
make &> /dev/null && make install &> /dev/null &&\
rm -rf /mnt/nginx-1.12.2
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
[root@docker nginx]# cd ../wwwroot/
[root@docker wwwroot]# vim index.html
this is dyf
[root@docker wwwroot]# vim /root/compose_nginx/docker-compose.yml
version: '3'
services:
nginx:
hostname: nginx
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- 1216:80
- 1217:443
networks:
- cluster
volumes:
- ./wwwroot:/usr/local/nginx/html
networks:
cluster:
[root@docker nginx]# docker-compose -f docker-compose.yml up -d //基于yml文件运行启动
[root@docker compose_nginx]# docker-compose ps //使用Compose容器编排查询
Name Command State Ports
------------------------------------------------------------------------------------
compose_nginx_nginx_1 /usr/local/nginx/sbin/ngi Up 0.0.0.0:1217->443/tcp,::
n ... :1217->443/tcp, 0.0.0.0:
1216->80/tcp,:::1216->80
/tcp
设备:192.168.198.128(Docker-ce 、Consul、 Consul-template)
192.168.198.129(Docker-ce、registrator)
192.168.198.128
[root@docker ~]# mkdir consul
[root@docker ~]# cd consul/
[root@docker consul]# unzip consul_0.9.2_linux_amd64.zip
Archive: consul_0.9.2_linux_amd64.zip
inflating: consul
mv consul /usr/bin
[root@docker consul]# consul agent \
> -server \
> -bootstrap \
> -ui \
> -data-dir=/var/lib/consuldata \
> -bind=192.168.198.128 \
> -client=0.0.0.0 \
> -node=consul-server01 &> /var/log/consul.log &
[1] 84084
[root@docker consul]# jobs
[1]+ 运行中 consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=192.168.118.44 -client=0.0.0.0 -node=consul-server01 &>/var/log/consul.log &
##查看集群信息
[root@docker consul]# consul members
Node Address Status Type Build Protocol DC
consul-server01 192.168.198.128:8301 alive server 0.9.2 2 dc1
[root@docker
consul]# consul info | grep leader
leader = true
leader_addr = 192.168.198.128:8300
在192.168.198.129上安装 Gliderlabs/Registrator
root@docker nginx]# docker run -d \ ## 安装 Gliderlabs/Registrator Gliderlabs/Registrator
> --name=registrator \
> --net=host \
> -v /var/run/docker.sock:/tmp/docker.sock \
> --restart=always \
> gliderlabs/registrator:latest \
> -ip=192.168.198.129 \
> consul://192.168.198.128:8500
##测试服务发现功能是否正常
[root@docker nginx]# docker run -itd -p:83:80 --name test-01 -h test01 nginx
[root@docker nginx]# docker run -itd -p:84:80 --name test-02 -h test02 nginx
[root@docker nginx]# docker run -itd -p:88:80 --name test-03 -h test03 httpd
[root@docker nginx]# docker run -itd -p:89:80 --name test-04 -h test04 httpd
192.168.198.128节点上安装配置
[root@docker consul]# vim /root/consul/nginx.ctmpl
upstream http_backend {
{{range service "nginx"}}
server {{.Address}}:{{.Port}}; #此处引用的变量会指向后端的地址和端口(动态变化)
{{end}}
}
server {
listen 83;
server_name localhost 192.168.198.128; #反向代理的IP地址(前端展示的NG服务的IP)
access_log /var/log/nginx/whd.cn-access.log;
index index.html index.php;
location / {
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr; #后端真实IP
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #转发地址
proxy_pass http://http_backend;
}
}
手工编译安装nginx
[root@docker consul]# yum install gcc pcre-devel zlib-devel -y
[root@docker consul]# tar zxvf nginx-1.12.2.tar.gz -C /opt
[root@docker consul]# cd /opt/nginx-1.12.2/
[root@docker nginx-1.12.2]# ./configure --prefix=/usr/local/nginx
[root@docker nginx-1.12.2]# make && make install
[root@docker nginx-1.12.2]# vim /usr/local/nginx/conf/nginx.conf ##修改配置文件
[root@docker nginx-1.12.2]# mkdir /usr/local/nginx/conf/vhost #创建虚拟机目录
[root@docker nginx-1.12.2]# mkdir /var/log/nginx ##创建日志文件目录
[root@docker nginx-1.12.2]# /usr/local/nginx/sbin/nginx ##启动nginx
[root@docker nginx-1.12.2]# netstat -antp | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 28727/nginx: master
配置并启动 template
[root@docker opt]# unzip consul-template_0.19.3_linux_amd64.zip ##上去consul-template包并解压
Archive: consul-template_0.19.3_linux_amd64.zip
inflating: consul-template
[root@docker opt]# mv consul-template /usr/bin/
##关联nginx 虚拟目录中的子配置文件
[root@docker opt]# consul-template -consul-addr 192.168.198.128:8500 \
> -template "/root/consul/nginx.ctmpl:/usr/local/nginx/conf/vhost/dyf.conf:/usr/local/nginx/sbin/nginx -s reload" \
> --log-level=info
##再开另一个终端查看
[root@docker opt]# cat /usr/local/nginx/conf/vhost/dyf.conf
upstream http_backend {
server 192.168.198.128:83;
server 192.168.198.129:84;
}
server {
listen 83;
server_name localhost 192.168.198.128;
access_log /var/log/nginx/dyf.cn-access.log;
index index.html index.php;
location / {
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://http_backend;
}
}
在192.168.198.129节点新建容器,确认注册到consul
[root@server docker]# docker run -itd -p:85:80 --name test-06 -h test06 nginx
dcc0eb9e689df6ef3128b4474627bbc85e4f8229f99c081888aa91425c3192c3
[root@docker ~]# cat /usr/local/nginx/conf/vhost/dyf.conf
upstream http_backend {
server 192.168.198.129:83;
server 192.168.198.129:84;
server 192.168.198.129:85; #新添加的
}
server {
listen 83;
server_name localhost 192.168.198.128;
access_log /var/log/nginx/dyf.cn-access.log;
index index.html index.php;
location / {
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://http_backend;
}
}