前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenDaylight Lithium-SR2 Cluster集群搭建

OpenDaylight Lithium-SR2 Cluster集群搭建

作者头像
SDNLAB
发布2018-04-03 11:33:41
1.2K0
发布2018-04-03 11:33:41
举报
文章被收录于专栏:SDNLABSDNLAB

目的

希望大家能够通过本教程对OpenDaylight集群的基本概念如shard/基本配置有所了解,感受OpenDaylight的High Availability(HA)(如果你同时运行着多台控制器,其中一台crash掉了,整个系统仍然还可以工作)。

本文主要由三个部分组成,前提条件与配置步骤主要介绍了如何配置OpenDaylight的集群,第二个部分验证High Availbility,主要是通过实验让大家对High Availability有更直观的认识。第三个部分写在最后,简要的指出使用集群的优势,我的偶像导师说了,如何保持数据的一致性在软件定义网络中是非常非常非常重要的!

实验

注:若命令以$ 开头,则代表这条命令是在shell中执行;若命令以karaf> 开头,则代表这条命令是在karaf中执行。

前提条件

1. 下载OpenDaylight Lithium-SR2,链接地址为:https://www.opendaylight.org/downloads,若OpenDaylight出了新版本,可以点击该页面的Release Archives,下载Lithium-SR2。

2. 检查Java版本 执行命令查看Java的版本:

$ java -version
java version "1.7.0_85"
OpenJDK Runtime Environment (rhel-2.6.1.2.el7_1-x86_64 u85-b01)
OpenJDK 64-Bit Server VM (build 24.85-b03, mixed mode)

3. 操作系统:3台Ubuntu 14.04.3 LTS,其IP地址分别为192.168.1.25,192.168.1.24,192.168.1.23

4. 请确保防火墙配置正确,本实验使用firewall-cmd命令来配置的防火墙 查看配置执行:

$ sudo firewall-cmd --list-all

配置结果如下:

public (default)
  interfaces:
  sources:
  services: dhcpv6-client ssh
  ports: 2550/tcp 6633/tcp 2551/tcp 8181/tcp 8181/udp
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

端口8181用于restconf,端口2550用于cluster-data,端口2551用于cluster-rpc,端口6633用于openflow 可以用sudo firewall-cmd --add-port=端口号/协议名称来添加可访问端口。

5. 请确保在启动控制器之前,上述所列端口没有被其他程序占用

配置步骤

本节以IP地址为192.168.1.25的控制器为例,介绍如何对控制器进行配置 1.解压下载的zip文件,并进入控制器目录 本文的控制器目录为解压distribution-karaf-0.3.2-Lithium-SR2.zip后所得distribution-karaf-0.3.2-Lithium-SR2的目录。

$ unzip distribution-karaf-0.3.2-Lithium-SR2.zip
$ cd distribution-karaf-0.3.2-Lithium-SR2

2.运行控制器

$ ./bin/karaf

3.安装集群组件 安装集群组件,如odl-mdsal-clustering、odl-openflowplugin-flow-services和odl-restconf-all后,在控制器目录中的configuration目录内会有initial目录生成,下文的配置文件均位于该initial目录内,安装odl-openflowplugin-flow-services和odl-restconf-all是为了下文测试。下文会利用restconf向config datastore中写入flow。

karaf> feature:install odl-mdsal-clustering odl-openflowplugin-flow-services odl-restconf-all

注:可以在karaf中执行log:tail来查看控制器安装feature的状态日志,按ctrl+c可以停止查看控制器状态日志显示。

4.安装Jolokia

karaf> feature:install http
karaf> bundle:install -s mvn:org.jolokia/jolokia-osgi/1.1.5

5. 退出控制器

karaf> logout

6. 配置akka.conf,module-shards.conf 这些文件由第三步中生成,位于控制器的/configuration/init/中。 本教程中三个控制器的IP地址如下: controller1_IP = 192.168.1.25 controller2_IP = 192.168.1.24 controller3_IP = 192.168.1.23

6.1 修改akka.conf文件中的信息 6.1.1 修改roles roles相当于某一个控制器的ID,也就是说在这个集群中,每一个控制器的roles是唯一的。 例如,对于192.168.1.25,将其设置为

roles = [
        "member-1"
      ]

以此类推,192.168.1.24设置为member-2,192.168.1.23设置为member-3.

6.1.2 修改hostname(有两处需要修改) 修改之前的结果如下所示:

hostname = "127.0.0.1"

将hostname的值设置为你运行该控制器的IP地址或者hostname,如在IP为192.168.1.25的主机中,设置

hostname ="192.168.1.25"

