diff --git a/doc/source/user/guides/clustering/cluster.rst b/doc/source/user/guides/clustering/cluster.rst
index b4772ef33..7ee5134e0 100644
--- a/doc/source/user/guides/clustering/cluster.rst
+++ b/doc/source/user/guides/clustering/cluster.rst
@@ -15,4 +15,179 @@
 Managing Clusters
 =================
 
-.. TODO(Qiming): Implement this guide
+Clusters are first-class citizens in Senlin service design. A cluster is
+defined as a collection of homogeneous objects. The "homogeneous" here means
+that the objects managed (aka. Nodes) have to be instantiated from the same
+"profile type".
+
+
+List Clusters
+~~~~~~~~~~~~~
+
+To examine the list of receivers:
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: list_cluster
+
+When listing clusters, you can specify the sorting option using the ``sort``
+parameter and you can do pagination using the ``limit`` and ``marker``
+parameters.
+
+Full example: `manage cluster`_
+
+
+Create Cluster
+~~~~~~~~~~~~~~
+
+When creating a cluster, you will provide a dictionary with keys and values
+according to the cluster type referenced.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: create_cluster
+
+Optionally, you can specify a ``metadata`` keyword argument that contains some
+key-value pairs to be associated with the cluster.
+
+Full example: `manage cluster`_
+
+
+Get Cluster
+~~~~~~~~~~~
+
+To get a cluster based on its name or ID:
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: get_cluster
+
+Full example: `manage cluster`_
+
+
+Find Cluster
+~~~~~~~~~~~~
+
+To find a cluster based on its name or ID:
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: find_cluster
+
+Full example: `manage cluster`_
+
+
+Update Cluster
+~~~~~~~~~~~~~~
+
+After a cluster is created, most of its properties are immutable. Still, you
+can update a cluster's ``name`` and/or ``params``.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: update_cluster
+
+Full example: `manage cluster`_
+
+
+Delete Cluster
+~~~~~~~~~~~~~~
+
+A cluster can be deleted after creation, When there are nodes in the cluster,
+the Senlin engine will launch a process to delete all nodes from the cluster
+and destroy them before deleting the cluster object itself.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: delete_cluster
+
+
+Cluster Add Nodes
+~~~~~~~~~~~~~~~~~
+
+Add some existing nodes into the specified cluster.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_add_nodes
+
+
+Cluster Del Nodes
+~~~~~~~~~~~~~~~~~
+
+Remove nodes from specified cluster.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_del_nodes
+
+
+Cluster Replace Nodes
+~~~~~~~~~~~~~~~~~~~~~
+
+Replace some existing nodes in the specified cluster.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_replace_nodes
+
+
+Cluster Scale Out
+~~~~~~~~~~~~~~~~~
+
+Inflate the size of a cluster.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_scale_out
+
+
+Cluster Scale In
+~~~~~~~~~~~~~~~~
+
+Shrink the size of a cluster.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_scale_in
+
+
+Cluster Resize
+~~~~~~~~~~~~~~
+
+Resize of cluster.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_resize
+
+
+Cluster Policy Attach
+~~~~~~~~~~~~~~~~~~~~~
+
+Once a policy is attached (bound) to a cluster, it will be
+enforced when related actions are performed on that cluster,
+unless the policy is (temporarily) disabled on the cluster
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_attach_policy
+
+
+Cluster Policy Detach
+~~~~~~~~~~~~~~~~~~~~~
+
+Once a policy is attached to a cluster, it can be detached
+from the cluster at user's request.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: cluster_detach_policy
+
+
+Cluster Check
+~~~~~~~~~~~~~
+
+Check cluster health status, Cluster members can be check.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: check_cluster
+
+
+Cluster Recover
+~~~~~~~~~~~~~~~
+
+To restore a specified cluster, members in the cluster will be checked.
+
+.. literalinclude:: ../../examples/clustering/cluster.py
+   :pyobject: recover_cluster
+
+
+.. _manage cluster: http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/clustering/cluster.py
+
diff --git a/examples/clustering/cluster.py b/examples/clustering/cluster.py
new file mode 100644
index 000000000..a4d46ce08
--- /dev/null
+++ b/examples/clustering/cluster.py
@@ -0,0 +1,172 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""
+Managing policies in the Cluster service.
+
+For a full guide see
+https://developer.openstack.org/sdks/python/openstacksdk/user/guides/cluster.html
+"""
+
+CLUSTER_NAME = "Test_Cluster"
+CLUSTER_ID = "47d808e5-ce75-4a1e-bfd2-4ed4639e8640"
+PROFILE_ID = "b0e3a680-e270-4eb8-9361-e5c9503fba0a"
+NODE_ID = "dd803d4a-015d-4223-b15f-db29bad3146c"
+POLICY_ID = "c0e3a680-e270-4eb8-9361-e5c9503fba00"
+
+
+def list_cluster(conn):
+    print("List clusters:")
+
+    for cluster in conn.clustering.clusters():
+        print(cluster.to_dict())
+
+    for cluster in conn.clustering.clusters(sort='name:asc'):
+        print(cluster.to_dict())
+
+
+def create_cluster(conn):
+    print("Create cluster:")
+
+    spec = {
+        "name": CLUSTER_NAME,
+        "profile_id": PROFILE_ID,
+        "min_size": 0,
+        "max_size": -1,
+        "desired_capacity": 1,
+    }
+
+    cluster = conn.clustering.create_cluster(**spec)
+    print(cluster.to_dict())
+
+
+def get_cluster(conn):
+    print("Get cluster:")
+
+    cluster = conn.clustering.get_cluster(CLUSTER_ID)
+    print(cluster.to_dict())
+
+
+def find_cluster(conn):
+    print("Find cluster:")
+
+    cluster = conn.clustering.find_cluster(CLUSTER_ID)
+    print(cluster.to_dict())
+
+
+def update_cluster(conn):
+    print("Update cluster:")
+
+    spec = {
+        "name": "Test_Cluster001",
+        "profile_id": "c0e3a680-e270-4eb8-9361-e5c9503fba0a",
+        "profile_only": True,
+    }
+    cluster = conn.clustering.update_cluster(CLUSTER_ID, **spec)
+    print(cluster.to_dict())
+
+
+def delete_cluster(conn):
+    print("Delete cluster:")
+
+    conn.clustering.delete_cluster(CLUSTER_ID)
+    print("Cluster deleted.")
+
+    # cluster support force delete
+    conn.clustering.delete_cluster(CLUSTER_ID, False, True)
+    print("Cluster deleted")
+
+
+def cluster_add_nodes(conn):
+    print("Add nodes to cluster:")
+
+    node_ids = [NODE_ID]
+    res = conn.clustering.cluster_add_nodes(CLUSTER_ID, node_ids)
+    print(res.to_dict())
+
+
+def cluster_del_nodes(conn):
+    print("Remove nodes from a cluster:")
+
+    node_ids = [NODE_ID]
+    res = conn.clustering.cluster_del_nodes(CLUSTER_ID, node_ids)
+    print(res.to_dict())
+
+
+def cluster_replace_nodes(conn):
+    print("Replace the nodes in a cluster with specified nodes:")
+
+    old_node = NODE_ID
+    new_node = "cd803d4a-015d-4223-b15f-db29bad3146c"
+    spec = {
+        old_node: new_node
+    }
+    res = conn.clustering.cluster_replace_nodes(CLUSTER_ID, **spec)
+    print(res.to_dict())
+
+
+def cluster_scale_out(conn):
+    print("Inflate the size of a cluster:")
+
+    res = conn.clustering.cluster_scale_out(CLUSTER_ID, 1)
+    print(res.to_dict())
+
+
+def cluster_scale_in(conn):
+    print("Shrink the size of a cluster:")
+
+    res = conn.clustering.cluster_scale_in(CLUSTER_ID, 1)
+    print(res.to_dict())
+
+
+def cluster_resize(conn):
+    print("Resize of cluster:")
+
+    spec = {
+        'min_size': 1,
+        'max_size': 6,
+        'adjustment_type': 'EXACT_CAPACITY',
+        'number': 2
+    }
+    res = conn.clustering.cluster_resize(CLUSTER_ID, **spec)
+    print(res.to_dict())
+
+
+def cluster_attach_policy(conn):
+    print("Attach policy to a cluster:")
+
+    spec = {'enabled': True}
+    res = conn.clustering.cluster_attach_policy(CLUSTER_ID, POLICY_ID,
+                                                **spec)
+    print(res.to_dict())
+
+
+def cluster_detach_policy(conn):
+    print("Detach a policy from a cluster:")
+
+    res = conn.clustering.cluster_detach_policy(CLUSTER_ID, POLICY_ID)
+    print(res.to_dict())
+
+
+def check_cluster(conn):
+    print("Check cluster:")
+
+    res = conn.clustering.check_cluster(CLUSTER_ID)
+    print(res.to_dict())
+
+
+def recover_cluster(conn):
+    print("Recover cluster:")
+
+    spec = {'check': True}
+    res = conn.clustering.recover_cluster(CLUSTER_ID, **spec)
+    print(res.to_dict())