この資料について

この資料は VCP Hands-on 「101-VCノードの起動、削除.ipynb」 の内容をJupyterNotebook環境のない状態でも閲覧できるように用意した自習用資料です。各ステップの終わりに、そのステップをJupyterNotebookで実行した様子を見ることができる動画がついています


VCノードの起動、削除

このNotebookではVCP SDKを利用してVCノードを起動、削除する手順を記しています。

概要

構成

用語説明

上の図、またはこれ以降に示す図に記されている構成要素についての簡単な説明を以下に記します。

  • VPC
    • Amazon が提供している AWS 内の仮想プライベートネットワーク環境
  • Amazon EC2
    • Amazon が提供している仮想コンピューティング環境
  • Azure Virtual Network
    • Microsoft が提供しているクラウド内の仮想プライベートネットワーク環境
  • Azure Virtual Machine
    • Microsoft が提供している仮想コンピューティング環境
  • VC Controller
    • VCPがユーザに対して提供しているサービス群
  • VC Controller Core
    • ユーザからのAPI呼び出しを受けとりUnitGroupの作成、削除などを行う
  • Grafana
    • 可視化ツール、ダッシュボードツール
    • VCP では VCノード のモニタリング状況を表示するのに利用している
  • VCP SDK
    • VCPの機能を呼び出して VM/BM の作成、削除などを行うPython3のライブラリ
  • VCノード
    • Amazon EC2, Azure Virtual Machine などの計算資源を抽象化したVCPのノード
  • Unit
    • 同質(同じ計算資源(cpu, memory, ...)、同じクラウド、同じ用途、...)であるVCノードをまとめて扱うためのもの
  • UnitGroup
    • 複数のUnitをまとめて扱うためのものです

操作手順

大まかな操作手順は以下のようになります。

  1. VCP SDKを用いてVCノード(Amazon EC2 インスタンス)を起動する
  2. 起動したVCノードに ssh でログインして操作する
  3. GrafanaでVCノードの利用状況を確認する
  4. Unit内のVCノードをスケールアウト、スケールインする
  5. 別のパブリッククラウド(Microsoft Azure)のVCノードを起動する
  6. 起動したVCノードをすべて削除する

アクセストークンの入力

VCP SDKを利用するにはVC Controllerのアクセストークンが必要となります。次のセルを実行すると入力枠が表示されるのでアクセストークンの値を入力してください。

アクセストークン入力後に Enter キーを押すことで入力が完了します。

In [1]:
from getpass import getpass
vcc_access_token = getpass()
········

このステップのJupyterNotebookでの実行の様子


VCノード(Amazon EC2インスタンス)の起動

VCP SDKを用いてVCノード(Amazon EC2インスタンス)を起動します。また、起動したVCノードに対してsshでログインして操作を行います。

EC2の起動

VCP SDKの初期化

VCP SDKの初期化を行います。

In [2]:
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を作成していないので、ヘッダー以外はなにも表示されないはずです。

In [3]:
# UnitGroupの一覧を DataFrame で表示する
vcp.df_ugroups()
Out[3]:
vcno vctype vcname state vcid cdate

次のセルを実行すると VCP SDK と VC Controller のバージョンが表示されます。

In [4]:
vcp.version()
vcplib:
  filename: /notebooks/notebook/vcpsdk/vcplib/occtr.py
  version: 20.08.0+20200831

vcpsdk:
  filename: /notebooks/notebook/vcpsdk/vcpsdk/vcpsdk.py
  version: 20.10.0+2021001

  plugin:
    aws: 1.2+20191001
    aws_disk: 1.0+20190408
    aws_spot: 1.1+20191001
    azure: 1.2+20191001
    vmware: 1.1+20191001
    azure_disk: 1.0+20190408
    sakura: 1.1+20191001
    sakura_disk: 1.0+20190930
    oracle: 1.0+20200331
    oracle_disk: 1.0+20200331
    aic: 1.2+20191001
    abc: 1.3+20190408
    hokudai: 1.1+20191001
    chameleon: 1.0+20200831
    chameleon_ext: 20200831
    gcp: 1.0+20190408
    onpremises: 1.0+20190408

vc_controller:
  host: 10.0.0.1
  name: vcc1045
  wait_timeout_sec: 1000(default 15min)
  vc_controller: 20.10.1+20210101
  vc_controller_git_tag: 20.10.1

  plugin:
    vmware: 1.1+20210101
    chameleon: 1.0+20210101
    azure: 1.2+20210101
    aws_spot: 1.1+20210101
    aic: 1.2+20210101
    sakura: 1.1+20210101
    hokudai: 1.1+20210101
    abc: 1.3+20210101
    oracle: 1.0+20210101
    aws: 1.2+20210101
    gcp: 1.0+20210101

このステップのJupyterNotebookでの実行の様子


UnitGroupの作成

handson101という名前の UnitGroup を作成します。

In [5]:
# UnitGroupの作成
unit_group = vcp.create_ugroup(
    'handson101'                   # UnitGroupの名前
)

作成したUnitGroupの状態を表示してみます。

UnitGroup の名前が handson101 であることと、その状態が RUNNING であることなどが確認できるはずです。

In [6]:
print(unit_group)
[Vc]
+ type[compute] name[handson101] vcno(96) state[RUNNING] vcid[1e2f45c347ad4ab9b803d673f987ae00]

UnitGroupの一覧を表示してみます。

In [7]:
# UnitGroupの一覧を DataFrame で表示する
vcp.df_ugroups()
Out[7]:
vcno vctype vcname state vcid cdate
0 96 compute handson101 RUNNING 1e2f45c3... 2021/03/17 05:49:33 UTC

このステップのJupyterNotebookでの実行の様子


UnitGroupの状態を確認する

UnitGroupに属している Unit の一覧を表示します。

まだ、このUnitGroupでは Unit を作成していないのでヘッダー以外は何も表示されません。

In [8]:
# Unitの一覧を DataFrame で表示する
unit_group.df_units()
Out[8]:
vctype vcno vcname vc_state vcid cdate unit_name unit_state

UnitGroupに属しているVCノードの一覧を表示します。

まだVCノードが存在していないので何も表示されません。

In [9]:
unit_group.df_nodes()
Out[9]:
[]

このステップのJupyterNotebookでの実行の様子


VCノードのspecを指定する

Unitを構成するVCノードがどのような設定であるかを指定するためのオブジェクトとしてVCP SDKではspecオブジェクトを用意しています。VCP SDKの利用者はspecオブジェクトのプロパティを設定することで Unitに起動するVCノードの設定内容を定義することができます。

specオブジェクトの設定項目の例を以下に示します。

  • 仮想マシンのインスタンスタイプ
    • m5.large, c5.large, ...
  • 仮想マシンのルートボリュームサイズ(GiB)
  • 仮想マシンに割り当てるプライベートIPアドレス
  • Unit内に作成するVCノードの数

設定できる項目はクラウドプロバイダ(aws, azure, ...)毎に異なります。

flavor の内容を確認する

specオブジェクトの全てのパラメータを毎回設定するのは煩雑になるので典型的な構成のパラメータセットを事前に定義しています。事前に定義したspecパラメータセットのことを VCP SDKでは flavorと呼んでいます。specに設定できるパラメータはクラウドプロバイダ毎に異なるので flavorの定義もクラウドプロバイダ毎に行っています。

次のセルを実行すると aws用に定義している flavor の一覧が表示されます。

In [10]:
vcp.df_flavors('aws')
Out[10]:
flavor instance_type volume_type volume_size
0 small m4.large gp2 8
1 medium m4.xlarge gp2 40
2 large m4.2xlarge gp2 100
3 gpu g3.4xlarge gp2 40

このステップのJupyterNotebookでの実行の様子


spec オブジェクトを作成する

specオブジェクトを作成します。specオブジェクトを作成するにはプロバイダとflavorを指定します。ここでは以下の値を指定します。

  • プロバイダ: aws
  • flavor: small