6.1.3 修改odl-cluster-data中的seed-nodes seeds node是用于告诉刚开启的控制器,你属于哪一个集群

seed-nodes = ["akka.tcp://opendaylight-cluster-data@[controller1_IP]:2550", "akka.tcp://opendaylight-cluster-data@[controller2_IP]:2550", "akka.tcp://opendaylight-cluster-data@[controller3_IP]:2550"]

6.1.4 修改odl-cluster-rpc中的seed-nodes

seed-nodes = ["akka.tcp://odl-cluster-rpc@[controller1_IP]:2551", "akka.tcp://odl-cluster-rpc@[controller2_IP]:2551", "akka.tcp://odl-cluster-rpc@[controller3_IP]:2551"]

重要的话要说三遍!!! 请注意data中是opendaylight-cluster-data,rpc中是odl-cluster-rpc! 请注意data中是opendaylight-cluster-data,rpc中是odl-cluster-rpc! 请注意data中是opendaylight-cluster-data,rpc中是odl-cluster-rpc!

6.2 修改module-shards.conf文件 这里引入shard的概念:The in-memory MD-SAL tree is broken up into a number of smaller sub-trees (inventory, topology, and default),个人理解就是将MD-SAL的树拆分成很多小部分,每一个部分就是一个shard,然后在该文件中指定某个部分需要在哪几个控制器上留有备份replicas,详见https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:Clustering#Shard。将每一个replicas都做如下设置

replicas = [
    "member-1",
    "member-2",
    "member-3"
]

这样设置后,module-shards.conf中的所有shards都会在三台控制器中存在。至此,对于控制器192.168.1.25的配置已经完成,其他两台控制器也需要如上配置步骤,注意修改hostname以及roles。 配置范例:https://github.com/shawlinlovelife/learn_odl_cluster。

7. 分别启动三台控制器 请注意三台的启动时间请稍有间隔,最先启动完成的控制器将成为leader节点,我的启动顺序是192.168.1.25、192.168.1.24、192.168.1.23。

$ JAVA_MAX_MEM=4G JAVA_MAX_PERM_MEM=512m ./karaf
$ JAVA_MAX_MEM=4G JAVA_MAX_PERM_MEM=512m ./karaf
$ JAVA_MAX_MEM=4G JAVA_MAX_PERM_MEM=512m ./karaf

当你在karaf中执行log:tail|grep clustering后,能够见到如下信息,则代表member-1已经被选举为leader

2015-12-14 23:06:36,247 | INFO  | ult-dispatcher-3 | RoleChangeNotifier               | 175 - org.opendaylight.controller.sal-clustering-commons - 1.2.2.Lithium-SR2 | RoleChangeNotifier for member-1-shard-default-config , received role change from Candidate to Leader

当然你也会看到有data等successfully之类的,然后有rpc等successfully之类的信息。

8. 查看member-1的shard的信息 可以向member-1所在的控制器,本例中为192.168.1.25发送HTTP请求:

GET http://:8181/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-inventory-config,type=DistributedConfigDatastore

上述URI中的name的结构如下:

<member-name>-shard-<shard-name-as-per-configuration>-<store-type>

其中<shard-name-as-per-configuration>是你在module-shards.conf中设置的name,

<store-type>可以是config或者是operational,URI中的<host IP>应该与<member-name>对应

请将<hostIP>替换为ID为member-1的控制器的IP,发送请求可以使用Postman,若配置成功将会得到如下结果:

{
  "timestamp": 1450151185,
  "status": 200,
  "request": {
    "mbean": "org.opendaylight.controller:Category=Shards,name=member-1-shard-inventory-config,type=DistributedConfigDatastore",
    "type": "read"
  },
  "value": {
    "ReadWriteTransactionCount": 0,
    "SnapshotTerm": -1,
    "LastLogIndex": -1,
    "LastLogTerm": -1,
    "PeerAddresses": "member-2-shard-inventory-config: akka.tcp://opendaylight-cluster-data@192.168.1.24:2550/user/shardmanager-config/member-2-shard-inventory-config, member-3-shard-inventory-config: akka.tcp://opendaylight-cluster-data@192.168.1.23:2550/user/shardmanager-config/member-3-shard-inventory-config",
    "ReplicatedToAllIndex": -1,
    "StatRetrievalError": null,
    "CurrentTerm": 66,
    "LastTerm": -1,
    "SnapshotCaptureInitiated": false,
    "ShardName": "member-1-shard-inventory-config",
    "FailedTransactionsCount": 0,
    "LastIndex": -1,
    "LastApplied": -1,
    "LastCommittedTransactionTime": "1970-01-01 08:00:00.000",
    "InMemoryJournalLogSize": 0,
    "StatRetrievalTime": "4.987 ms",
    "LastLeadershipChangeTime": "2015-12-15 11:45:35.668",
    "ReadOnlyTransactionCount": 0,
    "CommitIndex": -1,
    "VotedFor": "member-1-shard-inventory-config",
    "LeadershipChangeCount": 1,
    "FollowerInitialSyncStatus": true,
    "FailedReadTransactionsCount": 0,
    "SnapshotIndex": -1,
    "Leader": "member-1-shard-inventory-config",
    "CommittedTransactionsCount": 0,
    "AbortTransactionsCount": 0,
    "WriteOnlyTransactionCount": 0,
    "RaftState": "Follower",
    "FollowerInfo": [],
    "InMemoryJournalDataSize": 0,
    "PendingTxCommitQueueSize": 0
  }
}

