diff --git a/releasenotes/notes/clustering-service-cli-e15cc6627de293fa.yaml b/releasenotes/notes/clustering-service-cli-e15cc6627de293fa.yaml
new file mode 100644
index 00000000..9830157b
--- /dev/null
+++ b/releasenotes/notes/clustering-service-cli-e15cc6627de293fa.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - |
+    Enalble CLI to support clustering service in Tacker Server
diff --git a/tackerclient/shell.py b/tackerclient/shell.py
index 76903b33..d238de61 100644
--- a/tackerclient/shell.py
+++ b/tackerclient/shell.py
@@ -50,6 +50,7 @@ from tackerclient.tacker.v1_0 import extension
 from tackerclient.tacker.v1_0.nfvo import ns
 from tackerclient.tacker.v1_0.nfvo import nsd
 from tackerclient.tacker.v1_0.nfvo import vim
+from tackerclient.tacker.v1_0.nfvo import vnfcluster
 from tackerclient.tacker.v1_0.nfvo import vnffg
 from tackerclient.tacker.v1_0.nfvo import vnffgd
 from tackerclient.tacker.v1_0.vnfm import vnf
@@ -168,6 +169,16 @@ COMMAND_V1 = {
     'ns-list': ns.ListNS,
     'ns-delete': ns.DeleteNS,
     'ns-show': ns.ShowNS,
+
+    'cluster-create': vnfcluster.CreateCluster,
+    'cluster-delete': vnfcluster.DeleteCluster,
+    'cluster-list': vnfcluster.ListCluster,
+    'cluster-show': vnfcluster.ShowCluster,
+
+    'cluster-member-add': vnfcluster.AddClusterMember,
+    'cluster-member-show': vnfcluster.ShowClusterMember,
+    'cluster-member-list': vnfcluster.ListClusterMember,
+    'cluster-member-delete': vnfcluster.DeleteClusterMember,
 }
 
 COMMANDS = {'1.0': COMMAND_V1}