In [11]:
spec = vcp.get_spec('aws', 'small')

作成したspecの設定内容を確認してみます。

instance_typeパラメータに flavor の指定と対応するEC2インスタンスタイプm4.largeが設定されていることが確認できるはずです。 volume_size, volume_typeについてもそれぞれflavorと対応する値が設定されます。

In [12]:
print(spec)
========================
aws
------------------------

    cci_version: "1.1"
    name: 
    description: 
    private_network: default
    num_nodes: 1
    image: vcp/base:1.6.2
    recovery_mode: none
    docker_opt: {}
    params:
        {'v': [], 'e': []}

    instance_type: m4.large
    volume_size: 8
    volume_type: gp2
    volume_id: []
    cloud_image: default
    ip_address_list: []
    tags: {}
========================

specに対しては flavorで指定するだけではなく個々のパラメータを直接指定することもできます。例えば、以下のようなものが指定できます。

  • num_nodes
    • Unit内に作成するVCノードの数: デフォルト=1
  • ip_addresses
    • VCノードに割り当てるプライベートIPアドレスのリスト
    • このパラメータを指定しない場合は利用可能なアドレスが自動的に割り当てられる
  • instance_type
    • Amazon EC2のインスタンスタイプ
    • flavorで設定されているもの以外を利用したい場合に指定する
  • volume_size
    • Amazon EC2インスタンスのルートボリュームに割り当てるサイズ(GiB)
    • flavorで設定されているもの以外を利用したい場合に指定する
  • volume_type
    • Amazon EC2インスタンスのルートボリュームのEBSタイプ
    • flavorで設定されているもの以外を利用したい場合に指定する

試しに volume_sizeを指定してみます。

In [ ]:
spec.volume_size = 15

指定した値がspecの設定に反映されていることを確認してみます。

In [ ]:
print(spec)

volume_sizeの値が指定した値に変更されています。


このステップのJupyterNotebookでの実行の様子


sshの鍵ファイルを設定する

VCノードにsshでログインするためには事前に公開鍵認証の鍵を登録する必要があります。そのための設定をここで行います。

VCノードに登録する公開鍵認証の公開鍵のパスを次のセルで指定してください。

In [13]:
import os
ssh_public_key = os.path.expanduser('~/.ssh/id_rsa.pub')

指定した公開鍵を spec に設定します。

In [14]:
spec.set_ssh_pubkey(ssh_public_key)

sshの公開鍵に関する設定がspecに反映されたことを確認してみます。次のセルを実行するとparamseAUTHORIZED_KEYSに値が設定されていることが確認できます。

In [15]:
print(spec)
========================
aws
------------------------

    cci_version: "1.1"
    name: 
    description: 
    private_network: default
    num_nodes: 1
    image: vcp/base:1.6.2
    recovery_mode: none
    docker_opt: {}
    params:
        {'v': [], 'e': ['AUTHORIZED_KEYS=c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFET0NVZGV3YW9JM0ZQaWZNdWIrZGR2MmQxaUsybkZpU0Y4YktKTjlUMlBEbk42UHlhTVlId2ZucWtGSnZyYTc2T2lqQllUSy81V2gwaElYc0RaYmdkQ0lwR2F5WXpwRVBtUiszZnd0ZllickJ4T0JqdnBUYmI3MU9wS08zd0NNM2JmazRjZzJxdFJSTVk4T09iZFFpckZFUzdwMGpyVXVBVTI1Z3d0ZDByY2orOE9qTGx2Qk12L2RIejhpQmZYVE94QWtYaEVuVHFVZ0lYQXNUMW8wV2JmdXNXWEwyZGJNUmw2M0lMSXJQYjZkNGUwcWVZK3pwMVlkcHFnY2NHWG8yVnZOV0hKZUZZSmdtUmJPdUV2UitmbmpNNXRxa1JKZHNtSFRrWktVOFp3VFI5K0JTU3BZVXVieTljcTR6UUs0ZnVmdlRBeGg2R2dPODBmcDRGNkVzRVAgam92eWFuQDU3YmEzM2IxZGEwMwo=']}

    instance_type: m4.large
    volume_size: 8
    volume_type: gp2
    volume_id: []
    cloud_image: default
    ip_address_list: []
    tags: {}
========================

後でVCノードにログインする際にsshの秘密鍵も必要になるので、ここで設定しておきます。次のセルで秘密鍵のパスを指定してください。

In [16]:
ssh_private_key = os.path.expanduser('~/.ssh/id_rsa')

公開鍵と秘密鍵が正しいペアであることをチェックします。次のセルを実行してエラーにならないことを確認してください。

In [17]:
!grep -q "$(ssh-keygen -y -f {ssh_private_key})" {ssh_public_key}

このステップのJupyterNotebookでの実行の様子


Unitの作成とVCノードの起動

Unitを作成します。Unitを作成すると同時に VCノード(ここでは Amazon EC2インスタンス)が起動します。

処理が完了するまで1分半~2分程度かかります。

In [18]:
# Unitの作成(同時に VCノードが作成される)
unit = unit_group.create_unit(
    'aws-server',               # Unit名の指定
    spec
)
2021-03-17 14:51:17,538 - INFO - BOOTING ... 0 sec
2021-03-17 14:51:22,669 - INFO - BOOTING ... 5 sec
2021-03-17 14:51:27,792 - INFO - BOOTING ... 10 sec
2021-03-17 14:51:32,921 - INFO - BOOTING ... 15 sec
2021-03-17 14:51:38,048 - INFO - BOOTING ... 20 sec
2021-03-17 14:51:43,174 - INFO - BOOTING ... 25 sec
2021-03-17 14:51:48,298 - INFO - BOOTING ... 30 sec
2021-03-17 14:51:53,428 - INFO - BOOTING ... 35 sec
2021-03-17 14:51:58,554 - INFO - BOOTING ... 40 sec
2021-03-17 14:52:03,681 - INFO - BOOTING ... 45 sec
2021-03-17 14:52:08,807 - INFO - BOOTING ... 50 sec
2021-03-17 14:52:13,940 - INFO - BOOTING ... 55 sec
2021-03-17 14:52:19,106 - INFO - BOOTING ... 60 sec
2021-03-17 14:52:24,252 - INFO - BOOTING ... 65 sec
2021-03-17 14:52:29,377 - INFO - BOOTING ... 70 sec
2021-03-17 14:52:34,504 - INFO - BOOTING ... 75 sec
2021-03-17 14:52:39,632 - INFO - BOOTING ... 80 sec
2021-03-17 14:52:44,762 - INFO - BOOTING ... 85 sec
2021-03-17 14:52:49,886 - INFO - BOOTING ... 90 sec
2021-03-17 14:52:55,010 - INFO - BOOTING ... 95 sec
2021-03-17 14:53:00,144 - INFO - BOOTING ... 100 sec
2021-03-17 14:53:11,279 - INFO - unit aws-server is RUNNING

UnitGroupに属しているUnitの一覧表示を行い、Unitが作成されていることを確認します。

In [19]:
# Unitの一覧を DataFrame で表示する
unit_group.df_units()
Out[19]:
vctype vcno vcname vc_state vcid cdate unit_name unit_state
0 compute 96 handson101 RUNNING 1e2f45c3... 2021/03/17 05:49:33 UTC aws-server RUNNING

UnitGroupに属しているVCノードの一覧表示を行い、VCノードが起動していることを確認します。VCノードが正常に起動していることは node_state の表示が RUNNINGになっていることで確認できます。

In [20]:
# VCノードの一覧を DataFrame で表示する
unit_group.df_nodes()
Out[20]:
vcno vcname unit_name unit_state node_no node_id node_state cloud_instance_address cloud_instance_id cloud_instance_name volumes
0 96 handson101 aws-server RUNNING 1 0cd71952... RUNNING 172.30.2.65 i-03e8c8c9691502c9d VCP-f7944417-1e2f45c3 none

