[AWS] EC2 で OpenVPN サーバを起動する

OpenVPN サーバ作る必要があったので、作業メモ

OpenVPN サーバのローンチ

MarketPlace に AMI があるので、それから作るのが簡単です。
Launch on EC2: OpenVPN Access Server
上のリンクからローンチすればセキュリティグループも作ってくれるけど、自分でセキュリティグループ作りたい場合は、インバウンドで最低限以下を許可するように設定。

Connection Method Protocol Port Range Source (IP or Group)
SSH tcp 22 Anywhere or IP Range
HTTPS tcp 443 Anywhere
tcp 943 Anywhere
udp 1194 Anywhere

起動したら EIP 割り当てておけば、後々便利。

しばらくすると EC2 起動してくるので、ssh 接続してイニシャルセッティングする。

$ ssh -i ~/.ssh/openvpn.pem openvpnas@xxx.xxx.xxx.xxx
Welcome to OpenVPN Access Server Appliance 2.1.4b

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

user-data not available: HTTP Error 404: Not Found: util/ec2:12,util/ec2:7,python2.7/urllib2:154,python2.7/urllib2:437,python2.7/urllib2:550,python2.7/urllib2:475,python2.7/urllib2:409,python2.7/urllib2:558 (urllib2.HTTPError)

          OpenVPN Access Server
          Initial Configuration Tool
------------------------------------------------------
OpenVPN Access Server End User License Agreement (OpenVPN-AS EULA)
 ()

Please enter 'yes' to indicate your agreement [no]: yes

Once you provide a few initial configuration settings,
OpenVPN Access Server can be configured by accessing
its Admin Web UI using your Web browser.

Will this be the primary Access Server node?
(enter 'no' to configure as a backup or standby node)
> Press ENTER for default [yes]: yes

Please specify the network interface and IP address to be
used by the Admin Web UI:
(1) all interfaces: 0.0.0.0
(2) eth0: 192.168.0.1
Please enter the option number from the list above (1-2).
> Press Enter for default [2]: 2

Please specify the port number for the Admin Web UI.
> Press ENTER for default [943]: 943

Please specify the TCP port number for the OpenVPN Daemon
> Press ENTER for default [443]: 443

Should client traffic be routed by default through the VPN?
> Press ENTER for default [no]: no

Should client DNS traffic be routed by default through the VPN?
> Press ENTER for default [no]: yes

Use local authentication via internal DB?
> Press ENTER for default [yes]: yes

Private subnets detected: ['19.168.0.0/16']

Should private subnets be accessible to clients by default?
> Press ENTER for EC2 default [yes]: yes

To initially login to the Admin Web UI, you must use a
username and password that successfully authenticates you
with the host UNIX system (you can later modify the settings
so that RADIUS or LDAP is used for authentication instead).

You can login to the Admin Web UI as "openvpn" or specify
a different user account to use for this purpose.

Do you wish to login to the Admin UI as "openvpn"?
> Press ENTER for default [yes]: yes 
(admin ユーザ名変えたい時は、ここで no 答えて、次の質問で変えたい名前を入力)

Type the password for the 'openvpn' account:
Confirm the password for the 'openvpn' account:

> Please specify your OpenVPN-AS license key (or leave blank to specify later): 


Initializing OpenVPN...
Adding new user login...
useradd -s /sbin/nologin "openvpn"
Writing as configuration file...
Perform sa init...
Wiping any previous userdb...
Creating default profile...
Modifying default profile...
Adding new user to userdb...
Modifying new user as superuser in userdb...
Getting hostname...
Hostname: xxx.xxx.xxx.xxx
Preparing web certificates...
Getting web user account...
Adding web group account...
Adding web group...
Adjusting license directory ownership...
Initializing confdb...
Generating init scripts...
Generating PAM config...
Generating init scripts auto command...
Starting openvpnas...

NOTE: Your system clock must be correct for OpenVPN Access Server
to perform correctly.  Please ensure that your time and date
are correct on this system.

Initial Configuration Complete!

You can now continue configuring OpenVPN Access Server by
directing your Web browser to this URL:

https://xxx.xxx.xxx.xxx:943/admin
Login as "openvpn" with the same password used to authenticate
to this UNIX host.

During normal operation, OpenVPN AS can be accessed via these URLs:
Admin  UI: https://xxx.xxx.xxx.xxx:943/admin
Client UI: https://xxx.xxx.xxx.xxx:943/

See the Release Notes for this release at:
   http://www.openvpn.net/access-server/rn/openvpn_as_2_1_4b.html

openvpnas@openvpnas2:~$ sudo apt-get update && sudo apt-get upgrade

これで https://{public IP Address}:943/admin にアクセスすることで、ローンチした OpenVPN サーバの管理パネルに接続できます。
(自己署名証明書による HTTPS 接続なので、セキュリティ例外追加しないと接続できないので注意)

OpenVPN サーバで接続用のユーザ作成

https://{public IP Address}:943/admin から管理パネルにログインして [User Management] の [User Permitions] でユーザを追加。
[Allow Auto-login] にチェックしておくと、ユーザの設定が簡略化されるのでオススメ。

他の設定とか諸々はドキュメント参照。

OpenVPN クライアントのインストールと設定

Tunnelblick あたりをインストールしておけばいいです。
上の設定で VPN 接続用のユーザを作成してあるのであれば https://{public IP Address}:943/ にログイン。
Screen Shot 2017-02-22 at 12.54.03.png

すると、以下のような画面が表示されるので [Yourself (autologin profile)] ってリンクから ovpn ファイルをダウンロード。
Screen Shot 2017-02-22 at 12.54.13.png

ダウンロードした ovpn ファイルをダブルクリックすると Tunnelblick が起動して、よしなに設定してくれます。

iPhone とかでも VPN 接続したい場合は iPhoneやiPad (iOS) でOpenVPNを使ってみよう! を参考にしてみましょう。

MarketPlace にある AMI 使うと簡単にできて便利すなぁ。

参考 URL

続きを読む

DynamoDBのupdateItemのValidationException解消方法

AWSマネジメントコンソールでDynamoDBのテーブル作成する場合

スクリーンショット 2017-02-21 18.20.12.png

idはプライマリキーパーティションキーになっています。下記のソースをupdateItemすると

let updateParam = {
                        "TableName" : "test",
                        "Key" : {
                            "id" : {"S" : "12345"}
                        },
                        "UpdateExpression" : "SET #name =:name",
                        "ExpressionAttributeNames" : {
                            "#name" : "name"
                        },
                        "ExpressionAttributeValues" : {
                            ":name" : {"S" : "Jane"}
                        }
                    };
dynamodb.updateItem(updateParam, function(error, data) {
        if(error) {
            logger.error('error=' + util.inspect(error, false, null));
            if (error.retryable) {
                 //retry 
                 return;
            } else {
                //todo
                return;
            }
        } else {
            logger.info('update succeed');
        }
    });

ValidationException

下記のvalidationエラーが出ます。

ValidationException: The provided key element does not match the schema

原因

AWSのドキュメントをみたら

You can query only tables whose primary key is of hash-and-range type

マネジメントコンソールから作成されたテーブルのプライマリキーはシンプル (パーティションキー) または複合 (パーティションキーとソートキー) になっています。UpdateItemはサポートされたプライマリキーはハッシュかハッシュ&レンジです。

解決方法

コマンドでテーブル作成、プライマリキーのtypeを指定することです。

aws dynamodb create-table --table-name test --attribute-definitions '[{"AttributeName": "id", "AttributeType": "S"}]' --key-schema '[{"AttributeName": "id", "KeyType": "HASH"}]' --provisioned-throughput '{"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}'

もう一回上記のnodeを実行したら、正常に更新できました。

[2017-02-21 16:00:06.062] [INFO] [default] - update succeed
[2017-02-21 16:00:06.063] [INFO] [default] - update succeed
[2017-02-21 16:00:06.063] [INFO] [default] - update succeed
[2017-02-21 16:00:06.065] [INFO] [default] - update succeed
[2017-02-21 16:00:06.065] [INFO] [default] - update succeed
[2017-02-21 16:00:06.083] [INFO] [default] - update succeed
[2017-02-21 16:00:06.084] [INFO] [default] - update succeed
[2017-02-21 16:00:06.085] [INFO] [default] - update succeed
[2017-02-21 16:00:06.087] [INFO] [default] - update succeed

続きを読む

AWS IoT Device Shadowを試すためのpython mock

はじめに

AWS IoTを利用する1つの理由として、Thing shadowによるThing/Deviceコントロールが出来ることがあるかと思います。
一方で概要は理解できたものの、”Thing”がないから動作確認ができないとお思いの方も多いかと、、
こちらについては実はDeviceSDKを使えばLinux上で確認が可能です。
ここでは、EC2を仮想デバイスとして、Thing shadowの動作確認をしてみようと思います。

準備

AWS IoT

Thingの作成

