Skip to content

Commit b7e42e5

Browse files
authored
Update Bigtable Programmatic Scaling Example [(googleapis#1003)](GoogleCloudPlatform/python-docs-samples#1003)
* Update Bigtable Programmatic Scaling Example * Rename "autoscaling" to "metricscaler" and the the term "programmatic scaling" * Remove `strategies.py` to simplify example * Fix wrong sleep length bug * Add maximum node count * hegemonic review
0 parents  commit b7e42e5

File tree

5 files changed

+415
-0
lines changed

5 files changed

+415
-0
lines changed

samples/metricscaler/README.rst

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
.. This file is automatically generated. Do not edit this file directly.
2+
3+
Google Cloud Bigtable Python Samples
4+
===============================================================================
5+
6+
This directory contains samples for Google Cloud Bigtable. `Google Cloud Bigtable`_ is Google's NoSQL Big Data database service. It's the same database that powers many core Google services, including Search, Analytics, Maps, and Gmail.
7+
8+
9+
This sample demonstrates how to use `Stackdriver Monitoring`_
10+
to scale Cloud Bigtable based on CPU usage.
11+
12+
.. _Stackdriver Monitoring: http://cloud.google.com/monitoring/docs/
13+
14+
15+
.. _Google Cloud Bigtable: https://cloud.google.com/bigtable/docs/
16+
17+
Setup
18+
-------------------------------------------------------------------------------
19+
20+
21+
Authentication
22+
++++++++++++++
23+
24+
Authentication is typically done through `Application Default Credentials`_,
25+
which means you do not have to change the code to authenticate as long as
26+
your environment has credentials. You have a few options for setting up
27+
authentication:
28+
29+
#. When running locally, use the `Google Cloud SDK`_
30+
31+
.. code-block:: bash
32+
33+
gcloud auth application-default login
34+
35+
36+
#. When running on App Engine or Compute Engine, credentials are already
37+
set-up. However, you may need to configure your Compute Engine instance
38+
with `additional scopes`_.
39+
40+
#. You can create a `Service Account key file`_. This file can be used to
41+
authenticate to Google Cloud Platform services from any environment. To use
42+
the file, set the ``GOOGLE_APPLICATION_CREDENTIALS`` environment variable to
43+
the path to the key file, for example:
44+
45+
.. code-block:: bash
46+
47+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service_account.json
48+
49+
.. _Application Default Credentials: https://cloud.google.com/docs/authentication#getting_credentials_for_server-centric_flow
50+
.. _additional scopes: https://cloud.google.com/compute/docs/authentication#using
51+
.. _Service Account key file: https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount
52+
53+
Install Dependencies
54+
++++++++++++++++++++
55+
56+
#. Install `pip`_ and `virtualenv`_ if you do not already have them.
57+
58+
#. Create a virtualenv. Samples are compatible with Python 2.7 and 3.4+.
59+
60+
.. code-block:: bash
61+
62+
$ virtualenv env
63+
$ source env/bin/activate
64+
65+
#. Install the dependencies needed to run the samples.
66+
67+
.. code-block:: bash
68+
69+
$ pip install -r requirements.txt
70+
71+
.. _pip: https://pip.pypa.io/
72+
.. _virtualenv: https://virtualenv.pypa.io/
73+
74+
Samples
75+
-------------------------------------------------------------------------------
76+
77+
Metricscaling example
78+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
79+
80+
81+
82+
To run this sample:
83+
84+
.. code-block:: bash
85+
86+
$ python metricscaler.py
87+
88+
usage: metricscaler.py [-h] [--high_cpu_threshold HIGH_CPU_THRESHOLD]
89+
[--low_cpu_threshold LOW_CPU_THRESHOLD]
90+
[--short_sleep SHORT_SLEEP] [--long_sleep LONG_SLEEP]
91+
bigtable_instance bigtable_cluster
92+
93+
Scales Cloud Bigtable clusters based on CPU usage.
94+
95+
positional arguments:
96+
bigtable_instance ID of the Cloud Bigtable instance to connect to.
97+
bigtable_cluster ID of the Cloud Bigtable cluster to connect to.
98+
99+
optional arguments:
100+
-h, --help show this help message and exit
101+
--high_cpu_threshold HIGH_CPU_THRESHOLD
102+
If Cloud Bigtable CPU usage is above this threshold,
103+
scale up
104+
--low_cpu_threshold LOW_CPU_THRESHOLD
105+
If Cloud Bigtable CPU usage is below this threshold,
106+
scale down
107+
--short_sleep SHORT_SLEEP
108+
How long to sleep in seconds between checking metrics
109+
after no scale operation
110+
--long_sleep LONG_SLEEP
111+
How long to sleep in seconds between checking metrics
112+
after a scaling operation
113+
114+
115+
116+
117+
The client library
118+
-------------------------------------------------------------------------------
119+
120+
This sample uses the `Google Cloud Client Library for Python`_.
121+
You can read the documentation for more details on API usage and use GitHub
122+
to `browse the source`_ and `report issues`_.
123+
124+
.. _Google Cloud Client Library for Python:
125+
https://googlecloudplatform.github.io/google-cloud-python/
126+
.. _browse the source:
127+
https://github.com/GoogleCloudPlatform/google-cloud-python
128+
.. _report issues:
129+
https://github.com/GoogleCloudPlatform/google-cloud-python/issues
130+
131+
132+
.. _Google Cloud SDK: https://cloud.google.com/sdk/

samples/metricscaler/README.rst.in

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# This file is used to generate README.rst
2+
3+
product:
4+
name: Google Cloud Bigtable
5+
short_name: Cloud Bigtable
6+
url: https://cloud.google.com/bigtable/docs/
7+
description: >
8+
`Google Cloud Bigtable`_ is Google's NoSQL Big Data database service. It's
9+
the same database that powers many core Google services, including Search,
10+
Analytics, Maps, and Gmail.
11+
12+
description: |
13+
This sample demonstrates how to use `Stackdriver Monitoring`_
14+
to scale Cloud Bigtable based on CPU usage.
15+
16+
.. _Stackdriver Monitoring: http://cloud.google.com/monitoring/docs/
17+
18+
setup:
19+
- auth
20+
- install_deps
21+
22+
samples:
23+
- name: Metricscaling example
24+
file: metricscaler.py
25+
show_help: true
26+
27+
cloud_client_library: true

samples/metricscaler/metricscaler.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Copyright 2017 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Sample that demonstrates how to use Stackdriver Monitoring metrics to
16+
programmatically scale a Google Cloud Bigtable cluster."""
17+
18+
import argparse
19+
import time
20+
21+
from google.cloud import bigtable
22+
from google.cloud import monitoring
23+
24+
25+
26+
def get_cpu_load():
27+
"""Returns the most recent Cloud Bigtable CPU load measurement.
28+
29+
Returns:
30+
float: The most recent Cloud Bigtable CPU usage metric
31+
"""
32+
# [START bigtable_cpu]
33+
client = monitoring.Client()
34+
query = client.query('bigtable.googleapis.com/cluster/cpu_load', minutes=5)
35+
time_series = list(query)
36+
recent_time_series = time_series[0]
37+
return recent_time_series.points[0].value
38+
# [END bigtable_cpu]
39+
40+
41+
def scale_bigtable(bigtable_instance, bigtable_cluster, scale_up):
42+
"""Scales the number of Cloud Bigtable nodes up or down.
43+
44+
Edits the number of nodes in the Cloud Bigtable cluster to be increased
45+
or decreased, depending on the `scale_up` boolean argument. Currently
46+
the `incremental` strategy from `strategies.py` is used.
47+
48+
49+
Args:
50+
bigtable_instance (str): Cloud Bigtable instance ID to scale
51+
bigtable_cluster (str): Cloud Bigtable cluster ID to scale
52+
scale_up (bool): If true, scale up, otherwise scale down
53+
"""
54+
_MIN_NODE_COUNT = 3
55+
"""
56+
The minimum number of nodes to use. The default minimum is 3. If you have a
57+
lot of data, the rule of thumb is to not go below 2.5 TB per node for SSD
58+
clusters, and 8 TB for HDD. The bigtable.googleapis.com/disk/bytes_used
59+
metric is useful in figuring out the minimum number of nodes.
60+
"""
61+
62+
_MAX_NODE_COUNT = 30
63+
"""
64+
The maximum number of nodes to use. The default maximum is 30 nodes per zone.
65+
If you need more quota, you can request more by following the instructions
66+
<a href="https://cloud.google.com/bigtable/quota">here</a>.
67+
"""
68+
69+
_SIZE_CHANGE_STEP = 3
70+
"""The number of nodes to change the cluster by."""
71+
# [START bigtable_scale]
72+
bigtable_client = bigtable.Client(admin=True)
73+
instance = bigtable_client.instance(bigtable_instance)
74+
instance.reload()
75+
76+
cluster = instance.cluster(bigtable_cluster)
77+
cluster.reload()
78+
79+
current_node_count = cluster.serve_nodes
80+
81+
if scale_up:
82+
if current_node_count < _MAX_NODE_COUNT:
83+
new_node_count = min(current_node_count + 3, _MAX_NODE_COUNT)
84+
cluster.serve_nodes = new_node_count
85+
cluster.update()
86+
print('Scaled up from {} to {} nodes.'.format(
87+
current_node_count, new_node_count))
88+
else:
89+
if current_node_count > _MIN_NODE_COUNT:
90+
new_node_count = max(
91+
current_node_count - _SIZE_CHANGE_STEP, _MIN_NODE_COUNT)
92+
cluster.serve_nodes = new_node_count
93+
cluster.update()
94+
print('Scaled down from {} to {} nodes.'.format(
95+
current_node_count, new_node_count))
96+
# [END bigtable_scale]
97+
98+
99+
def main(
100+
bigtable_instance,
101+
bigtable_cluster,
102+
high_cpu_threshold,
103+
low_cpu_threshold,
104+
short_sleep,
105+
long_sleep):
106+
"""Main loop runner that autoscales Cloud Bigtable.
107+
108+
Args:
109+
bigtable_instance (str): Cloud Bigtable instance ID to autoscale
110+
high_cpu_threshold (float): If CPU is higher than this, scale up.
111+
low_cpu_threshold (float): If CPU is lower than this, scale down.
112+
short_sleep (int): How long to sleep after no operation
113+
long_sleep (int): How long to sleep after the number of nodes is
114+
changed
115+
"""
116+
cluster_cpu = get_cpu_load()
117+
print('Detected cpu of {}'.format(cluster_cpu))
118+
if cluster_cpu > high_cpu_threshold:
119+
scale_bigtable(bigtable_instance, bigtable_cluster, True)
120+
time.sleep(long_sleep)
121+
elif cluster_cpu < low_cpu_threshold:
122+
scale_bigtable(bigtable_instance, bigtable_cluster, False)
123+
time.sleep(long_sleep)
124+
else:
125+
print('CPU within threshold, sleeping.')
126+
time.sleep(short_sleep)
127+
128+
129+
if __name__ == '__main__':
130+
parser = argparse.ArgumentParser(
131+
description='Scales Cloud Bigtable clusters based on CPU usage.')
132+
parser.add_argument(
133+
'bigtable_instance',
134+
help='ID of the Cloud Bigtable instance to connect to.')
135+
parser.add_argument(
136+
'bigtable_cluster',
137+
help='ID of the Cloud Bigtable cluster to connect to.')
138+
parser.add_argument(
139+
'--high_cpu_threshold',
140+
help='If Cloud Bigtable CPU usage is above this threshold, scale up',
141+
default=0.6)
142+
parser.add_argument(
143+
'--low_cpu_threshold',
144+
help='If Cloud Bigtable CPU usage is below this threshold, scale down',
145+
default=0.2)
146+
parser.add_argument(
147+
'--short_sleep',
148+
help='How long to sleep in seconds between checking metrics after no '
149+
'scale operation',
150+
default=60)
151+
parser.add_argument(
152+
'--long_sleep',
153+
help='How long to sleep in seconds between checking metrics after a '
154+
'scaling operation',
155+
default=60 * 10)
156+
args = parser.parse_args()
157+
158+
while True:
159+
main(
160+
args.bigtable_instance,
161+
args.bigtable_cluster,
162+
float(args.high_cpu_threshold),
163+
float(args.low_cpu_threshold),
164+
int(args.short_sleep),
165+
int(args.long_sleep))

0 commit comments

Comments
 (0)