ここでは 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ノードが起動したことを確認するには、以下に示す方法で状態取得を行ってください。

  1. unit_group.df_units()

    • Unitの一覧表示のunit_stateの項目で Unitの状態を確認できます
    • 起動中は BOOTING、起動が完了して実行中になると RUNNING と表示されます
  2. unit.df_nodes(), unit_group.df_nodes()

    • VCノードの一覧表示のnode_stateの項目で VCノードの状態を確認できます
    • 起動中は BOOTING、起動が完了して実行中になると RUNNING と表示されます

非同期モードでUnit作成を行った場合でも、以下のメソッドを利用することで後からVCノード起動の待ち合わせを行うことができます。

  • unit_group.wait_unit_applied(unit_name)
    • unit_nameで指定されたUnitの状態が RUNNING または ERRORになるのを待ちます

このステップのJupyterNotebookでの実行の様子


疎通確認

起動した VCノードに対してpingを行ってみます。

まずUnitGroup内で起動しているVCノードに割り当てられているプライベートIPアドレスの値を取得して変数 ip_addressに格納します。

In [21]:
# 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)
172.30.2.65

実際に ping を行ってみます。

Codeセルで先頭に ! をつけるとシェルコマンドが実行できます。また {}で囲むことで Python の変数参照やコードの実行に置き換えることができます。詳しくは「IPython Documentation」などを参照してください。

In [22]:
!ping -c 5 {ip_address}
PING 172.30.2.65 (172.30.2.65) 56(84) bytes of data.
64 bytes from 172.30.2.65: icmp_seq=1 ttl=63 time=0.452 ms
64 bytes from 172.30.2.65: icmp_seq=2 ttl=63 time=0.306 ms
64 bytes from 172.30.2.65: icmp_seq=3 ttl=63 time=0.335 ms
64 bytes from 172.30.2.65: icmp_seq=4 ttl=63 time=0.321 ms
64 bytes from 172.30.2.65: icmp_seq=5 ttl=63 time=0.291 ms

--- 172.30.2.65 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.291/0.341/0.452/0.057 ms

このステップのJupyterNotebookでの実行の様子


VCノードに ssh でログインして操作する

起動したVCノードに ssh でログインして操作を行います。

まず、ログインする前に ~/.ssh/known_hosts のホストキーを更新します。

In [23]:
!touch ~/.ssh/known_hosts
# ~/.ssh/known_hosts から古いホストキーを削除する
!ssh-keygen -R {ip_address}

# ホストキーの登録
!ssh-keyscan -H {ip_address} >> ~/.ssh/known_hosts
Host 172.30.2.65 not found in /home/jovyan/.ssh/known_hosts
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1

ls -la を実行してみます。

In [24]:
!ssh -i {ssh_private_key} -l root {ip_address} /bin/ls -la
total 20
drwx------    1 root     root          4096 Oct  5 02:05 .
drwxr-xr-x    1 root     root          4096 Mar 17 05:52 ..
drwxr-xr-x    1 root     root          4096 Oct  5 01:59 .cache
drwxr-xr-x    3 root     root          4096 Oct  5 02:04 .gem
drwx------    1 root     root          4096 Mar 17 05:52 .ssh

VCノードにsshでログインするにはsshの引数に以下の指定が必要となります。

  • sshの identity ファイル(-i)
    • specオブジェクトに設定した公開鍵に対応する秘密鍵
  • ユーザ名(-l)
    • root
  • ログイン先のIPアドレス

sshのオプションを毎回指定するのも煩雑なので変数に設定しておきます。

In [25]:
ssh_opts = f"-i {ssh_private_key} -l root"

VCノードに対してuname -a, df -h などを実行してみます。

In [26]:
!ssh {ssh_opts} {ip_address} uname -a
Linux ip-172-30-2-65 4.4.0-159-generic #187-Ubuntu SMP Thu Aug 1 16:28:06 UTC 2019 x86_64 Linux
In [27]:
!ssh {ssh_opts} {ip_address} df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                   7.7G      3.3G      4.0G  45% /
tmpfs                     3.9G         0      3.9G   0% /sys/fs/cgroup
udev                      3.9G         0      3.9G   0% /dev
tmpfs                     3.9G         0      3.9G   0% /dev/shm
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/resolv.conf
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hostname
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hosts
/dev/xvda1                7.7G      3.3G      4.0G  45% /var/lib/docker
none                      3.9G         0      3.9G   0% /tmp

このステップのJupyterNotebookでの実行の様子


GrafanaでVCノードの利用状況を確認する

VCPではVCノードの利用状況(CPU負荷、メモリ使用量、ネットワーク)を確認するためGrafanaのダッシュボードを提供しています。

Grafanaへのログイン

Grafana からダッシュボードを開いてください。

最初にログイン画面が表示されるので ユーザ名、パスワードにそれぞれ admin, adminを入力してください。

Grafanaのログイン画面


このステップのJupyterNotebookでの実行の様子


負荷状況のグラフ表示

以下のように表示されます。左半分のグラフがBaseコンテナの負荷状況で、右半分がアプリケーションコンテナの負荷状況のグラフです。

負荷状況

VCノードに負荷をかけるために、アプリケーションコンテナで stress コマンドを実行します。

In [28]:
# 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
Unable to find image 'polinux/stress:latest' locally
latest: Pulling from polinux/stress
63bc94deeb28: Pulling fs layer
8d43371bad93: Pulling fs layer
63bc94deeb28: Verifying Checksum
63bc94deeb28: Download complete
8d43371bad93: Verifying Checksum
8d43371bad93: Download complete
63bc94deeb28: Pull complete
8d43371bad93: Pull complete
Digest: sha256:b6144f84f9c15dac80deb48d3a646b55c7043ab1d83ea0a697c09097aaad21aa
Status: Downloaded newer image for polinux/stress:latest
613f5324982bcde9bfcb849b280dfbb8263cfda2383de218beb55df7ece94d47

このステップのJupyterNotebookでの実行の様子


VCノードのスケールアウト、スケールイン

スケールアウト、スケールイン

VCノードのスケールアウト

Unitには specオブジェクトに指定されている設定と同一の VCノードを作成する機能があります。その機能を利用して Unit にVCノードを追加してみます。

まず、現在のVCノードの状況を確認しておきます。

In [29]:
# VCノードの一覧を DataFrame で表示する
unit.df_nodes()
Out[29]:
vcno vcname unit_name unit_state node_no node_id node_state cloud_instance_address cloud_instance_id cloud_instance_name volumes
0 96 handson101 aws-server RUNNING 1 0cd71952... RUNNING 172.30.2.65 i-03e8c8c9691502c9d VCP-f7944417-1e2f45c3 none

Unit に VCノードを追加するにはunitオブジェクトに対して add_nodes() を呼び出します。次のセルを実行するとUnitに VCノード が追加されます。

VCノード の起動には 1分半~2分程度かかります。

