本文共 10739 字,大约阅读时间需要 35 分钟。
原本是选择在自己的云服务器上搭建Docker,但是建集群的时候发现Mysql只能启动一个实例,第二个实例运行后会自动关闭,经过排查发现是渣渣服务器的内存不够支撑多实例。
于是还是借助虚拟机环境来搭建,也能模拟多台服务器安装的情况。本博客作为记录篇,用于Docker下快速搭建
Tomcat、Mysql、Nginx、Haproxy集群环境链接:https://pan.baidu.com/s/1zSxo5u_PrJhTuxNqShIvEA
提取码:w2es官方镜像地址http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1810.iso
一开始我是用Putty连接+WinSCP传输文件,后来发现新的工具XobaXterm功能还挺多的。
和VM一起都放在上面的网盘里了安装CentOS的虚拟机步骤就不复述了,为方便测试直接选用root账号登录,不嫌麻烦也可以用sudo获取root操作权限。
/-/y是指后续Y/N操作都以Y执行yum install -y docker//安装后执行显示版本则成功docker version
至 获取镜像加速地址
手动修改/etc/docker/daemon.json为 { 个人的加速地址 } 或者直接执行网址内的shell脚本//创建网关 避免每次重启ip变化
docker network create --subnet=172.18.0.0/16 mynetwork//拉取tomcat镜像docker pull tomcat//运行普通容器docker run --name tomcat -d tomcat//复制webapp出来 因为这个目录不是运行生成的就会直接被覆盖 容器运行后生成的不会被覆盖可以不复制docker cp tomcat:/usr/local/tomcat/webapps /docker/tomcat/webapps///删除容器docker stop tomcatdocker rm tomcat//运行正式容器 启动双实例共用webappsdocker run \-p 12001:8080 \--restart=always \--privileged=true \--name tomcat_02 \-v /docker/tomcat/tomcat_02/webapps:/usr/local/tomcat/tomcat/webapps \--network=mynetwork \--ip 172.18.0.12 \-d tomcat
//拉取mysql镜像 不加版本默认下最新版docker pull mysql:5.7.17//创建配置文件 内容在下面touch /docker/mysql/conf/my_01.cnf//创建挂载文件 需要与下面启动配置与my.cnf中配置的对应 配置文件存放路径:/docker/mysql/conf/my.conf数据文件存放路径:/docker/mysql/data日志文件存放路径:/docker/mysql/logs//查看镜像Image_iddocker images//启动mysql容器 启动失败使用docker logs --tail=30 mysql 查看//运行正式容器 启动双实例docker run \-p 22001:3306 \--restart=always \--privileged=true \--name mysql_02 \-e MYSQL_ROOT_PASSWORD=123456 \-v /docker/mysql/mysql_02/conf/my.cnf:/etc/mysql/my.cnf \-v /docker/mysql/mysql_02/logs:/usr/local/mysql/logs \-v /docker/mysql/mysql_02/data:/usr/local/mysql/data \--network=mynetwork \--ip 172.18.0.22 \-d mysql
[client]default-character-set=utf8port=3306[mysql]default-character-set=utf8 [mysqld]character-set-server=utf8collation-server=utf8_unicode_cidatadir=/usr/local/mysql/datasql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION[mysqld_safe]log_error=/usr/local/mysql/logs/mysql_error.logslow_query_log = 1#超过1秒则为慢查询long_query_time = 1 slow_query_log_file = /usr/local/mysql/logs/mysql_slow.log
再通过Navicat进行连接测试
看Mysql版本,可能需要开通远程登录权限,另外如果真实环境使用的话,服务器防火墙及云服务器安全组之类的都需要设置Nginx主要是web服务器,具备负载均衡LB的功能,多进程模式,社区活跃,然后是因为Nginx在负载均衡下的能力比Haproxy差一点,以及它不支持TCP,要实现Mysql的负载均衡要使用插件,所以后面又使用Haproxy作为负载均衡中间件使用。
//拉取nginx镜像docker pull nginx//运行普通容器docker run --name nginx -d nginx//复制容器运行必备的配置文件 直接挂载的话会被覆盖成空文件导致运行失败 容器运行后生成的不会被覆盖可以不复制docker cp nginx:/etc/nginx/nginx.conf /docker/nginx/conf///删除容器docker stop nginxdocker rm nginx//运行正式容器 docker run \-p 31001:80 \--restart=always \--privileged=true \--name nginx \-v /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \-v /docker/nginx/conf/conf.d:/etc/nginx/conf.d \-v /docker/nginx/html:/usr/share/nginx/html \-v /docker/nginx/logs:/var/log/nginx \--network=mynetwork \--ip 172.18.0.31 \-d nginx:latest
user nginx;worker_processes 4; #工作进程数,为CPU的核心数或者两倍error_log /var/log/nginx/error.log warn;pid /var/run/nginx.pid;events { use epoll; #Linux最常用支持大并发的事件触发机制 worker_connections 65535;}http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 120; #gzip on; #gzip on; limit_conn_zone $binary_remote_addr zone=perip:10m; #添加limit_zone,限制同一IP并发数 include /etc/nginx/conf.d/*.conf; #包含nginx虚拟主机配置文件目录}
upstream test { ip_hash; #server 192.168.65.129:18080 weight=1;#根据上面IIS配置 #server 192.168.65.129:18081 weight=1;#根据上面IIS配置 server 172.18.0.3:8080 weight=1; server 172.18.0.2:8080 weight=1;}server { listen 80; server_name localhost; #charset GB2312; location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://test; } # 查看nginx的并发连接数配置 location /NginxStatus { stub_status on; access_log off; auth_basic "NginxStatus"; } access_log off; error_page 404 /404.html; error_page 500 502 503 504 /404.html; location = /404.html { root html; } limit_conn perip 200; #同一ip并发数为200,超过会返回503}
//拉取haproxy镜像docker pull haproxy//创建配置文件 内容往下touch /docker/haproxy/config/haproxy.cfg//运行正式实例 同样创建多个实例 这里挂载的keepalived后续使用docker run \-p 32001:8888 -p 32002:3306 \--restart=always \--privileged=true \--name haproxy_02 \-v /docker/haproxy/haproxy_02/config:/usr/local/etc/haproxy \-v /docker/haproxy/haproxy_02/keepalived.conf:/etc/keepalived/keepalived.conf \--network=mynetwork \--ip 172.18.0.32 \-d haproxy
需要在MySQL中创建一个没有权限的haproxy用户,密码为空。Haproxy使用这个账户对MySQL数据库心跳检测,用户名可在配置文件中配置
global #工作目录 chroot /usr/local/etc/haproxy #日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info log 127.0.0.1 local5 info #守护进程运行 daemon defaults log global mode http #日志格式 option httplog #日志中不记录负载均衡的心跳检测记录 option dontlognull #连接超时(毫秒) timeout connect 5000 #客户端超时(毫秒) timeout client 50000 #服务器超时(毫秒) timeout server 50000 #监控界面 listen admin_stats #监控界面的访问的IP和端口 bind 0.0.0.0:8888 #访问协议 mode http #登录的URI相对地址 stats uri / #统计报告格式 stats realm Global\ statistics #登陆帐户信息 stats auth test:test#数据库负载均衡listen proxy-mysql #访问的IP和端口(前面ip=0代表任何ip都可访问) bind 0.0.0.0:3306 #网络协议 mode tcp #负载均衡算法(轮询算法) #轮询算法:roundrobin #权重算法:static-rr #最少连接算法:leastconn #请求源IP算法:source balance roundrobin #日志格式 option tcplog #在MySQL中创建一个没有权限的haproxy用户,密码为空。Haproxy使用这个账户对MySQL数据库心跳检测 option mysql-check user haproxy server NODE1 172.18.0.21:3306 check weight 1 maxconn 2000 server NODE2 172.18.0.21:3306 check weight 1 maxconn 2000 #使用keepalive检测死链 option tcpka
打开监控界面正常
keepalived的实现是要在docker服务内创建,所以要进入各自的宿主机进行安装
//进入容器docker exec -it haproxy_01 bash//安装keepalivedapt-get updateapt-get -y install keepalived//配置文件在haproxy的时候映射过,这里就不创建了 内容在下面有//开启keepalivedservice keepalived start//安装pingapt-get install iputils-ping//ip a 查看是否加入网卡 如果存在的话会显示keepalived配置的ipip a //容器及宿主机各自都测试是否连通ping 172.18.0.100
各自的容器和各自的keepalived都ping通后,宿主机也需要安装keepalived,宿主机的keepalived只是作为一个中转,因为外部Ip是没法直接访问到容器内部keepalived生成的vip的。
//宿主机安装keepalivedyum install -y keepalived//修改配置文件/etc/keepalived 在下面有//开启keepalivedservice keepalived start//然后ping虚拟ip 如果ping通而在外部网络不能访问 有防火墙就开端口 有安全组就设置白名单
成功在keepalived的虚拟ip上登录
多个容器的配置完全一样,但是要保证他们相互都能Ping通
vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 100 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 172.18.0.100 }}
vrrp_instance VI_1 { state MASTER#这里是宿主机的网卡,可以通过ip a查看当前自己电脑上用的网卡名是哪个 interface ens33 virtual_router_id 100 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { #这里是指定的一个宿主机上的虚拟ip,要外部能访问到的,作为中转连接至容器内keepalived172.18.0.100 192.168.65.222 }}#接受监听数据来源的端口,网页入口使用virtual_server 192.168.65.222 8888 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP #haproxy的对应ip端口 real_server 172.18.0.100 8888 { weight 1 }}#接受监听数据来源的端口,数据库使用virtual_server 192.168.65.222 3306 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP#haproxy的对应ip端口 real_server 172.18.0.100 3306 { weight 1 }}
首先,通过VM的克隆生成一个新的虚拟机,并运行Docker与Mysql。
或者直接用上述容器生成指令生成多个不同端口Mysql容器然后在找资料的过程发现Mysql集群方案实在是有点多,一时不知道做哪种方案。
1.master上将操作记录到二进制bin-log里面去
2.slaves读取bin-log日志到本地的中继日志relay-log 3.slaves执行relay-log里的事件1.基于语句的复制: 在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。一旦发现没法精确复制时, 会自动选着基于行的复制。
2.基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍。从mysql5.0开始支持。 3.混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。 和redis的aof有点类似vi /etc/my.cnf 如果是docker容器修改挂载文件即可
[mysqld]server-id=1 #这个id全局唯一,slaves上的id不能与之冲突log-bin=mysql-bin #必须开启二进制日志功能
重启数据库并进入执行语句
GRANT REPLICATION SLAVE ON *.* to 'test'@'%' identified by '123456'; #创建一个同步账户,用来同步数据用flush privileges;show master status;#记下数据内容file和position 要再slave中用#这里可以锁住所有表来防止slave部署过程中的修改,但是部署好最后要记得解锁
vi /etc/my.cnf 如果是docker容器修改挂载文件即可
[mysqld]server-id=2 #这个id,全局唯一,不能与master,或者其他slaves冲突log-bin=mysql-bin #slaves上没有必要开启bin-log功能,当slave作为其他slave的master时除外#binlog-do-db=databasename1,databasename2 #这个参数是指定需要复制的数据库名字,默认复制所有#binlog-ignore-db=databasename1,databasename2 #这个参数是指定不需要复制的数据库名字
重启数据库并进入执行语句
#stop SLAVE;change master to master_host='192.168.65.129',#如果是同服务器Docker部署的就使用服务器内部IP与端口master_port=9001,master_user='test',master_password='123456',master_log_file='mysql-bin.000007',#上面记录的值master_log_pos=311;#上面记录的值start SLAVE;show slave status;
非常关键 如果是采用VM复制的虚拟机,要修改宿主机挂载文件的/docker/mysql/data_01/auth.cnf的id,这个id不能重复,或者进容器内find / -name "auto.cnf"再修改,不过要安装vim比较麻烦
如果Slave_Sql_Running是NO,可以尝试执行
stop slave ;set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;start slave ;show slave STATUS;
总而言之,如果运行失败一定要去看日志文件 docker logs -f --tail=30 mysql01
测试了同服务器不同docker容器及不同服务器下的集群
192.168.65.129_9001 192.168.65.129_9002 192.168.65.130_9001 注意 服务器内部使用docker连接的话需要使用内部的IP及容器内部端口 服务器之间则直接使用外部IP与外部端口docker pull percona/percona-xtradb-cluster//创建挂载目录docker volume rm v1docker volume rm v2docker volume rm v3docker volume create --name v1docker volume create --name v2docker volume create --name v3//查看目录docker volume inspect v1 //创建网络docker network create --subnet=172.19.0.0/24 pxc//开防火墙firewall-cmd --zone=public --add-port=3301/tcp --permanentfirewall-cmd --zone=public --add-port=3302/tcp --permanentfirewall-cmd --reloaddocker run \-p 3301:3306 \--name=node1 \--privileged=true \-e CLUSTER_NAME=cluster1 \-e MYSQL_ROOT_PASSWORD=root \-e XTRABACKUP_PASSWORD=root \--net=pxc \--ip 172.19.0.2 \-d pxcdocker run \-p 3302:3306 \--name=node2 \--privileged=true \-e CLUSTER_NAME=cluster1 \-e MYSQL_ROOT_PASSWORD=root \-e XTRABACKUP_PASSWORD=root \ -e CLUSTER_JOIN=node1 \--net=pxc \--ip 172.19.0.3 \-d pxc
转载地址:http://veiob.baihongyu.com/