Hejdaの見る夢

一人前のエンジニアを目指して頑張ったこととかをつらつら書くブログ

プレビュー版 Azure Spot VMs を使ってみた🎉🎉

サマリ

  • Azure Spot VMs が新しくプレビューに追加されました。
  • 既に試用することが可能です。
  • 用途によっては、積極的に使っていきたい機能です。

経緯

2019/12/04 に @ThomasMaurer さんによって、以下のツイートがありました。

内容を簡単にまとめると以下のようです。

  • Azure Spot VMs というサービスがプレビューになったこと。
  • 上記のサービスは条件付きではあるけれど、 Azure VM をかなり割安で使用することが出来ること。
  • プレビューであるけれど、東京リージョンでも使えること。

関連するドキュメントは今のところ、以下の 3 点が公式ドキュメントとして見つけることが出来ました。

Azure Spot VMs とはいったい何か?

以下の特徴があります。

  • Azure VM を従来の金額から大幅に値下げした価格で使用することが出来ます。
  • VMスケールセット(VMSS)に対応しています。

とのことです。

これだけでも、インフラや SRE といった分野のエンジニアからすると、喉から手が出るほど欲しい機能です。

使用条件

VM のサイズの制限があり、以下の VM サイズでは Spot VM は使用出来ません。

実際に使ってみましょう

公式でチュートリアルが整備されています。

Azure portal

Azure CLI

Azure PowerShell

ARM テンプレート

Azure portal と Azure CLI を実際に試してみたいと思います。

試すだけであれば簡単で、登録などは不要なのですぐに試すことが出来ます。

Azure portal から試してみる

Azure portal >> Virtual mashines >> create virtual machine と選択すれば既に選べる状態になっています。

f:id:nari_kyu:20191207163308p:plain

また、Azure Spot instance を選ばなかった場合は Eviction type および、 Eviction policy の項が無くなるようです。

その後、諸々の設定を行い、最後に Create することで VM は起動します。

f:id:nari_kyu:20191207163441p:plain

いつもの VM となんら変わらないですね! 👏👏

Azure CLI から試してみる

Azure portal 上の Azure Cloud Shell から実行します。

それ以外の環境から実行する場合は、az コマンドのインストールや Azure への認証などが必要になります。

  • リソースグループの作成
    • 先ほど作成した spot-vm-test を使います。
    • 新しく作成する場合は下記のコマンドで作成出来ます。
az group create -n spot-vm-test-cli -l japaneast

### location を知りたい場合は以下のコマンドで確認が出来ます。
az account list-locations

ドキュメントに習って、 Azure CLIVM を作成していきます。

  • 環境変数を用います。
    • 試される場合は、この変数を好きな値に変更してください。
export _rg_name='spot-vm-test'
export _vm_name='spot-vm-test-cli'
  • az コマンドを用いて、 Spot VMs を作成します。
az vm create \
    --resource-group ${_rg_name} \
    --name ${_vm_name} \
    --image UbuntuLTS \
    --admin-username azureuser \
    --generate-ssh-keys \
    --priority Spot \
    --max-price -
  • 実際の Azure Cloud Shell の様子です。

f:id:nari_kyu:20191207165446p:plain

  • Spot VMs を作成した際に設定したログインユーザ名と、標準出力に秘密鍵(と公開鍵)の PATH および、 パブリック IP アドレス が出力されているので、その情報を元に SSH ログインしてみます。

f:id:nari_kyu:20191207170558p:plain

こちらも無事 SSH 出来ました!! 👏👏

ちなみに この VM は Spot VMs か否か を判断したい場合にどこを見ればいいか、現時点では分かりませんでした。

こちらは分かり次第、追記したいと思います😉

リソースの削除

作成した VM はいくら Spot VMs とはいえ課金が発生してしまうので、不要なったらリソースグループごと消してしまいましょう。

f:id:nari_kyu:20191207175239p:plain

まとめ