In [30]:
unit.add_nodes()
2021-03-17 14:55:59,855 - INFO - INDEFINITE ... 0 sec
2021-03-17 14:56:05,115 - INFO - INDEFINITE ... 5 sec
2021-03-17 14:56:10,382 - INFO - INDEFINITE ... 10 sec
2021-03-17 14:56:15,638 - INFO - INDEFINITE ... 15 sec
2021-03-17 14:56:20,896 - INFO - INDEFINITE ... 20 sec
2021-03-17 14:56:26,148 - INFO - INDEFINITE ... 25 sec
2021-03-17 14:56:31,397 - INFO - INDEFINITE ... 30 sec
2021-03-17 14:56:36,647 - INFO - INDEFINITE ... 35 sec
2021-03-17 14:56:41,894 - INFO - INDEFINITE ... 40 sec
2021-03-17 14:56:47,133 - INFO - INDEFINITE ... 45 sec
2021-03-17 14:56:52,385 - INFO - INDEFINITE ... 50 sec
2021-03-17 14:56:57,635 - INFO - INDEFINITE ... 55 sec
2021-03-17 14:57:03,021 - INFO - INDEFINITE ... 60 sec
2021-03-17 14:57:08,345 - INFO - INDEFINITE ... 65 sec
2021-03-17 14:57:13,599 - INFO - INDEFINITE ... 70 sec
2021-03-17 14:57:18,850 - INFO - INDEFINITE ... 75 sec
2021-03-17 14:57:24,087 - INFO - INDEFINITE ... 80 sec
2021-03-17 14:57:29,333 - INFO - INDEFINITE ... 85 sec
2021-03-17 14:57:34,582 - INFO - INDEFINITE ... 90 sec
2021-03-17 14:57:39,839 - INFO - INDEFINITE ... 95 sec
2021-03-17 14:57:45,085 - INFO - INDEFINITE ... 100 sec
2021-03-17 14:57:50,214 - INFO - unit aws-server is RUNNING
2021-03-17 14:57:50,215 - INFO - add_node completed.
Out[30]:
[<vcplib.occtr.VcNode at 0x7fe5aa7969d0>,
 <vcplib.occtr.VcNode at 0x7fe5aa796c50>]

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セルの先頭で ? を指定することで確認できます。

In [31]:
?unit.add_nodes

追加したVCノードの状態を確認するために、VCノードの一覧表示をおこなってみます。

In [32]:
unit.df_nodes()
Out[32]:
vcno vcname unit_name unit_state node_no node_id node_state cloud_instance_address cloud_instance_id cloud_instance_name volumes
0 96 handson101 aws-server RUNNING 1 0cd71952... RUNNING 172.30.2.65 i-03e8c8c9691502c9d VCP-f7944417-1e2f45c3 none
1 96 handson101 aws-server RUNNING 2 a4a7c575... RUNNING 172.30.2.7 i-05099dfef7e30ffa0 VCP-f7944417-1e2f45c3 none

起動している全てのVCノードに対して ping を行ってみます。

In [33]:
# 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()
['172.30.2.65', '172.30.2.7']
PING 172.30.2.65 (172.30.2.65) 56(84) bytes of data.
64 bytes from 172.30.2.65: icmp_seq=1 ttl=63 time=0.426 ms
64 bytes from 172.30.2.65: icmp_seq=2 ttl=63 time=0.314 ms
64 bytes from 172.30.2.65: icmp_seq=3 ttl=63 time=0.356 ms
64 bytes from 172.30.2.65: icmp_seq=4 ttl=63 time=0.353 ms
64 bytes from 172.30.2.65: icmp_seq=5 ttl=63 time=0.346 ms

--- 172.30.2.65 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3997ms
rtt min/avg/max/mdev = 0.314/0.359/0.426/0.036 ms

PING 172.30.2.7 (172.30.2.7) 56(84) bytes of data.
64 bytes from 172.30.2.7: icmp_seq=1 ttl=63 time=1.19 ms
64 bytes from 172.30.2.7: icmp_seq=2 ttl=63 time=0.309 ms
64 bytes from 172.30.2.7: icmp_seq=3 ttl=63 time=0.308 ms
64 bytes from 172.30.2.7: icmp_seq=4 ttl=63 time=0.331 ms
64 bytes from 172.30.2.7: icmp_seq=5 ttl=63 time=0.370 ms

--- 172.30.2.7 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4001ms
rtt min/avg/max/mdev = 0.308/0.502/1.196/0.348 ms

VCノードを追加したので ~/.ssh/known_hosts を更新します。

In [34]:
for address in ip_address:
    # ~/.ssh/known_hosts から古いホストキーを削除する
    !ssh-keygen -R {address}
    # ホストキーの登録
    !ssh-keyscan -H {address} >> ~/.ssh/known_hosts
# Host 172.30.2.65 found: line 16
# Host 172.30.2.65 found: line 17
# Host 172.30.2.65 found: line 18
/home/jovyan/.ssh/known_hosts updated.
Original contents retained as /home/jovyan/.ssh/known_hosts.old
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
Host 172.30.2.7 not found in /home/jovyan/.ssh/known_hosts
# 172.30.2.7:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.7:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.7:22 SSH-2.0-OpenSSH_8.1

追加で起動した VCノード は同じ Unit に属しているため同じ構成(cpu, memory, disk)になっています。そのことを確認するために、sshでログインして以下のコマンドを実行してみます。

  • カーネルバージョン
    • uname -a
  • CPU
    • cat /proc/cpuinfo
  • メモリ量
    • free
  • ディスク容量
    • df -h

ただし aws では同じインスタンスタイプに複数種類の CPU が混在していることがあり CPU が微妙に異なることがあります。

In [35]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} uname -a
    print()
172.30.2.65:
Linux ip-172-30-2-65 4.4.0-159-generic #187-Ubuntu SMP Thu Aug 1 16:28:06 UTC 2019 x86_64 Linux

172.30.2.7:
Linux ip-172-30-2-7 4.4.0-159-generic #187-Ubuntu SMP Thu Aug 1 16:28:06 UTC 2019 x86_64 Linux

In [36]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} cat /proc/cpuinfo | grep 'model name'
    print()
172.30.2.65:
model name	: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz
model name	: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz

172.30.2.7:
model name	: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz
model name	: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz

In [37]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} free
    print()
172.30.2.65:
              total        used        free      shared  buff/cache   available
Mem:        8173364      397444     6019368       12440     1756552     7620008
Swap:             0           0           0

172.30.2.7:
              total        used        free      shared  buff/cache   available
Mem:        8173364      381204     6058656       12496     1733504     7634168
Swap:             0           0           0

In [38]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} df -h
    print()
172.30.2.65:
Filesystem                Size      Used Available Use% Mounted on
overlay                   7.7G      3.3G      4.0G  45% /
tmpfs                     3.9G         0      3.9G   0% /sys/fs/cgroup
udev                      3.9G         0      3.9G   0% /dev
tmpfs                     3.9G         0      3.9G   0% /dev/shm
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/resolv.conf
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hostname
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hosts
/dev/xvda1                7.7G      3.3G      4.0G  45% /var/lib/docker
none                      3.9G         0      3.9G   0% /tmp

172.30.2.7:
Filesystem                Size      Used Available Use% Mounted on
overlay                   7.7G      3.3G      4.0G  45% /
tmpfs                     3.9G         0      3.9G   0% /sys/fs/cgroup
udev                      3.9G         0      3.9G   0% /dev
tmpfs                     3.9G         0      3.9G   0% /dev/shm
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/resolv.conf
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hostname
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hosts
/dev/xvda1                7.7G      3.3G      4.0G  45% /var/lib/docker
none                      3.9G         0      3.9G   0% /tmp

先程と同様に、負荷をかけるためにそれぞれのVCノードでアプリケーションコンテナによる stress コマンドの実行を行います。

In [39]:
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
53f3a2b689584bceb0272f3cd5d059731f3bbb2012770cefd071ff04a1a60ab0
Unable to find image 'polinux/stress:latest' locally
latest: Pulling from polinux/stress
63bc94deeb28: Pulling fs layer
8d43371bad93: Pulling fs layer
63bc94deeb28: Verifying Checksum
63bc94deeb28: Download complete
8d43371bad93: Verifying Checksum
8d43371bad93: Download complete
63bc94deeb28: Pull complete
8d43371bad93: Pull complete
Digest: sha256:b6144f84f9c15dac80deb48d3a646b55c7043ab1d83ea0a697c09097aaad21aa
Status: Downloaded newer image for polinux/stress:latest
2bcf2e8570d3ab2769ec6f354a273062b593edc9265b907dc6c1e24c4ea752db

Grafana で利用状況を確認してみます。


このステップのJupyterNotebookでの実行の様子


VCノードのスケールイン

現在Unitには2つのVCノードがありますが、そのうちの一つを削除してみます。

