さくらのクラウド APIを使ってサーバを立ち上げてみよう

さくらのナレッジで記事を書くのにあたって、さくらのクラウドで頻繁にサーバを立ち上げたり、削除したりしています。さくらのクラウドではWebブラウザ向けに管理画面を提供していますので、そこでサーバを設定したり、ネットワークの変更ができるようになっています。

しかし何度も操作を繰り返したり、時にミスして立ち上げ直したりしていると面倒になってきています。そこでさくらのクラウドではAPIが公開されていますので、このAPIを使ってサーバを自動で立ち上げられるようにしてみました。

さくらのクラウドでのサーバ立ち上げ手順

さくらのクラウドでサーバを立ち上げた経験がある方は分かると思いますが、サーバ立ち上げ中や設定中のステータス時にはGET/POST/PUT/DELETEなどのHTTPステータスやパラメータが表示されます。これは実際にAPIを叩いて実行されています。つまりこの手順と同じことをすればサーバが立ち上がる仕組みです。

この表示です。

一つのサーバを立ち上げる手順は以下のようになっています。

  1. サーバの作成
  2. ディスクの作成
  3. サーバとディスクの接続
  4. ディスクの修正
  5. 電源投入

このステップを踏んでいけばサーバが立ち上がります。

APIキーを取得する

さくらのクラウドをAPI操作するためには認証キーが必要です。設定画面のAPIキーメニューにて取得できます。

APIキーメニュー

最初はキーがありませんので作成します。キーはアクセストークンとシークレットキーからなります。どちらも大事なので不用意に公開したりしないでください。間違って公開してしまった場合は削除して作り直すのが良いでしょう。

APIキー。大事に保管してください。

node用ライブラリを取得する

さくらのクラウドではnode用ライブラリを配布しています。GitHubのsakura-internet/node-sacloudリポジトリからダウンロード可能です。ライセンスはMIT Licenseとなっています。

$ npm install -g sacloud

でインストール可能です。インストールされるとsacloudというコマンドが使えるようになりますが、今回はライブラリを直接操作します。

設定ファイルを作成する

ホームディレクトリに .sacloud.json というファイルを用意します。内容は次のようになります。

{
"access_token": "APIのアクセストークン",
"secret": "APIのシークレットトークン",
"password": "サーバ接続用のパスワード",
"public_key": ".ssh/id_rsa.pub" <- 公開鍵のパス
}

実行してみる

今回作成したスクリプトはGistに公開しています。CoffeeScriptで作成しています。

実行は次のように行います(別途 npm install -g coffeescript が必要です)。

$ coffee new_server.coffee server1

server1 というのはサーバ名です。実行すると次のように標準出力が流れます。

$ coffee new_server.coffee server1
Instanse ready
0/20480
3520/20480
9792/20480
16256/20480
19456/20480
Disk ready
Connected
Configured
Launched
Got server info.
Server launched.
Let's command. :-)  ssh core@133.242.17.208

これでCoreOSのサーバが一台立ち上がります。では順に説明します。

メイン処理

処理はとても簡単で、次のようになります。

sakura = new Sakura(JSON.parse(fs.readFileSync(file_path, 'utf-8')))
sakura.create_server(server_name).then (bol) ->
  console.log "Server launched."
  console.log "Let's command. :-) ", "ssh core@#{sakura.server.interfaces[0].ipAddress}"

設定ファイルを読み込んで、create_serverメソッドを実行しています。そうするとサーバ情報が返ってきますので、IPアドレスを表示しています。今回はあくまでも個人用としてCoreOS決め打ちになっていますので、サーバの接続もcore@にしています。

create_serverは次のようになっています。

create_server: (server_name) ->
  me = this
  me.server_name = server_name
  Promise.all([this.create_instance(server_name), this.create_disk()])
  .then (results) ->
    me.server_id = results[0]
    me.disk_id   = results[1]
    me.connect_server_disk()
  .then (bol) ->
    me.modify_disk()
  .then (bol) ->
    me.launch_server()
  .then (bol) ->
    me.get_server_info()

基本的にPromiseで順番に実行しているだけですが、最初のcreate_instance(サーバ作成)とcreate_disk(ディスク作成)は一緒に終わっている必要があるのでPromise.allを使っています。その後、connect_server_disk(サーバとディスクの接続)、modify_disk(ディスクの修正)、launch_server(電源投入)、get_server_info(サーバ情報取得)を順番に行っています。

サーバ作成処理

さくらのクラウドAPIは全体としてシンプルなので、殆どのメソッドが同じ形になっています。まずはサーバ作成処理です。

