2016 Swarm周 —— 第一部分:集群安装

本文讲的是2016 Swarm周 —— 第一部分:集群安装【编者的话】本文作为一个系列的第一篇,介绍了如何在Windows上在虚拟机中创建Swarm集群,同时配置了网络共享卷驱动,以及Consul服务发现。

在这篇文章中,我们将在Boot2Docker的VM之上创建一个本地的Swarm集群。

我们使用Consul作为kvstore来存储:
  • 结点发现和overlay网络
  • Swarm领导选举
  • 作为其他集群组件的配置存储(例如Interlock的配置)

Swarm使用了libkv库来支持除了Consul之外的多种存储后端,例如etcd、ZooKeeper等。

所有的Docker引擎都将通过开启了TLS的Docker-Machine创建,我们将会看到如何配置Boot2Docker的静态IP和netshareVolume驱动来在整个集群的节点上挂在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-windowsDocker Toolbox

但是,如果你被要求使用Hyper-V角色……—— Docker Toolbox不能也不应该被使用。

下面的步骤将会指导你在Windows 10(64位)上的Hyper-V中如何使用Docker、docker-machine和docker-compose。
  1. 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组件之后)。
    2016 Swarm周 —— 第一部分:集群安装

    由VMware的工具提供的VM网络服务也包含了一个DNS服务器,将任何DNS请求从虚拟机中转发到宿主机器。这意味着你只需要在Hyper-V的宿主机上管理etc/hosts文件来实现简单的、无IP的、虚拟机内部通信。

    在我们继续之前,注意你通过VMware NAT配置的虚拟交换机的名字,我的是VMware Nat。

    如果你决定使用Windows 10的Hyper-V的新的NAT交换机特性,你仍然需要一个DHCP和DNS的解决方案。
  2. Git、ssh、scp、openssl……

    安装git-for-windows来获得一个正统的控制台体验在Windows上是必须的。git-for-windows工具包也移除了在和Linux机器工作时对putty、plink和pageant的需求。

    尽管Windows 10的控制台改进了很多(透明、多行选择、全屏模式、CTRL+C/V支持等等)我仍然推荐使用ConEmu因为它有更多的功能(快速控制台分栏,在控制台之间切换,配置快捷键等等)。
  3. 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
    
  4. PowerShell配置

    为了控制Hyper-V,PowerShell需要有管理员权限。在ConEmu中按下WINDOWS+SHIFT+W允许你快速创建这样一个会话:
    2016 Swarm周 —— 第一部分:集群安装


    确保你的$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"
    
  5. 共享文件夹设置

    在这个demo中,我们假定有一个demo用户密码是demo在Hyper-V宿主机上创建了,这个用户有一个共享的可读写文件夹名子是demo。

设置键值存储

我们将使用Docker machine来运行Consul。在准备好docker machine之后,我们配置一个静态IP,启动Consul容器然后确定Consul在工作。
  1. 准备consul0机器

    通用的命令
    docker-machine create consul0
    

    在PowerShell中使用Hyper-V并设置自定义内存:
    dm create `
    --driver hyperv `
    --hyperv-virtual-switch "VMware NAT" `
    --hyperv-memory "512" consul0
    
  2. 设置一个静态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
    
  3. 重新生成证书

    Docker-Machine生成的证书只对旧IP合法,改变IP要求我们重新生成证书:
    dm regenerate-certs consul0
    
  4. 启动Consul

    Docker-Machine帮助你管理你的环境配置到正确的Boot2Docker虚拟机:
    docker-machine env consul0
    

    在PowerShell中激活这个环境(使用iex作为Invoke-Expression的别名),像下面这样:
    dm env consul0 | iex
    

    确定全部工作正常
    docker info
    

    启动一个单结点的Consul容器,暴露它的DNS和Consul API
    docker 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周 —— 第一部分:集群安装
上一篇:挂载非引用Assembly中的事件


下一篇:安装logstash,elasticsearch,kibana三件套(转)