まず、現在のVCノードの状況を確認しておきます。

In [40]:
# VCノードの一覧を DataFrame で表示する
unit.df_nodes()
Out[40]:
vcno vcname unit_name unit_state node_no node_id node_state cloud_instance_address cloud_instance_id cloud_instance_name volumes
0 96 handson101 aws-server RUNNING 1 0cd71952... RUNNING 172.30.2.65 i-03e8c8c9691502c9d VCP-f7944417-1e2f45c3 none
1 96 handson101 aws-server RUNNING 2 a4a7c575... RUNNING 172.30.2.7 i-05099dfef7e30ffa0 VCP-f7944417-1e2f45c3 none

Unit から VCノードを削除するにはオブジェクトunitに対して delete_nodes() を呼び出します。

複数の VCノード のうちどのVCノード を削除するかを引数で指定することができます。ここではip_addressパラメータを指定してVCノードに割り当てられている IPアドレスで VCノードを特定します。

VCノードを特定するパラメータが指定されなかった場合は削除対象となる VCノードは VCP SDK によって自動的に選択されます。

VCノードを特定するための他のパラメータに指定方法については次のセルを実行すると表示される情報で確認してください。

In [41]:
?unit.delete_nodes

では実際にVCノードを削除します。まず削除対象とするVCノードのIPアドレスを確認します。スケールアウトの節で追加したVCノードのIPアドレスを指定することにします。

In [42]:
# 削除対象とするVCノードの IPアドレスを表示 
print(ip_address[-1])                         # 後から追加した VCノード を削除対象とする
172.30.2.7

次のセルを実行するとUnit からVCノードが削除され、対応するAWS EC2インスタンスも削除されます。

VCノード の削除には 1分~2分程度かかります。

In [43]:
# VCノードの削除
unit.delete_nodes(
    ip_address=ip_address[-1]     # IPアドレスで削除対象を指定する
)
2021-03-17 15:00:52,343 - INFO - INDEFINITE ... 0 sec
2021-03-17 15:00:57,605 - INFO - INDEFINITE ... 5 sec
2021-03-17 15:01:02,864 - INFO - INDEFINITE ... 10 sec
2021-03-17 15:01:08,131 - INFO - INDEFINITE ... 15 sec
2021-03-17 15:01:13,399 - INFO - INDEFINITE ... 20 sec
2021-03-17 15:01:18,664 - INFO - INDEFINITE ... 25 sec
2021-03-17 15:01:23,913 - INFO - INDEFINITE ... 30 sec
2021-03-17 15:01:29,174 - INFO - INDEFINITE ... 35 sec
2021-03-17 15:01:34,439 - INFO - INDEFINITE ... 40 sec
2021-03-17 15:01:39,694 - INFO - unit aws-server is RUNNING
2021-03-17 15:01:39,695 - INFO - a node deleted.
2021-03-17 15:01:39,696 - INFO - deleted node(s) completed.
Out[43]:
[<vcplib.occtr.VcNode at 0x7fe5aa75be90>]

Unit内のVCノードの一覧を確認してみます。VCノードが減っていることが確認できるはずです。

In [44]:
unit.df_nodes()
Out[44]:
vcno vcname unit_name unit_state node_no node_id node_state cloud_instance_address cloud_instance_id cloud_instance_name volumes
0 96 handson101 aws-server RUNNING 1 0cd71952... RUNNING 172.30.2.65 i-03e8c8c9691502c9d VCP-f7944417-1e2f45c3 none

先ほど取得した2つのVCノードのIPアドレスに対して ping を行ってみます。 削除されている VCノード に対する ping が失敗するので、次のセルは必ずエラーになるはずです。

In [45]:
for address in ip_address:
    !ping -c 5 {address}
PING 172.30.2.65 (172.30.2.65) 56(84) bytes of data.
64 bytes from 172.30.2.65: icmp_seq=1 ttl=63 time=0.496 ms
64 bytes from 172.30.2.65: icmp_seq=2 ttl=63 time=0.328 ms
64 bytes from 172.30.2.65: icmp_seq=3 ttl=63 time=0.347 ms
64 bytes from 172.30.2.65: icmp_seq=4 ttl=63 time=0.364 ms
64 bytes from 172.30.2.65: icmp_seq=5 ttl=63 time=0.346 ms

--- 172.30.2.65 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.328/0.376/0.496/0.062 ms
PING 172.30.2.7 (172.30.2.7) 56(84) bytes of data.

--- 172.30.2.7 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4030ms

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-45-872b43d69686> in <module>
      1 for address in ip_address:
----> 2     get_ipython().system('ping -c 5 {address}')

/opt/conda/etc/ipython/startup/10-custom-get_ipython_system.py in <lambda>(x)
      5 
      6 save_get_ipython_system = get_ipython().system
----> 7 get_ipython().system = lambda x: get_ipython_system(x)
      8 
      9 # interactiveshell.py's system_piped() function comment saids:

/opt/conda/etc/ipython/startup/10-custom-get_ipython_system.py in get_ipython_system(_cmd)
     13     save_get_ipython_system(_cmd)
     14     if get_ipython().user_ns['_exit_code'] != 0:
---> 15         raise RuntimeError('Unexpected exit code: %d' % get_ipython().user_ns['_exit_code'])

RuntimeError: Unexpected exit code: 1

このステップのJupyterNotebookでの実行の様子


別のクラウド(Microsoft Azure)でVCノードを起動する

azure

Unit の追加

先程とは異なる構成のVCノードを追加するので、新たな Unit を作成します。

VCノードのspecを指定する

awsの場合と同様 spec オブジェクトを作成します。

まずはMicrosoft Azure向け flavor の定義内容を確認してみます。

In [46]:
vcp.df_flavors('azure')
Out[46]:
flavor vm_size disk_size_gb managed_disk_type
0 small Standard_B1s 40 Standard_LRS
1 medium Standard_D3_v2 100 Standard_LRS
2 large Standard_D4_v2 100 Premium_LRS

では、以下のパラメータを指定して specオブジェクトを作成します。

  • プロバイダ: azure
  • flavor: medium
In [47]:
spec_azure = vcp.get_spec('azure', 'medium')

作成したspec_azureの設定内容を確認してみます。

In [48]:
print(spec_azure)
========================
azure
------------------------

    cci_version: "1.1"
    name: 
    description: 
    private_network: default
    num_nodes: 1
    image: vcp/base:1.6.2
    recovery_mode: none
    docker_opt: {}
    params:
        {'v': [], 'e': []}


        vm_size: Standard_D3_v2
        disk_size_gb: 100
        managed_disk_type: Standard_LRS
        ext_managed_disk: []
        cloud_image: default
        ip_address_list: []
    tags: 
        tags: {}
========================

指定した flavorに対応する vm_size, disk_size_gb などが設定されていることが確認できます。


このステップのJupyterNotebookでの実行の様子


sshの公開鍵設定

VCノードに登録するsshの公開鍵を spec_azureに設定します。先ほど aws 向けのspecに設定したのと同じ値を指定しています。

In [49]:
spec_azure.set_ssh_pubkey(ssh_public_key)

このステップのJupyterNotebookでの実行の様子


specの設定内容を確認する

spec_azureの設定内容を確認してみます。