registryを選択し、thingsを選択。Thingペインが表示されたら、画面上部のcreateを押す。
スクリーンショット 2017-02-07 23.08.11.png

Thingの作成ですが、任意の名前を設定し、create thingを押す。
ここではthinnameを、shadow-testとしてます。

Thing作成後の画面で、Certificateを選択。表示された画面のcreate certificateを押す。
スクリーンショット 2017-02-07 23.11.03.png

作成された証明書3つをダウンロードしておいてください。(cert.pem/public.key/private.key)
また画面下部に表示された Activeを押し、証明書を有効化します。

Endpointの確認

AWS IoTコンソール、画面左下にあるSettingsを押し、表示された画面にエンドポイント確認、textなどにコピーしておいてください。
endpointはregionごとに一つとなります。
{random}.iot.{region}.amazon.com
の形で表示されます。

EC2

EC2の起動

EC2でamazon linuxを起動してください。t2.microで十分です。
EC2の起動方法がわからない方、こちらをご参考に。
HDDサイズもデフォルトで十分です。SSHでログインするためのGlobal IPの設定をお忘れなく。

EC2へIoT DeviceSDKのinstall

mockはpythonSDKで作っているのでPythonSDKをインストールします。
EC2のコンソールから以下のコマンドを発行

pip install AWSIoTPythonSDK

dummyプログラム(mock)の設置

必要なものとして

  • プログラム本体
  • setup.json
  • 証明書 3つ (rootCA/private/cert)

を配置します
本投稿では、/tmpの下で作業することを想定して記述します。

mkdir /tmp/dummy-shadow
cd /tmp/dummy-shadow
mkdir certs
cd certs

証明書の設定

rootCAの取得 (certsの下に配置します)
ベリサインのこちらから取得

curl https://www.symantec.com/content/en/us/enterprise/veisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem -o /tmp/root.pem

またこのcertsディレクトリに先程AWS IoTで作成したprivate/certの証明書を配置します。
scp/viでのコピペでも構いません。ファイル名は
cert => cert.pem
private => private.pem
としてください。以下の結果になるようにしてください。

ls -1 /tmp/certs
cert.pem
private.pem
root.pem

dummy(mock)の設置

/tmp/dummy-shadowで以下のファイルを配置します。
YOUR_AWSIOT_DOMAINは各自の環境に併せて、設定して下さい。
ドメインの確認は、AWS IoTのコンソール Settings => Custom endpointを参照して下さい。

setup.json
{
   "AWSIoT": {
        "ENDPOINT":"YOUR_AWSIOT_DOMAIN",
        "CERT_PATH":"./certs/",
        "KEYS":["cert.pem", "public.pem", "root.pem"]
   },
   "DEVICE":{
        "NAME":"shadow-test",
   }
}

以下にdummyプログラム

dummy-shadow.py
import os
import sys
import json
import time
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient


CONFIG_FILE = './setup.json'

#アプリ起動時の状態を固定で定義(shadowと同期する変数)
SIGNAL    = "green"
WAIT_TIME = 10

#コールバック関数からshadowを読み出すのでglobalで定義
shadow         = None
shadow_hundler = None

##########################################################
# setup.jsonから設定を読み出す
##########################################################
def readConfig():
    print 'start readConfig func'

    try:
        # read config file
        f = open(CONFIG_FILE, "r")
        jsonData = json.load(f)
        f.close()

        list = {}
        list["ENDPOINT"]    = jsonData["AWSIoT"]["ENDPOINT"]
        list["CERT_PATH"]   = jsonData["AWSIoT"]["CERT_PATH"]
        list["DEVICE_NAME"] = jsonData["DEVICE"]["NAME"]

        return list

    except Exception as e:
        print 'Config load error'
        print e.message
        sys.exit()

##########################################################
# Shadow update命令の発行
##########################################################
def updateThing(report):
    try: 
        report_json = '{"state":{"reported":'+ report + '}}'
        print "send currnet status to cloud-shadow"
        print report_json
        shadow_hundler.shadowUpdate(report_json, None, 5)

        return

    except Exception as e:
        print e.message
        sys.exit()

##########################################################
# shadowRegisterDeltaCallbackからコールバック型で呼び出される
#
##########################################################
def getDelta(payload, responseStatus, token):
    try:
        print '======get Delta======'
        dict_delta = json.loads(payload)
        print dict_delta
        state = dict_delta["state"]

        if state.has_key("wait_time"):
            delta = int(state["wait_time"])
            global WAIT_TIME
            WAIT_TIME = delta
            print "wait time change :%s" % WAIT_TIME
        if state.has_key('signal'):
            global SIGNAL
            SIGNAL = state['signal']
            print "SIGNAL change :%s" % SIGNAL

        report = json.dumps(dict_delta["state"])
        updateThing(report)

        return

    except Exception as e:
        print "Error on Delta function"
        print e.message
        raise

################################################
# Shadow接続の手続き関数
################################################
def initShadow(Config):
    ##--need device cert / private / rootCA--
    # rootCA: get from symantec
    ROOT_KEY    = Config['CERT_PATH'] + 'root.pem'
    CERT_KEY    = Config['CERT_PATH'] + 'cert.pem'
    PRIVATE_KEY = Config['CERT_PATH'] + 'private.pem'

    try:
        # init shadow connect procedure
        global shadow
        shadow = AWSIoTMQTTShadowClient(Config["DEVICE_NAME"])
        shadow.configureEndpoint(Config["ENDPOINT"], 8883)    # Setting URL-ENDPOINT & Port
        shadow.configureCredentials(ROOT_KEY, PRIVATE_KEY, CERT_KEY ) # Cert file setting
        shadow.configureConnectDisconnectTimeout(10)# CONNACK wait time (sec)
        shadow.configureMQTTOperationTimeout(5)     # QoS1 publish (sec)
        print 'start connct shadow'
        shadow.connect()
        print 'shadow connect'

        return

    except Exception as e:
        print 'Error on Init Shadow'
        raise

####
if __name__ == '__main__':
    Config = readConfig()

    try:
        initShadow(Config)
        print 'satrt subscribe shadow'
        shadow_hundler = shadow.createShadowHandlerWithName(Config['DEVICE_NAME'], True)
        shadow_hundler.shadowRegisterDeltaCallback(getDelta)
        default_state = '{"wait_time":' + str(WAIT_TIME) + ', "signal":"green"}'
        updateThing(default_state)

        while True:
            time.sleep(WAIT_TIME)
            print 'Currnet WAIT_TIME=%s' % str(WAIT_TIME)
            pass

    except KeyboardInterrupt:
         print 'Keyboard Interrupt'
         sys.exit()

    except Exception as e:
        print e.message
        sys.exit()

実行方法

python PROGRAM.py &

でバックグラウンド起動します。

shadow update

コンソールもしくは、CLIでshadow updateをします。
Resistor => Thing => [Thing名] => Shadowを選択します。

以下のようにdesiredセクションを追加し、wait_time:30 , signal:”green”で登録してみます。
するとdeltaとして、 wait_time:30 つまり差分のみがdeltaとしてthingにレポートされます。

スクリーンショット 2017-02-19 22.20.44.png

プログラム側のコンソールを見ると、deltaを受けソレが表示さているはずです。
で、コードの方をみてもらうとわかりますが、変数のwait_timeを変更し、[state]を送りかえしています。
deltaのstateには、結果整合としてあるべき状態が書いてあるので、正しく状態遷移が出来たらこれをreportするだけでいちいちJSONを作成する必要はありません。
上記の通り、正しく状態遷移出来ない状態で report するとズレますので要注意。

このレポートが送られるとdeltaがなくなり、desired/reportedが同じ値になっているはずです。

大まかなシーケンス

大まかなシーケンスを以下に示します。

スクリーンショット 2017-02-19 22.38.16.png

プログラム起動時に report statusとして ハードコーディングされている
SIGNAL = “green”
WAIT_TIME = 10
を通知します。何度か、shadowの状態を変えた場合はプログラム起動直後に上記初期パラメータを通知し、即deltaを受ける事になります。

免責

本投稿は、個人の意見で、所属する企業や団体は関係ありません。
また掲載しているsampleプログラムの動作に関しても保障いたしませんので、参考程度にしてください。

続きを読む

Tensorflow 1.0でGPU利用 with AWS

そろそろ春の足音がしだして、相変わらずの何もできてないっぷりに愕然とする今日このごろです。

さすがに何もしていないのはまずいので、以前触った TensorFlow を再び触り始めています。
相変わらずのGoogleクオリティで、APIが色々と変わっているような気がしますが、いろいろ忘れているので調度良いかなと。

何か一つ作ってみようと、作ってみている最中です(いずれ記事に・・・)が、DeepLearningとかコモディティ化してきていると言われているとはいえ、理解しながら作ろうとすると、もれなく数式とコンニチワするので、文字通りに頭の痛い日々です。でも楽しい。

Amazon LinuxでGPU利用する