结论验证

1.连接mininet(可跳过) 注:这步其实没必要,因为其实我们修改config的datastore而不是operational的datastore,这里有一个问题就是我修改config datastore的信息会不会直接反应到operational datastore中,知道的小伙伴请告诉我。 启动mininet,并连接到三台控制器中的任意一个控制器:

$ sudo mn --controller=remote,<某一个控制器IP> --topo=tree,3 --switch=ovsk,protocols=OpenFlow13 --mac

注:--mac 会使得mininet虚拟出来的host的mac地址从00:00:00:00:00:01开始,方便查看。

2. 向某一个控制器添加flow,查看其他两个控制器的data store是否也发生改变 本例利用Postman向IP地址为192.168.1.23的控制发送PUT请求,添加flow信息,其信息结构如下:

With PostMan:
Set headers:
Content-Type: application/xml
Accept: application/xml
Authentication
Use URL: http://192.168.1.23:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1
PUT
Use Body:


    <priority>2</priority&>
    <flow-name>Foo</flow-name>
    
        
            
                <type>2048</type>
            </ethernet-type>
        </ethernet-match>
        <ipv4-destination>10.0.10.2/24</ipv4-destination>
    </match>
    <id>1</id>
    <table_id>0</table_id>
    <instructions>
        <instruction>
            <order>0</order>
            <apply-actions>
                <action>
                   <order>0</order>
                  <dec-nw-ttl/>
                </action>
            </apply-actions>
        </instruction>
    </instructions>
</flow>

使用Postman向另外两个控制器发送如下所示的GET请求,你将会得到相同的结果:

GET http://:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/

不再需要设置Accept header。

结果实例如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
    <priority>2</priority>
    <flow-name>Foo</flow-name>
    <match>
        <ethernet-match>
            <ethernet-type>
                <type>2048</type>
            </ethernet-type>
        </ethernet-match>
        <ipv4-destination>10.0.10.2/24</ipv4-destination>
    </match>
    <id>1</id>
    <table_id>0</table_id>
    <instructions>
        <instruction>
            <order>0</order>
            <apply-actions>
                <action>
                  <order>0</order>
                   <dec-nw-ttl/>
                </action>
            </apply-actions>
        </instruction>
    </instructions>
</flow>

3. 关闭leader控制器,查看系统是否能正常工作(leader将发生转换) 3.1 关闭leader控制器,本例中关闭192.168.1.25的控制器。 3.2 通过向member-2发送GET请求,来查看当前的leader

GET http://:8181/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-2-shard-inventory-config,type=DistributedConfigDatastore

本例中此处host IP可以设置为192.168.1.24,请注意host IP应该与在akka.conf中设置的roles的值相对应 结果示例如下,可以看到leader已经更换成为member-2-shard-inventory-config,也有可能是member-3-shard-inventory-config