In [50]:
print(spec_azure)
========================
azure
------------------------

    cci_version: "1.1"
    name: 
    description: 
    private_network: default
    num_nodes: 1
    image: vcp/base:1.6.2
    recovery_mode: none
    docker_opt: {}
    params:
        {'v': [], 'e': ['AUTHORIZED_KEYS=c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFET0NVZGV3YW9JM0ZQaWZNdWIrZGR2MmQxaUsybkZpU0Y4YktKTjlUMlBEbk42UHlhTVlId2ZucWtGSnZyYTc2T2lqQllUSy81V2gwaElYc0RaYmdkQ0lwR2F5WXpwRVBtUiszZnd0ZllickJ4T0JqdnBUYmI3MU9wS08zd0NNM2JmazRjZzJxdFJSTVk4T09iZFFpckZFUzdwMGpyVXVBVTI1Z3d0ZDByY2orOE9qTGx2Qk12L2RIejhpQmZYVE94QWtYaEVuVHFVZ0lYQXNUMW8wV2JmdXNXWEwyZGJNUmw2M0lMSXJQYjZkNGUwcWVZK3pwMVlkcHFnY2NHWG8yVnZOV0hKZUZZSmdtUmJPdUV2UitmbmpNNXRxa1JKZHNtSFRrWktVOFp3VFI5K0JTU3BZVXVieTljcTR6UUs0ZnVmdlRBeGg2R2dPODBmcDRGNkVzRVAgam92eWFuQDU3YmEzM2IxZGEwMwo=']}


        vm_size: Standard_D3_v2
        disk_size_gb: 100
        managed_disk_type: Standard_LRS
        ext_managed_disk: []
        cloud_image: default
        ip_address_list: []
    tags: 
        tags: {}
========================

aws向けに最初に作成した specオブジェクトとspec_azureとの差分を確認してみます。

specオブジェクトの内部では aws は instance_type、azure はvm_size などそれぞれのクラウドプロバイダに応じたパラメータが設定されていることが確認できます。

In [51]:
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',
))
--- aws
+++ azure
@@ -1,10 +1,10 @@
 
 ========================
-aws
+azure
 ------------------------
 
     cci_version: "1.1"
-    name: aws-server
+    name: 
     description: 
     private_network: default
     num_nodes: 1
@@ -14,11 +14,13 @@
     params:
         {'v': [], 'e': ['AUTHORIZED_KEYS=c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFET0NVZGV3YW9JM0ZQaWZNdWIrZGR2MmQxaUsybkZpU0Y4YktKTjlUMlBEbk42UHlhTVlId2ZucWtGSnZyYTc2T2lqQllUSy81V2gwaElYc0RaYmdkQ0lwR2F5WXpwRVBtUiszZnd0ZllickJ4T0JqdnBUYmI3MU9wS08zd0NNM2JmazRjZzJxdFJSTVk4T09iZFFpckZFUzdwMGpyVXVBVTI1Z3d0ZDByY2orOE9qTGx2Qk12L2RIejhpQmZYVE94QWtYaEVuVHFVZ0lYQXNUMW8wV2JmdXNXWEwyZGJNUmw2M0lMSXJQYjZkNGUwcWVZK3pwMVlkcHFnY2NHWG8yVnZOV0hKZUZZSmdtUmJPdUV2UitmbmpNNXRxa1JKZHNtSFRrWktVOFp3VFI5K0JTU3BZVXVieTljcTR6UUs0ZnVmdlRBeGg2R2dPODBmcDRGNkVzRVAgam92eWFuQDU3YmEzM2IxZGEwMwo=']}
 
-    instance_type: m4.large
-    volume_size: 8
-    volume_type: gp2
-    volume_id: []
-    cloud_image: default
-    ip_address_list: []
-    tags: {}
+
+        vm_size: Standard_D3_v2
+        disk_size_gb: 100
+        managed_disk_type: Standard_LRS
+        ext_managed_disk: []
+        cloud_image: default
+        ip_address_list: []
+    tags: 
+        tags: {}
 ========================

このステップのJupyterNotebookでの実行の様子


Unitの作成とVCノードの起動

まず作成前のUnitGroup状態を確認しておきます。

In [52]:
from IPython.display import display

# Unitの一覧を DataFrame で表示する
display(unit_group.df_units())

# VCノードの一覧を DataFrame で表示する
display(unit_group.df_nodes())
vctype vcno vcname vc_state vcid cdate unit_name unit_state
0 compute 96 handson101 RUNNING 1e2f45c3... 2021/03/17 05:49:33 UTC aws-server RUNNING
vcno vcname unit_name unit_state node_no node_id node_state cloud_instance_address cloud_instance_id cloud_instance_name volumes
0 96 handson101 aws-server RUNNING 1 0cd71952... RUNNING 172.30.2.65 i-03e8c8c9691502c9d VCP-f7944417-1e2f45c3 none

Unitを作成します。

処理が完了するまでには 2~5分程度かかります。

In [53]:
# Unitの作成(同時に VCノードが作成される)
unit2 = unit_group.create_unit(
            'azure-server1',    # Unit 名
            spec_azure         # spec オブジェクト
        )
2021-03-17 15:04:13,791 - INFO - BOOTING ... 0 sec
2021-03-17 15:04:18,950 - INFO - BOOTING ... 5 sec
2021-03-17 15:04:24,106 - INFO - BOOTING ... 10 sec
2021-03-17 15:04:29,266 - INFO - BOOTING ... 15 sec
2021-03-17 15:04:34,434 - INFO - BOOTING ... 20 sec
2021-03-17 15:04:39,595 - INFO - BOOTING ... 25 sec
2021-03-17 15:04:44,760 - INFO - BOOTING ... 30 sec
2021-03-17 15:04:49,924 - INFO - BOOTING ... 35 sec
2021-03-17 15:04:55,084 - INFO - BOOTING ... 40 sec
2021-03-17 15:05:00,253 - INFO - BOOTING ... 45 sec
2021-03-17 15:05:05,420 - INFO - BOOTING ... 50 sec
2021-03-17 15:05:10,587 - INFO - BOOTING ... 55 sec
2021-03-17 15:05:15,758 - INFO - BOOTING ... 60 sec
2021-03-17 15:05:20,924 - INFO - BOOTING ... 65 sec
2021-03-17 15:05:26,089 - INFO - BOOTING ... 70 sec
2021-03-17 15:05:31,255 - INFO - BOOTING ... 75 sec
2021-03-17 15:05:36,424 - INFO - BOOTING ... 80 sec
2021-03-17 15:05:41,589 - INFO - BOOTING ... 85 sec
2021-03-17 15:05:46,755 - INFO - BOOTING ... 90 sec
2021-03-17 15:05:51,920 - INFO - BOOTING ... 95 sec
2021-03-17 15:05:57,091 - INFO - BOOTING ... 100 sec
2021-03-17 15:06:02,266 - INFO - BOOTING ... 105 sec
2021-03-17 15:06:07,428 - INFO - BOOTING ... 110 sec
2021-03-17 15:06:12,598 - INFO - BOOTING ... 115 sec
2021-03-17 15:06:17,767 - INFO - BOOTING ... 120 sec
2021-03-17 15:06:22,941 - INFO - BOOTING ... 125 sec
2021-03-17 15:06:28,106 - INFO - BOOTING ... 130 sec
2021-03-17 15:06:33,270 - INFO - BOOTING ... 135 sec
2021-03-17 15:06:38,431 - INFO - BOOTING ... 140 sec
2021-03-17 15:06:43,596 - INFO - BOOTING ... 145 sec
2021-03-17 15:06:48,765 - INFO - BOOTING ... 150 sec
2021-03-17 15:06:53,946 - INFO - BOOTING ... 155 sec
2021-03-17 15:06:59,116 - INFO - BOOTING ... 160 sec
2021-03-17 15:07:04,291 - INFO - BOOTING ... 165 sec
2021-03-17 15:07:09,449 - INFO - BOOTING ... 170 sec
2021-03-17 15:07:14,619 - INFO - BOOTING ... 175 sec
2021-03-17 15:07:19,791 - INFO - BOOTING ... 180 sec
2021-03-17 15:07:24,960 - INFO - BOOTING ... 185 sec
2021-03-17 15:07:30,133 - INFO - BOOTING ... 190 sec
2021-03-17 15:07:35,307 - INFO - BOOTING ... 195 sec
2021-03-17 15:07:40,469 - INFO - BOOTING ... 200 sec
2021-03-17 15:07:45,639 - INFO - BOOTING ... 205 sec
2021-03-17 15:07:50,809 - INFO - BOOTING ... 210 sec
2021-03-17 15:07:55,979 - INFO - BOOTING ... 215 sec
2021-03-17 15:08:01,144 - INFO - BOOTING ... 220 sec
2021-03-17 15:08:06,310 - INFO - BOOTING ... 225 sec
2021-03-17 15:08:11,471 - INFO - BOOTING ... 230 sec
2021-03-17 15:08:16,651 - INFO - BOOTING ... 235 sec
2021-03-17 15:08:21,823 - INFO - BOOTING ... 240 sec
2021-03-17 15:08:27,003 - INFO - BOOTING ... 245 sec
2021-03-17 15:08:32,177 - INFO - BOOTING ... 250 sec
2021-03-17 15:08:37,348 - INFO - BOOTING ... 255 sec
2021-03-17 15:08:42,522 - INFO - BOOTING ... 260 sec
2021-03-17 15:08:53,693 - INFO - unit azure-server1 is RUNNING

