Migrating DLUX, Clustering, Version and XSQL to reST
[docs.git] / docs / getting-started-guide / common-features / clustering.rst
1 Setting Up Clustering
2 =====================
3
4 Clustering Overview
5 -------------------
6
7 Clustering is a mechanism that enables multiple processes and programs to work
8 together as one entity.  For example, when you search for something on
9 google.com, it may seem like your search request is processed by only one web
10 server. In reality, your search request is processed by may web servers
11 connected in a cluster. Similarly, you can have multiple instances of
12 OpenDaylight working together as one entity.
13
14 Advantages of clustering are:
15
16 * Scaling: If you have multiple instances of OpenDaylight running, you can
17   potentially do more work and store more data than you could with only one
18   instance. You can also break up your data into smaller chunks (shards) and
19   either distribute that data across the cluster or perform certain operations
20   on certain members of the cluster.
21 * High Availability: If you have multiple instances of OpenDaylight running and
22   one of them crashes, you will still have the other instances working and
23   available.
24 * Data Persistence: You will not lose any data stored in OpenDaylight after a
25   manual restart or a crash.
26
27 The following sections describe how to set up clustering on both individual and
28 multiple OpenDaylight instances.
29
30 Multiple Node Clustering
31 ------------------------
32
33 The following sections describe how to set up multiple node clusters in OpenDaylight.
34
35 Deployment Considerations
36 ^^^^^^^^^^^^^^^^^^^^^^^^^
37
38 To implement clustering, the deployment considerations are as follows:
39
40 * To set up a cluster with multiple nodes, we recommend that you use a minimum
41   of three machines. You can set up a cluster with just two nodes. However, if
42   one of the two nodes fail, the cluster will not be operational.
43
44   .. note:: This is because clustering in OpenDaylight requires a majority of the
45              nodes to be up and one node cannot be a majority of two nodes.
46
47 * Every device that belongs to a cluster needs to have an identifier.
48   OpenDaylight uses the node's ``role`` for this purpose. After you define the
49   first node's role as *member-1* in the ``akka.conf`` file, OpenDaylight uses
50   *member-1* to identify that node.
51
52 * Data shards are used to contain all or a certain segment of a OpenDaylight's
53   MD-SAL datastore. For example, one shard can contain all the inventory data
54   while another shard contains all of the topology data.
55
56   If you do not specify a module in the ``modules.conf`` file and do not specify
57   a shard in ``module-shards.conf``, then (by default) all the data is placed in
58   the default shard (which must also be defined in ``module-shards.conf`` file).
59   Each shard has replicas configured. You can specify the details of where the
60   replicas reside in ``module-shards.conf`` file.
61
62 * If you have a three node cluster and would like to be able to tolerate any
63   single node crashing, a replica of every defined data shard must be running
64   on all three cluster nodes. 
65
66   .. note:: This is because OpenDaylight's clustering implementation requires a
67             majority of the defined shard replicas to be running in order to
68             function. If you define data shard replicas on two of the cluster nodes
69             and one of those nodes goes down, the corresponding data shards will not
70             function.
71
72 * If you have a three node cluster and have defined replicas for a data shard
73   on each of those nodes, that shard will still function even if only two of
74   the cluster nodes are running. Note that if one of those remaining two nodes
75   goes down, the shard will not be operational.
76
77 * It is  recommended that you have multiple seed nodes configured. After a
78   cluster member is started, it sends a message to all of its seed nodes.
79   The cluster member then sends a join command to the first seed node that
80   responds. If none of its seed nodes reply, the cluster member repeats this
81   process until it successfully establishes a connection or it is shut down.
82
83 * After a node is unreachable, it remains down for configurable period of time
84   (10 seconds, by default). Once a node goes down, you need to restart it so
85   that it can rejoin the cluster. Once a restarted node joins a cluster, it
86   will synchronize with the lead node automatically.
87
88 Setting Up a Multiple Node Cluster
89 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
90
91 To run OpenDaylight in a three node cluster, perform the following:
92
93 First, determine the three machines that will make up the cluster. After that,
94 do the following on each machine:
95
96 #. Copy the OpenDaylight distribution zip file to the machine.
97 #. Unzip the distribution.
98 #. Open the following .conf files:
99
100    * configuration/initial/akka.conf
101    * configuration/initial/module-shards.conf
102
103 #. In each configuration file, make the following changes:
104
105    Find every instance of the following lines and replace _127.0.0.1_ with the
106    hostname or IP address of the machine on which this file resides and
107    OpenDaylight will run::
108    
109       netty.tcp {
110         hostname = "127.0.0.1"
111    
112    .. note:: The value you need to specify will be different for each node in the
113              cluster.
114
115 #. Find the following lines and replace _127.0.0.1_ with the hostname or IP
116    address of any of the machines that will be part of the cluster::
117
118       cluster {
119         seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"]
120
121 #. Find the following section and specify the role for each member node. Here
122    we assign the first node with the *member-1* role, the second node with the
123    *member-2* role, and the third node with the *member-3* role::
124
125      roles = [
126        "member-1"
127      ]
128
129    .. note:: This step should use a different role on each node.
130
131 #. Open the configuration/initial/module-shards.conf file and update the
132    replicas so that each shard is replicated to all three nodes::
133
134       replicas = [
135           "member-1",
136           "member-2",
137           "member-3"
138       ]
139
140    For reference, view a sample config files <<_sample_config_files,below>>.
141
142 #. Move into the +<karaf-distribution-directory>/bin+ directory.
143 #. Run the following command::
144
145       JAVA_MAX_MEM=4G JAVA_MAX_PERM_MEM=512m ./karaf
146
147 #. Enable clustering by running the following command at the Karaf command line::
148
149       feature:install odl-mdsal-clustering
150
151 OpenDaylight should now be running in a three node cluster. You can use any of
152 the three member nodes to access the data residing in the datastore.
153
154 Sample Config Files
155 """""""""""""""""""
156
157 Sample ``akka.conf`` file::
158
159    odl-cluster-data {
160      bounded-mailbox {
161        mailbox-type = "org.opendaylight.controller.cluster.common.actor.MeteredBoundedMailbox"
162        mailbox-capacity = 1000
163        mailbox-push-timeout-time = 100ms
164      }  
165     
166      metric-capture-enabled = true
167     
168      akka {
169        loglevel = "DEBUG"
170        loggers = ["akka.event.slf4j.Slf4jLogger"]
171     
172        actor {
173     
174          provider = "akka.cluster.ClusterActorRefProvider"
175          serializers {
176                    java = "akka.serialization.JavaSerializer"
177                    proto = "akka.remote.serialization.ProtobufSerializer"
178                  }
179     
180                  serialization-bindings {
181                      "com.google.protobuf.Message" = proto
182     
183                  }
184        }
185        remote {
186          log-remote-lifecycle-events = off
187          netty.tcp {
188            hostname = "10.194.189.96"
189            port = 2550
190            maximum-frame-size = 419430400
191            send-buffer-size = 52428800
192            receive-buffer-size = 52428800
193          }
194        }
195     
196        cluster {
197          seed-nodes = ["akka.tcp://opendaylight-cluster-data@10.194.189.96:2550"]
198     
199          auto-down-unreachable-after = 10s
200     
201          roles = [
202            "member-1"
203          ]
204     
205        }
206      }
207    }
208     
209    odl-cluster-rpc {
210      bounded-mailbox {
211        mailbox-type = "org.opendaylight.controller.cluster.common.actor.MeteredBoundedMailbox"
212        mailbox-capacity = 1000
213        mailbox-push-timeout-time = 100ms
214      }
215     
216      metric-capture-enabled = true
217     
218      akka {
219        loglevel = "INFO"
220        loggers = ["akka.event.slf4j.Slf4jLogger"]
221     
222        actor {
223          provider = "akka.cluster.ClusterActorRefProvider"
224     
225        }
226        remote {
227          log-remote-lifecycle-events = off
228          netty.tcp {
229            hostname = "10.194.189.96"
230            port = 2551
231          }
232        }
233     
234        cluster {
235          seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@10.194.189.96:2551"]
236     
237          auto-down-unreachable-after = 10s
238        }
239      }
240    }
241
242 Sample ``module-shards.conf`` file::
243
244    module-shards = [
245        {
246            name = "default"
247            shards = [
248                {
249                    name="default"
250                    replicas = [
251                        "member-1",
252                        "member-2",
253                        "member-3"
254                    ]
255                }
256            ]
257        },
258        {
259            name = "topology"
260            shards = [
261                {
262                    name="topology"
263                    replicas = [
264                        "member-1",
265                        "member-2",
266                        "member-3"
267                    ]
268                }
269            ]
270        },
271        {
272            name = "inventory"
273            shards = [
274                {
275                    name="inventory"
276                    replicas = [
277                        "member-1",
278                        "member-2",
279                        "member-3"
280                    ]
281                }
282            ]
283        },
284        {
285             name = "toaster"
286             shards = [
287                 {
288                     name="toaster"
289                     replicas = [
290                        "member-1",
291                        "member-2",
292                        "member-3"
293                     ]
294                 }
295             ]
296        }
297    ]