Category Archives: Uncategorized

How to create pfx file from crt and key (pem file)

すみません、自分用のメモ。

開発中のテスト目的などで https (SSL/TLS) の証明書設定が必要になった際、わざわざお金を払って証明書の申請をするのは面倒。
こうした場合、ご存じの通り、「Let’s Encrypt」が使用できるので是非。(日本の場合、「SSL なう !」から使用しても良い。)

さて、その際、Certificate の入った crt ファイル (pem 形式) と private key を含む key ファイルが別々に生成されるが、Azure などではご存じの通り .pfx ファイル (private key を含む Personal Information Change) が必要になるため、以下のコマンドで簡単に作成すれば良い。
(Windows 環境の場合、cygwin や git に付属の bash、Windows が提供する bash などを使うと良い。)

openssl pkcs12 -export -out server.pfx -inkey {.key including private key} -in {.crt including certificate}

新規にパスワードを入力するよう促される。

Advertisements

Json.NET (Newtonsoft.Json) の基本的な使い方

意外と困っている人が多いので、今さらだが、まとめ。

JToken を使った基本操作

まず大前提として、使用するオブジェクト構成の理解が超重要。
構成は非常に簡単だ。オブジェクト (例: { "firstname" : "Subaru", "surname" : "Kokubun" })JObject、配列 (例 : [ { "surname" : "Kokubun" }, { "surname" : "Matsuzaki" }, ... ] ) は JArray、文字列や数値などのプリミティブは JValue、そして、これらに共通の親 (継承元) が JToken だ。(この構成を理解していないと、このあとの文書は理解できない !)

例えば、HTTP (REST API) を呼び出して、

{
  "results": [
    {
      "id": 1,
      "name": "pc",
      "price": 100000
    },
    {
      "id": 2,
      "name": "mouse",
      "price": 5000
    },
    {
      "id": 3,
      "name": "phone",
      "price": 30000
    }
  ]
}

の値が返ってきた場合、下記のサンプルコードの通りオブジェクト間を変換して最終的な値を取り出せる。

このサンプルでは、まず、{ "results" : ... } 全体は JObject で受け取り (10 – 11 行目)、results の中は配列なので JArray で受け取り (17 行目)、その配列の要素 1 つ 1 つは object なので JObject で受け取り (18 行目)、その中の値を JValue で受け取って (20, 22 行目)、最後に JValue の Value プロパティで .NET の object 型 (string, long, など) として中身を取得している (21, 23 行目)。

なお、いったん継承元である JToken で受けて、中身の構成に応じて JObject や JArray にキャストしても良い。(以降も同様)

using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Formatting;
using Newtonsoft.Json.Linq;