Unit作成後の状態を確認します。Unit とVCノードがそれぞれ2つあることが確認できるはずです。VCノード一覧ではそれぞれのVCノードの unit_name が異なることが確認できるはずです。またawsとazureのVCノードには異なるサブネットのIPアドレスが割り当てられていることが確認できます。

各プロバイダにどのようなサブネットを割り当てているのかについてはVCP Manager Web UI で確認ができます。

In [54]:
# Unitの一覧を DataFrame で表示する
display(unit_group.df_units())

# VCノードの一覧を DataFrame で表示する
display(unit_group.df_nodes())
vctype vcno vcname vc_state vcid cdate unit_name unit_state
0 compute 96 handson101 RUNNING 1e2f45c3... 2021/03/17 05:49:33 UTC aws-server RUNNING
1 compute 96 handson101 RUNNING 1e2f45c3... 2021/03/17 05:49:33 UTC azure-server1 RUNNING
vcno vcname unit_name unit_state node_no node_id node_state cloud_instance_address cloud_instance_id cloud_instance_name volumes
0 96 handson101 aws-server RUNNING 1 0cd71952... RUNNING 172.30.2.65 i-03e8c8c9691502c9d VCP-f7944417-1e2f45c3 none
1 96 handson101 azure-server1 RUNNING 1 35532b01... RUNNING 172.20.2.5 /subscriptions/d47388de-3ed7-4aa6-9e7c-5c09ecf55fd8/resourceGroups/niivcp/providers/Microsoft.Compute/virtualMachines/35532b01vm VCP-f7944417-1e2f45c3 none

VCノードを追加したので ~/.ssh/known_hosts を更新します。

In [55]:
for addr in unit_group.find_ip_addresses(node_state='RUNNING'):
    !ssh-keygen -R {addr}
    !ssh-keyscan -H {addr} >> ~/.ssh/known_hosts
# Host 172.30.2.65 found: line 16
# Host 172.30.2.65 found: line 17
# Host 172.30.2.65 found: line 18
/home/jovyan/.ssh/known_hosts updated.
Original contents retained as /home/jovyan/.ssh/known_hosts.old
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
# 172.30.2.65:22 SSH-2.0-OpenSSH_8.1
Host 172.20.2.5 not found in /home/jovyan/.ssh/known_hosts
# 172.20.2.5:22 SSH-2.0-OpenSSH_8.1
# 172.20.2.5:22 SSH-2.0-OpenSSH_8.1
# 172.20.2.5:22 SSH-2.0-OpenSSH_8.1

VCノードに対してping を実行してみます。

In [56]:
# UnitGroup内にあるVCノードのIPアドレスリストを取得する
ip_address = unit_group.find_ip_addresses(node_state='RUNNING')

# それぞれのVCノードに対してpingを実行する
for address in ip_address:
    !ping -c 5 {address}
    print()
PING 172.30.2.65 (172.30.2.65) 56(84) bytes of data.
64 bytes from 172.30.2.65: icmp_seq=1 ttl=63 time=0.348 ms
64 bytes from 172.30.2.65: icmp_seq=2 ttl=63 time=0.294 ms
64 bytes from 172.30.2.65: icmp_seq=3 ttl=63 time=0.321 ms
64 bytes from 172.30.2.65: icmp_seq=4 ttl=63 time=0.461 ms
64 bytes from 172.30.2.65: icmp_seq=5 ttl=63 time=0.827 ms

--- 172.30.2.65 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.294/0.450/0.827/0.197 ms

PING 172.20.2.5 (172.20.2.5) 56(84) bytes of data.
64 bytes from 172.20.2.5: icmp_seq=1 ttl=60 time=10.6 ms
64 bytes from 172.20.2.5: icmp_seq=2 ttl=60 time=10.6 ms
64 bytes from 172.20.2.5: icmp_seq=3 ttl=60 time=11.6 ms
64 bytes from 172.20.2.5: icmp_seq=4 ttl=60 time=10.8 ms
64 bytes from 172.20.2.5: icmp_seq=5 ttl=60 time=10.9 ms

--- 172.20.2.5 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 10.603/10.948/11.673/0.400 ms

VCPでは複数の異なるクラウドを仮想的に一つの計算基盤(仮想クラウド)のように扱える機能を提供しています。そのため異なるクラウド(aws, azure)で起動したVCノードであっても、追加の設定なしに互いに通信することができます。そのことを確認するために、作成した2つの VCノード の一方から他方に対して ping を行ってみます。

In [57]:
# pingを実行するVCノードのIPアドレスを表示する
print(ip_address[0])
print()

!ssh {ssh_opts} {ip_address[0]} \
    ping -c 10 {ip_address[1]}
172.30.2.65

PING 172.20.2.5 (172.20.2.5): 56 data bytes
64 bytes from 172.20.2.5: seq=0 ttl=61 time=10.075 ms
64 bytes from 172.20.2.5: seq=1 ttl=61 time=10.345 ms
64 bytes from 172.20.2.5: seq=2 ttl=61 time=12.031 ms
64 bytes from 172.20.2.5: seq=3 ttl=61 time=10.740 ms
64 bytes from 172.20.2.5: seq=4 ttl=61 time=14.267 ms
64 bytes from 172.20.2.5: seq=5 ttl=61 time=10.662 ms
64 bytes from 172.20.2.5: seq=6 ttl=61 time=10.570 ms
64 bytes from 172.20.2.5: seq=7 ttl=61 time=10.164 ms
64 bytes from 172.20.2.5: seq=8 ttl=61 time=10.061 ms
64 bytes from 172.20.2.5: seq=9 ttl=61 time=10.638 ms

--- 172.20.2.5 ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 10.061/10.955/14.267 ms

逆方向で同様のことを行ってみます。

In [58]:
# pingを実行するVCノードのIPアドレスを表示する
print(ip_address[1])
print()

!ssh {ssh_opts} {ip_address[1]} \
    ping -c 10 {ip_address[0]}
172.20.2.5

PING 172.30.2.65 (172.30.2.65): 56 data bytes
64 bytes from 172.30.2.65: seq=0 ttl=61 time=9.880 ms
64 bytes from 172.30.2.65: seq=1 ttl=61 time=11.098 ms
64 bytes from 172.30.2.65: seq=2 ttl=61 time=10.609 ms
64 bytes from 172.30.2.65: seq=3 ttl=61 time=9.699 ms
64 bytes from 172.30.2.65: seq=4 ttl=61 time=11.210 ms
64 bytes from 172.30.2.65: seq=5 ttl=61 time=10.099 ms
64 bytes from 172.30.2.65: seq=6 ttl=61 time=9.983 ms
64 bytes from 172.30.2.65: seq=7 ttl=61 time=9.952 ms
64 bytes from 172.30.2.65: seq=8 ttl=61 time=9.746 ms
64 bytes from 172.30.2.65: seq=9 ttl=61 time=9.855 ms