今作ってみているものは、学習をCPUだけでやると時間がかかってしょうがない+学習用データが大きすぎて洒落にならないため、GPUで実施したくなります。
GPUは一応部屋のPCについているとはいえ、CUDAのインストールトラウマもあって、流石に普段使いのPCにインストールするのが面倒です。

ちなみに現時点で、CPUだけで学習すると1ステップ辺り、1データで2分とかかかります。20000ステップとか考えたくもないですね。電気代的な意味で。

AzureでもGCPでもいいけれども、使い慣れてるAWSのGPUインスタンスを使ってみます(使ったことがなかった)。
(というか、個人とかの場合クラウドを使わないと現実的な時間で終わんないような)

まともに利用するとかなりの金額になりそうだったので、SpotFleetで用意しました。Spot Fleetになってから初めて利用しますが、ちゃんとドキュメントを読まないと、capacityの意味が?ってなりますね。でも6割り引きくらいで利用できるのはあまりに魅力的・・・。

さて、CUDAはつい最近知識をアップデートしましたが、かなりインストールが楽になっていてびっくりです。
そのなかでも楽をするために、Ubuntu16.04のAMIを利用することにしました。CUDA/cuDNNのライブラリをnvidiaのページからダウンロードします。cuDNNはアカウントが必要なので、作る必要があります。

CUDAライブラリは、runfileにしておくと楽です、が、今回はdebにしてしまったので、次のようになります。

$ sudo dpkg -i <ダウンロードしたパッケージ名>
$ sudo apt-get update
$ sudo apt-get install cuda

cudnnライブラリは、cudaをインストールした先に展開します。debでインストールした場合は /usr/local/lib/cuda に入るので、その下になるように入れましょう。

