Difference between revisions of "Trove-Replication-And-Clustering-API"
Imsplitbit (talk | contribs) |
Imsplitbit (talk | contribs) |
||
Line 1: | Line 1: | ||
+ | =Instance Object Changes= | ||
+ | Part of this proposal includes adding new properties to the json structure of an instance. | ||
+ | The first would be to add a "nodes" property which would be list of refs back to the nova | ||
+ | instance(s) that make up the trove instance. | ||
+ | |||
+ | The second would be a metadata storage that is of an open format to be used for storing | ||
+ | critical data that is pertinent to the trove instance. | ||
+ | |||
+ | ==INSTANCES== | ||
+ | ===Nodes=== | ||
+ | Because trove instances are a service type with an underlying nova resource(s) we can better | ||
+ | display the nova resource(s) that make up the instance of a service type. When looking at a | ||
+ | singular trove instance of something like redis or mysql the knowledge of the instance | ||
+ | resource isn't all that important. Currently trove knows about the instance from a nova | ||
+ | perspective but masks most of this information. This would look something like this: | ||
+ | |||
+ | '''GET''' /instances/{id} | ||
+ | <pre> | ||
+ | { | ||
+ | "instance": { | ||
+ | "created": "2013-05-08T22:43:34", | ||
+ | "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.rackspaceclouddb.com", | ||
+ | "id": "dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | "name": "json_rack_instance", | ||
+ | "status": "ACTIVE", | ||
+ | "updated": "2013-05-08T22:43:34", | ||
+ | "service_type": "mysql-5.1", | ||
+ | "nodes": [ | ||
+ | { | ||
+ | "flavor": { | ||
+ | "id": "1", | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/flavors/1", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/flavors/1", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ], | ||
+ | "volume": { | ||
+ | "size": 2, | ||
+ | "used": 0.16368598397821188 | ||
+ | }, | ||
+ | }, | ||
+ | ], | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | ===Metadata=== | ||
+ | The metadata looks much like our previous proposal. It contains critical information to the | ||
+ | configuration or topology of the cluster or replication agreement. This should look something | ||
+ | like this: | ||
+ | |||
+ | '''GET''' /instances/{id} | ||
+ | <pre> | ||
+ | { | ||
+ | "instance": { | ||
+ | "created": "2013-05-08T22:43:34", | ||
+ | "id": "cfeccbf4-ac5b-494a-99b7-61593a6a71b0", | ||
+ | "name": "multi-master-hotness", | ||
+ | "status": "ACTIVE", | ||
+ | "updated": "2013-05-08T22:43:34", | ||
+ | "service_type": "mysql-5.5", | ||
+ | "nodes": [ | ||
+ | { | ||
+ | "id": "dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | "hostname": "master-n01.example.com", | ||
+ | "flavor": { | ||
+ | "id": "1", | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/flavors/1", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/flavors/1", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ], | ||
+ | "volume": { | ||
+ | "size": 2, | ||
+ | "used": 0.16368598397821188 | ||
+ | }, | ||
+ | }, | ||
+ | { | ||
+ | "id": "4530736b-c1ff-4c07-9a9f-fa9bca418157", | ||
+ | "hostname": "master-n02.example.com", | ||
+ | "flavor": { | ||
+ | "id": "1", | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/flavors/1", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/flavors/1", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/instances/4530736b-c1ff-4c07-9a9f-fa9bca418157", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/instances/4530736b-c1ff-4c07-9a9f-fa9bca418157", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ], | ||
+ | "volume": { | ||
+ | "size": 2, | ||
+ | "used": 0.16368598397821188 | ||
+ | }, | ||
+ | }, | ||
+ | { | ||
+ | "id": "736b9820-7e91-4775-84b0-78e71d60ce4c", | ||
+ | "hostname": "master-n03.example.com", | ||
+ | "flavor": { | ||
+ | "id": "1", | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/flavors/1", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/flavors/1", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | "links": [ | ||
+ | { | ||
+ | "href": "https://service/v1.0/1234/instances/736b9820-7e91-4775-84b0-78e71d60ce4c", | ||
+ | "rel": "self" | ||
+ | }, | ||
+ | { | ||
+ | "href": "https://service/instances/736b9820-7e91-4775-84b0-78e71d60ce4c", | ||
+ | "rel": "bookmark" | ||
+ | } | ||
+ | ], | ||
+ | "volume": { | ||
+ | "size": 2, | ||
+ | "used": 0.16368598397821188 | ||
+ | }, | ||
+ | }, | ||
+ | ], | ||
+ | "metadata": { | ||
+ | "replication_contract": { | ||
+ | // We should use something more clear than just nova instance | ||
+ | // ids here but lets just use them for now for example. Maybe | ||
+ | // links? names? not sure what works best yet. | ||
+ | "dcc5c518-73c7-4471-83e1-15fae67a98eb": { | ||
+ | "replicates_to": [ | ||
+ | "4530736b-c1ff-4c07-9a9f-fa9bca418157", | ||
+ | ], | ||
+ | "replicates_from": [ | ||
+ | "736b9820-7e91-4775-84b0-78e71d60ce4c", | ||
+ | ], | ||
+ | "readable": True, | ||
+ | "writeable": True, | ||
+ | }, | ||
+ | "4530736b-c1ff-4c07-9a9f-fa9bca418157": { | ||
+ | "replicates_to": [ | ||
+ | "736b9820-7e91-4775-84b0-78e71d60ce4c", | ||
+ | ], | ||
+ | "replicates_from": [ | ||
+ | "dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | ], | ||
+ | "readable": True, | ||
+ | "writeable": True, | ||
+ | }, | ||
+ | "736b9820-7e91-4775-84b0-78e71d60ce4c": { | ||
+ | "replicates_to": [ | ||
+ | "dcc5c518-73c7-4471-83e1-15fae67a98eb", | ||
+ | ], | ||
+ | "replicates_from": [ | ||
+ | "4530736b-c1ff-4c07-9a9f-fa9bca418157", | ||
+ | ], | ||
+ | "readable": True, | ||
+ | "writeable": True | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
=Clustering and Replication= | =Clustering and Replication= | ||
A cluster is an independent service type. | A cluster is an independent service type. | ||
Line 45: | Line 258: | ||
<pre> | <pre> | ||
{ | { | ||
− | "metadata" { | + | "metadata": { |
"nodes": 3 | "nodes": 3 | ||
} | } |
Revision as of 00:31, 10 October 2013
Instance Object Changes
Part of this proposal includes adding new properties to the json structure of an instance. The first would be to add a "nodes" property which would be list of refs back to the nova instance(s) that make up the trove instance.
The second would be a metadata storage that is of an open format to be used for storing critical data that is pertinent to the trove instance.
INSTANCES
Nodes
Because trove instances are a service type with an underlying nova resource(s) we can better display the nova resource(s) that make up the instance of a service type. When looking at a singular trove instance of something like redis or mysql the knowledge of the instance resource isn't all that important. Currently trove knows about the instance from a nova perspective but masks most of this information. This would look something like this:
GET /instances/{id}
{ "instance": { "created": "2013-05-08T22:43:34", "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.rackspaceclouddb.com", "id": "dcc5c518-73c7-4471-83e1-15fae67a98eb", "name": "json_rack_instance", "status": "ACTIVE", "updated": "2013-05-08T22:43:34", "service_type": "mysql-5.1", "nodes": [ { "flavor": { "id": "1", "links": [ { "href": "https://service/v1.0/1234/flavors/1", "rel": "self" }, { "href": "https://service/flavors/1", "rel": "bookmark" } ] }, "links": [ { "href": "https://service/v1.0/1234/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", "rel": "self" }, { "href": "https://service/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", "rel": "bookmark" } ], "volume": { "size": 2, "used": 0.16368598397821188 }, }, ], } }
Metadata
The metadata looks much like our previous proposal. It contains critical information to the configuration or topology of the cluster or replication agreement. This should look something like this:
GET /instances/{id}
{ "instance": { "created": "2013-05-08T22:43:34", "id": "cfeccbf4-ac5b-494a-99b7-61593a6a71b0", "name": "multi-master-hotness", "status": "ACTIVE", "updated": "2013-05-08T22:43:34", "service_type": "mysql-5.5", "nodes": [ { "id": "dcc5c518-73c7-4471-83e1-15fae67a98eb", "hostname": "master-n01.example.com", "flavor": { "id": "1", "links": [ { "href": "https://service/v1.0/1234/flavors/1", "rel": "self" }, { "href": "https://service/flavors/1", "rel": "bookmark" } ] }, "links": [ { "href": "https://service/v1.0/1234/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", "rel": "self" }, { "href": "https://service/instances/dcc5c518-73c7-4471-83e1-15fae67a98eb", "rel": "bookmark" } ], "volume": { "size": 2, "used": 0.16368598397821188 }, }, { "id": "4530736b-c1ff-4c07-9a9f-fa9bca418157", "hostname": "master-n02.example.com", "flavor": { "id": "1", "links": [ { "href": "https://service/v1.0/1234/flavors/1", "rel": "self" }, { "href": "https://service/flavors/1", "rel": "bookmark" } ] }, "links": [ { "href": "https://service/v1.0/1234/instances/4530736b-c1ff-4c07-9a9f-fa9bca418157", "rel": "self" }, { "href": "https://service/instances/4530736b-c1ff-4c07-9a9f-fa9bca418157", "rel": "bookmark" } ], "volume": { "size": 2, "used": 0.16368598397821188 }, }, { "id": "736b9820-7e91-4775-84b0-78e71d60ce4c", "hostname": "master-n03.example.com", "flavor": { "id": "1", "links": [ { "href": "https://service/v1.0/1234/flavors/1", "rel": "self" }, { "href": "https://service/flavors/1", "rel": "bookmark" } ] }, "links": [ { "href": "https://service/v1.0/1234/instances/736b9820-7e91-4775-84b0-78e71d60ce4c", "rel": "self" }, { "href": "https://service/instances/736b9820-7e91-4775-84b0-78e71d60ce4c", "rel": "bookmark" } ], "volume": { "size": 2, "used": 0.16368598397821188 }, }, ], "metadata": { "replication_contract": { // We should use something more clear than just nova instance // ids here but lets just use them for now for example. Maybe // links? names? not sure what works best yet. "dcc5c518-73c7-4471-83e1-15fae67a98eb": { "replicates_to": [ "4530736b-c1ff-4c07-9a9f-fa9bca418157", ], "replicates_from": [ "736b9820-7e91-4775-84b0-78e71d60ce4c", ], "readable": True, "writeable": True, }, "4530736b-c1ff-4c07-9a9f-fa9bca418157": { "replicates_to": [ "736b9820-7e91-4775-84b0-78e71d60ce4c", ], "replicates_from": [ "dcc5c518-73c7-4471-83e1-15fae67a98eb", ], "readable": True, "writeable": True, }, "736b9820-7e91-4775-84b0-78e71d60ce4c": { "replicates_to": [ "dcc5c518-73c7-4471-83e1-15fae67a98eb", ], "replicates_from": [ "4530736b-c1ff-4c07-9a9f-fa9bca418157", ], "readable": True, "writeable": True } } } } }
Clustering and Replication
A cluster is an independent service type.
- This simplifies the configurations (ties to service_type)
- The guest impl can be different for each service_type
- We don't need cluster type and service_type when defining a cluster
Think: A instance is an instance is a cluster is an instance is NOT replication
CLUSTERING
Definition of cluster for purposes of Trove:
A cluster must provide
- High Availablility
- Fault Tolerance
A cluster object is represented as an instance with a metadata attribute
containing node information. A node is a sub-resource of a cluster and
has a limited number of actions that can be performed on them. A cluster
is made of of equal sized nodes using all the same flavor/disk size.
Cluster Operations
Create cluster:
Create a cluster with flavor X and size Y. All nodes are of equal size.
POST /instance
{ "name": "foobar", "flavor": "{flavor_id}", "service_type": "{service_type_id}", "size": 50, "metadata": { "nodes": 5, } }
Delete cluster:
- Deletes all nodes in the cluster and the cluster itself.
DELETE /instance/{id}
Downsize a cluster (Delete nodes): PATCH /instance/{id}
{ "metadata": { "nodes": 3 } }
Restart a cluster:
POST /instance/{id}/restart
{ "empty body?" }
Resize a cluster:
POST /instance/{id}/resize
{ "flavor": "flavor_id", "volume": { "size": 100 } }
Initialize cluster:
POST /instance/{id}/initialize
{ "pertinent data should go here..." }
Rebalance/restripe cluster:
POST /instance/{id}/rebalance
{ "pertinent data goes here" }
Node Operations:
Restart a node:
POST /instance/{id}/node/{id}/restart
{ "empty body?" }
Initialize a node:
POST /instance/{id}/node/{id}/initialize
{ "empty body?" }
REPLICATION
We think of replication as a capability of some service types. Not every service type will have this capability and it should be configurable via the service types capabilities feature.
What you cannot do: - create a master and slave in one call - one call per action means simplified workflow
Replication workflow:
1. Create an instance
2. Create an Nth instance with
- metadata {"master_instance": "id from 1", "replication_type": "typeid from replication_types api"}
- Caveat: adding a replicated slave will alter data on the master instance and will use the agent
to create the replication.
Replication Operations
Create Replication:
POST /instance
{ "name": "foobar", "flavor": "flavor_id", "service_type": "mysql-5.1", "size": 50, "metadata": { "replication_type": "replication_type_id", "replication_data": { "master_instance": "instance_uuid" } } }