Docker-machine+Docker swarm+Nginx+Nginx代理
这是一个swarm集群,从零开始搭建服务器环境,Docker-machine+Docker swarm+Nginx+Nginx代理
Docker-machine+Docker swarm+Nginx+Nginx代理
准备环境:
- 6台centos7操作系统(需要关闭防火墙,关闭selinux)
- IP地址划分
Docker-machine | Swarm node1 | Swarm node1 | Swarm node1 | Nginx服务 | Nginx代理 |
---|---|---|---|---|---|
192.168.100.70 | 192.168.100.71 | 192.168.100.72 | 192.168.100.73 | 192.168.100.74 | 192.168.100.75 |
docker版本
初始环境要求:
准备的是全新的操作系统,只需IP地址配置ok,全网可以互通。
项目执行之前需要实现的要求
全部不使用root,关闭密码验证,使用ssh密钥进行验证。
全部机器使用IP地址为70的这台作为堡垒机进行管理。
要求nginx代理为外部的提供访问的地址,(如果允许,可以再搭建一台dns解析服务和使用一台win7来进行测试。)
后续更多需求可根据实际进行添加。
修改不使用root,使用新用户admin操作
远程软件连接
使用终端软件连接,暂时没有关闭密钥验证和不使用root登录,所以使用root先登录
上传expect脚本
将我当初写的expect脚本复制到作为堡垒机的100.70这台服务器
简介:
- login.exp:里面包含了登录、新建用户、授权sudo使用权限、设置用户密码、复制公钥到新建用户的ssh目录下并关闭sshd服务的端口号和禁止密码验证登录操作。
- scp.exp:里面包含了将公钥上传到指定的服务器的指定目录下,以便提供给login.exp登录进行操作。
- sshlogin.sh:这里定义的是exp脚本中将会使用位置变量的参数,在这里定义后,exp脚本可以引用shell脚本的变量。
- wyf.pub:这是公钥文件,自己去生成一个
- passwd.txt:这个是shell脚本sshlogin.sh使用for循环的时候会使用到的各个位置变量的参数值。
- use.txt:中文操作手册
文件内容:
login.exp
1 | !/usr/bin/expect -f |
scp.exp
1 | !/usr/bin/expect -f |
sshlogin.sh
1 | !/bin/bash |
wyf.pub
1 | ssh-dss AAAAB3NzaC1kc3MAAACBANVB2rrIvkUGCJA6b/8h+GyKd1GVpxZFAM1n8sP2bo7TSkWpkxV81Y4zkdaYomsFDXLGnaI2QbHqv/pA0PndJFQ1NfYqbBw6FaGI1+cG8mgJBCPwVPmQnDvf4TPzJkEpdV1CK/wYjRVjuFL2lYOd8hepkNN4c96Dx5STdMyBSH+rAAAAFQCtUm3dYyX3j9pKY+yev3OKmB/LtwAAAIEAytEQ4hgceD7T00soGq/o0aS42QJoeZLJd/jwdIAqkUdg5y8q4lqzmlO2OaxD3YVf9eOYiuokZQu2qP5A+2iTbebpoqDDP8NksCgGPY+7viyKpUy+wrcm/Gwa0YA9B2mzpHudxXKuw/2wjtBKTjh+gFx7zlXBFHYaMdV8zsP/QkAAAACBALJc+rMJXSsS7+3i874iJIlP/r2qxrfkO4+qjmZoTbGYnhOzEzYbwP6newO27MBkaOHSPlWFh8kSQtiputcvg9GawG6Y6WO/0bfgHfxrDg0NnmQJgvcjMStGeuLwYB4NNG2KsomciN4hUruWHg0/+VwV8qknTHYFMJmOJC1ketuS |
passwd.txt
1 | 192.168.100.71 pwd@123 wyf5 wyf.pub 234 |
use.txt
1 | 复制当前目录下的所有文件到同一个文件夹中 |
expect脚本的配置文件修改
将其他5台服务器的信息写到passwd文件中
安装expect脚本执行命令
1 | yum -y install expect(这里我已经安装) |
检查各脚本是否有错误的地方
在login.exp这个脚本中重启sshd服务的操作,我注释掉了,先不重启,我们待会分别进去查看是否修改了配置文件,也是确保修改正确后再进行重启操作。
执行过程中,因为中文支持的原因提示的密码输入不一样,所以将提示修改为这样的(这里可以看出操作系统不同,所提示的也不同,需要对应操作系统来修改这里)
因为操作系统的原因,每台sshd_config的配置文件也不同,比如centos7的port前面会有一个#号,其他系统可能不同;
所以我们可以修改写两个sed
还有一个问题需要说明,我这里写成了222端口是问题的,比如#port 22,第一次修改后为port 222,第二次又会匹配下一条sed,既会变成port 2222。所以尽量不要用22开头的作为修改后的端口号
执行后在查看其中一台
后续重启sshd可能不成功,因为selinux和防火墙的原因,需要关闭。
查看无问题了,既重新启动sshd服务。
分别登录admin账户
我这里的
- root密码是pwd@123
- admin密码是qwaszx@)!&
- wyf公钥的密码是1836
上面这里因为关闭了密钥验证,所以这里要使用密钥的验证。
安装docker的等一系列服务
新增项目测试:
这里的100.70机器是全新的一台机器,当我们只安装docker-machine的时候看是否一定需要docker服务
查看三台节点服务器情况:
验证并没有安装docker服务
上传docker-machine到服务器并移动到全局变量下
1 | ls |
先查看其他作为swarm集群的几台机器的情况
可以看到上面的三个节点已经安装好了docker,
这里为什么需要sudo呢?
因为docker安装的时候是使用的root用户,admin用户是没有权限操作docker的。所以我们这里可以将admin用户加入到docker组(这个组是安装docker的时候自动创建的,这样admin就可以操作docker服务了)
1 | sudo gpasswd -a ${USER} docker |
或者
1 | sudo usermod -a -G docker admin |
重启docker
1 | sudo systemctl restart docker |
这里有个小问题
查看组,
可以看到docker组中有admin这个用户,但是还是无法使用docker命令,从权限可以看出docker组是用读取写入权限的。但是admin还是无法使用docker
解决方法就是关闭这个终端,重新连接
使用docker-machine 的驱动进行连接并管理其他服务器
100.70作为docker-machine管理器,并使用admin用户操作。
在admin用户下生成密钥对
将生成的公钥放到远程主机的admin(远程主机的admin账户是可以操作docker的)账户去,会提示输入远程主机的admin用户密码
这里出现的问题就是,我们已经关闭了每台主机的密码验证,这种是无法上传的,所以只有分别复制过去
第一个ssh是本地远程的xshell的公钥,第二个是100.70下的admin用户生成的公钥
测试能否远程
1 | ssh -p 222 admin@192.168.100.71 |
开始关联
注意,create 命令本是要创建虚拟主机并安装Docker,因为本例中的目标主机已经存在docker。所以已经安装会跳过的。-d 是 –driver的简写形式,主要用来指定使用什么驱动程序来创建目标主机。Docker Machine支持在云服务器上创建主机,就是靠使用不同的驱动来实现了。本例中使用 generic就可以了。接下来以 –generic开头的三个参数主要是指定操作的目标主机和使用的账户。最后一个参数 node1是虚拟机的名称,Docker Machine 会用它来设置目标主机的名称。
1 | docker-machine create -d generic --generic-ip-address=192.168.100.71 --generic-ssh-port=222 --generic-ssh-user=admin --generic-ssh-key ~/.ssh/id_rsa node1 |
这里会出错,原因是admin用户无法执行在创建过程中需要执行的命令。所以我们修改,将ssh密钥导入到root用户
删除node1,再次进行创建
1 | docker-machine create -d generic --generic-ip-address=192.168.100.71 --generic-ssh-port=222 --generic-ssh-user=root --generic-ssh-key ~/.ssh/id_rsa node1 |
等待过10分钟,基本就可以了
将另外的两个节点也加入进来
1 | for i in 2 3 ; do docker-machine create -d generic --generic-ip-address=192.168.100.7$i --generic-ssh-port=222 --generic-ssh-user=root --generic-ssh-key ~/.ssh/id_rsa node$i; done |
测试效果
现在测试100.70在不安装docker服务的情况下,使用了docker 节点的变量能否使用docker
从上面可以看出,并不能,原因是因为没有安装docker客户端。这里我们就不研究如何只安装客户端了,还是安装上docker服务吧,使用admin用户来安装
安装教程
https://docs.docker.com/engine/installation/linux/docker-ce/centos/#install-using-the-repository
这里当安装好了以后
上面可以看出安装的是docker-ce17.09版本,因为之前的变量导入还在,所以看到客户端版本为17.09,服务端是17.06。
移除变量后,再次查看,提示服务端并没运行,这样不就实现了我们的想法,只安装了客户端。
如果想运行服务,需要加入:
1 | sudo systemctl enable docker |
这里我不加入开机启动,和启动服务端。
建立swarm集群
将node1作为swarm集群的创建者
1 | docker swarm init --advertise-addr $(docker-machine ip node1) |
退出node1
1 | eval $(docker-machine env -u) |
分别将node2和node3,将作为节点服务器加入到集群中
1 | for i in 2 3; do docker-machine ssh node$i docker swarm join --token SWMTKN-1-2ov80t4wgnrmh4t1d48a0n3uxrrmaojkv9raf1733irvfiw4w2-d0vrx62myyg5wetxkd7r3jl7a $(docker-machine ip node1):2377; done |
查看集群的节点信息
批量修改加速器(这样无法实现),必须要ssh进去后操作后才可以实现
1 | for i in 1 2 3; do docker-machine ssh node$i curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://ac1e54d0.m.daocloud.io && sudo systemctl restart docker; done |
建立一个nginx测试容器
这里是三台机器组成集群,副本因子为3,
1 | docker-machine ssh node1 docker service create -p 80:80 --name swarm-nginx --replicas 3 fsoppelsa/swarm-nginx |
1 | docker-machine ssh node1 docker service ps swarm-nginx |
从上面可以看出node1作为集群建立者,管理者,也是会作为work节点建立容器的
这里我们可以猜想是不是作为节点管理者,在副本因子定义为2的时候,会不会优先选择非管理者建立节点
测试:
1 | docker-machine ssh node1 docker service create -p 8080:80 --name swarm-nginx8080 --replicas 2 fsoppelsa/swarm-nginx |
结果证明:没有定义策略的情况下,还是建立到了管理者node1上面
使用调度策略(约束)来建立一个不在管理者上建立容器的service
1 | docker-machine ssh node1 docker service create --constraint 'node.role!=manager' -p 88:80 --name swarm-nginx88 --replicas 3 fsoppelsa/swarm-nginx |
Swarm集群已经建立,清空所有的service。
搭建jenkins服务器(192.168.100.70)
搭建java和mvn环境
解压
1 | tar -zxf jdk-8u111-linux-x64.tar.gz |
设置环境变量
/etc/profile
1 | export JAVA_HOME=/usr/local/java |
生效
1 | source /etc/profile |
安装jenkins服务
建立一个jenkins目录
1 | mkdir Jenkins |
安装分屏命令screen
1 | sudo yum -y install screen |
建立一个名称为jenkins的screen分屏
1 | screen -S jenkins |
Ctrl+a+d返回终端
进入jenkins分屏
1 | screen -r jenkins |
Ctrl+a+d返回终端
Web浏览器打开登录http://192.168.100.70:404
切换为终端查看,并复制到web页面去
选择安装
安装好了后建立一个jenkins账户,密码为jenkins的管理员账户
修改jenkins的配置
Maven的配置
使用本地的maven
Java和git使用本地的
新建一个jenkins-swarm项目测试
自定义工作目录
1 | runuser -l admin -c 'docker-machine ssh node1 docker service create -p 80:80 --name swarm-nginx --replicas 3 fsoppelsa/swarm-nginx' |
这里因为docker-machine管理是使用的admin用户,而运行jenkins的root用户。所以root用户也无法使用docker-machine管理,这里我们使用runuser这个命令来执行,(是不是起到了安全的作用,我们可以建立一个用户来专门作为管理docker-machine的,)
保存后,点击立即构建
登录docker-machine的机器验证
访问验证
这里有一个猜想:
这里的docker-machine因为是使用的admin用户,所以docker-machine管理的主机的配置文件都放在/home/admin/.docker下,权限为700,这里我将权限设置为770后,并将root组设置为宿组,还是无法使用docker-machine,最后提示权限太高,导致无法运行。修改为700后即可。
构建一个maven项目
安装jenkins插件,
建立一个名为test-oss的maven项目
Git代码来源自己去配置配置好。存储位置:/tmp/jenkins-buildenv/${JOB_NAME}/workspace
build配置,指定pom.xml位置,第一次操作使用mvn install ,后续都使用mvn clean package -Dmaven.test.skip=true
Build操作使用shell脚本完成
因为运行jenkins的账户是root,所以使用runuser命令来操作,首先将jenkins的build后的代码复制到docker swarm的manager上,然后再由manager创建集群时候指定挂载
1 | BUILD_ID=DONTKILLME |
查看效果,稍微等下
做到这里的时候总结出一些更好的想法:
- 因为jenkins如果是使用的war的形式运行的,那么他会需要创建文件夹和配置文件,这样就需要管理权限,这样将会使用到root的权限,这样是有点不安全的,所以如果在真实环境中,推荐jenkins还是使用docker容器这样的方式来运行。
- 还有一种解决方式就是node1作为集群的manager,我们可以使用约束来不让他参与dockerservice的创建work节点容器,只作为jenkins这类的代码拉取工作。就可以省去我们这里的操作,需要在docker-machine控制台将文件夹复制到node1里面去,再运行dockerservice create的创建。
- docker swarm mode是使用service的方式建立集群并负载均衡。这样可以将项目整合在一起加强做集群
- 这里我的操作都没用到docker-machine env的操作,因为为了使用shell,只得使用ssh 节点 命令的方式来进行操作。
- Nginx服务器和nginx代理其实可以整合,但是我们为了优化配置,代理分开