本文讲的是2016 Swarm周 —— 第一部分:集群安装,
【编者的话】本文作为一个系列的第一篇,介绍了如何在Windows上在虚拟机中创建Swarm集群,同时配置了网络共享卷驱动,以及Consul服务发现。
在这篇文章中,我们将在Boot2Docker的VM之上创建一个本地的Swarm集群。
我们使用Consul作为kvstore来存储:
- 结点发现和overlay网络
- Swarm领导选举
- 作为其他集群组件的配置存储(例如Interlock的配置)
Swarm使用了 libkv 库来支持除了Consul之外的多种存储后端,例如etcd、ZooKeeper等。
所有的Docker引擎都将通过开启了TLS的Docker-Machine创建,我们将会看到如何配置Boot2Docker的静态IP和 netshare Volume驱动来在整个集群的节点上挂在VM主机的文件夹以持久化数据——使得任何有状态的容器能够在不同的结点上调度而不用丢失数据。
在一篇未来的文章中,我们将会看一下通过Docker-Compose在这个集群上部署和扩容 投票案例应用 ,使用最新的开启TLS验证的Interlock镜像来和Swarm通讯。
在第一部分创建的例子中,我们使用一个单结点的Consul集群和一个单结点的Swarm管理集群。为了高可用性,我们需要部署多个Consul和Swarm管理的从结点在一个负载均衡器之后,这将会在未来的一篇文章中探索。
最后,通过 Ansible容器 自动化所有的手动步骤将会是这个系列的完美总结。
我们将会使用Windows 10, Hyper-V 和PowerShell来安装,但是类似的初始化是可以在OSX上重复的(例如在netshare中将CIFS替换为NFS)。
Windows 10 环境初始化
在Windows上让一切准备就绪的最快的方法是安装 git-for-windows 和 Docker Toolbox 。但是,如果你被要求使用Hyper-V角色……—— Docker Toolbox不能也不应该被使用。
下面的步骤将会指导你在Windows 10(64位)上的Hyper-V中如何使用Docker、docker-machine和docker-compose。
- Hyper-V和NAT初始化
在Windows 10 的HyperV中添加NAT支持(2015第三季度)之前,推荐在Hyper-V上使用VMware的NAT和DHCP服务。
在你的虚拟网络上使用网络连接共享(ICS)也是可能的,但是我强烈反对。在以太网和WiFi之间切换时,ICS需要手动重新配置,这是不合适的。
在本文写作的时间,我仍然更喜欢在Hyper-V上使用VMware的网络服务,因为它提供最多的功能你甚至可以从VMware Workstation的安装中提取vmnetconfig.exe这个UI工具来方便的管理你的虚拟网络(在只安装了VMware Player组件之后)。
由VMware的工具提供的VM网络服务也包含了一个DNS服务器,将任何DNS请求从虚拟机中转发到宿主机器。这意味着你只需要在Hyper-V的宿主机上管理etc/hosts文件来实现简单的、无IP的、虚拟机内部通信。
在我们继续之前,注意你通过VMware NAT配置的虚拟交换机的名字,我的是VMware Nat。
如果你决定使用Windows 10的Hyper-V的新的NAT交换机特性,你仍然需要一个DHCP和DNS的解决方案。 - Git、ssh、scp、openssl……
安装git-for-windows来获得一个正统的控制台体验在Windows上是必须的。git-for-windows工具包也移除了在和Linux机器工作时对putty、plink和pageant的需求。
尽管Windows 10的控制台改进了很多(透明、多行选择、全屏模式、CTRL+C/V支持等等)我仍然推荐使用ConEmu因为它有更多的功能(快速控制台分栏,在控制台之间切换,配置快捷键等等)。 - Docker安装
在一个bash控制台中,执行下列命令:
下载Docker的Windows 64位二进制:curl -Lo /usr/bin/docker.exe https://get.docker.com/builds/Windows/x86_64/docker-1.10.3.exe
下载docker-machine的Windows 64位二进制(包括hyperv驱动)curl -Lo /usr/bin/docker-machine.exe https://github.com/docker/machine/releases/download/v0.6.0/docker-machine-Windows-x86_64.exe
下载docker-compose的Windows 64位二进制curl -Lo /usr/bin/docker-compose.exe https://github.com/docker/compose/releases/download/1.6.2/docker-compose-Windows-x86_64.exe
- PowerShell配置
为了控制Hyper-V,PowerShell需要有管理员权限。在ConEmu中按下WINDOWS+SHIFT+W允许你快速创建这样一个会话:
确保你的$PATH环境变量包含了我们之前下载所有二进制的/usr/bin/目录:$env:Path.Contains("$env:LOCALAPPDATA\Programs\Git\usr\bin")
应当返回True。
确认Docker工具在工作:docker --version; docker-machine --version; docker-compose --version
应当返回类似下面的内容:Docker version 1.10.3, build 20f81dd docker-machine.exe version 0.6.0, build e27fb87 docker-compose version 1.6.2, build e80fc83
在这篇指导中,我们使用以下别名:New-Alias "dm" "docker-machine"
- 共享文件夹设置
在这个demo中,我们假定有一个demo用户密码是demo在Hyper-V宿主机上创建了,这个用户有一个共享的可读写文件夹名子是demo。
设置键值存储
我们将使用Docker machine来运行Consul。在准备好docker machine之后,我们配置一个静态IP,启动Consul容器然后确定Consul在工作。- 准备consul0机器
通用的命令docker-machine create consul0
在PowerShell中使用Hyper-V并设置自定义内存:dm create ` --driver hyperv ` --hyperv-virtual-switch "VMware NAT" ` --hyperv-memory "512" consul0
- 设置一个静态IP(参考)并重启机器。
在这个例子中,虚拟机们使用了192.168.233.0/24
子网,NAT网关在192.168233.2
,DHCP范围是128-254
。我们将指定192.168.233.10
作为我们Consul结点的静态IP。记住你需要更新这些值来符合你的配置。
默认情况下,DHCP在Boot2Docker接口上是打开的,但是我们需要关闭它,通过杀死管理这个接口的进程:kill `more /var/run/udhcpc.eth0.pid`
先不要在Boot2Docker虚拟机上运行下列命令,我们需要在之后的步骤把它们加入到启动进程。
为了设置一个静态IP并且保证有一个到网关的默认路由,我们使用下列两个命令:ifconfig eth0 192.168.233.10 netmask 255.255.255.0 broadcast 192.168.233.255 up route add default gw 192.168.233.2
(译者注:这里为何不直接配置/etc/networking/interfaces?匪夷所思。)
如果我们不使用PowerShell,我们可以添加上面的命令作为启动脚本像下面这样:cat <<"EOF" | sudo tee /var/lib/boot2docker/bootsync.sh kill `more /var/run/udhcpc.eth0.pid` ifconfig eth0 192.168.233.10 netmask 255.255.255.0 broadcast 192.168.233.255 up route add default gw 192.168.233.2 EOF
或者使用PowerShell在宿主上执行一条命令echo "kill ``more /var/run/udhcpc.eth0.pid```n` ifconfig eth0 192.168.233.10 netmask 255.255.255.0 broadcast 192.168.233.255 up`n` route add default gw 192.168.233.2" | ` dm ssh consul0 "sudo tee /var/lib/boot2docker/bootsync.sh" > $null
接下来dm restart consul0
- 重新生成证书
Docker-Machine生成的证书只对旧IP合法,改变IP要求我们重新生成证书:dm regenerate-certs consul0
- 启动Consul
Docker-Machine帮助你管理你的环境配置到正确的Boot2Docker虚拟机:docker-machine env consul0
在PowerShell中激活这个环境(使用iex作为Invoke-Expression的别名),像下面这样:dm env consul0 | iex
确定全部工作正常docker info
启动一个单结点的Consul容器,暴露它的DNS和Consul APIdocker run -d -p 192.168.233.10:8500:8500 -p 192.168.233.10:53:8600/udp --name consul -h consul --restart always gliderlabs/consul-server -bootstrap
跟随你的Consul结点的启动进程:docker logs -f consul
按下CTRL+C并且添加一个静态的consul IP的记录到你的宿主hosts文件中(如果你的虚拟网络转发DNS查询到你的宿主机,这会允许所有你的结点通过consul0的主机名指向consul结点。"consul0" | ` % { "$($(Get-VM $_).NetworkAdapters[0].IpAddresses[0]) $_" } | ` ac $env:Windir\System32\Drivers\etc\hosts
确定Consul工作:iwr http://consul0:8500/v1/catalog/nodes | ConvertFrom-Json
配置Swarm管理器
我们将创建一个单结点的Swarm Manager(没有从结点)并使用下列Docker-Machine 参数 来配置我们的Swarm:Swarm 参数:
Flag | 描述
----- | -----
--swarm | 提供swarm代理
--swarm-master | 提供swarm manager
--swarm-discovery | 发现方法
我们也需要指定引擎的配置选项来在创建的Docker引擎中开启结点发现,这被支持overlay网络需要:
Option | 描述
----- | -----
--cluster-store | 键值存储的URL
--cluster-advertise | 集群结点到达这个结点的URL
--cluster-store-opt | 额外的集群参数
下面是一个Docker组件使用的默认端口
端口 | 协议
----- | -----
2375 | 不安全的docker API
2376 | TLS加密的docker API
3375 | 不安全的swarm API
3376 | TLS加密的swarm API
结合以上的信息,下面是我们通过PowerShell使用Docker-Machine创建我们的Swarm Manager的方法:
dm create ` --driver hyperv ` --hyperv-virtual-switch "VMware NAT" ` --swarm --swarm-master ` --swarm-discovery "consul://consul0:8500/cluster1" ` --engine-opt "cluster-store consul://consul0:8500" ` --engine-opt "cluster-advertise eth0:2376" ` --engine-opt "cluster-store-opt kv.path=cluster1/docker/overlay" master0
一旦我们的虚拟机被创建好了,我们能通过查看
/var/lib/boot2docker/profile
来确定引擎参数
dm ssh master0 cat /var/lib/boot2docker/profile
你可能注意到了我们位配置存储指定了自定义的路径,我们可以通过下列命令确定consul中实际存储的键:
iwr http://consul0:8500/v1/kv/?recurse | ConvertFrom-Json | ft Key
加入结点到Swarm Manager
为了创建Swarm结点,我们用和之前完全相同的步骤,只是不指定--swarm-master标志。额外的,我们可以根据我们给它们在我们的基础架构上指定的角色添加 标签 到我们的结点上:
dm create ` --driver hyperv ` --hyperv-virtual-switch "VMware NAT"` --swarm ` --swarm-discovery="consul://consul0:8500/cluster1" ` --engine-opt="cluster-store=consul://consul0:8500" ` --engine-opt="cluster-advertise=eth0:2376" ` --engine-opt="cluster-store-opt=kv.path=cluster1/docker/overlay" ` --engine-label="com.docker-saigon.group=frontend" ` --engine-label "com.docker-saigon.environment=dev" node0
不要忘了改变--engine-label的标志当提供不同角色的多个结点时。
确定结点加入了Swarm
检查Consul的数据:
iwr http://consul0:8500/v1/kv/?recurse | ConvertFrom-Json | ft Key
激活到Swarm集群的连接:
dm env --swarm master0 | iex
注意: 使用--swarm标志!
一旦这些结点变得可用,通过下列步骤安装netshare Volume驱动:
1. ssh进入这些结点(每个结点重复做):
dm ssh node0
2. 下载netshare压缩包
curl -Lo docker-volume-netshare_0.11.tar.gz https://dl.bintray.com//content/pacesys/docker/docker-volume-netshare_0.11_linux_amd64.tar.gz?direct
3. 展开压缩包到Boot2Docker的持久化硬盘
sudo tar -xf docker-volume-netshare_0.11.tar.gz -C /var/lib/boot2docker/ --strip=1 docker-volume-netshare_0.11_linux_amd64/docker-volume-netshare \ && rm -f docker-volume-netshare_0.11.tar.gz
4. 使用我们在Windows环境配置的时候创建的凭据来创建一个.netrc文件
sudo sh -c 'cat > /var/lib/boot2docker/.netrc <<EOF machine 192.168.233.1 username demo password demo domain 192.168.233.1 EOF'
5. 在开机时启动netshare volume驱动
echo '/var/lib/boot2docker/docker-volume-netshare cifs --netrc /var/lib/boot2docker >/var/lib/boot2docker/log/netshare 2>&1 </dev/null &' | sudo tee -a /var/lib/boot2docker/bootsync.sh > /dev/null
6. 重启结点
7. 确认netshare volume驱动在运行
dm ssh node0 ps xawu | grep netshare
在创建的swarm集群上的演示
我们快速的展示在结点之间通信、容器发现和从宿主机挂载共享存储来作为本文的总结。首先,确保我们在和Swarm manager交流:
dm env --swarm master0 | iex
列出已有网络:
docker network ls
注意:一个默认的网桥,宿主和空网络在集群的每一个结点上都存在。
通过Swarm创建一个新网络:
docker network create --subnet=10.0.10.0/24 nw
注意:最好在创建网络时提供子网
检查创建的网络
docker network ls
注意:这个网络被创建为集群上的一个overlay network,这是通过swarm创建网络时的默认行为。
让所有的结点来pull最新的alpine镜像:
docker pull alpine
如果你使用ConEmu, 按下
CTRL+SHIFT+O
来水平分割控制台
确保最新创建的控制台指向swarm master
New-Alias dm docker-machine dm env --swarm master0 | iex
监控
node0
上的netshare的日志:
dm ssh node0 tail -f /var/lib/boot2docker/log/netshare
在集群上的每个结点定义一个volume:
docker volume create -d cifs --name /192.168.233.1/demo
在集群上运行第一个容器:
docker run -dit --name container1 --net nw -v 192.168.233.1/demo:/demo alpine sh
注意:你应该注意到卷被挂载在node0上
在集群上运行第二个容器:
docker run -dit --name container2 --net nw -v 192.168.233.1/demo:/demo alpine sh
确认Swarm默认使用
spread
调度策略,每一个容器运行在一个单独的结点上:
docker ps
确认Container1 可以ping通Container2(使用主机名而不是IP即使它们在不同的结点上)
docker exec -it container1 ping container2
确认container1 可以在挂载的卷上创建文件:
docker exec -it container1 touch /demo/fromcontainer1
确认由container1创建的所有文件都可以被Container2获取:
docker exec -it container2 ls -l /demo/
提示和技巧
获取运行的虚拟机的列表:Get-VM | ? { $_.State -eq "Running" }
获取每一个运行的虚拟机的IP地址的列表:
Get-VM | ? { $_.State -eq "Running" } | select Name, Uptime, @{l="IpAddress";e={$_.NetworkAdapters[0].IpAddresses[0]}}
打开指定虚拟机的控制台
$vm = Get-VM consul0 vmconnect $env:COMPUTERNAME $vm.Name -G $vm.Id
打印每一个集群结点和它的IP(这可以被pipe到
Add-Content
命令来作为/etc/hosts):
"master0","node0","node1" | % { "$($(Get-VM $_).NetworkAdapters[0].IpAddresses[0]) $_ " }
(译者注:powershell什么鬼,期待win10的“native” bash早日发布)
原文链接:Swarm Week 2016 - Part 1: Cluster Setup (翻译:陈光)
原文发布时间为:2016-04-03
本文作者:Casgy
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:2016 Swarm周 —— 第一部分:集群安装