4个树莓派搭建Docker Swarm集群

16 篇文章 0 订阅
13 篇文章 0 订阅

树莓派上安装Docker 安装

这里我用官方的一键脚本安装。

更换国内镜像源

详细查看树莓派更换国内镜像源

运行安装脚本

 curl -fsSL get.docker.com -o get-docker.sh && sh get-docker.sh

安装完成后,可以运行hello world看看

sudo docker run hello-world

在这里插入图片描述

创建Swarm集群

Swarm 是 Docker 社区提供的原生支持 Docker 集群管理的工具。它可以把多个 Docker 主机组成的系统转换为单一的虚拟 Docker 主机,使得容器可以组成跨主机的子网网络。docker默认就带有Swarm。

初始化Swarm

我目前有4个树莓派,IP分别为
192.168.1.51 管理节点
192.168.1.52 管理节点
192.168.1.54 工作节点
192.168.1.55 管理节点

我在51上创建集群

docker swarm init --advertise-addr 192.168.1.51

创建完成后,可以通过 docker info 查看swarm的情况,
在这里插入图片描述

加入管理节点

在51上输入

docker swarm join-token manager

获取加入swarm集群管理节点的token,进行复制

在这里插入图片描述
然后分别在52和55上粘贴加入节点的命令。

docker swarm join --token SWMTKN-1-4uetltgpm9a8qsg6egosgg5z4qw3nqyhipqdgse81fejb6xipr-39jb6lthdno9qxei6xv8cbjop 192.168.1.51:2377

注意: 不要照抄我的token

加入工作节点

在51上输入

docker swarm join-token worker

获取加入swarm集群工作节点的token,进行复制

在这里插入图片描述
然后在54上粘贴刚才的命令

docker swarm join --token SWMTKN-1-4uetltgpm9a8qsg6egosgg5z4qw3nqyhipqdgse81fejb6xipr-e2ytxxf8lsizsb70hohablyns 192.168.1.51:2377

查看节点情况

在任意一个管理节点输入

docker node ls

查看各个节点的情况

在这里插入图片描述
至此Swarm集群创建完毕。

编写测试代码

我使用.net core框架,C#语言编写测试代码,集群上运行一个Server,监听udp的12345端口,当收到客户端发来的数据,就给客户端返回自己的ID和接收到的数据。Socket控件我使用Bouyei.NetFactory。使用方法可以参考下我以前写的简单例子,《使用 Bouyei.NetFactory控件在树莓派上进行socket通信》

Server端代码


using Bouyei.NetFactoryCore;
using System;
using System.Text;
using System.Threading;

namespace Server
{
    class Program
    {
        static string id = Guid.NewGuid().ToString();
        static void Main(string[] args)
        {
            UdpDemo();
        }

        private static void UdpDemo()
        {
            int port = 12345;            

            INetServerProvider serverProvider = NetServerProvider.CreateProvider(256, 4, NetProviderType.Udp);
            serverProvider.ReceivedOffsetHandler = GetReceivedSegmentHandler(serverProvider);
            serverProvider.Start(port);            

            Thread.Sleep(Timeout.InfiniteTimeSpan);
            serverProvider.Dispose();

        }

        private static OnReceivedSegmentHandler GetReceivedSegmentHandler(INetServerProvider serverProvider)
        {
            return new OnReceivedSegmentHandler((SegmentToken session) =>
            {
                string datas = Encoding.UTF8.GetString(session.Data.buffer, session.Data.offset, session.Data.size);
                Console.WriteLine("from IP:"+ session.sToken.TokenIpEndPoint.ToString() +"  Datas:"+ datas);
                serverProvider.Send(new SegmentToken(session.sToken, Encoding.UTF8.GetBytes("id:"+id +" -> "+ Encoding.UTF8.GetString(session.Data.buffer, session.Data.offset, session.Data.size)+" "+ DateTime.Now)));

            });
        }
    }
}


然后服务端添加Docker支持,相应的配置参考我另外的文章《树莓派上在Docker中跑.Net Core》

生成Docker镜像后,上传到私有仓库,方法可参考我的另外文章《docker 创建本地私有仓库》

客户端代码

客户端从PC机连接服务端,代码如下

