このNotebookではVCP SDKを利用してVCノードを起動、削除する手順を記しています。
上の図、またはこれ以降に示す図に記されている構成要素についての簡単な説明を以下に記します。
大まかな手順は以下のようになります。
VCP SDKを利用するにはVCコントローラのアクセストークンが必要となります。次のセルを実行すると入力枠が表示されるのでアクセストークンの値を入力してください。
アクセストークン入力後に Enter キーを押すことで入力が完了します。
from getpass import getpass
vcc_access_token = getpass()
VCP SDKを用いてVCノード(Amazon EC2インスタンス)を起動します。また、起動したVCノードに対してsshでログインして操作を行います。
VCP SDKの初期化を行います。
from common import logsetting
from vcpsdk.vcpsdk import VcpSDK
# VCP SDKの初期化
vcp = VcpSDK(
vcc_access_token, # VCCのアクセストークン
)
上のセルの実行結果がエラーとなり以下のようなメッセージが表示されている場合は、入力されたアクセストークンに誤りがあります。
2019-XX-XX XX:XX:XX,XXX - ERROR - config vc failed: http_status(403)
2019-XX-XX XX:XX:XX,XXX - ERROR - 2019/XX/XX XX:XX:XX UTC: VCPAuthException: xxxxxxx:token lookup is failed: permission denied
この場合はアクセストークンの入力からやり直してください。
vcp
からは UnitGroup の管理(作成、情報取得)や VCP SDK自体に関する情報取得を行うことができます。例えば、次のセルを実行するとUnitGroupの一覧が表示されます。
まだUnitGroupを作成していないので、ヘッダー以外はなにも表示されないはずです。
# UnitGroupの一覧を DataFrame で表示する
vcp.df_ugroups()
次のセルを実行すると VCP SDK と VCコントローラのバージョンが表示されます。
vcp.version()
handson101
という名前の UnitGroup を作成します。
# UnitGroupの作成
unit_group = vcp.create_ugroup(
'handson101' # UnitGroupの名前
)
作成したUnitGroupの状態を表示してみます。
UnitGroup の名前が
handson101
であることと、その状態がRUNNING
であることなどが確認できるはずです。
print(unit_group)
UnitGroupの一覧を表示してみます。
# UnitGroupの一覧を DataFrame で表示する
vcp.df_ugroups()
UnitGroupに属している Unit の一覧を表示します。
まだ、このUnitGroupでは Unit を作成していないのでヘッダー以外は何も表示されません。
# Unitの一覧を DataFrame で表示する
unit_group.df_units()
UnitGroupに属しているVCノードの一覧を表示します。
まだVCノードが存在していないので何も表示されません。
unit_group.df_nodes()
Unitを構成するVCノードがどのような設定であるかを指定するためのオブジェクトとしてVCP SDKではspec
オブジェクトを用意しています。VCP SDKの利用者はspec
オブジェクトのプロパティを設定することで Unitに起動するVCノードの設定内容を定義することができます。
spec
オブジェクトの設定項目の例を以下に示します。
設定できる項目はクラウドプロバイダ(aws, azure, ...)毎に異なります。
spec
オブジェクトの全てのパラメータを毎回設定するのは煩雑になるので典型的な構成のパラメータセットを事前に定義しています。事前に定義したspec
パラメータセットのことを VCP SDKでは flavor
と呼んでいます。spec
に設定できるパラメータはクラウドプロバイダ毎に異なるので flavor
の定義もクラウドプロバイダ毎に行っています。
次のセルを実行すると aws用に定義している flavor
の一覧が表示されます。
vcp.df_flavors('aws')
specオブジェクトを作成します。specオブジェクトを作成するにはプロバイダとflavor
を指定します。ここでは以下の値を指定します。
aws
small
spec = vcp.get_spec('aws', 'small')
作成したspec
の設定内容を確認してみます。
instance_type
パラメータにflavor
の指定と対応するEC2インスタンスタイプm4.large
が設定されていることが確認できるはずです。volume_size
,volume_type
についてもそれぞれflavor
と対応する値が設定されます。
print(spec)
spec
に対しては flavor
で指定するだけではなく個々のパラメータを直接指定することもできます。例えば、以下のようなものが指定できます。
試しに volume_size
を指定してみます。
spec.volume_size = 15
指定した値がspec
の設定に反映されていることを確認してみます。
print(spec)
volume_size
の値が指定した値に変更されています。
VCノードにsshでログインするためには事前に公開鍵認証の鍵を登録する必要があります。そのための設定をここで行います。
VCノードに登録する公開鍵認証の公開鍵のパスを次のセルで指定してください。
import os
ssh_public_key = os.path.expanduser('~/.ssh/id_rsa.pub')
指定した公開鍵を spec
に設定します。
spec.set_ssh_pubkey(ssh_public_key)
sshの公開鍵に関する設定がspec
に反映されたことを確認してみます。次のセルを実行するとparams
のe
のAUTHORIZED_KEYS
に値が設定されていることが確認できます。
print(spec)
後でVCノードにログインする際にsshの秘密鍵も必要になるので、ここで設定しておきます。次のセルで秘密鍵のパスを指定してください。
ssh_private_key = os.path.expanduser('~/.ssh/id_rsa')
公開鍵と秘密鍵が正しいペアであることをチェックします。次のセルを実行してエラーにならないことを確認してください。
!grep -q "$(ssh-keygen -y -f {ssh_private_key})" {ssh_public_key}
Unitを作成します。Unitを作成すると同時に VCノード(ここでは Amazon EC2インスタンス)が起動します。
処理が完了するまで1分半~2分程度かかります。
# Unitの作成(同時に VCノードが作成される)
unit = unit_group.create_unit(
'aws-server2', # Unit名の指定
spec
)
UnitGroupに属しているUnitの一覧表示を行い、Unitが作成されていることを確認します。
# Unitの一覧を DataFrame で表示する
unit_group.df_units()
UnitGroupに属しているVCノードの一覧表示を行い、VCノードが起動していることを確認します。VCノードが正常に起動していることは node_state
の表示が RUNNING
になっていることで確認できます。
# VCノードの一覧を DataFrame で表示する
unit_group.df_nodes()
ここでは VCノードの起動が完了するまで待ち合わせるモードでUnitの作成を行いましたが、非同期処理でUnit, VCノードの作成を行うこともできます。create_unit()
のwait_for
パラメータにFalse
を指定すると非同期モードでのUnit, VCノードの作成が行えます。
unit = unit_group.create_unit('aws-server', spec, wait_for=False)
非同期モードでUnitを作成した場合にUnitやVCノードが起動したことを確認するには、以下に示す方法で状態取得を行ってください。
unit_group.df_units()
unit_state
の項目で Unitの状態を確認できますBOOTING
、起動が完了して実行中になると RUNNING
と表示されますunit.df_nodes()
, unit_group.df_nodes()
node_state
の項目で VCノードの状態を確認できますBOOTING
、起動が完了して実行中になると RUNNING
と表示されます非同期モードでUnit作成を行った場合でも、以下のメソッドを利用することで後からVCノード起動の待ち合わせを行うことができます。
unit_group.wait_unit_applied(unit_name)
RUNNING
または ERROR
になるのを待ちます起動した VCノードに対してping
を行ってみます。
まずUnitGroup内で起動しているVCノードに割り当てられているプライベートIPアドレスの値を取得して変数 ip_address
に格納します。
# unit_group.find_ip_addresses() は UnitGroup内の全VCノードのIPアドレスのリストを返します
ip_address = unit_group.find_ip_addresses(node_state='RUNNING')[0] # 今は1つのVCノードのみ起動しているので [0] で最初の要素を取り出す
print(ip_address)
実際に ping
を行ってみます。
Codeセルで先頭に
!
をつけるとシェルコマンドが実行できます。また{}
で囲むことで Python の変数参照やコードの実行に置き換えることができます。詳しくは「IPython Documentation」などを参照してください。
まず、ログインする前に ~/.ssh/known_hosts のホストキーを更新します。
!touch ~/.ssh/known_hosts
# ~/.ssh/known_hosts から古いホストキーを削除する
!ssh-keygen -R {ip_address}
# ホストキーの登録
!ssh-keyscan -H {ip_address} >> ~/.ssh/known_hosts
ls -la
を実行してみます。
!ssh -i {ssh_private_key} -l root {ip_address} /bin/ls -la
VCノードにsshでログインするにはsshの引数に以下の指定が必要となります。
spec
オブジェクトに設定した公開鍵に対応する秘密鍵root
sshのオプションを毎回指定するのも煩雑なので変数に設定しておきます。
ssh_opts = f"-i {ssh_private_key} -l root"
VCノードに対してuname -a
, df -h
などを実行してみます。
!ssh {ssh_opts} {ip_address} uname -a
!ssh {ssh_opts} {ip_address} df -h
VCPではVCノードの利用状況(CPU負荷、メモリ使用量、ネットワーク)を確認するための情報収集・可視化ツールとしてGrafanaのダッシュボードを提供しています。
以下のセルを実行して Grafana ダッシュボードを開いてください。
最初にログイン画面が表示されるので ユーザ名、パスワードにそれぞれ admin
, admin
を入力してください。
vcc_ctr = vcp.vcc_info()['host']
http_host = vcc_ctr.split(':')[0]
grafana_url = "https://{}/grafana/d/vcp/vcp-metrics?refresh=5s".format(http_host)
print(grafana_url)
VCノードに負荷をかけるために、アプリケーションコンテナで stress コマンドを実行します。
# 60秒間だけ CPU x 2 とメモリ 128 MB を消費する
!ssh {ssh_opts} {ip_address} \
/usr/local/bin/docker run -td --rm --name stress-0 polinux/stress \
stress --cpu 2 --io 1 --vm 2 --vm-bytes 128M --timeout 60s --verbose
# 60秒間だけ CPU x 2 とメモリ 128 MB を消費する (2回目)
!ssh {ssh_opts} {ip_address} \
/usr/local/bin/docker run -td --rm --name stress-1 polinux/stress \
stress --cpu 2 --io 1 --vm 2 --vm-bytes 128M --timeout 60s --verbose
Unitには spec
オブジェクトに指定されている設定と同一の VCノードを作成する機能があります。その機能を利用して Unit にVCノードを追加してみます。
まず、現在のVCノードの状況を確認しておきます。
# VCノードの一覧を DataFrame で表示する
unit.df_nodes()
Unit に VCノードを追加するにはunit
オブジェクトに対して add_nodes()
を呼び出します。次のセルを実行するとUnitに VCノード が追加されます。
VCノード の起動には 1分半~2分程度かかります。
unit.add_nodes()
add_node()
を呼び出すことで追加されるVCノードの数はデフォルトでは1ですが、パラメータnum_add_nodes
を設定することで追加するVCノード数を変更することが出来ます。例えば3ノードを追加するには以下のような指定を行います。
unit.add_nodes(num_add_nodes=3)
また、追加するVCノードのIPアドレスを指定する場合は、以下のような指定を行います。
unit.add_nodes(ip_address='172.30.2.30')
他にどんなパラメータを指定することが出来るかについては次のセルのように Codeセルの先頭で ?
を指定することで確認できます。
?unit.add_nodes
追加したVCノードの状態を確認するために、VCノードの一覧表示をおこなってみます。
unit.df_nodes()
起動している全てのVCノードに対して ping
を行ってみます。
# Unit内のVCノードのIPアドレスのリストを取得する
ip_address = unit.find_ip_addresses(node_state='RUNNING')
print(ip_address)
# それぞれのIPアドレスに対して pingコマンドを実行する
for address in ip_address:
!ping -c 5 {address}
print()
VCノードを追加したので ~/.ssh/known_hosts を更新します。
for address in ip_address:
# ~/.ssh/known_hosts から古いホストキーを削除する
!ssh-keygen -R {address}
# ホストキーの登録
!ssh-keyscan -H {address} >> ~/.ssh/known_hosts
追加で起動した VCノード は同じ Unit に属しているため同じ構成(cpu, memory, disk)になっています。そのことを確認するために、sshでログインして以下のコマンドを実行してみます。
ただし aws では同じインスタンスタイプに複数種類の CPU が混在していることがあり CPU が微妙に異なることがあります。
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} uname -a
print()
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} cat /proc/cpuinfo | grep 'model name'
print()
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} free
print()
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} df -h
print()
先程と同様に、負荷をかけるためにそれぞれのVCノードでアプリケーションコンテナによる stress コマンドの実行を行います。
for idx, address in enumerate(ip_address):
# 60秒間だけ CPU x 2 とメモリ 128 MB を消費する
!ssh {ssh_opts} {address} \
/usr/local/bin/docker run -td --rm --name stress-{idx} polinux/stress \
stress --cpu 2 --io 1 --vm 2 --vm-bytes 128M --timeout 60s --verbose
Grafana で利用状況を確認してみます。
現在Unitには2つのVCノードがありますが、そのうちの一つを削除してみます。
まず、現在のVCノードの状況を確認しておきます。
# VCノードの一覧を DataFrame で表示する
unit.df_nodes()
Unit から VCノードを削除するにはオブジェクトunit
に対して delete_nodes()
を呼び出します。
複数の VCノード のうちどのVCノード を削除するかを引数で指定することができます。ここではip_address
パラメータを指定してVCノードに割り当てられている IPアドレスで VCノードを特定します。
VCノードを特定するパラメータが指定されなかった場合は削除対象となる VCノードは VCP SDK によって自動的に選択されます。
VCノードを特定するための他のパラメータに指定方法については次のセルを実行すると表示される情報で確認してください。
?unit.delete_nodes
では実際にVCノードを削除します。まず削除対象とするVCノードのIPアドレスを確認します。スケールアウトの節で追加したVCノードのIPアドレスを指定することにします。
# 削除対象とするVCノードの IPアドレスを表示
print(ip_address[-1]) # 後から追加した VCノード を削除対象とする
次のセルを実行するとUnit からVCノードが削除され、対応するAWS EC2インスタンスも削除されます。
VCノード の削除には 1分~2分程度かかります。
# VCノードの削除
unit.delete_nodes(
ip_address=ip_address[-1] # IPアドレスで削除対象を指定する
)
Unit内のVCノードの一覧を確認してみます。VCノードが減っていることが確認できるはずです。
unit.df_nodes()
先ほど取得した2つのVCノードのIPアドレスに対して ping
を行ってみます。
削除されている VCノード に対する ping
が失敗するので、次のセルは必ずエラーになるはずです。
for address in ip_address:
!ping -c 5 {address}
先程とは異なる構成のVCノードを追加するので、新たな Unit を作成します。
AWSの場合と同様 spec
オブジェクトを作成します。
AWSの場合からの変更点は、specの作成等で指定するプロバイダ名を、使用するプロバイダのものに変更するだけです。 ここでの具体的な変更箇所は次の2つのAPIの引数になります。
VCPSDK::df_flavors()
VCPSDK::get_spec()
VCP SDKで現在使用可能なクラウドプロバイダと、それを使用する際の引数に指定するプロバイダ名の値は以下のとおりです。
クラウドプロバイダ | プロバイダ名 |
---|---|
Amazon EC2 | aws |
Microsoft Azure | azure |
Oracle Cloud Infrastructure | oracle |
さくらのクラウド | sakura |
VMware vSphere | vmware |
ここでは、Microsoft Azure でVCノードを作成します。
下記の 'azure'
を指定した箇所を変更することで、他のプロバイダでも同様の操作をすることができます。
まず最初に、Microsoft Azure 用に定義している flavor
の内容を確認します。
vcp.df_flavors('azure')
続いて、以下のパラメータを指定して spec
オブジェクトを作成します。
azure
medium
spec_azure = vcp.get_spec('azure', 'medium')
作成したspec_azure
の設定内容を確認してみます。
print(spec_azure)
指定した flavor
に対応する vm_size
, disk_size_gb
などが設定されていることが確認できます。
VCノードに登録するsshの公開鍵を spec_azure
に設定します。先ほど aws 向けのspec
に設定したのと同じ値を指定しています。
spec_azure.set_ssh_pubkey(ssh_public_key)
spec_azure
の設定内容を確認してみます。
print(spec_azure)
aws向けに最初に作成した spec
オブジェクトとspec_azure
との差分を確認してみます。
spec
オブジェクトの内部では aws はinstance_type
、azure はvm_size
などそれぞれのクラウドプロバイダに応じたパラメータが設定されていることが確認できます。
from difflib import unified_diff
import sys
sys.stdout.writelines(unified_diff(
str(spec).splitlines(True),
str(spec_azure).splitlines(True),
fromfile='aws',
tofile='azure',
))
まず作成前のUnitGroup状態を確認しておきます。
from IPython.display import display
# Unitの一覧を DataFrame で表示する
display(unit_group.df_units())
# VCノードの一覧を DataFrame で表示する
display(unit_group.df_nodes())
Unitを作成します。
処理が完了するまでには 2~5分程度かかります。
# Unitの作成(同時に VCノードが作成される)
unit2 = unit_group.create_unit(
'azure-server', # Unit 名
spec_azure # spec オブジェクト
)
Unit作成後の状態を確認します。Unit とVCノードがそれぞれ2つあることが確認できるはずです。VCノード一覧ではそれぞれのVCノードの unit_name が異なることが確認できるはずです。またawsとazureのVCノードには異なるサブネットのIPアドレスが割り当てられていることが確認できます。
# Unitの一覧を DataFrame で表示する
display(unit_group.df_units())
# VCノードの一覧を DataFrame で表示する
display(unit_group.df_nodes())
VCノードを追加したので ~/.ssh/known_hosts を更新します。
for addr in unit_group.find_ip_addresses(node_state='RUNNING'):
!ssh-keygen -R {addr}
!ssh-keyscan -H {addr} >> ~/.ssh/known_hosts
# UnitGroup内にあるVCノードのIPアドレスリストを取得する
ip_address = unit_group.find_ip_addresses(node_state='RUNNING')
VCPでは複数の異なるクラウドを仮想的に一つの計算基盤(仮想クラウド)のように扱える機能を提供しています。そのため異なるクラウド(aws, azure)で起動したVCノードであっても、追加の設定なしに互いに通信することができます。そのことを確認するために、作成した2つの VCノード の一方から他方に対して ping
を行ってみます。
# pingを実行するVCノードのIPアドレスを表示する
print(ip_address[0])
print()
!ssh {ssh_opts} {ip_address[0]} \
ping -c 10 {ip_address[1]}
逆方向で同様のことを行ってみます。
# pingを実行するVCノードのIPアドレスを表示する
print(ip_address[1])
print()
!ssh {ssh_opts} {ip_address[1]} \
ping -c 10 {ip_address[0]}
Azureに追加で起動した VCノード は aws とは異なる構成(cpu, memory, disk)になってるはずです。そのことを確認するために、sshでログインして以下のコマンドを実行してみます。
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} uname -a
print()
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} cat /proc/cpuinfo | grep 'model name'
print()
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} free
print()
for address in ip_address:
print(address + ':')
!ssh {ssh_opts} {address} df -h
print()
最後に先程と同様に、負荷をかけるためにそれぞれのVCノードで stress コマンドを実行します。これまで同様 stressコマンドはアプリケーションコンテナとして実行します。
for unit in unit_group.find_units():
address = unit.find_ip_addresses(node_state='RUNNING')
# 60秒間だけ CPU x 2 とメモリ 128 MB を消費する
!ssh {ssh_opts} {address[0]} \
/usr/local/bin/docker run -td --rm --name stress-{unit.name} polinux/stress \
stress --cpu 2 --io 1 --vm 2 --vm-bytes 128M --timeout 60s --verbose
Grafanaで利用状況を確認してみます。
print(grafana_url)
ここまで作成した全てのリソース(UnitGroup, Unit、VCノード)を削除します。この操作を行うことで AWS EC2インスタンスやAzure VMなどのクラウドに作成したリソースが削除されます。
全てのリソースの削除には 4~5分程度かかります。
unit_group.cleanup()
削除後の状態を確認してみます。
# UnitGroupの一覧を DataFrame で表示する
vcp.df_ugroups()