プレビュー版なので仕様変更がある可能性が高いですが、それを差し引いてもすぐにでも積極的に使っていきたい機能です。

個人的な思い

※ ここから下は完全に個人的な感想です。

このサービスはすべてのリージョンで使用出来ることや、ほぼすべて VM サイズで使用出来ることもすごいのですが、個人的には VM スケールセット(VMSS) に対応してるというのがとても意味が大きいと考えています。

昨今は PaaS を代表としたインフラを考慮しない設計が注目を浴びていますが、要件によっては VM を扱わなくてはならず、VMスケールセット を構築している環境も多いと思います。

Azure Spot VMs は 中断できるワークロードに最適 とあるように、ユーザ側の意図しないタイミングで落ちる可能性があります。

これが逆に良くて、この条件を加味した VM に依存しないアークテクチャ設計 を求められることになり、結果的にインフラレイヤーにおけるカオスエンジニアリングを意識したアーキテクチャを考えざるを得ない状況になると予想します。

結果として DevOps や SRE といった基盤よりのエンジニアの腕の見せどころとなり、よりクラウドネイティブな設計をさざるを得なくなります。

さらに個人的な願いとしては AKS の Node に使いたいと思っていて、何か貢献出来ればいいなぁと思いつつ、 CLI および Terraform の実装待ちというステータスです😊

Microsoft Learn もくもく会に参加しました(※ 注意書き有

注意点

※ 当日はわたしは咳喘息の悪化に伴い、本当は参加していません!!

※ この記事は、行きたかった気持ちを供養する記事です…

Microsoft Learn もくもく会とは

紹介

今回は、第10回 Microsoft Learn もくもく会 @品川 に参加してきたので、その時のメモになります。(※ 参加出来ていません)

雰囲気や内容を把握して頂き、今後参加される際の参考になればと思います。

あと、 Twitter でおだしょーさん(@MS_odasho)を追いかけていると、より詳細な雰囲気が掴めると思います

楽しそうですよね!! :)

当日の時間の流れや雰囲気

ざっくりなスケジュール

  • 12:30 ~
    • 受付
  • 13:10 ~
    • 会の説明
  • 13:15 ~
    • 自己紹介
  • 13:20 ~
    • もくもくタイム開始
  • 16:45 ~
    • 成果発表
  • 17:00
    • 解散

雰囲気

  • (普通の?)もくもく会
  • 飲み物はフリードリンクをいただけるので、適宜動く感じ

あまりツイートが見つからなかったので、みんな集中してやっていたのかなと思います!

アドベントカレンダーについて

話しが変わるのですが、すこし前に Twitter で以下のやりとりがあり、 Microsoft Learn のアドベントカレンダーを作ることになり、勉強会でも紹介がありました。(これは予想)

今回はこのアドベントカレンダー作成と実施も兼ねて参加したので、効率的に時間を使えたかと思います。(※ 参加出来ていません)

なお、勉強会後は有志で夕飯を食べに行ったそうなのですが、私は次の予定があったので、先に帰りました。

次回参加出来る機会があれば、ごはんまでご一緒出来るといいなと思います :D

わたしが作成しているコレクション

まとめとか感想とか

Microsost learn は本当にすごくよく出来たサービスであり、もろもろのサービスの質や量、認定精度、社員さんの対応などを考えると Microsoft の本気というか、ある意味 余裕さ さえ感じました。

本当にエンジニア(も)を大切にしているんだなという印象が他のクラウドよりもより強く感じます。

しかし、 Microsost Learn はキッカケでしかないため、ここで得た知識や技術を使って実際に Azure を動かして、なにかアウトプットをしたいなと思います!! ;)

Azure Citadel のすゝめ 🧐

サマリ

Azure Citadel に感動したのでそれをおすすめする記事です!!

f:id:nari_kyu:20191104143355p:plain

どんなサイトなの??

https://azurecitadel.com/about/