using Bouyei.NetFactoryCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Client
{
    class Program
    {
        static IList<IpAddress> ips;
        static int c = 1000*1000;
        static INetClientProvider clientProvider = null;
        static bool isConn;
        static string currIP = "";
        static DateTime latestTime = DateTime.Now;
        static void Main(string[] args)
        {
            ips = new List<IpAddress>();
            ips.Add(new IpAddress()
            {
                IP = "192.168.1.51",
                isOk = true
            });
            ips.Add(new IpAddress()
            {
                IP = "192.168.1.52",
                isOk = true
            });
            ips.Add(new IpAddress()
            {
                IP = "192.168.1.54",
                isOk = true
            });
            ips.Add(new IpAddress()
            {
                IP = "192.168.1.55",
                isOk = true
            });




            clientProvider = NetClientProvider.CreateProvider(4096, 4, NetProviderType.Udp);
            clientProvider.ReceivedOffsetHandler = new OnReceivedSegmentHandler((SegmentToken session) =>
            {
                latestTime = DateTime.Now;
                Console.WriteLine("from server : " + Encoding.UTF8.GetString(session.Data.buffer, session.Data.offset,
                    session.Data.size));

            });

            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Interval = 5 * 1000;
            timer.Elapsed += Timer_Elapsed;
            timer.Start();

            ConnectServer();

            HandleSomething();

            


            Thread.Sleep(Timeout.InfiniteTimeSpan);
        }

        /// <summary>
        /// 程序执行时间测试
        /// </summary>
        /// <param name="dateBegin">开始时间</param>
        /// <param name="dateEnd">结束时间</param>
        /// <returns>返回(秒)单位,比如: 0.00239秒</returns>
        public static double ExecDateDiff(DateTime dateBegin, DateTime dateEnd)
        {
            TimeSpan ts1 = new TimeSpan(dateBegin.Ticks);
            TimeSpan ts2 = new TimeSpan(dateEnd.Ticks);
            TimeSpan ts3 = ts2.Subtract(ts1).Duration();
            //你想转的格式
            return ts3.TotalSeconds;
        }

        private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (ExecDateDiff(latestTime, DateTime.Now) > 10)
            {
                isConn = false;
            }
            else
            {
                isConn = true;
            }

            if (!isConn)
            {
                var ip = ips.FirstOrDefault(x => x.IP.Contains(currIP));
                ip.isOk = false;
                ConnectServer();
            }
        }

        static void ConnectServer()
        {
            int port = 12345;

            var ipList = ips.Where(x => x.isOk).ToList();
            Random rd = new Random();
            int index = rd.Next(ipList.Count);
            var ip = ipList[index];

            if (ip!=null)
            {
                Console.WriteLine($"正在连接->{ip.IP}:{port}");
                clientProvider.ConnectTo(port, ip.IP);
                currIP = ip.IP;
            }
            else
            {
                foreach(var ip1 in ips)
                {
                    ip1.isOk = true;
                }
            }

            


        }



        static void HandleSomething()
        {
            while (c > 0)
            {
                Console.WriteLine($"Send -> {c}");
                clientProvider.Send(new SegmentOffset(Encoding.UTF8.GetBytes((c).ToString())));

                c--;
                Thread.Sleep(500);

            }
        }
    }


    class IpAddress
    {
        public string IP { get; set; }
        public bool isOk { get; set; }
    }
}

生成。

创建Swarm服务

在leader的树莓派上,把Server从私有仓库拉取下来。
然后创建服务

docker service create --replicas 3 -p 12345:12345/udp  111.111.3.210:5000/bystdnetfactorydemo

我创建了一个Service,运行了3个副本的Server端程序,对外监听12345的udp端口。运行成功后,可以通过 docker service ls 查看服务
在这里插入图片描述

客户端连接服务端

打开多个Client,程序启动后会自动连接服务端,并每隔500毫秒给服务端发送数据,docker Swarm会根据负载均衡,自动分配一个副本与客户端连接。下图中可以看到,我打开了3个Client端,服务端返回的ID是不一致的。
在这里插入图片描述
加入集群的节点,我们都可以使用其IP来访问集群,如果某个节点断掉或者故障了,可以使用其余节点进行连接集群,如果故障节点刚好运行副本,集群也会自动迁移,在其他节点上运行一个副本顶替。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值