{
  "timestamp": 1450155472,
  "status": 200,
  "request": {
    "mbean": "org.opendaylight.controller:Category=Shards,name=member-2-shard-inventory-config,type=DistributedConfigDatastore",
    "type": "read"
  },
  "value": {
    "ReadWriteTransactionCount": 0,
    "SnapshotTerm": 66,
    "LastLogIndex": 8,
    "LastLogTerm": 66,
    "PeerAddresses": "member-3-shard-inventory-config: akka.tcp://opendaylight-cluster-data@192.168.1.23:2550/user/shardmanager-config/member-3-shard-inventory-config, member-1-shard-inventory-config: akka.tcp://opendaylight-cluster-data@192.168.1.25:2550/user/shardmanager-config/member-1-shard-inventory-config",
    "ReplicatedToAllIndex": 7,
    "StatRetrievalError": null,
    "CurrentTerm": 66,
    "SnapshotCaptureInitiated": false,
    "LastTerm": 66,
    "ShardName": "member-2-shard-inventory-config",
    "FailedTransactionsCount": 0,
    "LastIndex": 8,
    "LastApplied": 8,
    "LastCommittedTransactionTime": "2015-12-15 12:52:54.697",
    "InMemoryJournalLogSize": 1,
    "StatRetrievalTime": "6.524 ms",
    "LastLeadershipChangeTime": "2015-12-15 10:57:32.216",
    "ReadOnlyTransactionCount": 0,
    "VotedFor": "member-2-shard-inventory-config",
    "CommitIndex": 8,
    "LeadershipChangeCount": 1,
    "FollowerInitialSyncStatus": false,
    "FailedReadTransactionsCount": 0,
    "SnapshotIndex": 7,
    "Leader": "member-2-shard-inventory-config",
    "CommittedTransactionsCount": 9,
    "AbortTransactionsCount": 0,
    "WriteOnlyTransactionCount": 0,
    "RaftState": "Leader",
    "FollowerInfo": [
      {
        "id": "member-3-shard-inventory-config",
        "timeSinceLastActivity": "0:00:00.206",
        "nextIndex": 9,
        "matchIndex": 8,
        "active": true
      },
      {
        "id": "member-1-shard-inventory-config",
        "timeSinceLastActivity": "0:02:41.409",
        "nextIndex": 9,
        "matchIndex": 8,
        "active": false
      }
    ],
    "InMemoryJournalDataSize": 1248,
    "PendingTxCommitQueueSize": 0
  }
}

4. 插入一条新的flow,本例向member-2中插入

With PostMan:
Set headers:
Content-Type: application/xml
Accept: application/xml
Authentication
Use URL: http://192.168.1.23:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/12
PUT
Use Body:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="urn:opendaylight:flow:inventory">
    <priority>2</priority>
    <flow-name>Foo2</flow-name>
    <match>
        <ethernet-match>
            <ethernet-type>
                <type>2048</type>
            </ethernet-type>
        </ethernet-match>
        <ipv4-destination>10.0.10.2/24</ipv4-destination>
    </match>
    <id>12</id>
    <table_id>0</table_id>
    <instructions>
        <instruction>
            <order>0</order>
            <apply-actions>
                <action>
                   <order>0</order>
                   <dec-nw-ttl/>
                </action>
            </apply-actions>
        </instruction>
    </instructions>
</flow>

5. 查看member-3中的信息是否也更新了

GET http://192.168.1.23:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/

若正常,则member-3中的信息已经更新

{
  "flow-node-inventory:table": [
    {
      "id": 0,
      "flow": [
        {
          "id": "12",
          "match": {
            "ipv4-destination": "10.0.10.2/24",
            "ethernet-match": {
              "ethernet-type": {
                "type": 2048
              }
            }
          },
          "flow-name": "Foo2",
          "table_id": 0,
          "priority": 2,
          "instructions": {
            "instruction": [
              {
                "order": 0,
                "apply-actions": {
                  "action": [
                    {
                      "order": 0,
                      "dec-nw-ttl": {}
                    }
                  ]
                }
              }
            ]
          }
        },
        {
          "id": "1",
          "match": {
            "ipv4-destination": "10.0.10.2/24",
            "ethernet-match": {
              "ethernet-type": {
                "type": 2048
              }
            }
          },
          "flow-name": "Foo2",
          "table_id": 0,
          "priority": 2,
          "instructions": {
            "instruction": [
              {
                "order": 0,
                "apply-actions": {
                  "action": [
                    {
                      "order": 0,
                      "dec-nw-ttl": {}
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  ]
}

6. 重新开启在3.1中关闭的控制器,验证在9.2.3中添加的flow,是否存在

GET http://192.168.1.25:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/

若结果正常,则它显示的应该与9.2.4中信息相同。

注:本实验验证了一部分关于OpenDaylight Cluster的功能,事实上一个集群的功能远不止这些。ODL的用户手册中还指出了以下三个: • Scaling: If you have multiple controllers running, you can potentially do more work with or store more data on those controllers if they are clustered. You can also break up your data into smaller chunks (known as shards) and either distribute that data across the cluster or perform certain operations on certain members of the cluster.

• High Availability: If you have multiple controllers running and one of them crashes, you would still have the other instances working and available.

• Data Persistence: You will not lose any data gathered by your controller after a manual restart or a crash.

我近期的另一个目标是对OpenDaylight集群进行性能测试,希望有经验的小伙伴能够给我推荐一些工具。这是我第一篇有一点点技术向的博文,希望能给大家提供点参考与帮助。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2015-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SDNLAB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目的
  • 实验
    • 前提条件
      • 配置步骤
      • 结论验证
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档