首页
About Me
推荐
weibo
github
Search
1
linuxea:gitlab-ci之docker镜像质量品质报告
49,197 阅读
2
linuxea:如何复现查看docker run参数命令
21,468 阅读
3
Graylog收集文件日志实例
18,257 阅读
4
git+jenkins发布和回滚示例
17,882 阅读
5
linuxea:jenkins+pipeline+gitlab+ansible快速安装配置(1)
17,778 阅读
ops
Openvpn
Sys Basics
rsync
Mail
NFS
Other
Network
HeartBeat
server 08
Code
Awk
Shell
Python
Golang
virtualization
KVM
Docker
openstack
Xen
kubernetes
kubernetes-cni
Service Mesh
Data
Mariadb
PostgreSQL
MongoDB
Redis
MQ
Ceph
TimescaleDB
kafka
surveillance system
zabbix
ELK Stack
Open-Falcon
Prometheus
victoriaMetrics
Web
apache
Tomcat
Nginx
自动化
Puppet
Ansible
saltstack
Proxy
HAproxy
Lvs
varnish
更多
互联咨询
最后的净土
软件交付
持续集成
gitops
devops
登录
Search
标签搜索
kubernetes
docker
zabbix
Golang
mariadb
持续集成工具
白话容器
linux基础
nginx
elk
dockerfile
Gitlab-ci/cd
最后的净土
基础命令
jenkins
docker-compose
gitops
haproxy
saltstack
Istio
marksugar
累计撰写
676
篇文章
累计收到
140
条评论
首页
栏目
ops
Openvpn
Sys Basics
rsync
Mail
NFS
Other
Network
HeartBeat
server 08
Code
Awk
Shell
Python
Golang
virtualization
KVM
Docker
openstack
Xen
kubernetes
kubernetes-cni
Service Mesh
Data
Mariadb
PostgreSQL
MongoDB
Redis
MQ
Ceph
TimescaleDB
kafka
surveillance system
zabbix
ELK Stack
Open-Falcon
Prometheus
victoriaMetrics
Web
apache
Tomcat
Nginx
自动化
Puppet
Ansible
saltstack
Proxy
HAproxy
Lvs
varnish
更多
互联咨询
最后的净土
软件交付
持续集成
gitops
devops
页面
About Me
推荐
weibo
github
搜索到
26
篇与
的结果
2019-01-21
linuxea:白话容器之Registry与Harbor的构建和使用 (26)
Registry用于保存docker镜像,包括镜像的层次结构和元数据,用户可以自己创建Registry,也可以使用官方的dockerhub,这些Registry支持第三方注册。但是这些Registry在互联网上,使用时候下载的速度不会再快,并且在实际使用中,有多数进行下载,宽带也会成为一个问题。为了达到最快的拉取目的,我们就需要自己构建Registry。Private RegistryRegistry主要用于托管镜像,Registry默认是https的,如果要使用http就需要特别的指定。为了能够使我们快速构建Registry,dockre提供了一个项目distribution,安装即可。而在docker官方已经将Registry作为镜像,由此,我们直接使用Registry镜像就可以运行Registry。Registry主要用于托管镜像,而Registry本身也是托管在容器中,容器的文件系统会随着容器的终止而删除的,Registry运行在容器后这些镜像是不能存放在容器中的,我们将它存储到存储卷内,如:网络存储。当然也可以在本地存放。这种方式很简单就可以运行起来一个Registry。如果不想使用这种方式,也可以使用docker-distribution安装docker-distribution[root@www-linuxea ~]$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo[root@www-linuxea ~]$ yum install docker-distribution -y[root@www-linuxea ~]$ rpm -ql docker-distribution /etc/docker-distribution/registry/config.yml 配置文件 /usr/bin/registry /usr/lib/systemd/system/docker-distribution.service /usr/share/doc/docker-distribution-2.6.2 /usr/share/doc/docker-distribution-2.6.2/AUTHORS /usr/share/doc/docker-distribution-2.6.2/CONTRIBUTING.md /usr/share/doc/docker-distribution-2.6.2/LICENSE /usr/share/doc/docker-distribution-2.6.2/MAINTAINERS /usr/share/doc/docker-distribution-2.6.2/README.md /var/lib/registry 仓库默认目录而后我修改了仓库目录[root@www-linuxea ~]$ mkdir /data/Registry[root@www-linuxea ~]$ cat /etc/docker-distribution/registry/config.yml version: 0.1 log: fields: service: registry storage: cache: layerinfo: inmemory filesystem: rootdirectory: /data/Registry http: addr: :5000[root@www-linuxea ~]$ systemctl start docker-distribution.service [root@www-linuxea ~]$ ss -tlnp|grep 5000 LISTEN 0 32768 *:5000 *:* users:(("registry",pid=9228,fd=3))如果5000端口正常就说明启动成功管理标签我修改了hosts,通过域名来进行打标[root@www-linuxea ~]$ echo "10.10.240.145 registry.linuxea.com" >> /etc/hosts[root@www-linuxea ~]$ cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 10.10.10.250 mirrors.ds.com 10.10.240.145 registry.linuxea.com而后重新打标签,将marksugar/httpd:v7 修改为registry.linuxea.com:5000/marksugar/httpd:v7[root@www-linuxea ~]$ docker tag marksugar/httpd:v7 registry.linuxea.com:5000/marksugar/httpd:v7推送默认是要使用https协议,而服务器断是http,所以这里会报错如下[root@www-linuxea ~]$ docker push registry.linuxea.com:5000/marksugar/httpd:v7 The push refers to repository [registry.linuxea.com:5000/marksugar/httpd] Get https://registry.linuxea.com:5000/v2/: http: server gave HTTP response to HTTPS client通过标记http来解决[root@www-linuxea ~]$ cat /etc/docker/daemon.json { "insecure-registries": ["registry.linuxea.com:5000"] }而后重启[root@www-linuxea ~]$ systemctl restart docker 而后再次推送[root@www-linuxea ~]$ docker push registry.linuxea.com:5000/marksugar/httpd:v7 The push refers to repository [registry.linuxea.com:5000/marksugar/httpd] e37e4dcca4e6: Pushed 7e0e76680fcf: Pushed 7e36f706b93d: Pushed 2d1436269532: Pushed 7030e9e24693: Pushed df64d3292fd6: Pushed v7: digest: sha256:9fd332615f424252c54583f31946816039a5f69d648a35034426be904c75a5e6 size: 1568推送的文件存放在存储目录下,我这里的路径位置是/data/Registry/docker/registry/v2/repositories/marksugar/httpd,在此之下是层目录和上传目录,这些文件又会链接到blobs下[root@DS-linuxea ~]$ ls /data/Registry/docker/registry/v2/repositories/marksugar/httpd _layers _manifests _uploads这些推送过的镜像如果要被pull使用,那么使用的客户端就也需要配置insecure-registriesHarborHarbor是vmware开源的镜像仓库,harbor的安装是非常麻烦的,不过可以使用compose来组合安装。而docker-compose也是一个简单的编排工具,这个编排工具中可以将docker run的命令组合在一个文件中调用,并且可以控制容器的启动顺序。docker-compose的前身是Fig,也是最早最火的编排工具,比k8s早,而后docker公司收购Fig。而在docker-compose中也有多个版本,有2,3版本我们下载离线包安装https://storage.googleapis.com/harbor-releases/release-1.6.0/harbor-offline-installer-v1.6.2.tgz[root@www-Node61_linuxea ~]$ tar xf harbor-offline-installer-v1.6.2.tgz -C /data [root@www-Node61_linuxea ~]$ cd /data/harbor/在harbor.cfg中需要按需修改一些配置,比如hostname,而后./install.sh 在这个docker-compose中定义的文件的映射关系,启动的服务顺序,网络模式,暴露端口等都被事先预设好了,也就是精心设计过的。暂停服务:docker-compose stop重启服务:docker-compose restart启动服务:docker-compose -f ./docker-compose.yaml up -d关闭删除服务:docker-compose down[root@www-Node61_linuxea /data/harbor]# ./install.sh ... [Step 4]: starting Harbor ... Creating network "harbor_harbor" with the default driver Creating harbor-log ... done Creating harbor-adminserver ... done Creating registry ... done Creating redis ... done Creating harbor-db ... done Creating harbor-ui ... done Creating harbor-jobservice ... done Creating nginx ... done ✔ ----Harbor has been installed and started successfully.---- Now you should be able to visit the admin portal at http://registry.linuxea.com. For more details, please visit https://github.com/goharbor/harbor . ...Harbor是监听在宿主机的80端口,我们通过浏览器直接访问。用户名:admin,密码:Harbor12345vmware Harbor的开发有一大部分是中国人,大概也就是如此才会这么快就有中文支持而后可以创建普通用户普通用户也是可以创建项目,推送镜像的客户端推送镜像到仓库新建一个dev项目,而后推送,格式如下推送前需要重新修改标签推送镜像 在项目中标记镜像: docker tag SOURCE_IMAGE[:TAG] registry.linuxea.com/dev/IMAGE[:TAG] 推送镜像到当前项目: docker push registry.linuxea.com/dev/IMAGE[:TAG]NODT那么,在推送之前,我们还需要将此前的配置修改,此前使用distribution,是5000端口,此刻使用Harbor的80端口[root@www-LinuxEA ~]$ cat /etc/docker/daemon.json { "insecure-registries": ["registry.linuxea.com"] }重启[root@www-LinuxEA /data/harbor]$ systemctl restart docker打标签[root@www-LinuxEA ~]$ docker tag marksugar/httpd:v7 registry.linuxea.com/dev/httpd:v7而后登陆到Harbor[root@www-LinuxEA ~]$ docker login registry.linuxea.com Username: linuxea 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推送即可[root@www-LinuxEA ~]$ docker push registry.linuxea.com/dev/httpd:v7 The push refers to repository [registry.linuxea.com/dev/httpd] e37e4dcca4e6: Pushed 7e0e76680fcf: Pushed 7e36f706b93d: Pushed 2d1436269532: Pushed 7030e9e24693: Pushed df64d3292fd6: Pushed v7: digest: sha256:9fd332615f424252c54583f31946816039a5f69d648a35034426be904c75a5e6 size: 1568回到Harbor,已经能够看到这些详细的信息。
2019年01月21日
3,289 阅读
0 评论
0 点赞
2019-01-18
linuxea:白话容器之CPU与内存资源限制测试(25)
配置在前面了解了容器之CPU与内存资源限制概述,我们进行简单的资源限制测试我们下载lorel/docker-stress-ng测试我们在dockerhub上选择latest版本拉取到本地[root@linuxEA-145 /data/harbor]$ docker pull lorel/docker-stress-ng Using default tag: latest latest: Pulling from lorel/docker-stress-ng c52e3ed763ff: Pull complete a3ed95caeb02: Pull complete 7f831269c70e: Pull complete Digest: sha256:c8776b750869e274b340f8e8eb9a7d8fb2472edd5b25ff5b7d55728bca681322 Status: Downloaded newer image for lorel/docker-stress-ng:latestmemory可以使用 docker run --name stress --rm lorel/docker-stress-ng --help查看帮助 -m N, --vm N start N workers spinning on anonymous mmap (-m N,- vm N启动N个工作人员在匿名mmap上旋转) --vm-bytes N allocate N bytes per vm worker (default 256MB) (--vm-bytes N为每个vm worker分配N个字节(默认为256MB) )我们先对内存进行压测使用-m 指定配置大小为256m,而后使用 --vm 2 ,一个vm的默认是256M,压测观测下[root@linuxEA-145 /data/harbor]$ docker run --name stress --rm -m 256m lorel/docker-stress-ng --vm 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm观测内存的使用情况[root@linuxEA-145 ~]$ docker top stress UID PID PPID C STIME TTY TIME CMD root 12685 12670 0 11:52 ? 00:00:00 /usr/bin/stress-ng --vm 2 root 12716 12685 0 11:52 ? 00:00:00 /usr/bin/stress-ng --vm 2 root 12717 12685 0 11:52 ? 00:00:00 /usr/bin/stress-ng --vm 2 root 12799 12717 70 11:52 ? 00:00:00 /usr/bin/stress-ng --vm 2 root 12810 12716 5 11:52 ? 00:00:00 /usr/bin/stress-ng --vm 2可以使用docker stats stress,内存最多使用在限制内的大小[root@linuxEA-145 ~]$ docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 3b96828e471a stress 0.00% 255.9MiB / 256MiB 99.95% 712B / 42B 2.36GB / 20.5GB 5 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 3b96828e471a stress 137.67% 255.8MiB / 256MiB 99.92% 712B / 42B 2.53GB / 21.8GB 5 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 3b96828e471a stress 137.67% 255.8MiB / 256MiB 99.92% 712B / 42B 2.53GB / 21.8GB 5 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 3b96828e471a stress 139.01% 255.8MiB / 256MiB 99.91% 712B / 42B 2.69GB / 23GB 5可以看到这个内存一直在使用达99%cpu我们在验证下CPU限制使用2核心,也就是最多使用200%,运行8个进程使用(无论起多少进程,只有2核心分配)请注意,这样的限制只能使用2个cpu,那就意味着0-3的cpu任何两个都会被使用,并不固定在那一颗CPU[root@linuxEA-145 /data/harbor]$ docker run --name stress --rm --cpus 2 lorel/docker-stress-ng --cpu 8 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 8 cpu使用docker top stress观测,8个进程已经运行[root@linuxEA-145 ~]$ docker top stress UID PID PPID C STIME TTY TIME CMD root 32201 32185 0 14:19 ? 00:00:00 /usr/bin/stress-ng --cpu 8 root 32232 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8 root 32233 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8 root 32234 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8 root 32235 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8 root 32236 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8 root 32237 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8 root 32238 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8 root 32239 32201 25 14:19 ? 00:00:01 /usr/bin/stress-ng --cpu 8而CPU最多使用200[root@linuxEA-145 ~]$ docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS d4b2a1641d67 stress 200.05% 18.77MiB / 3.848GiB 0.48% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS d4b2a1641d67 stress 200.05% 18.77MiB / 3.848GiB 0.48% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS d4b2a1641d67 stress 199.37% 18.77MiB / 3.848GiB 0.48% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS d4b2a1641d67 stress 199.37% 18.77MiB / 3.848GiB 0.48% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS d4b2a1641d67 stress 200.50% 18.77MiB / 3.848GiB 0.48% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS d4b2a1641d67 stress 200.50% 18.77MiB / 3.848GiB 0.48% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS d4b2a1641d67 stress 200.10% 18.77MiB / 3.848GiB 0.48% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS假如我们没有限制,将会跑近400%,也就是全部资源被使用当然,也可以指定运行在那一颗之上。比如,限制运行在0,2上这样--cpuset-cpus 0,2 只会运行在0,2不会运行在其他的CPU核心上。[root@linuxEA-145 /data/harbor]$ docker run --name stress --rm --cpuset-cpus 0,2 lorel/docker-stress-ng --cpu 8 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 8 cpu仍然在限制内[root@linuxEA-145 ~]$ docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 21537336658b stress 200.76% 21.71MiB / 3.848GiB 0.55% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 21537336658b stress 200.76% 21.71MiB / 3.848GiB 0.55% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 21537336658b stress 200.29% 21.71MiB / 3.848GiB 0.55% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 21537336658b stress 200.29% 21.71MiB / 3.848GiB 0.55% 0B / 42B 0B / 0B 9 而后我们在宿主机查看top,0,2cpu已经跑满,说明限制是ok的[root@linuxEA-145 /data/harbor]$ top top - 14:25:02 up 85 days, 23:51, 4 users, load average: 2.37, 3.31, 3.04 Tasks: 167 total, 9 running, 91 sleeping, 0 stopped, 0 zombie %Cpu0 : 99.3/0.3 100[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ] %Cpu1 : 0.7/0.7 1[|| ] %Cpu2 : 100.0/0.0 100[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||] %Cpu3 : 1.0/1.0 2[|| ] KiB Mem : 29.4/4034596 [||||||||||||||||||||||||||||| ] KiB Swap: 1.9/4190204 [|| ] PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 582 root 20 0 6924 2444 620 R 25.2 0.1 0:04.17 stress-ng-cpu 590 root 20 0 6924 2444 620 R 25.2 0.1 0:04.16 stress-ng-cpu 583 root 20 0 6924 3960 620 R 24.9 0.1 0:04.16 stress-ng-cpu 584 root 20 0 6924 3960 620 R 24.9 0.1 0:04.16 stress-ng-cpu 585 root 20 0 6924 2444 620 R 24.9 0.1 0:04.16 stress-ng-cpu 587 root 20 0 6924 2444 620 R 24.9 0.1 0:04.16 stress-ng-cpu --cpu-shares共享那如果是共享的方式就不同了共享的方式--cpu-shares,在没有使用的时候都会被吃掉,如果有其他的容器运行则分配给别人[root@linuxEA-145 /data/harbor]$ docker run --name stress --rm --cpu-shares 1024 lorel/docker-stress-ng stress --cpu 8 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 8 cpu只运行一个容器的时候,CPU 400%[root@linuxEA-145 ~]$ docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 399.67% 17.14MiB / 3.848GiB 0.44% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 399.67% 17.14MiB / 3.848GiB 0.44% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 400.42% 17.14MiB / 3.848GiB 0.44% 0B / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 400.42% 17.14MiB / 3.848GiB 0.44% 0B / 42B 0B / 0B 9我们在运行一个容器,也做限制为512[root@linuxEA-145 /data/harbor]$ docker run --name stress1 --rm --cpu-shares 512 lorel/docker-stress-ng stress --cpu 8 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 8 cpu在来观测此前运行一个容器时候的stress,现在已经掉到266%左右[root@linuxEA-145 ~]$ docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 265.84% 17.14MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 267.23% 17.14MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 267.23% 17.14MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS dc3c61506fb9 stress 265.52% 17.14MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B 而stress1的使用是133%[root@linuxEA-145 ~]$ docker stats stress1 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 2db9d935886c stress1 133.23% 17.16MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 2db9d935886c stress1 132.16% 17.16MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 2db9d935886c stress1 132.16% 17.16MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B 9 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 2db9d935886c stress1 133.08% 17.16MiB / 3.848GiB 0.44% 1.07kB / 42B 0B / 0B CPU资源被两个容器动态瓜分在资源紧张的情况下,可以调整--oom-kill-disadble禁用被kill,和--oom-score-adj调整优先级来尽量避免优先被kill
2019年01月18日
3,358 阅读
0 评论
0 点赞
2019-01-17
linuxea:白话容器之CPU与内存资源限制概述(24)
我们知道容器能够运行,依赖内核的两个特性,一个是名称空间,一个是控制组。默认在docker中是没有任何资源限制的,在某些极端情况下能够几乎耗尽docker主机之上的所有资源。在此基础之上docker provides提供了一个控制容器能够使用多少内存,cpu,io,我们可以进行控制cpu和内存,而IO较弱控制。而其中的内存是非可压缩资源,CPU是可压缩资源。当容器内的进程耗尽CPU时,并且申请更多内存时候,可能会产生OOM。而CPU则不会出现这种问题。这些资源的限制依赖于capabilities资源限制从名称空间和cgroup来进行定义MemoryOOM如果在linux主机上,内核探测到当前宿主机已经没有足够内存可用于执行某些重要的系统功能,就会抛出OOME,并且开始启动kill 进程,以便于释放资源。一旦发生OOME,任何进程都有可能会被杀死 ,包括docker daemon在内如果内核发现内存被几乎耗尽无法执行本身的运作的时候,会进行检测使用内存异常的hogs进程。但是并不是使用内存最多的就是被杀掉的进程。这可能取决于,申请的内存总大小内耗尽比例来取决最佳被杀掉的进程,这个列表顺序可能是逆序的。为此,docker特地调整了docker daemon的OOM优先级,但是容器的优先级并未调整。为了便于控制,引入了一个oom-adj的功能,以防止系统中的重要进程被杀死,并定义要杀死的进程的顺序。oom_adj的可能值范围为-17到+15。分数越高,相关过程越有可能被OOM杀手杀死。如果 oom_adj设置为-17,则不会考虑将该进程用于OOM查杀。在每一个进程可以分配一个OOM-score的得分计算,根据其不良分数选择在内存不足情况下被杀死,,这个得分计算根据内存的申请的空间参考:https://lwn.net/Articles/317814/ https://lwn.net/Articles/391222/ https://lwn.net/Articles/548180/ https://lwn.net/Articles/391206/对于一些非常重要的容器,在启动的时候就需要调整oom_adj,另外也可以定义容器的策略,在出现OOM被kill后就restart默认是没有对资源限制的,限制容器的内存和CPU资源是有选项可以使用:内存资源raw,swap| `-m` 要么 `--memory=` | 限制容器使用内存,单位是k,b,m,g作为单位使用,可单独使用 | | `--memory-swap`* | 允许此容器交换到磁盘的内存量。查看[`--memory-swap`详情](https://docs.docker.com/config/containers/resource_constraints/#--memory-swap-details)。这个选项生效依赖于raw的选项是否配置 | | `--memory-swappiness` | 默认情况下,主机内核可以交换容器使用的匿名页面的百分比。您可以设置`--memory-swappiness`0到100之间的值,以调整此百分比。查看[`--memory-swappiness`详情](https://docs.docker.com/config/containers/resource_constraints/#--memory-swappiness-details)。 0并不是不使用| | `--memory-reservation` | 允许您指定小于软件限制的软限制`--memory`,当Docker检测到主机上的争用或内存不足时,该限制将被激活。如果使用`--memory-reservation`,则必须将其设置为低于`--memory`优先级。因为它是软限制,所以不保证容器不超过限制。 | | `--kernel-memory` | 容器可以使用的最大内核内存量。允许的最小值是`4m`。由于内核内存无法换出,因此内核内存不足的容器可能会阻塞主机资源,这可能会对主机和其他容器产生副作用。查看[`--kernel-memory`详情](https://docs.docker.com/config/containers/resource_constraints/#--kernel-memory-details)。 | | `--oom-kill-disable` | 默认情况下,如果发生内存不足(OOM)错误,内核会终止容器中的进程。要更改此行为,请使用该`--oom-kill-disable`选项。仅在已设置`-m/--memory`选项的容器上禁用OOM杀手。如果`-m`未设置该标志,则主机可能会耗尽内存,并且内核可能需要终止主机系统的进程才能释放内存。 |参考:https://docs.docker.com/config/containers/resource_constraints/#limit-a-containers-access-to-memory--memory-swap和memory联系与区别memswapmemory功能正数s正数M容器可用中总空间为s,其中ram为M,swap为(s-m),若S=M,则无可用swap资源。这里的可用内存并不是s+m!0正数M下相当于未设置swap不设置正数M若主机(docker host)启用了swap,则容器的可用swap为2*M-1正数M若主机(docker host)启用了swap,则容器可使用最大至宿主机上的所有swap空间的swap资源容器内使用free命令看到的swap空间并不具有其所展现出的空间的指示意义CPU每一个容器都可以使用宿主机上所有的CPU资源。作为用户来讲,可以设置各种约束来限制给定容器访问主机的CPU额度。我们知道,CPU的核心数是少于进程数的,一个系统之上运行了很多个进程,运行的进程数量大于核心数量的时候, 那个才是优先被运行?大多数用户使用和配置是由CFS调度程序来决定的。内核管理中最重要的一个组件CFS(Completely Fair Scheduler),处理调度进程在本地的核心之上,用于普通Linux进程的Linux内核CPU调度程序。多个运行时标志允许您配置容器具有的CPU资源访问量。使用这些设置时,Docker会修改主机上容器的cgroup的设置。然而每个进程都是有优先级的,这种非实时优先级,有效范围是100-139,这个范围是可以使用nice(niceness scale)进行调整,-20到19,数字越小优先级越高。默认nice值为零。在1.13及更高版本中,支持实时调度程序。另外,还有实时优先级,0-99,默认范围为1到99,这些都是内核级的。然后100到139用于用户空间(非实时),调度器CFS就是调度这些100-139之间的进程的延伸阅读:CFS: https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txtCFS: https://en.wikipedia.org/wiki/Completely_Fair_Scheduler进程调度:https://en.wikipedia.org/wiki/Completely_Fair_SchedulerCPU调度:https://www.studytonight.com/operating-system/cpu-scheduling进程优先级调整:https://bencane.com/2013/09/09/setting-process-cpu-priority-with-nice-and-renice/https://developer.ibm.com/tutorials/l-lpic1-103-6/https://www.ostechnix.com/change-priority-process-linux/https://www.nixtutor.com/linux/changing-priority-on-linux-processes/https://www.tecmint.com/set-linux-process-priority-using-nice-and-renice-commands/CPU资源也分为io密集型和CPU密集型,对于cpu密集型的可能需要调低优先级,当调度后就会耗时较长,而IO密集型是IO调度。对于占用很长时间的进程动态调低优先级,对于那些占用CPU很少又经常调度不上去的(CPU)将会调整高一些。CPU分配:选项描述--cpus=<value>指定容器可以使用的可用CPU资源量。例如,如果主机有两个CPU并且您已设置--cpus="1.5",则容器最多保证一个半CPU。这相当于设置--cpu-period="100000"和--cpu-quota="150000"。可在Docker 1.13及更高版本中使用。--cpu-period=<value>指定CPU CFS调度程序周期,它与并用 --cpu-quota。默认为100微秒。大多数用户不会更改默认设置。如果您使用Docker 1.13或更高版本,请--cpus改用。--cpu-quota=<value>对容器施加CPU CFS配额。--cpu-period限制前容器限制为每秒的微秒数。作为有效上限。如果您使用Docker 1.13或更高版本,请--cpus改用。--cpuset-cpus限制容器可以使用的特定CPU或核心。如果您有多个CPU,则容器可以使用的以逗号分隔的列表或连字符分隔的CPU范围。第一个CPU编号为0.有效值可能是0-3(使用第一个,第二个,第三个和第四个CPU)或1,3(使用第二个和第四个CPU)。--cpu-shares将此标志设置为大于或小于默认值1024的值,以增加或减少容器的重量,并使其可以访问主机的CPU周期的较大或较小比例。仅在CPU周期受限时才会强制执行此操作。当有足够的CPU周期时,所有容器都会根据需要使用尽可能多的CPU。这样,这是一个软限制。--cpu-shares不会阻止容器以群集模式进行调度。它为可用的CPU周期优先考虑容器CPU资源。它不保证或保留任何特定的CPU访问权限。参考:https://docs.docker.com/config/containers/resource_constraints/#configure-the-default-cfs-scheduler而--cpu-shares是按照比例切分。1024:512比如当前系统上运行了两个人容器,第一个容器是1024,第二个容器是512,假如这俩个容器都需要可能多的使用CPU。假如CPU资源有100份(100%),分为2分之一,各占512,而CPU资源以512为单位分为三份在两个容器上,如下:第一个容器占2份,而第二个容器占用1份,如果此时第二个容器启动后并没有占用CPU,那么第一个容器就可以占用第二个容器的512,这种方式就是共享式。在需要的时候就分配需要的额度,不需要的时候就给需要的使用。1024:512:2048假如现在有更大的比例,如下图这样一来就是分为了七份,2+1+4,分七份后后可用资源占用比例就不一样了,最后的2048是分成了4份542。同样,如果其中某一份容器或多个容器暂时不占用分配自己的CPU资源,仍然会被其他繁忙的容器所占用全部。也就是说,只要容器都在使用,就按照比例分配,如果只有一个使用,其他的不使用,这个使用的容器能够占用所有的CPU资源。如果有两个在使用,就按照剩下的比例分配给使用的,这个过程是随时动态调整的。任何一个容器不使用,就会被其他使用的容器说分配掉。CPU是可压缩资源,可随时加入更多的容器使用,只不过不同的分法,得到的结果不一样而已。CPU可压缩资源通过共享方式来分派,可压缩,也可随时调整比例。CPUshares有一特点,假如有4核心cpu,其中没一个容器的进程可任意调度到任何一个核心上面运行。一共使用1024比例,但是另外2个容器都不运行,那这个容器就不单单有一颗CPU的运算能力,而是有4颗CPU的运算能力,一颗CPU是100%,4个就相当于有400%的CPU。--cpus当然,也可以限制,假设如果一共有4核心,一个进程最多使用2个核心,且无论其他CPU空闲超过2个以上或者其他,被限制的cpu只能使用2核心,另外两个核心是空闲的(任意取其二,剩下不取) 。如下图左假设使用限制是2核心,也就是说,在4核心的cpu上使用的最多只能是200%,一个核心为100%,那也就是2颗核心。而现在可能是另外的一种方式,同样适用2核心,最多使用200%,但是却是每个核心各50%,重量不超过200%即可。如下图右但是,我们也可以限制核心数。--cpuset-cpus--cpus意味着这个进程只能运行在那个CPU核心。假如有4个核心,用的是0和3进行编号,那1和2就不能使用这些分配可以分为几种:1,按照压缩方式比例分配2,限定最多使用的核心数3,限定使用那些个CPU假如只有--cpuset-cpus限制了只能使用的0和1,那说明只能使用两个CPU,也就是200%,也可以限制使用的cpu时间周期和配额,这些选项在run或create时间使用。
2019年01月17日
3,904 阅读
0 评论
0 点赞
2019-01-16
linuxea:白话容器之dockerfile ARG和ONBUILD使用(6)(23)
shell该SHELL指令允许覆盖用于shell形式的命令的默认shell 。Linux上的默认shell是["/bin/sh", "-c"],而在Windows上["cmd", "/S", "/C"]。该SHELL指令必须以JSON格式写入Dockerfile。参考:https://docs.docker.com/engine/reference/builder/#shellSTOPSIGNAL该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如9,或SIGNAME格式的信号名,例如SIGKILL,例如15,停止容器。如果要发送其他的信号就要在这里定义STOPSIGNAL signalARGARG指令定义了一个变量,可以docker build使用该--build-arg <varname>=<value> 标志在构建时将该变量传递给构建器。这样定义的Dockerfile可以适用于较多的场景,尤其是程序版本迭代。如果指定了未在Dockerfile中定义的构建参数,则构建会输出警告。示例:定义ARG author默认是"linuxea.com.cn"ARG author="linuxea.com.cn" LABEL maintainer="${author}"[root@linuxEA-145 /data/linuxea3]$ cat Dockerfile FROM nginx:1.14.2-alpine ARG author="linuxea.com.cn" LABEL maintainer="${author}" ENV NGINX_ROOT="/data/wwwroot" ADD entrypoint.sh /bin/entrypoint.sh ADD index.html ${NGINX_ROOT}/ EXPOSE 8080/tcp 80/tcp HEALTHCHECK --interval=3s --timeout=3s --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT:-80}||exit 1 #HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT} || exit 1 CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]build[root@linuxEA-145 /data/linuxea3]$ docker build --build-arg author="mark www.linuxea.com" -t marksugar/nginx:v5 .查看,marksugar/nginx:v5的Labels是默认的linuxea.com.cn[root@linuxEA-145 /data/linuxea3]$ docker inspect -f {{.ContainerConfig.Labels}} marksugar/nginx:v5 map[maintainer:linuxea.com.cn]而后重新build,重新赋值--build-arg author="mark www.linuxea.com"[root@linuxEA-145 /data/linuxea3]$ docker build --build-arg author="mark www.linuxea.com" -t marksugar/nginx:v6 .而后在查看,赋值被生效[root@linuxEA-145 /data/linuxea3]$ docker inspect -f {{.ContainerConfig.Labels}} marksugar/nginx:v6 map[maintainer:mark www.linuxea.com]ONBUILDdocker onbuild用于指定当前的docker镜象用作另一个镜象的基本镜象时候运行的命令,在使用前,需要一个静态的基本镜象,而后其动态配置会在新的镜象(子镜象)发生作用,或者在新镜象依赖之前构建镜象的情况下使用!ONBUILD用于在Dockerfile中定义一个触发器,Dockerfile用于build镜像文件,此镜像文件可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件疑问当使用各种指令创建一个dockerfile,并在dockerfile指定了onbuild指令,当我们使用docker build使用当前的dockerfile构建镜象的时候,将会创建一个新的docker镜象,但onbuild指令不会应用于当前的docker镜象,仅仅作为将要创建新的景象用作为另外一个dockerfile中的基本镜象时候,才会应用此选项。在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器ONBULD <INSTRUCTION>尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如:mysql:5.6-onbuild在ONBUILD指令中使用ADD或COPY指令如果缺少指定的源文件时会失败(比如二次build copy,本地却无文件)。多数情况下,ONBUILD会执行ADD或者RUN进行下载安装等。也就说ONBUILD不会在自己构建的时候执行,而是在被其他人使用作为基础镜像的时候才会执行。添加一条ONBUILD,示例如下:ONBUILD ADD http://10.10.240.145/CentOS-Base.repo /etc/如下:[root@linuxEA-145 /data/linuxea3]$ cat Dockerfile FROM nginx:1.14.2-alpine ARG author="linuxea.com.cn" LABEL maintainer="${author}" ENV NGINX_ROOT="/data/wwwroot" ADD entrypoint.sh /bin/entrypoint.sh ADD index.html ${NGINX_ROOT}/ EXPOSE 8080/tcp 80/tcp HEALTHCHECK --interval=3s --timeout=3s --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT:-80}||exit 1 #HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT} || exit 1 ONBUILD ADD http://10.10.240.145/CentOS-Base.repo /etc/ CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]而后build为marksugar/httpd:v7[root@linuxEA-145 /data/linuxea3]$ docker build -t marksugar/httpd:v7 . Sending build context to Docker daemon 4.608kB Step 1/11 : FROM nginx:1.14.2-alpine ---> d956af1ad36a Step 2/11 : ARG author="linuxea.com.cn" ---> Using cache ---> c4c543206ad1 Step 3/11 : LABEL maintainer="${author}" ---> Using cache ---> 36edfcb86dfb Step 4/11 : ENV NGINX_ROOT="/data/wwwroot" ---> Using cache ---> 6547ed95f45a Step 5/11 : ADD entrypoint.sh /bin/entrypoint.sh ---> Using cache ---> d650f4dcb46c Step 6/11 : ADD index.html ${NGINX_ROOT}/ ---> Using cache ---> 865b4df58910 Step 7/11 : EXPOSE 8080/tcp 80/tcp ---> Using cache ---> 1454ea1fc5e3 Step 8/11 : HEALTHCHECK --interval=3s --timeout=3s --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT:-80}||exit 1 ---> Using cache ---> 157834157357 Step 9/11 : ONBUILD ADD http://10.10.240.145/CentOS-Base.repo /etc/ ---> Running in 37e29f61d449 Removing intermediate container 37e29f61d449 ---> f334451b2c4c Step 10/11 : CMD ["/usr/sbin/nginx","-g","daemon off;"] ---> Running in d3b24f896853 Removing intermediate container d3b24f896853 ---> b9307347b1ce Step 11/11 : ENTRYPOINT ["/bin/entrypoint.sh"] ---> Running in cd1f126e961f Removing intermediate container cd1f126e961f ---> a79987f1e18a Successfully built a79987f1e18a Successfully tagged marksugar/httpd:v7[root@linuxEA-145 /data/linuxea3]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE marksugar/httpd v7 a79987f1e18a About a minute ago 17.7MB重新写一个Dockerfile,调用刚刚构建的marksugar/httpd:v7[root@linuxEA-145 /data/linuxea4]$ cat Dockerfile FROM marksugar/httpd:v7 RUN echo "helo" >> /tmp/linuxea.txt在build的时候,就会执行上一个Dockerfile中的ONBUILD命令,如下:[root@linuxEA-145 /data/linuxea4]$ docker build -t onbuild:1 . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM marksugar/httpd:v7 # Executing 1 build trigger Downloading [==================================================>] 1.664kB/1.664kB ---> b64f3cd2ba7f Step 2/2 : RUN echo "helo" >> /tmp/linuxea.txt ---> Running in e9f45b68bb24 Removing intermediate container e9f45b68bb24 ---> 63bced5b493c Successfully built 63bced5b493c Successfully tagged onbuild:1而后run起来验证下[root@linuxEA-145 /data/linuxea4]$ docker run --name onbuild --rm onbuild:1 ls /etc/CentOS-Base.repo /etc/CentOS-Base.repo[root@linuxEA-145 /data/linuxea4]$ docker run --name onbuild --rm onbuild:1 cat /etc/CentOS-Base.repo # CentOS-Base.repo # # The mirror system uses the connecting IP address of the client and the # update status of each mirror to pick mirrors that are updated to and # geographically close to the client. You should use this for CentOS updates # unless you are manually picking other mirrors. # # If the mirrorlist= does not work for you, as a fall back you can try the # remarked out baseurl= line instead. # # [base] name=CentOS-$releasever - Base mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 ...
2019年01月16日
3,877 阅读
0 评论
0 点赞
2019-01-14
linuxea:白话容器之dockerfile health check使用(5)(22)
health check当我们基于镜像启动一个容器的时候,容器在什么时候退出,又在什么时候运行?事实上只要这个容器的主进程不是运行在后台,也没有停止,那么这个容器就不会停止。容器在判断容器正常与否,并不会根据容器是否能够正常服务,而仅仅是看容器主进程是否运行着,因此这种判断机制并不能说明容器就是健康的。那么我们就可以使用curl,或者wget,向主页发起请求,如果主页内容状态是对的,或者内容是我们期望的来判断是否运行正常,这样的精度才是我们想要的health check并不是检测一次就是ok的,他是一个周期的持续性的检测当容器指定了运行状况检查时,除了正常状态外,它还具有运行状况。这个状态最初是starting。每当健康检查通过时,它就会变成healthy(以前的状态)。经过一定数量的连续失败后,它就变成了unhealthy--interval=DURATION(间隔时间,默认值:30s)--timeout=DURATION(超时秒数,默认值:30s)--start-period=DURATION(默认值:0s)--retries=N(失败的重试次数,默认值:3)start period:容器在启动的时候,可能需要一定的准备的初始化时间,如果容器被run就开始检测,那如果容器也没有准备妥当,那此时检测肯定是失败的。那么就需要给容器一个启动的准备时间来做初始化。而这个start-period就是。检测发出后返回状态值:0:成功 - 容器健康且随时可用1:不健康 - 容器无法正常工作2:保留 - 不要使用此退出代码例如,要检查每五分钟左右网络服务器能够在三秒钟内为网站的主页面提供服务:HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1这样以来就不依赖进程是否运行来判断,而是判断访问是否正常来判断接着上面的Dockerfile,添加一行,时间均是3s,方便测试:--interval=3s--timeout=3s--start-period=3sHEALTHCHECK --interval=3s --timeout=3s --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT:-80}[root@linuxEA-145 /data/linuxea3]$ cat Dockerfile FROM nginx:1.14.2-alpine LABEL maintainer="linuxea.com" ENV NGINX_ROOT="/data/wwwroot" ADD entrypoint.sh /bin/entrypoint.sh ADD index.html ${NGINX_ROOT}/ EXPOSE 8080/tcp 80/tcp HEALTHCHECK --interval=3s --timeout=3s --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT:-80} || exit 1 #HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${NGPORT} || exit 1 CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]而后build[root@linuxEA /data/linuxea3]$ docker build -t marksugar/nginx:v3 .run起来后,就会发起wget -O - -q http://${IP:-0.0.0.0}:${NGPORT:-80},说明状态健康[root@linuxEA-145 /data/linuxea3]$ docker run --name linuxea --rm -e "NGPORT=8080" marksugar/nginx:v3 127.0.0.1 - - [08/Dec/2018:15:23:15 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2018:15:23:18 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2018:15:23:21 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2018:15:23:24 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2018:15:23:27 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2018:15:23:30 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2018:15:23:33 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-" 127.0.0.1 - - [08/Dec/2018:15:23:36 +0000] "GET / HTTP/1.1" 200 28 "-" "Wget" "-"此时我将端口修改为81,而81并没有监听,wget将失败,也就没有了wget日志,而docker ps 将能看到状态为unhealthy,说明不健康[root@linuxEA-145 /data/linuxea3]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 13fcf1bd14c4 marksugar/nginx:v4 "/bin/entrypoint.sh …" 19 seconds ago Up 18 seconds (unhealthy) 80/tcp, 8080/tcp linuxea查看docker inspect --format "{{json .State.Health }}" <container name> | jq示例2我创建了一个小的node.js web服务器,只需用'OK'响应任何请求。但是,服务器还有一个切换开/关状态的开关,而不会实际关闭服务器的进程。这是它的代码:"use strict"; const http = require('http'); function createServer () { return http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('OK\n'); }).listen(8080); } let server = createServer(); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); if (server) { server.close(); server = null; res.end('Shutting down...\n'); } else { server = createServer(); res.end('Starting up...\n'); } }).listen(8081);当服务器处于开启状态时,它将在端口8080处侦听并返回OK到任何进入该端口的请求。curl 8081端口将关闭服务器,另一个curl将再次启用它:[root@linuxEA-145 ~]$ node server.js # switch to another terminal [root@linuxEA-145 ~]$ curl 127.0.0.1:8080 # OK [root@linuxEA-145 ~]$ curl 127.0.0.1:8081 # Shutting down... [root@linuxEA-145 ~]$ curl 127.0.0.1:8080 # curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused [root@linuxEA-145 ~]$ curl 127.0.0.1:8081 # Starting up... [root@linuxEA-145 ~]$ curl 127.0.0.1:8080 # OK现在让我们将server.js放入带有运行状况检查的Dockerfile中,构建一个镜像并将其作为容器启动:FROM node COPY server.js / EXPOSE 8080 8081 HEALTHCHECK --interval=5s --timeout=10s --retries=3 CMD curl -sS 127.0.0.1:8080 || exit 1 CMD [ "node", "/server.js" ][root@linuxEA-145 ~]$ docker build . -t server:latest # Lots, lots of output [root@linuxEA-145 ~]$ docker run -d --rm -p 8080:8080 -p 8081:8081 server # ec36579aa452bf683cb17ee44cbab663d148f327be369821ec1df81b7a0e104b [root@linuxEA-145 ~]$ curl 127.0.0.1:8080 # OK创建的容器ID开头ec3,这应该足以在以后识别它,所以现在我们可以跳转到健康检查监视容器运行状况Docker用于检查容器健康状况的主要命令是 docker inspect。它产生巨大的JSON作为响应,但我们感兴趣的唯一部分是它的 State.Health属性:[root@linuxEA-145 ~]$ docker inspect ec3 | jq '.[].State.Health' #{ # "Status": "healthy", # "FailingStreak": 0, # "Log": [ # { # "Start": "2017-06-27T04:07:03.975506353Z", # "End": "2017-06-27T04:07:04.070844091Z", # "ExitCode": 0, # "Output": "OK\n" # }, #... }当前状态是“健康的”,我们甚至可以看到健康检查记录 Log 收集。但是,在调用端口8081并等待3 * 5秒(允许三次检查失败)之后,镜像将会改变。[root@linuxEA-145 ~]$ curl 127.0.0.1:8081 # Shutting down... # 15 seconds later [root@linuxEA-145 ~]$ docker inspect ec3 | jq '.[].State.Health' #{ # "Status": "unhealthy", # "FailingStreak": 4, # "Log": [ # ... # { # "Start": "2017-06-27T04:16:27.668441692Z", # "End": "2017-06-27T04:16:27.740937964Z", # "ExitCode": 1, # "Output": "curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused\n" # } # ] #}等了15秒多一点,所以健康检查连续4次失败(FailingStreak)。正如预期的那样,docker的状态确实变为“不健康”。但是,只要至少一次健康检查成功,Docker就会将容器恢复到“健康”状态:[root@linuxEA-145 ~]$ curl 127.0.0.1:8081 # Starting up... [root@linuxEA-145 ~]$ docker inspect ec3 | jq '.[].State.Health.Status' # "healthy"使用Docker事件检查运行状况除了直接检查容器状态外,我们还可以听取docker events:[root@linuxEA-145 ~]$ docker events --filter event=health_status # 2017-06-27T00:23:03.691677875-04:00 container health_status: healthy ec36579aa452bf683cb17ee44cbab663d148f327be369821ec1df81b7a0e104b (image=server, name=eager_swartz) # 2017-06-27T00:23:23.998693118-04:00 container health_status: unhealthy ec36579aa452bf683cb17ee44cbab663d148f327be369821ec1df81b7a0e104b (image=server, name=eager_swartz)Docker事件可能有点繁琐,这就是我必须使用的原因--filter。命令本身不会立即退出并保持运行,在事件发生时打印出事件。健康状况和Swarm服务为了尝试运行状况检查如何影响Swarm服务,我暂时将本地Docker实例转换为Swarm模式docker swarm init,现在我可以执行以下操作:[root@linuxEA-145 ~]$ docker service create -p 8080:8080 -p8081:8081 \ --name server \ --health-cmd='curl -sS 127.0.0.1:8080' \ --health-retries=3 \ --health-interval=5s \ server #unable to pin image server to digest: errors: #denied: requested access to the resource is denied #unauthorized: authentication required #ohkvwbsk06vkjyx69434ndqij这使用本地构建的server 镜像将新服务放入Swarm中。Docker对镜像是本地的并返回一堆错误这一事实并不满意,但最终确实返回了新创建的服务的ID:docker service ls #ID NAME MODE REPLICAS IMAGE #ohkvwbsk06vk server replicated 1/1 servercurl 127.0.0.1:8080 将再次工作,发送请求8081将像往常一样关闭服务。但是,这次短时间后端口8080将在没有明确启用服务器的情况下再次开始工作。事情是,只要Swarm注意到容器变得不健康,因此整个服务不再满足所需状态(“运行”),它就会完全关闭容器并启动一个新容器。通过检查我们server 服务的任务集合,我们实际上可以看到它的痕迹 :[root@linuxEA-145 ~]$ docker service ps server #ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS #mt67hkhp7ycr server.1 server moby Running Running 50 seconds ago #pj77brhfhsjm \_ server.1 server moby Shutdown Failed about a minute ago "task: non-zero exit (137): do…"每个Swarm容器都有一个分配给它的任务。当容器死亡时,相应的任务也会关闭,Swarm会创建一对新任务和一个容器。docker service ps 显示给定服务和容器的整个任务链死亡和复活。在我们的特定情况下server,id的初始任务pj77brhfhsjm被标记为失败,docker inspect 甚至说明原因:[root@linuxEA-145 ~]$ docker inspect pj77 | jq '.[].Status.Err' # "task: non-zero exit (137): dockerexec: unhealthy container"“unhealthy container”,这就是原因。但最重要的是,整个服务自动从不健康的状态恢复,几乎没有明显的停机时间Docker运行状况检查是一个小功能,允许将shell命令附加到容器并使用它来检查容器的内容是否足够活跃。对于Docker引擎独立模式下的容器,它只是为它添加健康/不健康的属性(health_status当值更改时加上docker事件),但在Swarm模式下,它实际上将关闭有故障的容器并创建一个停机时间非常短的新容器。
2019年01月14日
4,252 阅读
0 评论
0 点赞
1
2
...
6