diff --git a/tackerclient/tacker/v1_0/nfvo/vnfcluster.py b/tackerclient/tacker/v1_0/nfvo/vnfcluster.py
new file mode 100644
index 00000000..cfb9185a
--- /dev/null
+++ b/tackerclient/tacker/v1_0/nfvo/vnfcluster.py
@@ -0,0 +1,191 @@
+# 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.
+
+from tackerclient.tacker import v1_0 as tackerV10
+import yaml
+
+_CLUSTER = 'cluster'
+_CLUSTER_MEMBER = 'clustermember'
+
+
+class ListCluster(tackerV10.ListCommand):
+    """List Clusters that belong to a given tenant."""
+
+    resource = _CLUSTER
+    list_columns = ['id', 'name', 'vnfd_id', 'status', 'vip_endpoint']
+
+
+class ShowCluster(tackerV10.ShowCommand):
+    """Show information of a given Cluster."""
+
+    resource = _CLUSTER
+
+
+class DeleteCluster(tackerV10.DeleteCommand):
+    """Delete a given Cluster."""
+
+    resource = _CLUSTER
+
+
+class CreateCluster(tackerV10.CreateCommand):
+    """Create a Cluster."""
+
+    resource = _CLUSTER
+
+    def add_known_arguments(self, parser):
+        parser.add_argument(
+            'name', metavar='NAME',
+            help='Set a name for the VNF cluster')
+        vnfd_group = parser.add_mutually_exclusive_group(required=True)
+        vnfd_group.add_argument(
+            '--vnfd-id',
+            help='VNFD ID to use as template to create member VNF')
+        vnfd_group.add_argument(
+            '--vnfd-name',
+            help='VNFD name to use as template to create member VNF')
+        parser.add_argument('--policy-file',
+                            help='Specify policy file for cluster',
+                            required=True)
+        parser.add_argument(
+            '--description',
+            help='Set a description for the created VNF cluster')
+
+    def args2body(self, parsed_args):
+        body = {self.resource: {}}
+        tacker_client = self.get_client()
+        tacker_client.format = parsed_args.request_format
+
+        if parsed_args.vnfd_name:
+            _id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
+                                                          'vnfd',
+                                                          parsed_args.
+                                                          vnfd_name)
+            parsed_args.vnfd_id = _id
+        policy_info = None
+        with open(parsed_args.policy_file) as f:
+            policy_info = yaml.safe_load(f.read())
+        tackerV10.update_dict(parsed_args, body[self.resource],
+                              ['tenant_id', 'name', 'vnfd_id', 'description'])
+        if policy_info:
+            body[self.resource]['policy_info'] = policy_info
+        return body
+
+
+class AddClusterMember(tackerV10.CreateCommand):
+    """Add a new Cluster Member to given Cluster."""
+
+    resource = _CLUSTER_MEMBER
+
+    def add_known_arguments(self, parser):
+        parser.add_argument(
+            'name', metavar='NAME',
+            help='Set a name for the VNF cluster member')
+        cluster_group = parser.add_mutually_exclusive_group()
+        cluster_group.add_argument(
+            '--cluster-id',
+            help='VNFD ID to use as template to create member VNF')
+        cluster_group.add_argument(
+            '--cluster-name',
+            help='VNFD name to use as template to create member VNF')
+        vnfd_group = parser.add_mutually_exclusive_group()
+        vnfd_group.add_argument(
+            '--vnfd-id',
+            help='Set a id for the VNFD')
+        vnfd_group.add_argument(
+            '--vnfd-name',
+            help='Set a name for the VNFD')
+        parser.add_argument(
+            '--role',
+            help='Set a [Active/Standby] role to cluster member',
+            required=True)
+        vim_group = parser.add_mutually_exclusive_group()
+        vim_group.add_argument(
+            '--vim-id',
+            help='Set a VIM ID to deploy cluster member')
+        vim_group.add_argument(
+            '--vim-name',
+            help='Set a VIM name to deploy cluster member')
+
+    def args2body(self, parsed_args):
+        body = {self.resource: {}}
+
+        tacker_client = self.get_client()
+        tacker_client.format = parsed_args.request_format
+        if parsed_args.cluster_name:
+            _id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
+                                                          'cluster',
+                                                          parsed_args.
+                                                          cluster_name)
+            parsed_args.cluster_id = _id
+        if parsed_args.vnfd_name:
+            _id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
+                                                          'vnfd',
+                                                          parsed_args.
+                                                          vnfd_name)
+            parsed_args.vnfd_id = _id
+        parsed_args.role = parsed_args.role.upper()
+        if parsed_args.vim_name:
+            _id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
+                                                          'vim',
+                                                          parsed_args.
+                                                          vim_name)
+            parsed_args.vim_id = _id
+        tackerV10.update_dict(parsed_args, body[self.resource],
+                              ['tenant_id', 'name', 'cluster_id', 'vnfd_id',
+                               'role', 'vim_id'])
+        return body
+
+
+class ListClusterMember(tackerV10.ListCommand):
+    """List Cluster Members that belong to a given tenant."""
+
+    resource = _CLUSTER_MEMBER
+
+    def add_known_arguments(self, parser):
+        cluster_group = parser.add_mutually_exclusive_group(required=True)
+        cluster_group.add_argument(
+            '--cluster-id',
+            help='Set a ID for the queried cluster')
+        cluster_group.add_argument(
+            '--cluster-name',
+            help='Set a name for the queried cluster')
+
+    def args2body(self, parsed_args):
+        body = {self.resource: {}}
+        tacker_client = self.get_client()
+        tacker_client.format = parsed_args.request_format
+
+        if parsed_args.cluster_name:
+            _id = tackerV10.find_resourceid_by_name_or_id(tacker_client,
+                                                          'cluster',
+                                                          parsed_args.
+                                                          cluster_name)
+            parsed_args.cluster_id = _id
+
+        tackerV10.update_dict(parsed_args, body[self.resource],
+                              ['tenant_id', 'cluster_id'])
+        return body
+
+    list_columns = ['id', 'name', 'cluster_id', 'role', 'vnf_id',
+                    'vim_id', 'mgmt_url', 'lb_member_id']
+
+
+class DeleteClusterMember(tackerV10.DeleteCommand):
+    """Delete a given Cluster Member."""
+
+    resource = _CLUSTER_MEMBER
+
+
+class ShowClusterMember(tackerV10.ShowCommand):
+    """Show information of a given Cluster Member."""
+
+    resource = _CLUSTER_MEMBER
diff --git a/tackerclient/v1_0/client.py b/tackerclient/v1_0/client.py
index abdb03f4..d9b5dc35 100644
--- a/tackerclient/v1_0/client.py
+++ b/tackerclient/v1_0/client.py
@@ -368,6 +368,11 @@ class Client(ClientBase):
     nss_path = '/nss'
     ns_path = '/nss/%s'
 
+    clusters_path = '/clusters'
+    cluster_path = '/clusters/%s'
+    cluster_members_path = '/clustermembers'
+    cluster_member_path = '/clustermembers/%s'
+
     # API has no way to report plurals, so we have to hard code them
     # EXTED_PLURALS = {}
 
@@ -662,3 +667,44 @@ class Client(ClientBase):
     @APIParamsCall
     def delete_ns(self, ns):
         return self.delete(self.ns_path % ns)
+
+    @APIParamsCall
+    def create_cluster(self, body=None):
+        return self.post(self.clusters_path, body)
+
+    @APIParamsCall
+    def list_clusters(self, retrieve_all=True, **_params):
+        clusters = self.list('clusters', self.clusters_path,
+                             retrieve_all, **_params)
+        return clusters
+
+    @APIParamsCall
+    def show_cluster(self, cluster, **_params):
+        member = self.get(self.cluster_path % cluster,
+                          params=_params)
+        return member
+
+    @APIParamsCall
+    def delete_cluster(self, cluster):
+        return self.delete(self.cluster_path % cluster)
+
+    @APIParamsCall
+    def create_clustermember(self, body=None):
+        return self.post(self.cluster_members_path, body)
+
+    @APIParamsCall
+    def list_clustermembers(self, retrieve_all=True, **_params):
+        cluster_members = self.list('clustermembers',
+                                    self.cluster_members_path,
+                                    retrieve_all, **_params)
+        return cluster_members
+
+    @APIParamsCall
+    def show_clustermember(self, clustermember, **_params):
+        member = self.get(self.cluster_member_path % clustermember,
+                          params=_params)
+        return member
+
+    @APIParamsCall
+    def delete_clustermember(self, clustermember):
+        return self.delete(self.cluster_member_path % clustermember)