HttpClient cl = new HttpClient();
cl.DefaultRequestHeaders.Accept.Add(
  new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage res = await cl.GetAsync("http://example.com/someapi");
JObject jres =
  await res.Content.ReadAsAsync<JObject>(new[] { new JsonMediaTypeFormatter() });

// The following result is :
// name is pc, price is 100000.
// name is mouse, price is 5000.
// name is phone, price is 30000.
JArray jarr = (JArray)jres["results"];
foreach (JObject jobj in jarr)
{
  JValue nameValue = (JValue)jobj["name"];
  string name = (string)nameValue.Value;
  JValue priceValue = (JValue)jobj["price"];
  long price = (long)priceValue.Value;
  Console.WriteLine($"name is {name}, price is {price}.");
}

なお、上記の 10 行目で受け取った jres で、jres.ToString() とすれば、Json 全体が (改行や空白など) きれいにフォーマットされた文字列として取得できる。

例えば、下記のサンプルコードのように、いったん JToken (JObject, JArray, JValue など) を使ってオブジェクトを組み立て、それを 14 行目のように HTTP Body の文字列に変換して HTTP (REST) を投げることができる。

using System.Net.Http;
using Newtonsoft.Json.Linq;

// Sent body is :
// {
//   "eventname": "Developer Meeting",
//   "eventdate": "2016-10-24T17:30:00"
// }
JObject newObj = new JObject();
newObj.Add("eventname", new JValue("Developer Meeting"));
newObj.Add("eventdate", new JValue(new DateTime(2016, 10, 24, 17, 30, 0)));
HttpClient cl = new HttpClient();
HttpContent jsonContent = new StringContent(
  newObj.ToString(),
  Encoding.UTF8,
  "application/json");
HttpResponseMessage res = cl.PostAsync(uri, jsonContent).Result;

逆に、文字列から Json.NET の Object (JObject, JArray, 等々) を生成するには、Parse メソッドを使う。
例えば、上述の HTTP (REST API) から Json.NET のオブジェクトを取得するサンプル コードは、下記の通りいったん string で受けて (9 -10 行目)、それを Parse メソッドでオブジェクトに変換する方法で記述しても良い。(以降の処理は、上述と同じソースコードになるので省略。)

using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;

HttpClient cl = new HttpClient();
cl.DefaultRequestHeaders.Accept.Add(
  new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage res = await cl.GetAsync("http://example.com/someapi");
string jstr =
  await res.Content.ReadAsStringAsync();
JObject jres = JObject.Parse(jstr);
...

なお、今回は、返ってくる結果が { "results" : ... } なので JObject で受けているが (上記の 11 行目)、下記の例のように、受け取る内容によって型を変える必要があるので注意してほしい。

using Newtonsoft.Json.Linq;

var obj = JObject.Parse(@"{ ""firstname"" : ""Subaru"", ""surname"" : ""Kokubun"" }");
// Result : "My family name is Kokubun."
Console.WriteLine($"My family name is {obj["surname"]}.");

var arr = JArray.Parse(@"[ { ""surname"" : ""Kokubun"" }, { ""surname"" : ""Matsuzaki"" } ]");
// Result : "Kokubun", "Matsuzaki"
foreach(var item in arr)
{
  Console.WriteLine(item["surname"]);
}

LINQ to JSON

.NET プログラマーなら IEnumerable のオブジェクトで LINQ to Object のクエリー (Select, Where など) が使えることは知っていると思うが、上記で紹介した JToken (JObject, JArray, など) も、for 文をわざわざ使わず、LINQ to JSON を使ってクエリーが実行できる。

本投稿ではこの説明は割愛するが、詳細は「Json.NET Documentation : LINQ to Json」を参照してほしい。

JsonConvert による Serialize / Desirialize

なお、Json のオブジェクトと文字列の変換には、もう 1 つ別の方法もある。

Json.NET 以前の DataContractJsonSerializer の頃から使われていた手法だが、対応するクラス構成を作成しておき、一気に Serialize / Deserialize する方法だ。
下記のサンプルコードは、上述の { "results" : ... } を変換するサンプルをこの方法で書き直したコードだ。

変換後のオブジェクトは自然なクラスなので扱いやすい一方、この方法で注意してほしいのは、あくまで静的に構成が決まっている場合しか使えないという点。中身を確認しながら動的に処理をするケースでは使えないので注意してほしい。

using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

[JsonObject]
public class ReturnedData
{
  [JsonProperty("results")]
  public ItemData[] Results { get; set; }
}

[JsonObject]
public class ItemData
{
  [JsonProperty("id")]
  public int Id { get; set; }
  [JsonProperty("name")]
  public string Name { get; set; }
  [JsonProperty("price")]
  public int Price { get; set; }
}
...

// メインの処理
HttpClient cl = new HttpClient();
cl.DefaultRequestHeaders.Accept.Add(
  new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage res = await cl.GetAsync("http://example.com/someapi");
string jstr =
  await res.Content.ReadAsStringAsync();
ReturnedData jres = JsonConvert.DeserializeObject<ReturnedData>(jstr);
...

Json.NET は、いまや空気のように普通に使われるので、この程度のことは知っておいて損はない。

 

PowerShell Gallery の Module の利用方法 (よく使うコマンド集)

完全な自分のためのメモ。

PowerShell Gallery の Module を探したり (Find)、持って来たり (Install)、使えるようにしたり (Import) といった、最低限おぼえておくべき、よく使うコマンドを列挙する。

PowerShell Gallery から希望する Module を探す場合

Find-Module | Where-Object { $_.Name -match "{search string}" }

探した Module で、利用可能な Version (すべて) を表示する場合

Find-Module -Name {module name} -AllVersions

見つけた Module をマシンに Install する (ローカルに持ってくる) 場合

Install-Module {module name}

特定の Version を決めうちで Install する場合

Install-Module {module name} -RequiredVersion {version}

マシンに Install 済の使用可能な Module の一覧を取得する場合

Get-Module -ListAvailable

Install された Module (つまり、その Module 内の Command) を使える状態にする場合
(ただし、Windows PowerShell のウィンドウを閉じてセッションを終了したら終わり。いつも使う場合は、毎回 Windows PowerShell 起動時に、このコマンドを実行すること。)

Import-Module {module name}

Import 済の有効な (使える) Module の一覧を取得する場合

Get-Module

その Module 内で使える Command (Cmdlet) の一覧を取得する場合

Get-Command -Module {module name}

利用可能な Command を文字列で絞り込む場合

Get-Command *{search string}* -Module {module name}

Module をマシンから Uninstall する場合

Uninstall-Module {module name}

ただし、上記は単一の Module だけを追加・削除するので注意。
例えば、Web PI などインストーラー経由で複数の Module をまとめてインストールするケースでは、[プログラムと機能] (programs and features) などから Uninstall するほうが良い。そうすると、Install 時に入れた関連する Module すべてを削除してくれるためだ。(例えば、Azure PowerShell など)

Azure で Docker Cluster を構成するさまざまな方法

ここでは、Azure を使ってマルチ インスタンスや Cluster を構成するさまざまな方法をまとめたい。(Swarm, Mesos, Kubernetes 自体の構成方法の話ではなく、Azure に構成する際の考え方。)
いろいろと使える情報 (サンプルの構成ファイルなど) もあるので、それらの紹介 (リンク) もあわせて以下に記載する。

Azure + Docker の超基本

クラスタの話をする前に、まず、Azure で Docker を使う場合の超基本的な話を整理しておく。(知らない人のために)

Azure 上で Docker を使う場合、ざっくり下記の 2 つが使える。
(この他に、Docker 社が提供している Docker Cloud、Mesosphere が提供している DCOS でも、Azure を正式サポートしているが、これらについては本投稿の対象外とする。)

  • 普通に Azure Virtual Machine (IaaS, VM) を立ち上げて Container を立てる方法
  • Azure Container Service (ACS) と呼ばれるコンテナのホスティングを管理するサービス型の Azure リソースを使って Container 作成と管理をおこなう方法。
    やや乱暴な説明だが、AWS, Google を使っている人は、Amazon EC2 Container Service (ECS), Google Container Engine (GCE) と同じ位置づけのいわゆる「サービス」型のホスティング環境と思えば良い。(内部的な話は後述)

前者の VM (Azure Virtual Machine) を使うケースについて、Azure Virtual Machine (IaaS 環境) に docker container を構成するには、直球で Virtual Machine に docker のダウンロード・インストールをおこなっても良いが、Azure の場合は、Virtual Machine Extension と呼ばれる「VM に対する追加の構成要素 (リソースの 1 つ)」を使って docker のインストールと構成が可能だ。(よって、Azure 上で Docker を扱う場合、この “Extension” という言葉は良く出てくることになる。)
この構成をおこなうには、大きく下記の 3 通りの方法がある。

まずもっとも一般的な方法として、Azure CLI (Command-line Interface) のコマンド ユーティリティ (Azure 専用のコマンド ユーティリティ) を使う方法がある。(Azure CLI の azure vm docker create コマンドですぐに構成できる。)

Azure CLI を使って Docker VM Extension を構成する方法 :
https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-docker-with-xplat-cli/

VM + Docker の 2 番目の方法として、ARM (Azure Resource Manager) の Resource template と呼ばれる展開用の json ファイルを使って、Virtual Machine Extension を (json で) 記述する方法がある。
VM Extension にはさまざまな種類があるが、その 1 つとして Docker Extension と呼ばれるものがあるので、これを使えば簡単に構成できるようになっている。(なお、sh を実行するための VM Extension も用意されているので、この sh を使って Docker を構成する方法もある。)
展開をコード化して自動化したい場合にはすごく使える方法なので、上記 (コマンド ユーティリティ) で展開がうまくいったら、さいごに ARM の template としてコード化してみると良いだろう。(なお、このあと紹介する template を見る前に、最低限、ここで紹介している How-to 程度は理解できるようにしておいてほしい。)

Docker を構成した resource template の例 :
(下記の azuredeploy.json が開始点だ。以降も同様。。。)
https://github.com/Azure/azure-quickstart-templates/tree/master/docker-simple-on-ubuntu

抜粋すると以下のような感じだ。(ハイライト部分が DockerExtension)

. . .

{
  "apiVersion": "2015-06-15",
  "type": "Microsoft.Compute/virtualMachines",
  "name": "vmtest01",
  "location": "East US",
  . . . (途中省略)
},
{
  "type": "Microsoft.Compute/virtualMachines/extensions",
  "name": "testvm01/dockerex01",
  "apiVersion": "2015-06-15",
  "location": "East US",
  "dependsOn": [
    "Microsoft.Compute/virtualMachines/vmtest01"
  ],
  "properties": {
    "publisher": "Microsoft.Azure.Extensions",
    "type": "DockerExtension",
    "typeHandlerVersion": "1.0",
    "autoUpgradeMinorVersion": true,
    "settings": {}
  }
}

. . .

VM + Docker のおまけとして、docker 標準の client でも構成可能だ。
Azure の Docker サポートは MS が勝手に対応しているのではなく、Azure と Docker の双方が対応している形で、docker driver の 1 つとして azure がサポートされているからだ。上述の ARM のような “Azure かぶれ” な方法ではなく、オープンなツールやフレームワークなどから呼び出す場合は、この方法が使えるだろう。
(この具体的方法はここでは省略するが、下記ブログを参照してほしい。)

Docker client のみを使って Azure 上の Docker container を作成する例 :
https://blogs.msdn.microsoft.com/tsmatsuz/2015/10/08/azure-docker-machine-on-linux-from-pc-mac/

また、Azure Container Service (ACS) については、本投稿でテーマとしている「Cluster」の話と大きく関連しているので後述する。

Compose

まずは、IaaS v2 (Azure Virtual Machine) を使った構成を中心に整理しよう。

最初に、クラスタ (Cluster) ではなく、単なるマルチインスタンス (複数台) 構成の話だが、Azure では docker compose も柔軟に扱えるようになっている。

Azure の ARM (Azure Resource Manager) template の場合は、上述の Docker Extension で Compose の記述がサポートされていて、下記の通り ARM template の json に混ぜて構成が可能だ。(なお、コマンドを使った場合は「Azure VM Docker Compose Quickstart」で記載しているように普通に Compose を構成するだけ。)

Docker Compose を使って WordPress と MySQL を構成する template の例 :
https://github.com/Azure/azure-quickstart-templates/tree/master/docker-wordpress-mysql

抜粋すると以下のような感じだ。

. . .
{
  "apiVersion": "2015-06-15",
  "type": "Microsoft.Compute/virtualMachines",
  "name": "testvm01",
  "location": "East US",
  . . .
},
{
  "type": "Microsoft.Compute/virtualMachines/extensions",
  "name": "testvm01/dockerex01",
  "apiVersion": "2015-06-15",
  "location": "East US",
  "dependsOn": [
    "Microsoft.Compute/virtualMachines/rtestvm01"
  ],
  "properties": {
    "publisher": "Microsoft.Azure.Extensions",
    "type": "DockerExtension",
    "typeHandlerVersion": "1.0",
    "autoUpgradeMinorVersion": true,
    . . .
    "settings": {
      "compose": {
        "db": {
          "image": "mysql",
          "ports": [
            "3306:3306"
          ],
          "volumes": [
            "/var/lib/mysql:/var/lib/mysql"
          ],
          "environment": [
            "MYSQL_ROOT_PASSWORD"
          ]
        },
        "wordpress": {
          "image": "wordpress",
          "ports": [
            "80:80"
          ],
          "links": [
            "db:mysql"
          ]
        }
      }
    }
  }
}
. . .

Docker Compose の scale コマンドで、起動する container の数も柔軟に制御できる。

分散クラスタ

Production を考える場合、単に複数のコンテナが起動していれば良いというわけではない。
複数の物理マシンに点在する複数のコンテナを柔軟に管理するために、Swarm、Mesos などのオーケストレーション エンジンを使うのが一般的だ。

Azure VM (IaaS v2) を使って Docker + Swarm, Mesos, Marathon 等で分散クラスタを構成する場合は、専用の Extension はないので、上述の Compose を使うか、sh の実行をおこなうことになる。(コマンドの場合の例は「Azure Virtual Machine : How to use docker with swarm」参照。)

例えば、下記は、ARM (Azure Resource Manager) template で、上述した Compose を使って Swarm をインストールしている例だ。

Docker Compose と使って Swarm を構成する template の例 :
https://github.com/Azure/azure-quickstart-templates/tree/master/docker-swarm-cluster

Azure VM Extension には Linux の sh を実行する Extension (CustomScriptForLinux Extension) もあるので、Compose を使わずにすべて sh だけで構成する方法もある。
例えば、下記は mesos, zookeeper 等も含む構成を sh で記述しているが (適宜パラメータ化をおこなっている)、こうした sh を CustomScriptForLinux Extension を使って実行すれば良い。(下記では docker 自体も sh でインストールしている。)

#!/bin/bash

###########################################################
# Configure Mesos One Box
#
# This installs the following components
# - zookeepr
# - mesos master
# - marathon
# - mesos agent
###########################################################

set -x

echo "starting mesos cluster configuration"
date
ps ax

SWARM_VERSION="1.0.0-rc2"

#############
# Parameters
#############

MASTERCOUNT=$1
MASTERMODE=$2
MASTERPREFIX=$3
SWARMENABLED=$4
MARATHONENABLED=$5
CHRONOSENABLED=$6
ACCOUNTNAME=$7
set +x
ACCOUNTKEY=$8
set -x
AZUREUSER=$9
SSHKEY=${10}
HOMEDIR="/home/$AZUREUSER"
VMNAME=`hostname`
VMNUMBER=`echo $VMNAME | sed 's/.*[^0-9]\([0-9]\+\)*$/\1/'`
VMPREFIX=`echo $VMNAME | sed 's/\(.*[^0-9]\)*[0-9]\+$/\1/'`

echo "Master Count: $MASTERCOUNT"
echo "Master Mode: $MASTERMODE"
echo "Master Prefix: $MASTERPREFIX"
echo "vmname: $VMNAME"
echo "VMNUMBER: $VMNUMBER, VMPREFIX: $VMPREFIX"
echo "SWARMENABLED: $SWARMENABLED, MARATHONENABLED: $MARATHONENABLED, CHRONOSENABLED: $CHRONOSENABLED"
echo "ACCOUNTNAME: $ACCOUNTNAME"

###################
# setup ssh access
###################

SSHDIR=$HOMEDIR/.ssh
AUTHFILE=$SSHDIR/authorized_keys
if [ `echo $SSHKEY | sed 's/^\(ssh-rsa \).*/\1/'` == "ssh-rsa" ] ; then
  if [ ! -d $SSHDIR ] ; then
    sudo -i -u $AZUREUSER mkdir $SSHDIR
    sudo -i -u $AZUREUSER chmod 700 $SSHDIR
  fi

  if [ ! -e $AUTHFILE ] ; then
    sudo -i -u $AZUREUSER touch $AUTHFILE
    sudo -i -u $AZUREUSER chmod 600 $AUTHFILE
  fi
  echo $SSHKEY | sudo -i -u $AZUREUSER tee -a $AUTHFILE
else
  echo "no valid key data"
fi

###################
# Common Functions
###################

ensureAzureNetwork()
{
  # ensure the host name is resolvable
  hostResolveHealthy=1
  for i in {1..120}; do
    host $VMNAME
    if [ $? -eq 0 ]
    then
      # hostname has been found continue
      hostResolveHealthy=0
      echo "the host name resolves"
      break
    fi
    sleep 1
  done
  if [ $hostResolveHealthy -ne 0 ]
  then
    echo "host name does not resolve, aborting install"
    exit 1
  fi

  # ensure the network works
  networkHealthy=1
  for i in {1..12}; do
    wget -O/dev/null http://bing.com
    if [ $? -eq 0 ]
    then
      # hostname has been found continue
      networkHealthy=0
      echo "the network is healthy"
      break
    fi
    sleep 10
  done
  if [ $networkHealthy -ne 0 ]
  then
    echo "the network is not healthy, aborting install"
    ifconfig
    ip a
    exit 2
  fi
  # ensure the host ip can resolve
  networkHealthy=1
  for i in {1..120}; do
    hostname -i
    if [ $? -eq 0 ]
    then
      # hostname has been found continue
      networkHealthy=0
      echo "the network is healthy"
      break
    fi
    sleep 1
  done
  if [ $networkHealthy -ne 0 ]
  then
    echo "the network is not healthy, cannot resolve ip address, aborting install"
    ifconfig
    ip a
    exit 2
  fi
}
ensureAzureNetwork
HOSTADDR=`hostname -i`

ismaster ()
{
  if [ "$MASTERPREFIX" == "$VMPREFIX" ]
  then
    return 0
  else
    return 1
  fi
}
if ismaster ; then
  echo "this node is a master"
fi

isagent()
{
  if ismaster ; then
    if [ "$MASTERMODE" == "masters-are-agents" ]
    then
      return 0
    else
      return 1
    fi
  else
    return 0
  fi
}
if isagent ; then
  echo "this node is an agent"
fi

zkhosts()
{
  zkhosts=""
  for i in `seq 1 $MASTERCOUNT` ;
  do
    if [ "$i" -gt "1" ]
    then
      zkhosts="${zkhosts},"
    fi

    IPADDR=`getent hosts ${MASTERPREFIX}${i} | awk '{ print $1 }'`
    zkhosts="${zkhosts}${IPADDR}:2181"
    # due to mesos team experience ip addresses are chosen over dns names
    #zkhosts="${zkhosts}${MASTERPREFIX}${i}:2181"
  done
  echo $zkhosts
}

zkconfig()
{
  postfix="$1"
  zkhosts=$(zkhosts)
  zkconfigstr="zk://${zkhosts}/${postfix}"
  echo $zkconfigstr
}

######################
# resolve self in DNS
######################

echo "$HOSTADDR $VMNAME" | sudo tee -a /etc/hosts

################
# Install Docker
################

echo "Installing and configuring docker and swarm"

time wget -qO- https://get.docker.com | sh

# Start Docker and listen on :2375 (no auth, but in vnet)
echo 'DOCKER_OPTS="-H unix:///var/run/docker.sock -H 0.0.0.0:2375"' | sudo tee /etc/default/docker
# the following insecure registry is for OMS
echo 'DOCKER_OPTS="$DOCKER_OPTS --insecure-registry 137.135.93.9"' | sudo tee -a /etc/default/docker
sudo service docker restart

ensureDocker()
{
  # ensure that docker is healthy
  dockerHealthy=1
  for i in {1..3}; do
    sudo docker info
    if [ $? -eq 0 ]
    then
      # hostname has been found continue
      dockerHealthy=0
      echo "Docker is healthy"
      sudo docker ps -a
      break
    fi
    sleep 10
  done
  if [ $dockerHealthy -ne 0 ]
  then
    echo "Docker is not healthy"
  fi
}
ensureDocker

############
# setup OMS
############

if [ $ACCOUNTNAME != "none" ]
then
  set +x
  EPSTRING="DefaultEndpointsProtocol=https;AccountName=${ACCOUNTNAME};AccountKey=${ACCOUNTKEY}"
  docker run --restart=always -d 137.135.93.9/msdockeragentv3 http://${VMNAME}:2375 "${EPSTRING}"
  set -x
fi

##################
# Install Mesos
##################

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E56151BF
DISTRO=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
CODENAME=$(lsb_release -cs)
echo "deb http://repos.mesosphere.io/${DISTRO} ${CODENAME} main" | sudo tee /etc/apt/sources.list.d/mesosphere.list
time sudo add-apt-repository -y ppa:openjdk-r/ppa
time sudo apt-get -y update
time sudo apt-get -y install openjdk-8-jre-headless
if ismaster ; then
  time sudo apt-get -y --force-yes install mesosphere
else
  time sudo apt-get -y --force-yes install mesos
fi

#########################
# Configure ZooKeeper
#########################

zkmesosconfig=$(zkconfig "mesos")
echo $zkmesosconfig | sudo tee /etc/mesos/zk

if ismaster ; then
  echo $VMNUMBER | sudo tee /etc/zookeeper/conf/myid
  for i in `seq 1 $MASTERCOUNT` ;
  do
    IPADDR=`getent hosts ${MASTERPREFIX}${i} | awk '{ print $1 }'`
    echo "server.${i}=${IPADDR}:2888:3888" | sudo tee -a /etc/zookeeper/conf/zoo.cfg
    # due to mesos team experience ip addresses are chosen over dns names
    #echo "server.${i}=${MASTERPREFIX}${i}:2888:3888" | sudo tee -a /etc/zookeeper/conf/zoo.cfg
  done
fi

#########################################
# Configure Mesos Master and Frameworks
#########################################
if ismaster ; then
  quorum=`expr $MASTERCOUNT / 2 + 1`
  echo $quorum | sudo tee /etc/mesos-master/quorum
  hostname -i | sudo tee /etc/mesos-master/ip
  hostname | sudo tee /etc/mesos-master/hostname
  echo 'Mesos Cluster on Microsoft Azure' | sudo tee /etc/mesos-master/cluster
fi

if ismaster  && [ "$MARATHONENABLED" == "true" ] ; then
  # setup marathon
  sudo mkdir -p /etc/marathon/conf
  sudo cp /etc/mesos-master/hostname /etc/marathon/conf
  sudo cp /etc/mesos/zk /etc/marathon/conf/master
  zkmarathonconfig=$(zkconfig "marathon")
  echo $zkmarathonconfig | sudo tee /etc/marathon/conf/zk
  # enable marathon to failover tasks to other nodes immediately
  echo 0 | sudo tee /etc/marathon/conf/failover_timeout
  #echo false | sudo tee /etc/marathon/conf/checkpoint
fi

#########################################
# Configure Mesos Master and Frameworks
#########################################
if ismaster ; then
  # Download and install mesos-dns
  sudo mkdir -p /usr/local/mesos-dns
  sudo wget https://github.com/mesosphere/mesos-dns/releases/download/v0.2.0/mesos-dns-v0.2.0-linux-amd64.tgz
  sudo tar zxvf mesos-dns-v0.2.0-linux-amd64.tgz
  sudo mv mesos-dns-v0.2.0-linux-amd64 /usr/local/mesos-dns/mesos-dns
  RESOLVER=`cat /etc/resolv.conf | grep nameserver | tail -n 1 | awk '{print $2}'`

  echo "
{
  \"zk\": \"zk://127.0.0.1:2181/mesos\",
  \"refreshSeconds\": 1,
  \"ttl\": 0,
  \"domain\": \"mesos\",
  \"port\": 53,
  \"timeout\": 1,
  \"listener\": \"0.0.0.0\",
  \"email\": \"root.mesos-dns.mesos\",
  \"resolvers\": [\"$RESOLVER\"]
}
" > mesos-dns.json
  sudo mv mesos-dns.json /usr/local/mesos-dns/mesos-dns.json

  echo "
description \"mesos dns\"
# Start just after the System-V jobs (rc) to ensure networking and zookeeper
# are started. This is as simple as possible to ensure compatibility with
# Ubuntu, Debian, CentOS, and RHEL distros. See:
# http://upstart.ubuntu.com/cookbook/#standard-idioms
start on stopped rc RUNLEVEL=[2345]
respawn
exec /usr/local/mesos-dns/mesos-dns -config /usr/local/mesos-dns/mesos-dns.json" > mesos-dns.conf
  sudo mv mesos-dns.conf /etc/init
  sudo service mesos-dns start
fi


#########################
# Configure Mesos Agent
#########################
if isagent ; then
  # Add docker containerizer
  echo "docker,mesos" | sudo tee /etc/mesos-slave/containerizers
  # Add resources configuration
  if ismaster ; then
    echo "ports:[1-21,23-4399,4401-5049,5052-8079,8081-32000]" | sudo tee /etc/mesos-slave/resources
  else
    echo "ports:[1-21,23-5050,5052-32000]" | sudo tee /etc/mesos-slave/resources
  fi
  hostname -i | sudo tee /etc/mesos-slave/ip
  hostname | sudo tee /etc/mesos-slave/hostname

  # Add mesos-dns IP addresses at the top of resolv.conf
  RESOLV_TMP=resolv.conf.temp
  rm -f $RESOLV_TMP
  for i in `seq $MASTERCOUNT` ; do
      echo nameserver `getent hosts ${MASTERPREFIX}${i} | awk '{ print $1 }'` >> $RESOLV_TMP
  done

  cat /etc/resolv.conf >> $RESOLV_TMP
  mv $RESOLV_TMP /etc/resolv.conf
fi

##############################################
# configure init rules restart all processes
##############################################

echo "(re)starting mesos and framework processes"
if ismaster ; then
  sudo service zookeeper restart
  sudo service mesos-master start
  if [ "$MARATHONENABLED" == "true" ] ; then
    sudo service marathon start
  fi
  if [ "$CHRONOSENABLED" == "true" ] ; then
    sudo service chronos start
  fi
else
  echo manual | sudo tee /etc/init/zookeeper.override
  sudo service zookeeper stop
  echo manual | sudo tee /etc/init/mesos-master.override
  sudo service mesos-master stop
fi

if isagent ; then
  echo "starting mesos-slave"
  sudo service mesos-slave start
  echo "completed starting mesos-slave with code $?"
else
  echo manual | sudo tee /etc/init/mesos-slave.override
  sudo service mesos-slave stop
fi

echo "processes after restarting mesos"
ps ax

# Run swarm manager container on port 2376 (no auth)
if ismaster && [ "$SWARMENABLED" == "true" ] ; then
  echo "starting docker swarm:$SWARM_VERSION"
  echo "sleep to give master time to come up"
  sleep 10
  echo sudo docker run -d -e SWARM_MESOS_USER=root \
      --restart=always \
      -p 2376:2375 -p 3375:3375 swarm:$SWARM_VERSION manage \
      -c mesos-experimental \
      --cluster-opt mesos.address=0.0.0.0 \
      --cluster-opt mesos.port=3375 $zkmesosconfig
  sudo docker run -d -e SWARM_MESOS_USER=root \
      --restart=always \
      -p 2376:2375 -p 3375:3375 swarm:$SWARM_VERSION manage \
      -c mesos-experimental \
      --cluster-opt mesos.address=0.0.0.0 \
      --cluster-opt mesos.port=3375 $zkmesosconfig
  sudo docker ps
  echo "completed starting docker swarm"
fi
echo "processes at end of script"
ps ax
echo "Finished installing and configuring docker and swarm"
date
echo "completed mesos cluster configuration"

Kubernetes

上記では技術計算等で扱う大規模分散構成のようなクラスタを想定したが、例えば、同一構成の展開・管理では Kubernetes クラスタと組み合わせた Scaling も組み合わせたくなるだろう。(通常、Azure Virtual Machine で Web や AP の負荷分散をおこなう場合には Azure 標準の Load Balancer リソースが使えるが、ここに Docker が入ってきた場合には話が変わってくる。)
この場合も上記と同じ話で、compose か sh で書いて展開することになる。

なお、残念ながら Azure Quickstart Templates にこのサンプルはあがっていないが、下記の Kubernetes の Github に Azure の場合の構成方法について書かれているので、これを参考にスクリプト化などしてほしい。

[Kubernetes on Azure] Start Guide :
https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/getting-started-guides/coreos/azure/README.md

Azure Container Service (ACS)

※ 以降、2016/02/18 追記

冒頭で述べた Azure Container Service (ACS) を使うと、自身で明示的に VM を立てずに Service のクラスタを立ち上げて管理できる。Swarm、Apache Mesos、さらに Marathon などに対応しているので、上述の分散クラスタを扱う場合にもって来いなサービスだ。(むしろ、クラスタを立てずに使うようなシンプルな使い方はできない。)

現在、下記の ARM template を使ってクラスタ (サービス インスタンス) を配置 (作成) するが、内部では結果的に、Virtual Machine Scale Sets (VM Scale Sets) や Load Balancer のリソース が起動している。(利用者にとって単一のサービス インスタンスとして管理できるだけで、実際には VM などの IaaS 環境が使われているということ。ECS 同様、GCE のような Full Managed なサービスではない。)
Amazon EC2 Container Service (ECS)、Google Container Engine (GCE) 同様、今後は Auto Scale に対応しようということだろう。

Mesos による ACS (Azure Container Service) クラスタの配置
https://github.com/Azure/azure-quickstart-templates/tree/master/acs-mesos

Swarm による ACS (Azure Container Service) クラスタの配置
https://github.com/Azure/azure-quickstart-templates/tree/master/acs-swarm

クラスタを作成した後は、Mesos UI などの標準のツールで管理できるという点は相当 魅力的だ。いったん配置してしまえば、Apache Mesos、Swarm の利用者にとって説明の必要はないだろう。(ただし、プログラムから管理する場合は、ACS が提供する REST API も使用可能。)

Red Hat を Microsoft Azure (IaaS v2) で動かす

[2016/02/18 追記] Red Hat Enterprise が Azure Marketplace (Gallery) から選択可能になったので、今後はこれを使用できます ! (以下の投稿は、Red Hat の Repository から Image を持ち込んで使う方法を記載)

azure_redhat

Red Hat Enterprise が Microsoft Azure にようやく対応したが、Azure Resource Manager (ARM) ベースの仮想マシンで動かす方法に悩んだのでメモしておく。(いま動かすなら、当然、v2 で動かしたい。)

なお、下記の細かなコマンドの中身などは、概ね、「Prepare a Red Hat-based Virtual Machine for Azure」に記載されているので、ここではどのようなことするかステップややっていることを述べておく。

まず必ず最初にハマるポイントだが、現在、Azure Marketplace (Gallery) に Red Hat のイメージはない。(今後提供される予定のようだが、少なくとも 2016 年 01 月時点では。。。)
後述する Document や Channel 9 (動画) で紹介されているが、自分で image を取得して構成し、Azure 上に展開する必要がある。

下記は、Linux の Host (Client) から作業している想定で記載する。

  1. Red Hat Enterprise のイメージを取得する
    (例えば、https://access.redhat.com/ から KVM Guest Image などを取得すると良い)
  2. 上記で取得した Red Hat の Virtual Machine (image) を起動して接続 (ログイン) する。
  3. まず、構成ファイルなどを編集して Network 関連の構成をおこなう。
    詳細は「Prepare a Red Hat-based Virtual Machine for Azure」に書かれているので参考にしてほしい。
  4. 下記の手順で Azure Linux VM Agent (WALinuxAgent) のインストールをおこなう。
    1. そのために、まず Package のインストールができるよう、Red Hat Enterprise を Subscribe しておく
      (sudo subscription-manager register)
    2. EPEL Repository の取得と有効化をおこなう
    3. Azure Linux VM Agent (WALinuxAgent) をインストールする (yum コマンド)
    4. Red Hat Enterprise を UnSubscribe する
      (sudo subscription-manager unregister)
  5. インストールした Azure Linux VM Agent を使って Generalize (Azure の展開に備えた Clean-up) を実行
    (sudo waagent -force -deprovision)
  6. Virtual Machine を shutdown する
  7. 上記で作成されたマシン イメージ ( .raw .qcow2 .vmdk など) を qemu-img コマンドを使って .vhd ファイルに変換する (qemu-img コマンドの -O オプションに vpc と指定する)。
    ただし、Azure に展開する vhd の Virtual Size は 1 MB で Round されている必要があるので要注意。.qcow2 などの場合、いったん .raw に変換した後で、qemu-img resize コマンドで 1 MB 単位に Round して、そのあとで .vhd に変換する。(Hyper-V などで作ったイメージの Virtual Size は必ず Round されているが、Linux 上の VM はそうとは限らない。)
  8. Azure CLI や Azure Resource Manager (ARM) の template を使って、上記のカスタム イメージ (vhd ファイル) を Azure に配置し、ARM ベースの Virtual Machine (VM v2) を作成する。
    この具体的手順や注意点は「Azure Resource Manager の template の How-to」の「custom image の利用」に書かれているようなので参考。(上記のように作成した vhd を、この方法で展開することが可能。)
  9. さいごに、展開された Red Hat Enterprise の VM (v2 image) にログインして Subscribe
    (sudo subscription-manager register)

結論を書くと、 上記の 8 以外 (上記の 1 – 7, 9) はドキュメントや Channel9 でも紹介されている内容と同じ。要は、作った .vhd を ただ ARM Base で展開すれば良いということのようだ。

 

※ 参考情報

Document : Prepare a Red Hat-based Virtual Machine for Azure

Channel9 : Uploading a Red Hat Enterprise Linux (RHEL) 7.1 image to Microsoft Azure

 

Redis のすべての key と value を確認する

Redis に入っているすべての key と value を表示する PHP のサンプル コードを掲載。(自分の備忘録用)
下記では、ライブラリーとして Predis を使用した。

<?php
require "vendor/autoload.php";
Predis\Autoloader::register();

$r = new Predis\Client("tcp://test.redis.cache.windows.net:6379");
$r->auth("PcDPRkroG6M...");

// when using prefix
//$pre = $r->getOptions()->__get('prefix')->getPrefix();

$keys = $r->keys("*");
foreach ($keys as $key) {
//  if (substr($key, 0, strlen($pre)) == $pre) {
//    $key = substr($key, strlen($pre));
//  }
  $val = $r->get($key);
  echo 'key=' . $key . '; val=' . $val . '<br />';
}

$r->close();
echo 'list-up complete !';
?>

簡単に試したいなら、Azure Redis Cache + Visual Studio Online “Monaco” (Azure Web App) がおすすめ。
ブラウザーだけを使って (ローカル環境を汚さずに)、タダで動かせる!(上記は、実際に Azure で動かしたサンプル。Azure Redis Cache については こちら を参照。)

HTML で要素に関連した event function (click など) を確認する – IE でようやく可能に …

HTML で要素 (Element) に関連付いている click、mouseover などのイベント (event) を調べたくなるときが多いかと思うが、その方法について記載しておく。

「何をいまさら」と思うかもしれないが、Internet Explorer 11 の F12 開発者ツール (F12 Developer Tools) でようやく可能になった。正直、いままで、この機能がなかったので、別の開発者ツールや、コンソールを使った面倒な検査をおこなっていたが、IE だけでこの辺りも可能になった。

では、手順を簡単に記載しておこう。

まず当然だが、Internet Explorer 11 (IE 11) を起動し、F12 キーを押す。(F12 開発者ツールが起動する。)

つぎに、開発者ツール上部の矢印のアイコン (下図) をクリックし、ガイドが表示されるので、HTML の中から検査したい要素の箇所をクリックする。
これも、従来、可能だったことで、特に目新しくない。

select_element

ここからがポイントだ。
HTML の要素が表示されるが、右のペインに注目していただくと、「イベント」という新しいタブが存在している。これをクリックすると、下図の通り、関連付いた JavaScript の関数が表示される。(下記では、<a /> タグに関連付いた click イベントの関数が表示されている。名前の設定されていない Anonymouse の関数も、もちろん表示される。)

view_event

ここで表示されている関数 (上図の jquery.js) はクリック可能で、クリックすると、該当の関数 (上記の場合は handle) が表示される。
さらに、一般に、表示される JavaScript は minimize されているため読みづらいが、ここで「整形出力の有効化」のアイコン (下図) をクリックすると、ちゃんと JavaScript の整形化 (beautify) もおこなってくれる。VS に貼り直したり、Online JSON Viewer や Dirty Markup などの外部ツールと組み合わせる必要もない。

beautify_javascript

新しい開発者ツールは、開発者のフィードバックをちゃんと反映しているようで、かなり良い感じだ。まだ Windows 8.1 が必要だが、他でも使えるようになったら是非おすすめしたい。

2013/09/20 追記 – IE 11 単体でのダウンロードが可能になったようです!
http://windows.microsoft.com/ja-jp/internet-explorer/ie-11-release-preview