create_instance: (server_name) ->
  me = this
  return new Promise (onFulfilled, onRejected) ->
    me.client.createRequest(
      method: 'POST'
      path:   'server'
      body:
        Server:
          Zone       :
            ID: 31001 # 石狩第1ゾーン
          ServerPlan:
            ID: 2001  # プラン/1Core-2GB
          Name: server_name
          Description: ''
          ConnectedSwitches: [
            _operation: "internet",
            Scope: "shared"
            BandWidthMbps: 100
            virtio: true
          ]
          Tags       : []
    ).send (err, result) ->
      console.log("Instanse ready")
      onFulfilled(result.response.server.id)

こちらもWeb APIを使った非同期処理になるのでPromiseで囲んでいます。後は /server へPOSTメソッドで情報を送信しているだけです。送っている情報としては、ゾーン(石狩第1または第2)、サーバのプラン、ネットワーク接続情報になります。

ディスク作成

次にディスクの作成です。

create_disk: ->
  me = this
  return new Promise (onFulfilled, onRejected) ->
    me.client.createRequest(
      method: 'POST'
      path:   'disk'
      body:
        Disk:
          Plan: ID: 4
          Zone: ID: 31001 # 石狩第1ゾーン
          SourceArchive:
            ID: 112600559834
          SizeMB: 20480
          Connection: "virtio"
          Name: strftime("%Y/%m/%d %H:%M:%Sに新規作成されたサーバ")
    ).send (err, result) ->
      throw new Error(err) if err
      disk_id = result.response.disk.id
      id = setInterval( ->
        me.client.createRequest(
          method: 'GET'
          path:   'disk/' + disk_id
        ).send (err, result) ->
          if result.response.disk.migratedMB == result.response.disk.sizeMB
            console.log("Disk ready")
            clearInterval(id)
            onFulfilled(disk_id)
          else
            console.log("#{result.response.disk.migratedMB}/#{result.response.disk.sizeMB}")
      , 5000)

基本的にはサーバ作成と同じですが、注意点としてはアーカイブの選択があります。このIDはゾーンによって異なりますので注意してください。調べ方としてはWebのダッシュボードでアーカイブ選択に表示されている数字をメモする方法になります。

また、ディスクの作成が終わった後、データのコピー処理が行われるのでそのステータスを5秒おきにチェックしています。ディスクの作成が終わらないとサーバとディスクの接続ができませんのでご注意ください。

ディスクのコピーが終わったら同じくPromiseを終えています。

サーバとディスクの接続

サーバとディスクを接続するのはとても簡単です。

connect_server_disk: ->
  me = this
  return new Promise (onFulfilled, onRejected) ->
    me.client.createRequest(
      method: 'PUT'
      path:   "disk/#{me.disk_id}/to/server/#{me.server_id}"
    ).send (err, result) ->
      console.log("Connected")
      onFulfilled(1)

出来上がったサーバとディスクのIDを使ってWeb APIを呼び出すだけで完了します。

ディスクの修正

ディスクの修正は設定ファイルで指定している公開鍵の取得とパスワードの設定を行っています。

modify_disk: ->
  me = this
  public_key = fs.readFileSync(process.env.HOME + "/" + me.config.public_key, 'utf-8')
  return new Promise (onFulfilled, onRejected) ->
    me.client.createRequest(
      method: 'PUT'
      path:   "disk/#{me.disk_id}/config"
      body:
        Password: me.config.password
        SSHKey:
          PublicKey: public_key
        HostName: me.server_name
    ).send (err, result) ->
      console.log("Configured")
      onFulfilled(1)

こちらも分かりやすいかと思います。

サーバへの電源投入

いよいよ電源投入です。こちらはとてもシンプルです。

launch_server: ->
  me = this
  return new Promise (onFulfilled, onRejected) ->
    me.client.createRequest(
      method: 'PUT'
      path:   "server/#{me.server_id}/power"
    ).send (err, result) ->
      console.log("Launched")
      onFulfilled(1)

サーバの情報取得

最後にサーバの情報を取得します。

get_server_info: ->
  me = this
  return new Promise (onFulfilled, onRejected) ->
    me.client.createRequest(
      method: 'GET'
      path:   "server/#{me.server_id}"
    ).send (err, result) ->
      me.server = result.response.server
      console.log("Got server info.")
      onFulfilled(1)

これで指定したサーバだけの情報が得られます。

まとめ

いかがでしょうか。さくらのクラウドAPIを使うと、クラウドにサーバを立てるという一連の作業がステップバイステップで見られて面白いですよね。今回は石狩第1、かつCoreOSでといったかなり決めうちの立ち上げになっています。パラメータを修正すれば、自分好みの設定を作成するのも難しくはないと思います。

企業などでクラウドを立ち上げる場合、用途に合わせてパラメータはだいたい固定値で設定されると思いますので、予めこうやって準備しておけば後はコマンド一つでサーバ立ち上げができるようになるでしょう。ぜひご活用ください!

さくらのクラウド API v1.1 ドキュメント

おしらせ