$ tar xf cudnn-*.tgz
$ sudo cp cuda/include/* /usr/local/cuda/include
$ sudo cp cuda/lib64/* /usr/local/cuda/lib64
Tensorflowが1.0になりましたが、GPU版の要求CUDAが8.0(最新)になり、同時に要求されるnvidia-driverのバージョンが375系になるという、非常に悲しい出来事がありました。過去を振り返らないnvidiaとGoogleらしい決断とでもいうのでしょうか。
そして悲劇として、Tokyoリージョンで利用できるg2インスタンスだと、K520というGPUを積んでいるのですが、これがで、367.*系のドライバでしか動かないのです・・・。
そのため、tensorflowのバージョンを下げるか、USリージョンでp2インスタンスを利用する必要があります。
今回は涙をのんでUSリージョンにP2を立てました。Tokyoにも来てくれることを願います。

そして、.bash_profileLD_LIBRARY_PATH を設定します。これを忘れるとライブラリの読み込みでエラーになって( ゚д゚)ハッ!てなります。

if [[ -z $LD_LIBRARY_PATH ]]; then
    export LD_LIBRARY_PATH=/usr/local/cuda/lib64
else
    export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
fi

ちゃんと動作しているかどうかは、非常に簡単なTensorflowプログラムを動かしてみるのが一番手っ取り早いです。

import tensorflow as tf
sess = tf.session()
hello = sess.run(tf.constant('Hello, world!'))
print(hello)

うまく動作すると、次のようなログが出ます。

I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcublas.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcufft.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcurand.so.8.0 locally
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE3 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:910] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_device.cc:885] Found device 0 with properties:
name: Tesla K80
major: 3 minor: 7 memoryClockRate (GHz) 0.8235
pciBusID 0000:00:1e.0
Total memory: 11.17GiB
Free memory: 11.11GiB
I tensorflow/core/common_runtime/gpu/gpu_device.cc:906] DMA: 0
I tensorflow/core/common_runtime/gpu/gpu_device.cc:916] 0:   Y
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0

メモリ11GiBて・・・。さすがサーバー用のGPUは驚異的です。

Tensorflowのプロファイルを取りたい

GPUを利用していても、実際に早くなったのかどうか、は計測してみないとわからないものです。まぁ大体は速くなるんですけど、想定より遅いとかもありますし。

この場合、gperfとかそういったもので取得することも出来るようですが、軟弱な我々としては、やはりChromeとかFirefoxで慣れたタイムライン表示とかがいいです。可視化最高。TensorflowはGoogle主導で開発しているためかどうかはわからないけれど、これを行うための機能がすでにあります。

既存のTensorFlowプログラムに、以下のようなコードを追記します。

from tensorflow.python.client import timeline

with tf.Session() as sess:
    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
    run_metadata = tf.RunMetadata()

    sess.run(
        training_op,
        feed_dict=feed,
        run_metadata=run_metadata,
        options=run_options)

    # write train
    tl = timeline.Timeline(run_metadata.step_stats)
    ctf = tl.generate_chrome_trace_format()
    with open('timeline.json', 'w') as f:
        f.write(ctf)

こうやると、timeline.jsonというのがローカルに出来ます。これを、Chromeのアドレスバーで chrome://tracing といれて出るページで読み込ませてやると、見慣れた?タイムライン表示が行えます。内容的にはTensorflowのoperation単位になってるようです。

ただし、事前に LD_LIBRARY_PATH/usr/local/cuda-8.0/extras/CUPTI/lib64 を追加しておく必要があります。この中にあるlibcuptiが読み込めないとエラーになるためです。

GPUの活用は正義(多分)

最初はg2インスタンスでやろうと思っていたのですが、まさかの使えない問題でp2インスタンスを利用することになるとは思いませんでした・・・。USリージョンだとSSHがまさしく「あー海越えてるなー」って速度になるんでストレスフルですね!

とりあえず、学習とかモデルとか、その辺りを勉強しながら進めていく、というのはなんだか久しぶりで、かなり新鮮です。データセットを集める手法の確立とかも大事ですが、そこはまぁ頑張ればいいので・・・。

新しいものをすぐ使いたくなるような人(主に自分)の助けになれば幸いです。

続きを読む

[JAWS-UG CLI] IoT #16 ダミーデバイスでShadowを操作

前提条件

MacOS X El Capitanでは動作しません。

  • iot-dataコマンドは、OpenSSL 1.0.1以上が必要となるため、この手順はEC2インスタンス上などで実施してください。
変数の設定(EC2)
export AWS_ACCESS_KEY_ID='アクセスキーID'
export AWS_SECRET_ACCESS_KEY='シークレットアクセスキーID'

IoTへの権限

AWS IoTに対してフル権限があること。

AWS CLIのバージョン

以下のバージョンで動作確認済

  • AWS CLI 1.11.47
コマンド
aws --version
結果(例)
aws-cli/1.11.49 Python/2.7.10 Darwin/15.6.0 botocore/1.5.12

バージョンが古い場合は最新版に更新しましょう。

コマンド
sudo -H pip install -U awscli

ダミーデバイス(EC2)の構築済み

http://qiita.com/tcsh/items/8ec8419b9170f2cc36f0

0. 準備

0.1. リージョンの決定

構築するリージョンを決めます。 (カレントユーザが利用するカレントリージ
ョンも切り変わります。)

コマンド(東京リージョンの場合)
export AWS_DEFAULT_REGION='ap-northeast-1'

0.2. プロファイルの確認

プロファイルが想定のものになっていることを確認します。

コマンド
aws configure list
結果(例)
            Name                    Value             Type    Location
            ----                    -----             ----    --------
         profile         administrator-prjz-mbp13        env    AWS_DEFAULT_PROFILE
      access_key     ****************XXXX shared-credentials-file
      secret_key     ****************XXXX shared-credentials-file
          region                         ap-northeast-1  env    AWS_DEFAULT_REGION

AssumeRoleを利用している場合はprofileが ”と表示されます。 そ
れ以外のときにprofileが ” と表示される場合は、以下を実行して
ください。

変数の設定:

     export AWS_DEFAULT_PROFILE=<IAMユーザ名>

0.3. モノ名の指定

変数の設定
IOT_THING_NAME='handson-thing-20170220'

1. 事前作業

2. Shadowの中でdummy内の変数を制御

2.1. Shadowの確認

変数の設定
FILE_OUTPUT='result-dummy-before.json'
コマンド
aws iot-data get-thing-shadow \
  --thing-name ${IOT_THING_NAME} \
  ${FILE_OUTPUT} \
  && cat ${FILE_OUTPUT}
結果(例)
An error occurred (ResourceNotFoundException) when calling the GetThingShadow operation: No shadow exists with name: 'handson-thing-20170220'

2.2. Shadow作成

変数の設定
FILE_OUTPUT='result-dummy-01.json'
IOT_DATA_PAYLOAD='{"state":{"reported":{"wait_time":20, "signal":"green"}}}'
コマンド
echo ${IOT_DATA_PAYLOAD} | jsonlint
結果
{
  "state": {
    "reported": {
      "wait_time": 20,
      "signal": "green"
    }
  }
}
変数の確認
cat << ETX

  IOT_THING_NAME:   ${IOT_THING_NAME}
  IOT_DATA_PAYLOAD: ${IOT_DATA_PAYLOAD}
  FILE_OUTPUT:      ${FILE_OUTPUT}

ETX
コマンド
aws iot-data update-thing-shadow \
  --thing-name ${IOT_THING_NAME} \
  --payload "${IOT_DATA_PAYLOAD}" \
  ${FILE_OUTPUT} \
  && cat ${FILE_OUTPUT}
結果(例)
{"state":{"reported":{"wait_time":20,"signal":"green"}},"metadata":{"reported":{"wait_time":{"timestamp":1487505988},"signal":{"timestamp":1487505988}}},"version":1,"timestamp":1487505988}

2.3. shadow update

変数の設定
FILE_OUTPUT='result-shadow-01.json'
IOT_DATA_PAYLOAD='{"state":{"desired":{"wait_time":20, "signal":"green"}}}'
コマンド
echo ${IOT_DATA_PAYLOAD} | jsonlint
結果
{
  "state": {
    "desired": {
      "wait_time": 20,
      "signal": "green"
    }
  }
}
変数の確認
cat << ETX

  IOT_THING_NAME:   ${IOT_THING_NAME}
  IOT_DATA_PAYLOAD: ${IOT_DATA_PAYLOAD}
  FILE_OUTPUT:      ${FILE_OUTPUT}

ETX
コマンド
aws iot-data update-thing-shadow \
  --thing-name ${IOT_THING_NAME} \
  --payload "${IOT_DATA_PAYLOAD}" \
  ${FILE_OUTPUT} \
  && cat ${FILE_OUTPUT}
結果(例)
{"state":{"desired":{"wait_time":20,"signal":"green"}},"metadata":{"desired":{"wait_time":{"timestamp":1487506160},"signal":{"timestamp":1487506160}}},"version":2,"timestamp":1487506160}

2.4. shadowの確認

変数の設定
FILE_OUTPUT='result-shadow-after.json'
コマンド
aws iot-data get-thing-shadow \
  --thing-name ${IOT_THING_NAME} \
  ${FILE_OUTPUT} \
  && cat ${FILE_OUTPUT}
結果(例)
{"state":{"desired":{"wait_time":20,"signal":"green"},"reported":{"wait_time":20,"signal":"green"}},"metadata":{"desired":{"wait_time":{"timestamp":1487506160},"signal":{"timestamp":1487506160}},"reported":{"wait_time":{"timestamp":1487505988},"signal":{"timestamp":1487505988}}},"version":2,"timestamp":1487506296}

2.5. ダミーデバイス (EC2)

コマンド(EC2)
cd ~/shadow/ \
  && python dummy_shadow.py
結果
start readConfig func
start connct shadow
shadow connect
satrt subscribe shadow
send currnet status to cloud-shadow
{"state":{"reported":{"wait_time":10, "signal":"green"}}}

ダミーデバイスのプログラム停止 (EC2)

Ctrl+Cでプログラムを停止します。

3. Shadowの変数でプログラムを終了させる(電源管理イメージ)

3.1. Thing名の変更

ここでは、Thing名を現時点で存在しない「handson-thing-20170220_power」に変更します。

変数の設定
IOT_THING_NAME="${IOT_THING_NAME}_power"

3.2. Shadow更新

変数の設定
FILE_OUTPUT='result-multi-01.json'
IOT_DATA_PAYLOAD='{"state":{"desired":{"power":"on"}}}'
コマンド
echo ${IOT_DATA_PAYLOAD} | jsonlint
結果
{
  "state": {
    "desired": {
      "power": "on"
    }
  }
}
変数の確認
cat << ETX

  IOT_THING_NAME:   ${IOT_THING_NAME}
  IOT_DATA_PAYLOAD: ${IOT_DATA_PAYLOAD}
  FILE_OUTPUT:      ${FILE_OUTPUT}

ETX
コマンド
aws iot-data update-thing-shadow \
  --thing-name ${IOT_THING_NAME} \
  --payload "${IOT_DATA_PAYLOAD}" \
  ${FILE_OUTPUT} \
  && cat ${FILE_OUTPUT}
結果(例)
{"state":{"desired":{"power":"on"}},"metadata":{"desired":{"power":{"timestamp":1487506888}}},"version":3,"timestamp":1487506888}

3.3. shadowの確認

変数の設定
FILE_OUTPUT='result-shadow-after.json'
コマンド
aws iot-data get-thing-shadow \
  --thing-name ${IOT_THING_NAME} \
  ${FILE_OUTPUT} \
  && cat ${FILE_OUTPUT}
結果(例)
{"state":{"desired":{"wait_time":20,"signal":"green","power":"on"},"reported":{"wait_time":20,"signal":"green"},"delta":{"power":"on"}},"metadata":{"desired":{"wait_time":{"timestamp":1487506160},"signal":{"timestamp":1487506160},"power":{"timestamp":1487506888}},"reported":{"wait_time":{"timestamp":1487505988},"signal":{"timestamp":1487505988}}},"version":3,"timestamp":1487506913}

3.4. ダミーデバイス (EC2)

コマンド(EC2)
cd ~/shadow/ \
  && python multi_shadow.py
結果
start readConfig func
satrt subscribe power-shadow
start connct shadow tmp01_power
Send power on to shadow name
satrt subscribe config-shadow
start connct shadow tmp01
send currnet status to cloud-shadow
{"state":{"reported":{"wait_time":10, "signal":"green"}}}

ダミーデバイスのプログラム停止 (EC2)

Ctrl+Cでプログラムを停止します。

4. 事後作業

完了

続きを読む

[JAWS-UG CLI] EC2:#2 インスタンスの作成 (Public + UserData)

前提条件

EC2への権限

EC2に対してフル権限があること。

AWS CLIのバージョン

以下のバージョンで動作確認済

  • AWS CLI 1.11.14
コマンド
aws --version

結果(例):

  aws-cli/1.11.19 Python/2.7.10 Darwin/15.6.0 botocore/1.4.76

バージョンが古い場合は最新版に更新しましょう。

コマンド
sudo -H pip install -U awscli

AWSアカウントの属性

AWSアカウントがEC2-Classicに対応していないこと。

コマンド
AWS_SUPPORT_PLATFORMS=$( 
         aws ec2 describe-account-attributes 
           --query 'AccountAttributes[?AttributeName == `supported-platforms`].AttributeValues[].AttributeValue' 
           --output text 
) && echo ${AWS_SUPPORT_PLATFORMS}

結果:

  VPC

注釈: ‘VPC’の他に’EC2’が表示される場合、別のアカウントを作成もしくは
利用し てください。

0. 準備

0.1. リージョンの決定

変数の設定
export AWS_DEFAULT_REGION='ap-northeast-1'

0.2. 変数の確認:

プロファイルが想定のものになっていることを確認します。

変数の確認
aws configure list

結果(例):

        Name                    Value             Type    Location
        ----                    -----             ----    --------
     profile       ec2full-prjZ-mbp13        env    AWS_DEFAULT_PROFILE
  access_key     ****************XXXX shared-credentials-file
  secret_key     ****************XXXX shared-credentials-file
      region        ap-northeast-1        env    AWS_DEFAULT_REGION

0.3. VPCの指定

既存のVPCに割り当てられているCIDRブロックを確認します。

コマンド
aws ec2 describe-vpcs 
        --query 'Vpcs[].CidrBlock'

結果(例):

  [
    "172.31.0.0/16",
    "10.192.0.0/16"
  ]

ここでは、10.192.0.0/16を範囲とするVPCを選択します。

変数の設定
VPC_CIDR='10.192.0.0/16'

VPC IDを取得します。

コマンド
VPC_ID=$( 
        aws ec2 describe-vpcs 
          --filters Name=cidr,Values=${VPC_CIDR} 
          --query 'Vpcs[].VpcId' 
          --output text 
) 
        && echo ${VPC_ID}

結果(例):

  vpc-xxxxxxxx

0.4. サブネットの指定

変数の設定
VPC_SUBNET_CIDR='10.192.0.0/24'
コマンド
VPC_SUBNET_ID=$( 
        aws ec2 describe-subnets 
          --filters Name=cidrBlock,Values=${VPC_SUBNET_CIDR} 
          --query 'Subnets[].SubnetId' 
          --output text 
) 
        && echo ${VPC_SUBNET_ID}

結果(例):

  subnet-xxxxxxxx

0.5. UserDataの指定

変数の設定
FILE_EC2_USERDATA='userdata.bash'

1. 事前作業

1.1. プライベートアドレスの決定

選択したサブネットのアドレス範囲内で、起動するインスタンスのプライベー
トIPアドレスを指定します。

変数の設定
EC2_PRIVATE_ADDR='10.192.0.8'

1.2. セキュリティグループの決定

セキュリティグループの一覧を確認します。

コマンド
aws ec2 describe-security-groups 
        --query "SecurityGroups[?VpcId == ` ${VPC_ID}`].GroupName"

結果(例):

  [
    "default",
    "ec2-ssh-global-inbound"
  ]

利用するセキュリティグループ名を指定します。

変数の設定
VPC_SG_NAME='ec2-ssh-global-inbound'
コマンド
VPC_SG_ID=$( 
        aws ec2 describe-security-groups 
          --filter Name=group-name,Values=${VPC_SG_NAME} 
          --query "SecurityGroups[?VpcId == ` ${VPC_ID}`].GroupId" 
          --output text 
) 
        && echo ${VPC_SG_ID}

結果(例):

  sg-xxxxxxxx

セキュリティグループを配列に入れておきます。

変数の設定
ARRAY_VPC_SG_ID="${VPC_SG_ID} ${ARRAY_VPC_SG_ID}" 
        && echo ${ARRAY_VPC_SG_ID}

1.3. キーペアの指定

まず、キーペアの一覧を確認します。

コマンド
aws ec2 describe-key-pairs 
        --query 'KeyPairs[].KeyName'

結果(例):

  [
      "<キーペアー名>"
  ]

利用するキーペア名を指定します。

変数の設定
EC2_KEY_PAIR_NAME='<キーペアー名>'

利用するキーペアの秘密鍵ファイルを指定します。

変数の設定
FILE_SSH_KEY="${HOME}/.ssh/<キーペア秘密鍵のファイル名>" 
        && echo ${FILE_SSH_KEY}

秘密鍵が存在することを確認しましょう。

コマンド
ls ${FILE_SSH_KEY}

1.4. イメージIDの決定

AMIを選択します。

変数の設定
AMZLINUX_VERSION='2016.03.3'
EC2_IMAGE_NAME="amzn-ami-hvm-${AMZLINUX_VERSION}.x86_64-gp2"
コマンド
EC2_IMAGE_ID=$( 
        aws ec2 describe-images 
          --filters Name=name,Values="${EC2_IMAGE_NAME}" 
          --query 'Images[].ImageId' --output text 
) 
        && echo ${EC2_IMAGE_ID}

結果(例):

  ami-XXXXXXXX

1.5. インスタンスタイプの決定

変数の設定
EC2_INSTANCE_TYPE='t2.micro'

1.6. 稼動インスタンスを確認

同一リージョンでインスタンスが起動していないことを確認します。

コマンド
EC2_INSTANCE_STATUS='running'
コマンド
aws ec2 describe-instances 
        --filters Name=instance-state-name,Values=${EC2_INSTANCE_STATUS}

結果:

  {
      "Reservations": []
  }

2. インスタンス起動

2.1. インスタンス起動

変数の確認
cat << ETX

        EC2_IMAGE_ID:              ${EC2_IMAGE_ID}
        EC2_INSTANCE_TYPE:         ${EC2_INSTANCE_TYPE}
        EC2_KEY_PAIR_NAME:         ${EC2_KEY_PAIR_NAME}
        EC2_PRIVATE_ADDR:          ${EC2_PRIVATE_ADDR}
        ARRAY_VPC_SG_ID:           ${ARRAY_VPC_SG_ID}
        VPC_SUBNET_ID              ${VPC_SUBNET_ID}
        FILE_EC2_USERDATA:         ${FILE_EC2_USERDATA}

ETX
コマンド
aws ec2 run-instances 
        --image-id ${EC2_IMAGE_ID} 
        --instance-type ${EC2_INSTANCE_TYPE} 
        --security-group-ids ${ARRAY_VPC_SG_ID} 
        --key-name ${EC2_KEY_PAIR_NAME} 
        --subnet-id ${VPC_SUBNET_ID} 
        --private-ip-address ${EC2_PRIVATE_ADDR} 
        --associate-public-ip-address  
        --user-data file://${FILE_EC2_USERDATA}

結果(例):

  {
    "OwnerId": "XXXXXXXXXXXX",
    "ReservationId": "r-xxxxxxxxxxxxxxxxx",
    "Groups": [],
    "Instances": [
      {
          "Monitoring": {
              "State": "disabled"
          },
          "PublicDnsName": "",
          "RootDeviceType": "ebs",
          "State": {
              "Code": 0,
              "Name": "pending"
          },
          "EbsOptimized": false,
          "LaunchTime": "2016-12-05T01:23:45.000Z",
          "PrivateIpAddress": "10.192.0.8",
          "ProductCodes": [],
          "VpcId": "vpc-xxxxxxxx",
          "StateTransitionReason": "",
          "InstanceId": "i-xxxxxxxxxxxxxxxxx",
          "ImageId": "ami-xxxxxxxx",
          "PrivateDnsName": "ip-xxx-xxx-xxx-xxx.ap-northeast-1ap-northeast-1.compute.internal",
          "KeyName": "<キーペアー名>",
          "SecurityGroups": [
              {
                  "GroupName": "ec2-ssh-global-inbound",
                  "GroupId": "sg-xxxxxxxx"
              }
          ],
          "ClientToken": "",
          "SubnetId": "subnet-xxxxxxxx",
          "InstanceType": "t2.micro",
          "NetworkInterfaces": [
              {
                  "Status": "in-use",
                  "MacAddress": "xx:xx:xx:xx:xx:xx",
                  "SourceDestCheck": true,
                  "VpcId": "vpc-xxxxxxxx",
                  "Description": "",
                  "NetworkInterfaceId": "eni-xxxxxxxx",
                  "PrivateIpAddresses": [
                      {
                          "Primary": true,
                          "PrivateIpAddress": "10.192.0.8"
                      }
                  ],
                  "Attachment": {
                      "Status": "attaching",
                      "DeviceIndex": 0,
                      "DeleteOnTermination": true,
                      "AttachmentId": "eni-attach-xxxxxxxx",
                      "AttachTime": "2016-12-05T01:23:45.000Z"
                  },
                  "Groups": [
                      {
                          "GroupName": "<キーペアー名>",
                          "GroupId": "sg-xxxxxxxx"
                      }
                  ],
                  "SubnetId": "subnet-xxxxxxxx",
                  "OwnerId": "XXXXXXXXXXXX",
                  "PrivateIpAddress": "10.192.0.8"
              }
          ],
          "SourceDestCheck": true,
          "Placement": {
              "Tenancy": "default",
              "GroupName": "",
              "AvailabilityZone": "ap-northeast-1a"
          },
          "Hypervisor": "xen",
          "BlockDeviceMappings": [],
          "Architecture": "x86_64",
          "StateReason": {
              "Message": "pending",
              "Code": "pending"
          },
          "RootDeviceName": "/dev/xvda",
          "VirtualizationType": "hvm",
          "AmiLaunchIndex": 0
      }
    ]
  }

2.2. インスタンスIDの取得

起動中のインスタンスからインスタンスIDを取得します。

コマンド
EC2_INSTANCE_ID=$( 
        aws ec2 describe-instances 
          --filters Name=private-ip-address,Values=${EC2_PRIVATE_ADDR} 
          --query 'Reservations[].Instances[].InstanceId' 
          --output text 
) 
        && echo ${EC2_INSTANCE_ID}

結果(例):

  i-xxxxxxxxxxxxxxxxx

3. 事後作業

3.1 インスタンスのステータス確認

コマンド
EC2_INSTANCE_STATE=$( 
        aws ec2 describe-instances 
        --instance-ids ${EC2_INSTANCE_ID} 
        --query 'Reservations[].Instances[].State.Name' 
        --output text 
) 
        && echo ${EC2_INSTANCE_STATE}

結果(例):

  running

3.2. パブリックIPアドレスの取得

コマンド
EC2_PUBLIC_IP=$( 
        aws ec2 describe-instances 
          --instance-id ${EC2_INSTANCE_ID} 
          --query "Reservations[].Instances[].PublicIpAddress" 
          --output text 
) 
        && echo ${EC2_PUBLIC_IP}

結果(例):

  xxx.xxx.xxx.xxx

4. インスタンスへのログイン

4.1. SSHログイン

変数の確認
cat << ETX

        FILE_SSH_KEY:  ${FILE_SSH_KEY}
        EC2_PUBLIC_IP: ${EC2_PUBLIC_IP}

ETX
コマンド
ssh -i ${FILE_SSH_KEY} ec2-user@${EC2_PUBLIC_IP}

結果(例):

  The authenticity of host '54.xxx.xxx.xxx (54.xxx.xxx.xxx)' can't be established.
  RSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx.
  Are you sure you want to continue connecting (yes/no)?

入力:

  yes

結果(例):

  Warning: Permanently added '54.xxx.xxx.xxx' (RSA) to the list of known hosts.

         __|  __|_  )
         _|  (     /   Amazon Linux AMI
        ___|___|___|

  https://aws.amazon.com/amazon-linux-ami/2015.03-release-notes/
  24 package(s) needed for security, out of 53 available
  Run "sudo yum update" to apply all updates.

4.2. パッケージ更新

コマンド
sudo yum update -y

4.3. EC2メタ情報の確認

コマンド(EC2インスタンス)
echo -e "n"   && curl http://169.254.169.254/latest/meta-data/public-ipv4   && echo -e "n"

結果(例):

  xxx.xxx.xxx.xxx

4.4. EC2インスタンスからログアウト

コマンド(EC2インスタンス)
exit

完了

続きを読む

MySQLで外部キー付きテーブルをSET FOREIGN_KEY_CHECKS=0;でリストアしているのに外部キー制約違反が出るとき

タイトルが長くてすみません。
かなりレアケースな話のため、タイトルをピンポイントにしないと…ということで。

MySQL(InnoDB)で、mysqldumpでダンプしたデータに外部キー制約付きテーブルが含まれる場合、「SET FOREIGN_KEY_CHECKS=0;」をしてからリストアする必要があります。

例えば、MySQLクライアントを起動し、

mysql> SET FOREIGN_KEY_CHECKS=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SOURCE 【ダンプファイル名】;

でリストアしたりしますが、このようにしたとしても、場合により外部キー制約違反(例:エラーコード1005とメッセージ中のエラー150の組み合わせ)が出ることがあります。

14.19.5 InnoDB のエラーコード(MySQL 5.6 リファレンスマニュアル)

「SET FOREIGN_KEY_CHECKS=0;」しているのになぜ?と思ってしまいますが、よく見ると、他にも「MySQL server has gone away」(または「MySQL サーバーが存在しなくなりました」)というエラーメッセージが表示されていることがあります。

原因

パケットが大きすぎるクエリがクライアントからサーバに投げられる
      ↓
・サーバがクライアントとの接続(セッション)を切断する
      ↓
・クライアントがサーバに再接続する
      ↓
「SET FOREIGN_KEY_CHECKS=1;」の状態に戻る
      ↓
・この状態で外部キー制約に関わるクエリが投げられ、外部キー制約違反が検出されると、エラーが出る

という流れでエラーが出ている可能性があります。
※すべてがこのケースにあてはまるわけではありません。あくまでも一例です。なお、ここでいう「パケット」は「TCPのパケット」のことではなくて「MySQLのパケット」ですので、TCPのパケット長は関係ありません。

MySQL サーバーが存在しなくなりました(MySQL 5.6 リファレンスマニュアル)

対処

「max_allowed_packet」を十分大きな値に設定してからリストアします。

ダンプをリストアする場合、アプリケーションで通常投げられるよりも長いクエリがサーバに投げられることがあります。
そのため、アプリケーションで投げられるクエリだけを想定して「max_allowed_packet」を設定した場合、ダンプからリストアする際のクエリが受け付けられない可能性があります。
※例えば、複数のTEXT/BLOBカラムを持つテーブルがあって、レコードをINSERT/UPDATEする際にそれらのカラムを同時にINSERT/UPDATEすることがない(必ず個別にINSERT/UPDATEする)場合に、それに合わせて max_allowed_packet を設定しているケース。
ただ、どちらかというと新しく立てたサーバに「max_allowed_packetを設定し忘れた」とか「0を1個入れ忘れた」というケースのほうが多そうですが。

「パケットが大きすぎます」というエラーメッセージが出てくれれば原因に気づきやすいのですが、先に示したリファレンスマニュアルに記されている通り、「MySQL サーバーが存在しなくなりました」(英語表記では「MySQL server has gone away」)というエラーメッセージが出て接続(セッション)が切れてしまうことがあるので非常にわかりづらいです。

さらに、外部キー制約付きテーブルをリストアしている場合は、「SET FOREIGN_KEY_CHECKS=0;」を付けているにもかかわらず外部キー制約違反のエラーが出るため、ますます原因に辿り着きにくくなります。
※「MySQL server has gone away」が先に出てくれればまだわかりやすいのですが、場合によっては外部キー制約違反のエラーが先に出てから「MySQL server has gone away」が出ることがあります。こうなると、「外部キー制約違反が原因でサーバへの接続が切れた」と誤解してしまいます。

まとめ(?)

「外部キー制約付きテーブルをリストアするときは SET FOREIGN_KEY_CHECKS=0; で」
と、
「MySQL server has gone away が出る原因の1つに max_allowed_packet が小さいことが挙げられる」
は、それぞれ良く知られたことですが、組み合わさってトラブルが発生すると(エラーの出方が若干トリッキーなこともあって)原因の特定に手間取る…という話でした。

なお、厳密にはMySQLの話ではないですが…。
Amazon(AWS)のAuroraの設定に関して、「初期設定のままで使うのが良い」と言われることがよくありますが、これは設定全般のことを指して言っているのではないので、注意が必要です(あくまでも性能を出すために必要なグローバル/スレッドバッファサイズなどの適正値の話)。
例えば、以下のような設定は、使う環境に合わせて設定する必要があります。

  • innodb_file_per_table
  • innodb_file_format
  • innodb_large_prefix

max_allowed_packet も同じです。

続きを読む

AWS E2 G2インスタンス上にKeras環境を構築する 2017年2月版

はじめに

Deep Learningをやろうと思ったらでかい計算資源が必要なのが当たり前なのだけど、手持ちのPCのスペックで十分とかそうそうありはしないので、EC2のGPUインスタンスをささっと立てて使うのも手だと思う。

FrameworkはKerasでバックエンドはTensorFlow GPUバージョン。それをpyenv仮想環境でセットアップする構成とした。先日TensorFlow 1.0がリリースされてtf.kerasが実装されたみたいだけどまだ試してないので普通にKeras使うことにする。

環境構築についてはこちらを参考にさせていただいた。
AWSのGPUインスタンスでTensorFlowを動かす

インスタンスの作成

EC2 Instance: クイックスタートにある Ubuntu Server 16.04 LTS (HVM), SSD Volume Type
Type : g2.2xlarge
ストレージなどはとりあえず標準構成(メモリ15GB, ストレージ8GB)

セットアップ

まずはSSHでログインする

ssh -i ~/[ec2key].pem ubuntu@[Instance IP]

エフェメラルストレージを作業ディレクトリにするためシンボリックリンクを作成する

CUDAとかけっこうでかいので作業の途中で空き容量が足りなくなる。/mnt/tmp/へのシンボリックリンクを作成してエフェメラルストレージを作業領域に使う。

sudo mkdir /mnt/tmp
sudo chmod 777 /mnt/tmp
sudo rm -rf /tmp
sudo ln -s /mnt/tmp /tmp
cd /tmp

Ubuntuを最新にアップグレードする

sudo apt-get update
sudo apt-get upgrade -y

ロケールを設定する

upgrade後ロケール関係のwarningが出てうざいので

sudo apt-get install language-pack-ja
sudo update-locale LANG=ja_JP.UTF-8

セットアップに必要なモジュールをインストールする

sudo apt-get install python
sudo apt-get install -y build-essential python-pip python-dev git python-numpy swig python-dev default-jdk zip zlib1g-dev ipython

NVIDIAドライバとの衝突をさけるため、Nouveauのブラックリストを追加する

echo -e "blacklist nouveau\nblacklist lbm-nouveau\noptions nouveau modeset=0\nalias nouveau off\nalias lbm-nouveau off\n" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
echo options nouveau modeset=0 | sudo tee -a /etc/modprobe.d/nouveau-kms.conf
sudo update-initramfs -u
sudo reboot

再起動後、ログインしてlinux-image-extra-virtualをインストールする。

ssh -i ~/[ec2key].pem ubuntu@[Instance IP]
sudo apt-get install -y linux-image-extra-virtual
sudo reboot

再起動後、ログインしてlinux-headersをインストールする。

ssh -i ~/[ec2key].pem ubuntu@[Instance IP]
sudo apt-get install -y linux-source linux-headers-`uname -r`

CUDA Toolkit v8 をセットアップする

現時点での最新バージョンは 8.0。
ダウンロードしてインストールする

cd /tmp
wget https://developer.nvidia.com/compute/cuda/8.0/prod/local_installers/cuda_8.0.44_linux-run
chmod +x cuda_8.0.44_linux-run
./cuda_8.0.44_linux-run  -extract=`pwd`/nvidia_installers
cd nvidia_installers/
sudo ./NVIDIA-Linux-x86_64-367.48.run
# Acceptを選択する。kernelセットアップはプログレスバーが100%になってからしばらく時間がかかる
# OK を選択する
# OK を選択する
# Yes を選択する
# OK を選択する
sudo modprobe nvidia
sudo ./cuda-linux64-rel-8.0.44-21122537.run
# Readmeが表示されるので q で終了する
# accept と入力してエンター
# install Path: default
# shortcut?: default

cuDNN をセットアップ

https://developer.nvidia.com/cudnn からcuDNNを一度ローカルにDownloadする
cuDNNはDeveloperサインアップしないと落とせないため。仕方がない。

ローカルのターミナルからダウンロードしたcuDNNをEC2インスタンスに転送する

scp -i [ec2key].pem cudnn-8.0-linux-x64-v5.1.tgz ubuntu@[Instance IP]:/tmp

EC2インスタンスにもどる

cd /tmp
tar -xzf cudnn-8.0-linux-x64-v5.1.tgz
sudo mv ./cuda/lib64/* /usr/local/cuda/lib64/
sudo mv ./cuda/include/* /usr/local/cuda/include/

~/.bashrcに以下を追記する

# cuDNN
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64"
export CUDA_HOME=/usr/local/cuda
source ~/.bashrc

Python 仮想環境の構築

python -V
Python 2.7.12
sudo apt-get install git gcc make openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv

~/.bash_profileを作成して以下を記載する

# pyenv
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
# virtualenv
eval "$(pyenv virtualenv-init -)"
export PYENV_VIRTUALENV_DISABLE_PROMPT=1
source ~/.bash_profile

Keras用仮想環境をつくる

pyenv install 3.5.3
pyenv virtualenv 3.5.3 keras
pyenv activate keras
python -V
Python 3.5.3

Tensorflowをインストールする

pip install tensorflow-gpu

TensorFlowのバージョンを確認してみて以下のようになってたらGPUが使えるようになっている。

python -c 'import tensorflow as tf; print(tf.__version__)'
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcublas.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcufft.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcurand.so.8.0 locally
1.0.0

Kerasをインストールする

pip install pillow
pip install h5py
pip install matplotlib
pip install keras

keras examplesを実行してみる

cd /tmp
git clone https://github.com/fchollet/keras.git
cd keras/examples

とりあえずMNISTをCNNで解くやつを実行してみる

python mnist_cnn.py
Using TensorFlow backend.
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so locally
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.pkl.gz
X_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_device.cc:885] Found device 0 with properties: 
name: GRID K520
major: 3 minor: 0 memoryClockRate (GHz) 0.797
pciBusID 0000:00:03.0
Total memory: 3.94GiB
Free memory: 3.91GiB
I tensorflow/core/common_runtime/gpu/gpu_device.cc:906] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:916] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GRID K520, pci bus id: 0000:00:03.0)
60000/60000 [==============================] - 13s - loss: 0.3770 - acc: 0.8839 - val_loss: 0.0932 - val_acc: 0.9709
Epoch 2/12
60000/60000 [==============================] - 11s - loss: 0.1363 - acc: 0.9603 - val_loss: 0.0632 - val_acc: 0.9801
Epoch 3/12
60000/60000 [==============================] - 11s - loss: 0.1064 - acc: 0.9687 - val_loss: 0.0509 - val_acc: 0.9835
Epoch 4/12
60000/60000 [==============================] - 11s - loss: 0.0900 - acc: 0.9736 - val_loss: 0.0443 - val_acc: 0.9857
Epoch 5/12
60000/60000 [==============================] - 11s - loss: 0.0769 - acc: 0.9775 - val_loss: 0.0405 - val_acc: 0.9865
Epoch 6/12
60000/60000 [==============================] - 11s - loss: 0.0689 - acc: 0.9795 - val_loss: 0.0371 - val_acc: 0.9870
Epoch 7/12
60000/60000 [==============================] - 11s - loss: 0.0649 - acc: 0.9803 - val_loss: 0.0361 - val_acc: 0.9881
Epoch 8/12
60000/60000 [==============================] - 11s - loss: 0.0594 - acc: 0.9823 - val_loss: 0.0356 - val_acc: 0.9886
Epoch 9/12
60000/60000 [==============================] - 11s - loss: 0.0547 - acc: 0.9841 - val_loss: 0.0321 - val_acc: 0.9889
Epoch 10/12
60000/60000 [==============================] - 11s - loss: 0.0525 - acc: 0.9841 - val_loss: 0.0320 - val_acc: 0.9889
Epoch 11/12
60000/60000 [==============================] - 11s - loss: 0.0506 - acc: 0.9850 - val_loss: 0.0323 - val_acc: 0.9892
Epoch 12/12
60000/60000 [==============================] - 11s - loss: 0.0471 - acc: 0.9856 - val_loss: 0.0314 - val_acc: 0.9897
Test score: 0.0314083654978
Test accuracy: 0.9897

実行時間は: 2:23 (データのダウンロード時間除く)。手持ちのMBAでは35分ほどかかったので10倍以上速い。
1epochあたり10秒くらいかよ。

調子に乗ってIMDBのLSTMという重たそうなやつもやってみた。

python imdb_cnn_lstm.py
Using TensorFlow backend.
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so locally
Loading data...
25000 train sequences
25000 test sequences
Pad sequences (samples x time)
X_train shape: (25000, 100)
X_test shape: (25000, 100)
Build model...
Train...
Train on 25000 samples, validate on 25000 samples
Epoch 1/2
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_device.cc:885] Found device 0 with properties: 
name: GRID K520
major: 3 minor: 0 memoryClockRate (GHz) 0.797
pciBusID 0000:00:03.0
Total memory: 3.94GiB
Free memory: 3.91GiB
I tensorflow/core/common_runtime/gpu/gpu_device.cc:906] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:916] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GRID K520, pci bus id: 0000:00:03.0)
   30/25000 [..............................] - ETA: 1397s - loss: 0.6936 - acc: 0.4333I tensorflow/core/common_runtime/gpu/pool_allocator.cc:247] PoolAllocator: After 3811 get requests, put_count=2890 evicted_count=1000 eviction_rate=0.346021 and unsatisfied allocation rate=0.530307
I tensorflow/core/common_runtime/gpu/pool_allocator.cc:259] Raising pool_size_limit_ from 100 to 110
  360/25000 [..............................] - ETA: 160s - loss: 0.6935 - acc: 0.4833I tensorflow/core/common_runtime/gpu/pool_allocator.cc:247] PoolAllocator: After 2156 get requests, put_count=2374 evicted_count=1000 eviction_rate=0.42123 and unsatisfied allocation rate=0.373377
I tensorflow/core/common_runtime/gpu/pool_allocator.cc:259] Raising pool_size_limit_ from 256 to 281
  870/25000 [>.............................] - ETA: 94s - loss: 0.6925 - acc: 0.5287I tensorflow/core/common_runtime/gpu/pool_allocator.cc:247] PoolAllocator: After 4249 get requests, put_count=4491 evicted_count=1000 eviction_rate=0.222668 and unsatisfied allocation rate=0.192281
I tensorflow/core/common_runtime/gpu/pool_allocator.cc:259] Raising pool_size_limit_ from 655 to 720
25000/25000 [==============================] - 63s - loss: 0.3815 - acc: 0.8210 - val_loss: 0.3519 - val_acc: 0.8456
Epoch 2/2
25000/25000 [==============================] - 60s - loss: 0.1970 - acc: 0.9238 - val_loss: 0.3471 - val_acc: 0.8534
24990/25000 [============================>.] - ETA: 0sTest score: 0.347144101623
Test accuracy: 0.853440059948

実行時間: 2:25 (データのダウンロード時間除く)。MBAでこれも40分以上かかったやつなので圧倒的。

さらに調子に乗ってもっと重たそうなやつをやってみる。mnist_acgan.pyはMNISTをACGAN(Auxiliary Classifier Generative Adversarial Network)というやつで解くみたい。DCGANの親戚か?詳しくはここに載ってるみたいだけど難しいので後回しにする。
とりあえずGANなので重いだろう。どんなもんだろうか。

python mnist_acgan.py
Using TensorFlow backend.
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so locally
Epoch 1 of 50
  0/600 [..............................] - ETA: 0sI tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_device.cc:885] Found device 0 with properties: 
name: GRID K520
major: 3 minor: 0 memoryClockRate (GHz) 0.797
pciBusID 0000:00:03.0
Total memory: 3.94GiB
Free memory: 3.91GiB
I tensorflow/core/common_runtime/gpu/gpu_device.cc:906] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:916] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GRID K520, pci bus id: 0000:00:03.0)
W tensorflow/core/common_runtime/bfc_allocator.cc:217] Ran out of memory trying to allocate 3.74GiB. The caller indicates that this is not a failure, but may mean that there could be performance gains if more memory is available.
599/600 [============================>.] - ETA: 1s   
Testing for epoch 1:
component              | loss | generation_loss | auxiliary_loss
-----------------------------------------------------------------
generator (train)      | 3.88 | 1.49            | 2.39 
generator (test)       | 3.36 | 1.04            | 2.32 
discriminator (train)  | 2.11 | 0.53            | 1.58 
discriminator (test)   | 2.12 | 0.70            | 1.43 
Epoch 2 of 50
 44/600 [=>............................] - ETA: 732s

1epoch終わるのに 15分ほどかかった。あと48epochある。。果てしないしお金かかるので途中でやめた。まあでも半日回せば結果出そう。すごいな。

作業後のディスク空き状況

df -k
Filesystem     1K-blocks    Used Available Use% Mounted on
udev             7679880       0   7679880   0% /dev
tmpfs            1539900    8800   1531100   1% /run
/dev/xvda1       8117828 6149060   1533492  81% /
tmpfs            7699496       0   7699496   0% /dev/shm
tmpfs               5120       0      5120   0% /run/lock
tmpfs            7699496       0   7699496   0% /sys/fs/cgroup
/dev/xvdb       66946696 3017852  60521484   5% /mnt
tmpfs            1539904       0   1539904   0% /run/user/1000

システムディスクの使用量は81%。エフェメラルストレージはインスタンスがstopすると揮発するのでデフォルトの8GBが不安ならストレージ要領を拡張しとくとよい。

AMIにしてからg2.xlargeインスタンスを作成してみたらエラーになる

構築できたインスタンスのスナップショットをとって、AMIからg2.xlargeインスタンスを作成してみた。ちゃんと動くか試行。

pyenv activate keras
python -V
 Python 3.5.3
python -c 'import tensorflow as tf; print(tf.__version__)'
Traceback (most recent call last):
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/python/__init__.py", line 61, in <module>
    from tensorflow.python import pywrap_tensorflow
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/python/pywrap_tensorflow.py", line 28, in <module>
    _pywrap_tensorflow = swig_import_helper()
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/python/pywrap_tensorflow.py", line 24, in swig_import_helper
    _mod = imp.load_module('_pywrap_tensorflow', fp, pathname, description)
  File "/home/ubuntu/.pyenv/versions/3.5.3/lib/python3.5/imp.py", line 242, in load_module
    return load_dynamic(name, filename, file)
  File "/home/ubuntu/.pyenv/versions/3.5.3/lib/python3.5/imp.py", line 342, in load_dynamic
    return _load(spec)
ImportError: libcudart.so.8.0: cannot open shared object file: No such file or directory

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/__init__.py", line 24, in <module>
    from tensorflow.python import *
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/python/__init__.py", line 72, in <module>
    raise ImportError(msg)
ImportError: Traceback (most recent call last):
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/python/__init__.py", line 61, in <module>
    from tensorflow.python import pywrap_tensorflow
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/python/pywrap_tensorflow.py", line 28, in <module>
    _pywrap_tensorflow = swig_import_helper()
  File "/home/ubuntu/.pyenv/versions/keras/lib/python3.5/site-packages/tensorflow/python/pywrap_tensorflow.py", line 24, in swig_import_helper
    _mod = imp.load_module('_pywrap_tensorflow', fp, pathname, description)
  File "/home/ubuntu/.pyenv/versions/3.5.3/lib/python3.5/imp.py", line 242, in load_module
    return load_dynamic(name, filename, file)
  File "/home/ubuntu/.pyenv/versions/3.5.3/lib/python3.5/imp.py", line 342, in load_dynamic
    return _load(spec)
ImportError: libcudart.so.8.0: cannot open shared object file: No such file or directory


Failed to load the native TensorFlow runtime.

See https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/get_started/os_setup.md#import_error

for some common reasons and solutions.  Include the entire stack trace
above this error message when asking for help.

TensorFlowがエラーを吐く。よくわからないけどCUDA関係か?
AMI化ができるかどうかはあとで検討が必要かも。断続的に使う場合はインスタンスをstopして置いとくのがいいかもしれない。

まとめ

上記Kerasの環境構築までは一時間以内でできる。インスタンスstopして置いとくのもいいけど、使いたい時にサラから構築してもそんなに手間ではない。
使用頻度とかケースに応じて考えるのがいいだろう。つーかTensorFlow GPUの環境構築以前と比べてめっちゃ楽になったな。

続きを読む

RedHat7にPHP7のインストール

あるサーバーにPHP7を入れてほしいという依頼が来た。

インスタンスの情報収集

$ uname -a
Linux xxx.compute.internal 3.10.0-514.el7.x86_64 #1 SMP Wed Oct 19 11:24:13 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.3 (Maipo)
$ cat /proc/version
Linux version 3.10.0-514.el7.x86_64 (mockbuild@x86-039.build.eng.bos.redhat.com) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) ) #1 SMP Wed Oct 19 11:24:13 EDT 2016
項目 内容
OS Red Hat Enterprise Linux Server 7.3
アーキテクチャ x86_64
gcc 4.8.5

wgetのインストール

wgetが入っていなかったのでインストール。rpmファイルの取得に使います。

# yum install wget

yumリポジトリの追加

リポジトリはAWSのデフォルトのまま。

# yum repolist
Loaded plugins: amazon-id, rhui-lb, search-disabled-repos
repo id                                                                repo name                                                                             status
rhui-REGION-client-config-server-7/x86_64                              Red Hat Update Infrastructure 2.0 Client Configuration Server 7                            6
rhui-REGION-rhel-server-releases/7Server/x86_64                        Red Hat Enterprise Linux Server 7 (RPMs)                                              13,838
rhui-REGION-rhel-server-rh-common/7Server/x86_64                       Red Hat Enterprise Linux Server 7 RH Common (RPMs)                                       209
repolist: 14,053

epelのリポジトリの追加

epelとは、Extra Packages for Enterprise Linuxの略称で、RedHatやCentOSは保守的で使えるrpmパッケージ自体やそのバージョンが限られているので、新しいものを使いたい場合は、epelをリポジトリに追加することにより、Fadoraと同様のパッケージの利用が可能になる。
詳しくは、https://fedoraproject.org/wiki/About_EPEL/ja

# wget http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/7/x86_64/e/epel-release-7-9.noarch.rpm
# rpm -ivh epel-release-7-9.noarch.rpm

リポジトリを確認。epelが追加された。

# yum repolist
Loaded plugins: amazon-id, rhui-lb, search-disabled-repos
repo id                                                                repo name                                                                             status
epel/x86_64                                                            Extra Packages for Enterprise Linux 7 - x86_64                                        11,184
rhui-REGION-client-config-server-7/x86_64                              Red Hat Update Infrastructure 2.0 Client Configuration Server 7                            6
rhui-REGION-rhel-server-releases/7Server/x86_64                        Red Hat Enterprise Linux Server 7 (RPMs)                                              13,838
rhui-REGION-rhel-server-rh-common/7Server/x86_64                       Red Hat Enterprise Linux Server 7 RH Common (RPMs)                                       209
repolist: 25,237

remiのリポジトリの追加

remiリポジトリを追加するためには、epelリポジトリの追加を先にしておく必要がある。

# rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
# rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

リポジトリの確認。remiが追加されている。

# yum repolist
Loaded plugins: amazon-id, rhui-lb, search-disabled-repos
remi-safe                                                                                                                                   | 2.9 kB  00:00:00
remi-safe/primary_db                                                                                                                        | 906 kB  00:00:03
repo id                                                                repo name                                                                             status
epel/x86_64                                                            Extra Packages for Enterprise Linux 7 - x86_64                                        11,184
remi-safe                                                              Safe Remi's RPM repository for Enterprise Linux 7 - x86_64                             2,000
rhui-REGION-client-config-server-7/x86_64                              Red Hat Update Infrastructure 2.0 Client Configuration Server 7                            6
rhui-REGION-rhel-server-releases/7Server/x86_64                        Red Hat Enterprise Linux Server 7 (RPMs)                                              13,838
rhui-REGION-rhel-server-rh-common/7Server/x86_64                       Red Hat Enterprise Linux Server 7 RH Common (RPMs)                                       209
repolist: 27,237

念のためリポジトリのデータベースの参照も確認。
なんかたくさん入ってるぞ!

# ls /etc/yum.repos.d/
epel.repo          redhat.repo                     redhat-rhui.repo  remi-php70.repo  remi.repo       rhui-load-balancers.conf
epel-testing.repo  redhat-rhui-client-config.repo  remi-php54.repo   remi-php71.repo  remi-safe.repo

PHPのインストール

さて下準備が長くなりましたが、本題のPHP7のインストールです。
開発に必要と思われるものを一気に入れちゃいます。

# yum install --enablerepo=epel,remi-php70 php php-mbstring php-pear php-fpm php-mcrypt php-mysql

確認。

# php -v
PHP 7.0.16 (cli) (built: Feb 14 2017 17:22:12) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies

でけた!

続きを読む

Elastic Volumes (Amazon EBS)

ついにEC2インスタンスを起動したままEBSのボリュームタイプと容量・IOPSの変更ができるようになりました!

Elastic Volumes(エラスティックボリューム)という機能だそうです。
新しいボリュームタイプではないのですね。

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/considerations.html
を見ると
– Magneticは対象外
– サイズ縮小は当然NG
– 変更後は6時間変更不可
– 2016/11/1以前にアタッチされたボリュームはインスタンスの停止・起動、またはボリュームのデタッチ・アタッチが必要
らしい。他にも制約や前提ありますね。読み込まないと。

紹介記事

続きを読む