簡単にまとめると以下のようです。意訳なので間違ってたらごめんなさい :(

  • Azure Citadel はイギリスのとあるコミュニティチームに属している、数人の Microsoft クラウドアーキテクト達が共同で立ち上げたコミュニティサイトである。
  • Microsoft の公式なサイトではない。
  • イギリス国内外問わず、 Microsoft (社員) 外の技術的なコントリビューターによるコントリビュート (contributes) が存在している。
  • 記事に前提知識が必要なものも少なくなく、 Azure への基礎的な理解は Microsoft Learn などの公式の Microsoft サイトを参照すること。

また、閲覧のみであれば会員登録も必要無く自由に閲覧することが出来ます。

GitHub Pages でホスティングしているので、ページのソースを見ることも出来ます。

具体的にどんなものがあるの??

2019/11 現在のカテゴリーとその説明は以下の 11 項目

https://azurecitadel.com/categories/

f:id:nari_kyu:20191104143336p:plain

  • Automation
    • Operate at scale and manage your cloud resources optimally through governance and automation. Subscribe to the feed in the footer!
  • Cloud Native
    • Understand how to build cloud native, modern apps with containers, serverless & Kubernetes.
  • Data & AI
    • Real world AI with cognitive services, bots data-analytics and machine learning.
  • DevOps
    • Deploy & build software faster through pipelines, with automation and DevOps practices.
  • Fundamentals
    • Core concepts of Azure and information on getting started for beginners.
  • Infrastructure
    • Virtual machines & networking are still the backbone of many cloud architectures.
  • Internet Of Things
    • Build production-grade IoT applications and configure your IoT solution.
  • Pre-Reqs
    • Get yourself set up and ready to take on the labs.
  • Security
  • Specialised Workloads
    • Specialised topics such as SAP, HPC and other demanding enterprise workloads.
  • Web & Mobile
    • Developing using web & mobile platforms using RESTful APIs. Azure platform services and API management.

感想とか

Microsoft Learn や 公式ドキュメントもありますが、Azure Citadel は(自分の GitHub に誘導することも出来るなどの)エンジニアとしてある程度自由度を持ったコミュニティのように感じました。(もちろん Azure Citadel で完結する記事も多くあると思います。)

そして、記事や閲覧者が増えることによって、コミュニティとしての成長の余地は十分にあるサイトだとも感じました。

将来、このようなコミュニティサイトで多くのエンジニアが自分の価値を表現出来ると期待しています。

いつの日か、自分でも(もちろん英語で)投稿出来るように頑張ります :D

Azure Storage を Terraform で構築するサンプルを公開しました!! 🎉🎉🎉

動悸

Serverlessdays Tokyo 2019 にて素敵な登壇があり、実際に書いてみようと思いました。

  • Azure でサーバーレス、 Infrastructure as Code どうしてますか? by @dz_
    • Have fun! 💖

www.slideshare.net

Terraform は普段から書いているし、ちょうど Google Cloud Storage をいじっていたので、 同じストレージ系だからそこまで時間かけずにいけるだろうと思い、 Azure Storage の中の Azure Blob を調べるとこからはじめました。

調査と実際に簡単な検証、コードを公開出来るようにまとめるまでに 8 時間くらいかかりました。

Azure に慣れていないので、 Terraform において Azure にログインするとこで一回心が折れましたが、なんとかミニマムで公開出来るくらいにはまとまりました。

サンプルコード

以下の Repository が実際に作成したサンプルコードです。

github.com

実際にやってみる

Azure のアカウントの作成

ここは他に記事におまかせします。

Docker のインストール

実行環境を Dockerfile で用意しています。

したがって、作業マシンに Docker Engine をインストールしてください。

参考: Install Docker

Repository の取得

今回は自作した Repository を使って、挙動を確認していきます。

  • Repository を clone します。
cd {YOUR_WORKSPACE}
git clone https://github.com/iganari/package-azure.git
cd storage/terraform/
$ tree
.
├── Dockerfile
├── README.ja.md
├── README.md
├── docker-build-run.sh
├── images
│   └── irasutoya
│       ├── azarashi
│       │   ├── animal_chara_computer_azarashi.png
│       │   ├── animal_chara_smartphone_azarashi.png
│       │   └── animal_gomafu_azarashi_baby.png
│       ├── hiyoko
│       │   ├── animal_mark_hiyoko.png
│       │   ├── hiyoko.png
│       │   ├── hiyoko_baby.png
│       │   └── niwatori_hiyoko_koushin.png
│       └── penguin
│           ├── animal_chara_computer_penguin.png
│           ├── animal_chara_smartphone_penguin.png
│           ├── natsubate_penguin.png
│           └── ondanka_animal_penguin.png
├── provider.tf
├── resource_group.tf
├── storage.tf
├── terraform.tf
└── variables.tf

5 directories, 20 files

Terraform の設定ファイルの説明を簡単に示します。

  • terraform.tf
    • Terraform のバージョンを固定します。
    • Terraform はバージョンが上がるのが早いので可能な限り、固定したほうがいいでしょう。
terraform {
  required_version = "0.12.12"
}
resource "azurerm_resource_group" "arg_default" {
  name     = "${lookup(var.common, "rsg_name")}"
  location = "${lookup(var.common, "rsg_location")}"
}
resource "random_string" "asa-suffix" {
  length  = "8"
  upper   = false
  lower   = true
  number  = false
  special = false
}

resource "azurerm_storage_account" "asa_default" {
  name                     = "${lookup(var.storage, "asa_name")}${random_string.asa-suffix.id}"
  resource_group_name      = "${azurerm_resource_group.arg_default.name}"
  location                 = "${lookup(var.common, "rsg_location")}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_storage_container" "asc_default" {
  name                  = "${lookup(var.storage, "asc_name")}"
  resource_group_name   = "${azurerm_resource_group.arg_default.name}"
  storage_account_name  = "${azurerm_storage_account.asa_default.name}"
  container_access_type = "private"
}

resource "azurerm_storage_blob" "asb_default_01" {
  name                   = "penguin_01.png"
  resource_group_name    = "${azurerm_resource_group.arg_default.name}"
  storage_account_name   = "${azurerm_storage_account.asa_default.name}"
  storage_container_name = "${azurerm_storage_container.asc_default.name}"
  type                   = "Block"
  source                 = "images/irasutoya/penguin/animal_chara_computer_penguin.png"
}
resource "azurerm_storage_blob" "asb_default_02" {
  name                   = "sample/penguin_02.png"
  resource_group_name    = "${azurerm_resource_group.arg_default.name}"
  storage_account_name   = "${azurerm_storage_account.asa_default.name}"
  storage_container_name = "${azurerm_storage_container.asc_default.name}"
  type                   = "Block"
  source                 = "images/irasutoya/penguin/animal_chara_smartphone_penguin.png"
}

resource "azurerm_storage_blob" "asb_default_03" {
  count = "${length(var.image-hiyoko)}"

  # same version
  name = "sample03/hiyoko/${element(var.image-hiyoko, count.index)}"
  # # rename version
  # name = "sample03/hiyoco-${lookup(var.image-hiyoko, count.index)}"

  resource_group_name    = "${azurerm_resource_group.arg_default.name}"
  storage_account_name   = "${azurerm_storage_account.asa_default.name}"
  storage_container_name = "${azurerm_storage_container.asc_default.name}"
  type                   = "Block"
  source                 = "images/irasutoya/hiyoko/${element(var.image-hiyoko, count.index)}"
}
  • variables.tf
    • 変数をまとめておく設定ファイルです。
variable "common" {
  type = "map"
  default = {
    rsg_name     = "rsg-sample"
    rsg_location = "West Europe"
  }
}

variable "storage" {
  type = "map"
  default = {
    asa_name = "asasample"  # name can only consist of lowercase letters and numbers, and must be between 3 and 24 characters long.
    asc_name = "asc-sample"  # Only lowercase alphanumeric characters and hyphens allowed.
  }
}

variable "image-hiyoko" {
  default = [
    "animal_mark_hiyoko.png",
    "hiyoko_baby.png",
    "hiyoko.png",
    "niwatori_hiyoko_koushin.png"
  ]
}

以上が Terraform の設定ファイルになります。

また、 Dockerfile を用いた環境を構築するために、以下のようのなシェルスクリプトも用意しました。

  • docker-build-run.sh
#!/bin/bash

set -xeu

_I_TAG='pkg-azure-storage-tf'
BASEPATH=$(cd `dirname $0`; pwd)
DIREPATH=`echo $BASEPATH | awk -F\/ '{print $NF}'`

set +eu
docker rm -f ${_I_TAG}
set -eu

docker build . -t ${_I_TAG}

docker run --rm \
           -it \
           -v $BASEPATH:/opt/iganari/$DIREPATH \
           -w /opt/iganari/$DIREPATH \
           -h ${_I_TAG} \
           --name ${_I_TAG} \
           ${_I_TAG} \
           /bin/sh

上記のファイルを用意したら、実行していきます。

Docker コンテナを用いて、 Terraform を実行する

  • Docker コンテナの起動をします。
    • 以降、 🐳 がついているものはこの Docker コンテナ上で実行しているものとします。
sh docker-build-run.sh
  • 🐳 az コマンドのバージョンの確認します。
    • 執筆当時は 2 系を使用していますが、読むタイミングによってはバージョンがもっと進んでいる可能性があります。
# az --version
azure-cli (2.0.57)
  • 🐳 Terraform のバージョンを確認します。
    • 執筆当時は 0.12.12 系を使用していますが、読むタイミングによってはバージョンがもっと進んでいる可能性があります。
    • しかし、今回の環境においては terraform.tf で Terraform のバージョンを指定しているため、このバージョンでしか実行出来ないようになっています。
    • Dockerfile にもこのバージョンを指定してインストールしているため、このバージョンが使用出来ない場合はそもそも Docker コンテナが起動しない可能性があります。
# terraform --version
Terraform v0.12.12
  • 🐳 az コマンドを持ちいて、 Azure にログインします。
az login
### 例

# az login
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code {ここに認証用のコードが出力されています} to 

f:id:nari_kyu:20191028050452p:plain

### ブラウザでの認証が完了する以下のように、現在使用出来るサブスクリプションが表示されます。

authenticate.
[
  {
    "cloudName": "AzureCloud",
    "id": "xxxxxxxxxxxxxxxxxxxxx",
    "isDefault": false,
    "name": "xxxxxxxxxxxxxxxxxxxxx",
    "state": "Warned",
    "tenantId": "xxxxxxxxxxxxxxxxxxxxx",
    "user": {
      "name": "xxxxxxxxxxxxxxxxxxxxx",
      "type": "user"
    }
  },
  {
    "cloudName": "AzureCloud",
    "id": "xxxxxxxxxxxxxxxxxxxxx",
    "isDefault": true,
    "name": "xxxxxxxxxxxxxxxxxxxxx",
    "state": "Enabled",
    "tenantId": "xxxxxxxxxxxxxxxxxxxxx",
    "user": {
      "name": "xxxxxxxxxxxxxxxxxxxxx",
      "type": "user"
    }
  },
.
.
.
以下、割愛
  • 🐳 現在のデフォルトのサブスクリプションを確認します。
    • 環境によっては、複数出てくるかもしれませんが、重要なのは IsDefault のカラムが Trure になっているものです。
az account
OR
az account list -o table
### 例

# az account list -o table
A few accounts are skipped as they don't have 'Enabled' state. Use '--all' to display them.
Name                        CloudName    SubscriptionId                        State    IsDefault
--------------------------  -----------  ------------------------------------  -------  -----------
iganari-dev                 AzureCloud   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  Enabled  True
_s_id='{上記でSubscriptionIdの項のもの}'
az account set --subscription ${_s_id}
### 確認のため
az account list -o table
  • 🐳 Terraform の初期設定を行います。
    • 実際に Terraform を実行するために必要なプラグイン等をダウンロードします。
    • 今回は random と azurerm のプラグインが必要になります。
terraform init
### 例

# terraform init

Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "random" (hashicorp/random) 2.2.1...
- Downloading plugin for provider "azurerm" (hashicorp/azurerm) 1.35.0...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.azurerm: version = "~> 1.35"
* provider.random: version = "~> 2.2"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
  • 🐳 Terraform にてテストを実行します。
    • 新規作成の場合は特に問題は出ないかと思いますが、もし問題があれば修正しましょう。
terraform plan
# terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.arg_default will be created
  + resource "azurerm_resource_group" "arg_default" {
      + id       = (known after apply)
      + location = "westeurope"
      + name     = "rsg-sample"
      + tags     = (known after apply)
    }
.
.
.
割愛
.
.
.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
  • 🐳 テストが無事に通ったら、実際にリソースを作るコマンドを実行します。
terraform apply
### 例
# terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.arg_default will be created
  + resource "azurerm_resource_group" "arg_default" {
      + id       = (known after apply)
      + location = "westeurope"
      + name     = "rsg-sample"
      + tags     = (known after apply)
    }

.
.
.
割愛
.
.
.


Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

********************************************
*** 上記のように、確認を求めらるので、 yes とします。
*** 下記が yes と入力した後の出力です。
********************************************

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

random_string.asa-suffix: Creating...
random_string.asa-suffix: Creation complete after 0s [id=sxvygxvo]

.
.
.
割愛
.
.
.

azurerm_storage_blob.asb_default_03[0]: Creation complete after 8s [id=https://asasamplesxvygxvo.blob.core.windows.net/asc-sample/sample03/hiyoko/animal_mark_hiyoko.png]

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

**********************************************************
*** 上記のように出たら、実行完了なので、ブラウザで確認してみましょう。
**********************************************************

ブラウザでリソースを確認します。

  • ストレージ アカウント にて asasample から始まるリソースをクリックします。
    • asasample より後ろは乱数を生成しています。

f:id:nari_kyu:20191028050715p:plain

f:id:nari_kyu:20191028050730p:plain

  • コンテナーをクリックし、asc-sample をクリックします。

f:id:nari_kyu:20191028050803p:plain

f:id:nari_kyu:20191028050813p:plain

  • 試しに penguin_01.png をクッリクし、ダウンロードをしてみます。

f:id:nari_kyu:20191028051013p:plain

f:id:nari_kyu:20191028051027p:plain

  • 問題無くダウンロード出来れば、いらすとやさんからお借りしたペンギンの画像がダウンロードされます。
    • せっかくなので、他の画像もダウンロードしてみてくださいね!

f:id:nari_kyu:20191028051041p:plain

リソースの削除

  • 検証が終わったら、 Azure のリソースは削除しましょう。

    • Azure Storage はアカウント作成後 12ヶ月を過ぎると無料枠が無くなり、通常の課金が発生します。
  • 🐳 Terraform にてリソース削除をします。

terraform destroy

まとめとか感想とか

Terraform を通じて、 Azure のリソースの IaC(Infrastructure as Code) をすこしだけ触れられたかと思います。

難しく無いと言えば難しくないのですが、慣れないとかなり手こずる箇所もあるかと思いますので、サンプルを作ってみましたが如何でしたでしょうか??

動かなかったり、脆弱性があった場合はぜひ Issues にて教えて頂けると幸いです(-人-) ---> issues

ソースには細かい Tips も結構いれてあるのですが、細部まで説明出来なかったので、また他の記事で書きたいと思います。

Have fun! 💖