这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

容器篇

主要记录容器相关技能。

容器基础界还在不断向前发展,持续更新认知。

自15年开始接触容器,当时容器就是Docker,Docker就是容器,当然现在docker仍是主流的容器runtime方案,随着k8s的规模落地,生态也在潜移默化的变化着,此篇会把以前编写的一些文章挪移到此处,顺便开启新的认知。

1 - 百宝箱脚本

记录常用命令脚本。
  • 备份所有docker镜像
mkdir -p images && cd images
for image in `docker images | grep -v REPOSITORY | awk '{print $1":"$2}'`; do
    echo "saving the image of ${image}"
    docker save ${image} >  ${image////-}.tar
    echo -e "finished saving the image of \033[32m ${image} \033[0m"
done
  • 批量加载本地tar镜像
for image in `ls *.tar`; do
    echo "loading the image of ${image}"
    docker load < ${image}
    echo -e "finished loading the image of \033[32m ${image} \033[0m"
done
  • 批量杀死僵尸进程
ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' | awk '{print $2}' | xargs kill -9

2 - docker网络

介绍docker自带的几种网络模型

自去年就开始推动公司业务使用docker了, 至今也一年多了,但对docker网络的认知一直一知半解。。。

主要是太忙,加上线上业务也没出过关于网络吞吐性能方面的问题,就没太大动力去搞明白, 现在闲下来了,搞之!

环境声明

  • 以下内容只针对OS: Ubuntu16.04 docker: 1.10.3的环境, 写本文时docker最新的release版本是1.11.2,还有什么CoreOS,Unikernel 之类的(表示都没玩过)。

docker更新迭代速度太快了,公司业务只用到基本功能,所以没动力跟进它的更新了 各种新时代下的产物频出啊, CoreOS为linux的发行版, 没需求,好遗憾.

docker的网络模式

一开始安装完docker, 它就会默认创建3个网络, 使用__docker network ls__查看

➜  blog git:(master) docker network ls
NETWORK ID          NAME                DRIVER
46416a43fbc6        bridge              bridge              
45398901e9f0        none                null                
9440a8140e68        host                host

当启动一个容器时, 默认使用bridge模式, 可以通过 --net 指定其它模式。

下面先简要说明下各自的概念

  • bridge 模式

容器间之所以能通信,就靠宿主机上的docker0了, docker0就是bridge模式下默认创建的虚拟设备名称

➜  blog git:(master) ✗ ifconfig docker0
docker0   Link encap:Ethernet  HWaddr 02:42:49:56:7c:3b  
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:49ff:fe56:7c3b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:78103 errors:0 dropped:0 overruns:0 frame:0
          TX packets:47578 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:17485434 (17.4 MB)  TX bytes:82163889 (82.1 MB)

ifocnfig可以看到很多信息, mac地址,IP等这些也可以通过参数指定成别的。

  • none模式

none网络模式下的容器里是缺少网络接口的,例如eth0等,但会有一个lo设备。

没用过也没见过这样的业务场景, 不做过多说明

  • host模式

容器直接操作宿主机的网络栈, 无疑是性能最好的网络模式, 可以认为是无带宽损耗的。

细说bridge模式

这也是我们线上正在在用的网络模式。

bridge模式主要利用了iptables的Masquerading和DNAT功能。

未完。。。

3 - Swarm篇

Docker内置容器编排方案,,,(弃用)。

Docker内置容器编排方案

当年的swarm、k8s、mesos三大系统竞争之激烈,现在都归于k8s了。

3.1 - 构建生产环境级的docker Swarm集群-1

构建生产环境级的docker Swarm集群。

此文档适用于低于1.12版本的docker,之后swarm已内置于docker-engine里。

  1. 硬件需求

至少5台PC服务器, 分别如下作用

  • manager0
  • manager1
  • consul0
  • node0
  • node1
  1. 每台PC上安装docker-engine

一台一台的ssh上去执行,或者使用ansible批量部署工具。

安装docker-engine

curl -sSL https://get.docker.com/ | sh

启动之,并使之监听2375端口

sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

亦可修改配置,使之永久生效

mkdir /etc/systemd/system/docker.service.d
cat <<EOF >>/etc/systemd/system/docker.service.d/docker.conf
[Service]
  ExecStart=
  ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --dns 180.76.76.76  --insecure-registry registry.cecf.com -g /home/Docker/docker
EOF
  1. 启动discovery后台

在consul0上启动consul服务,manager用其来认证node连接并存储node状态, 理应建立discovery的高可用,这里简化之

docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap
  1. 创建Swarm集群

在manager0上创建the primary manager, 自行替换manager0_ip和consul0_ip的真实IP地址。

docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise <manager0_ip>:4000 consul://<consul0_ip>:8500

在manager1上启动replica manger

docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise <manager1_ip>:4000 consul://<consul0_ip>:8500

--replication

  1. 在node上执行加入集群操作

分别在node0和node1上执行加入集群操作

docker run -d swarm join --advertise=<node_ip>:2375 consul://<consul0_ip>:8500
  1. 在manger0上查看集群状态
docker -H :4000 info

3.2 - 构建生产环境级的docker Swarm集群-2

构建生产环境级的docker Swarm集群。

此文档适用于不低于1.12版本的docker,因为swarm已内置于docker-engine里。

  1. 硬件需求

这里以5台PC服务器为例, 分别如下作用

  • manager0
  • manager1
  • node0
  • node1
  • node2
  1. 每台PC上安装docker-engine

一台一台的ssh上去执行,或者使用ansible批量部署工具。

安装docker-engine

curl -sSL https://get.docker.com/ | sh

启动之,并使之监听2375端口

sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

亦可修改配置,使之永久生效

mkdir /etc/systemd/system/docker.service.d
cat <<EOF >>/etc/systemd/system/docker.service.d/docker.conf
[Service]
  ExecStart=
  ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --dns 180.76.76.76  --insecure-registry registry.cecf.com -g /home/Docker/docker
EOF

如果开启了防火墙,需要开启如下端口

  • TCP port 2377 for cluster management communications
  • TCP and UDP port 7946 for communication among nodes
  • TCP and UDP port 4789 for overlay network traffic
  1. 创建swarm
docker swarm init --advertise-addr <MANAGER-IP>

我的实例里如下:

[root@manager0 ~]# docker swarm init --advertise-addr 10.42.0.243
Swarm initialized: current node (e5eqi0lue90uidzsfddeqwfl8) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-3iskhw3lsc9pkdtijj1d23lg9tp7duj18f477i5ywgezry7zlt-dfwjbsjleoajcdj13psu702s6 \
    10.42.0.243:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

使用 --advertise-addr 来声明manager0的IP,其他的nodes必须可以和此IP互通, 一旦完整初始化,此node即是manger又是worker node.

通过docker info来查看

$ docker info

Containers: 2
Running: 0
Paused: 0
Stopped: 2
  ...snip...
Swarm: active
  NodeID: e5eqi0lue90uidzsfddeqwfl8
  Is Manager: true
  Managers: 1
  Nodes: 1
  ...snip...

通过docker node ls来查看集群的node信息

[root@manager0 ~]# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
e5eqi0lue90uidzsfddeqwfl8 *  manager0  Ready   Active        Leader

这里的*来指明docker client正在链接在这个node上。

  1. 加入swarm集群

执行在manager0上产生docker swarm init产生的结果即可

如果当时没记录下来,还可以在manager上补看 想把node以worker身份加入,在manager0上执行下面的命令来补看。

docker swarm join-token worker

想把node以manager身份加入,在manager0上执行下面的命令来来补看。

docker swarm join-token manager

为了manager的高可用,我这里需要在manager1上执行

docker swarm join \
--token SWMTKN-1-3iskhw3lsc9pkdtijj1d23lg9tp7duj18f477i5ywgezry7zlt-86dk7l9usp1yh4uc3rjchf2hu \
10.42.0.243:2377

我这里就是依次在node0-2上执行

docker swarm join \
  --token SWMTKN-1-3iskhw3lsc9pkdtijj1d23lg9tp7duj18f477i5ywgezry7zlt-dfwjbsjleoajcdj13psu702s6 \
  10.42.0.243:2377

这样node就会加入之前我们创建的swarm集群里。

再通过docker node ls来查看现在的集群情况, swarm的集群里是以node为实例的

[root@manager0 ~]# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
0tr5fu8ebi27cp2ot210t67fx    manager1  Ready   Active        Reachable
46irkik4idjk8rjy7pqjb84x0    node1     Ready   Active
79hlu1m7x9p4cc4npa4xjuax3    node0     Ready   Active
9535h8ow82s8mzuw5kud2mwl3    consul0   Ready   Active
e5eqi0lue90uidzsfddeqwfl8 *  manager0  Ready   Active        Leader

这里MANAFER标明各node的身份,空即为worker身份。

  1. 部署服务
Usage:	docker service COMMAND

Manage Docker services

Options:
      --help   Print usage

Commands:
  create      Create a new service
  inspect     Display detailed information on one or more services
  ps          List the tasks of a service
  ls          List services
  rm          Remove one or more services
  scale       Scale one or multiple services
  update      Update a service

部署示例如下:

docker service create --replicas 2 --name helloworld alpine ping 300.cn

docker service ls罗列swarm集群的所有services docker service ps helloworld查看service部署到了哪个node上 docker service inspect helloworld 查看service 资源、状态等具体信息 docker servcie scale helloworld=5来扩容service的个数 docker service rm helloworld 来删除service docker service update 来实现更新service的各项属性,包括滚动升级等。

可更新的属性包含如下:

Usage:	docker service update [OPTIONS] SERVICE

Update a service

Options:
      --args string                    Service command args
      --constraint-add value           Add or update placement constraints (default [])
      --constraint-rm value            Remove a constraint (default [])
      --container-label-add value      Add or update container labels (default [])
      --container-label-rm value       Remove a container label by its key (default [])
      --endpoint-mode string           Endpoint mode (vip or dnsrr)
      --env-add value                  Add or update environment variables (default [])
      --env-rm value                   Remove an environment variable (default [])
      --help                           Print usage
      --image string                   Service image tag
      --label-add value                Add or update service labels (default [])
      --label-rm value                 Remove a label by its key (default [])
      --limit-cpu value                Limit CPUs (default 0.000)
      --limit-memory value             Limit Memory (default 0 B)
      --log-driver string              Logging driver for service
      --log-opt value                  Logging driver options (default [])
      --mount-add value                Add or update a mount on a service
      --mount-rm value                 Remove a mount by its target path (default [])
      --name string                    Service name
      --publish-add value              Add or update a published port (default [])
      --publish-rm value               Remove a published port by its target port (default [])
      --replicas value                 Number of tasks (default none)
      --reserve-cpu value              Reserve CPUs (default 0.000)
      --reserve-memory value           Reserve Memory (default 0 B)
      --restart-condition string       Restart when condition is met (none, on-failure, or any)
      --restart-delay value            Delay between restart attempts (default none)
      --restart-max-attempts value     Maximum number of restarts before giving up (default none)
      --restart-window value           Window used to evaluate the restart policy (default none)
      --stop-grace-period value        Time to wait before force killing a container (default none)
      --update-delay duration          Delay between updates
      --update-failure-action string   Action on update failure (pause|continue) (default "pause")
      --update-parallelism uint        Maximum number of tasks updated simultaneously (0 to update all at once) (default 1)
  -u, --user string                    Username or UID
      --with-registry-auth             Send registry authentication details to swarm agents
  -w, --workdir string                 Working directory inside the container

3.3 - 构建生产环境级的docker Swarm集群-3

构建生产环境级的docker Swarm集群。

如前文所述,默认已经搭建好环境,基于docker1.12版本。

[root@manager0 ~]# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
0bbmd3r7aphs374qaea4zcieo    node2     Ready   Active
3qmxzyauc0bz4kjqvld9uogz5    manager1  Ready   Active        Reachable
5ewbdtvaopj4ltwqx0a4i65nt *  manager0  Ready   Drain         Leader
5oxxpgk69fnwe5w210kovrqi9    node1     Ready   Active
7s1ilay2wkjgt09bp2z0743m7    node0     Ready   Active
  1. 创建第一个服务,以redis为例 swarm里容器间通信需要使用overlay模式,所以需要提前建立一个
docker network create -d overlay  --subnet 10.254.0.0/16 --gateway  10.254.0.1 mynet1
docker service create --name redis --network mynet1 redis
  1. 在manager上查看服务部署情况
[root@manager0 ~]# docker service ps redis
ID                         NAME     IMAGE  NODE   DESIRED STATE  CURRENT STATE           ERROR
9avksjfqr2gxm413dfrezrmgr  redis.1  redis  node1  Running        Running 17 seconds ago

实例里,同样可以去node1上用docker ps查看

以上只是最基本的集群创建服务的用法,从中可见,swarm的的调度基本单元是task, 没有pod的概念,一个task可以简单理解成一个docker run的结果。目前swarm里也不支持compose。

docker官方称,以后会支持vm、pod的调度单元,具体日期未知。

  1. 服务调度策略

使用docker service create创建服务, 这其中选择再哪个节点部署,docker 提供了三种调度策略;

  • spread: 默认策略,尽量均匀分布,找容器数少的结点调度
  • binpack: 和spread相反,尽量把一个结点占满再用其他结点
  • random: 随机
  1. 服务的高可用和load-balance

通过--replicas参数可以设置服务容器的数量,已达到高可用状态;

#创建多副本
docker service update --replicas 4 redis

#查看副本部署情况
[root@manager0 ~]# docker service ps redis
ID                         NAME     IMAGE  NODE      DESIRED STATE  CURRENT STATE               ERROR
9avksjfqr2gxm413dfrezrmgr  redis.1  redis  node1     Running        Running 13 minutes ago      
0olv1sfz6d79wdnorw7jgoyri  redis.2  redis  manager1  Running        Running about a minute ago  
f3n6deesjlkxu4k48lzabieus  redis.3  redis  node2     Running        Preparing 3 minutes ago     
80bzarvkiytpv1690sla6unt2  redis.4  redis  node0     Running        Running about a minute ago

#验证多可用, 总共4个副本,docker内置的DNS服务会默认使用round-robin调度策略来解析主机。
root@9ed77b4b4432:/data# redis-cli -h redis
redis:6379> set user 1
OK
redis:6379> exit
root@9ed77b4b4432:/data# redis-cli -h redis
redis:6379> get user
(nil)
redis:6379> set user 2
OK
redis:6379> exit
root@9ed77b4b4432:/data# redis-cli -h redis
redis:6379> get user
(nil)
redis:6379> set user 3
OK
redis:6379> exit
root@9ed77b4b4432:/data# redis-cli -h redis
redis:6379> get user
(nil)
redis:6379> set user 4
OK
redis:6379> exit
root@9ed77b4b4432:/data# redis-cli -h redis
redis:6379> get user
"1"
redis:6379>

4 - 从docker迁移到containerd

记录从docker迁移到containerd的事项

记录个人从docker迁移到containerd的事项

介绍

https://github.com/containerd/containerd

TODO.

安装containerd

下载必要组件:https://github.com/containerd/nerdctl/releases,