--- 172.30.2.65 ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 9.699/10.213/11.210 ms

このステップのJupyterNotebookでの実行の様子


VCノードに ssh でログインして操作する

Azureに追加で起動した VCノード は aws とは異なる構成(cpu, memory, disk)になってるはずです。そのことを確認するために、sshでログインして以下のコマンドを実行してみます。

  • カーネルバージョン
    • uname -a
  • CPU
    • cat /proc/cpuinfo
  • メモリ量
    • free
  • ディスク容量
    • df -h
In [59]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} uname -a
    print()
172.30.2.65:
Linux ip-172-30-2-65 4.4.0-159-generic #187-Ubuntu SMP Thu Aug 1 16:28:06 UTC 2019 x86_64 Linux

172.20.2.5:
Linux 35532b01 4.15.0-1082-azure #92~16.04.1-Ubuntu SMP Tue Apr 14 22:28:34 UTC 2020 x86_64 Linux

In [60]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} cat /proc/cpuinfo | grep 'model name'
    print()
172.30.2.65:
model name	: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz
model name	: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz

172.20.2.5:
model name	: Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
model name	: Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
model name	: Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
model name	: Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz

In [61]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} free
    print()
172.30.2.65:
              total        used        free      shared  buff/cache   available
Mem:        8173364      360744     6050100       12440     1762520     7656748
Swap:             0           0           0

172.20.2.5:
              total        used        free      shared  buff/cache   available
Mem:       14361900      642324    11592268        8868     2127308    13567704
Swap:             0           0           0

In [62]:
for address in ip_address:
    print(address + ':')
    !ssh {ssh_opts} {address} df -h
    print()
172.30.2.65:
Filesystem                Size      Used Available Use% Mounted on
overlay                   7.7G      3.3G      4.0G  45% /
tmpfs                     3.9G         0      3.9G   0% /sys/fs/cgroup
udev                      3.9G         0      3.9G   0% /dev
tmpfs                     3.9G         0      3.9G   0% /dev/shm
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/resolv.conf
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hostname
/dev/xvda1                7.7G      3.3G      4.0G  45% /etc/hosts
/dev/xvda1                7.7G      3.3G      4.0G  45% /var/lib/docker
none                      3.9G         0      3.9G   0% /tmp

172.20.2.5:
Filesystem                Size      Used Available Use% Mounted on
overlay                  96.7G      2.8G     94.0G   3% /
tmpfs                     6.8G         0      6.8G   0% /sys/fs/cgroup
udev                      6.8G         0      6.8G   0% /dev
tmpfs                     6.8G         0      6.8G   0% /dev/shm
/dev/sda1                96.7G      2.8G     94.0G   3% /etc/resolv.conf
/dev/sda1                96.7G      2.8G     94.0G   3% /etc/hostname
/dev/sda1                96.7G      2.8G     94.0G   3% /etc/hosts
/dev/sda1                96.7G      2.8G     94.0G   3% /var/lib/docker
none                      6.8G         0      6.8G   0% /tmp

最後に先程と同様に、負荷をかけるためにそれぞれのVCノードで stress コマンドを実行します。これまで同様 stressコマンドはアプリケーションコンテナとして実行します。

In [63]:
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
ad3b21deec631067e90cfd6065f577b131b091c69e52fb5a68e4b2e8aa6d1c1d
Unable to find image 'polinux/stress:latest' locally
latest: Pulling from polinux/stress
63bc94deeb28: Pulling fs layer
8d43371bad93: Pulling fs layer
8d43371bad93: Verifying Checksum
8d43371bad93: Download complete
63bc94deeb28: Verifying Checksum
63bc94deeb28: Download complete
63bc94deeb28: Pull complete
8d43371bad93: Pull complete
Digest: sha256:b6144f84f9c15dac80deb48d3a646b55c7043ab1d83ea0a697c09097aaad21aa
Status: Downloaded newer image for polinux/stress:latest
048ff12ef0ddde5f3d694135374d5d84c2f8a16cd25c87a309a9a61f6f125454

Grafanaで利用状況を確認してみます。


このステップのJupyterNotebookでの実行の様子


全てのVCノードを削除する

ここまで作成した全てのリソース(UnitGroup, Unit、VCノード)を削除します。この操作を行うことで AWS EC2インスタンスやAzure VMなどのクラウドに作成したリソースが削除されます。

全てのリソースの削除には 4~5分程度かかります。

In [64]:
unit_group.cleanup()
2021-03-17 15:11:48,369 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 0 sec
2021-03-17 15:11:53,540 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 5 sec
2021-03-17 15:11:58,713 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 10 sec
2021-03-17 15:12:03,883 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 15 sec
2021-03-17 15:12:09,047 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 20 sec
2021-03-17 15:12:14,214 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 25 sec
2021-03-17 15:12:19,389 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 30 sec
2021-03-17 15:12:24,561 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 35 sec
2021-03-17 15:12:29,731 - INFO - aws-server is DELETING
azure-server1 is DELETING ... 40 sec
2021-03-17 15:12:34,859 - INFO - azure-server1 is DELETING ... 45 sec
2021-03-17 15:12:39,987 - INFO - azure-server1 is DELETING ... 50 sec
2021-03-17 15:12:45,117 - INFO - azure-server1 is DELETING ... 55 sec
2021-03-17 15:12:50,242 - INFO - azure-server1 is DELETING ... 60 sec
2021-03-17 15:12:55,364 - INFO - azure-server1 is DELETING ... 65 sec
2021-03-17 15:13:00,480 - INFO - azure-server1 is DELETING ... 70 sec
2021-03-17 15:13:05,609 - INFO - azure-server1 is DELETING ... 75 sec
2021-03-17 15:13:10,739 - INFO - azure-server1 is DELETING ... 80 sec
2021-03-17 15:13:15,865 - INFO - azure-server1 is DELETING ... 85 sec
2021-03-17 15:13:20,999 - INFO - azure-server1 is DELETING ... 90 sec
2021-03-17 15:13:26,136 - INFO - azure-server1 is DELETING ... 95 sec
2021-03-17 15:13:31,267 - INFO - azure-server1 is DELETING ... 100 sec
2021-03-17 15:13:36,387 - INFO - azure-server1 is DELETING ... 105 sec
2021-03-17 15:13:41,515 - INFO - azure-server1 is DELETING ... 110 sec
2021-03-17 15:13:46,641 - INFO - azure-server1 is DELETING ... 115 sec
2021-03-17 15:13:51,775 - INFO - azure-server1 is DELETING ... 120 sec
2021-03-17 15:13:56,896 - INFO - azure-server1 is DELETING ... 125 sec
2021-03-17 15:14:02,033 - INFO - azure-server1 is DELETING ... 130 sec
2021-03-17 15:14:07,163 - INFO - azure-server1 is DELETING ... 135 sec
2021-03-17 15:14:12,295 - INFO - azure-server1 is DELETING ... 140 sec
2021-03-17 15:14:17,418 - INFO - azure-server1 is DELETING ... 145 sec
2021-03-17 15:14:22,550 - INFO - azure-server1 is DELETING ... 150 sec
2021-03-17 15:14:27,680 - INFO - azure-server1 is DELETING ... 155 sec
2021-03-17 15:14:32,812 - INFO - azure-server1 is DELETING ... 160 sec
2021-03-17 15:14:37,942 - INFO - azure-server1 is DELETING ... 165 sec
2021-03-17 15:14:43,066 - INFO - azure-server1 is DELETING ... 170 sec
2021-03-17 15:14:48,196 - INFO - azure-server1 is DELETING ... 175 sec
2021-03-17 15:14:53,263 - INFO - cleanup completed. vc  is cleanup(no unit)

削除後の状態を確認してみます。

In [65]:
# UnitGroupの一覧を DataFrame で表示する
vcp.df_ugroups()
Out[65]:
vcno vctype vcname state vcid cdate

このステップのJupyterNotebookでの実行の様子