メインコンテンツまでスキップ

· 約6分
moritalous
お知らせ

過去にQiitaに投稿した内容のアーカイブです。

正月休みに勉強しようと思って、Elasticsearch実践ガイドを買いました。 Amazonで買ったけど、インプレスで電子書籍版が半額😱😱😱(期間限定のようです) 初心者の私にはちょうどいい入門書でした!

前からやりたかった、Kibanaを使わずにKibanaっぽいグラフを作ることができました~!

スクリーンショット (86).png

環境構築

OS: Ubuntu 18.04.1 (on VirtualBox) ホスト名:ubuntu.local

インストール

https://www.elastic.co/guide/en/elasticsearch/reference/current/deb.html https://www.elastic.co/guide/en/kibana/current/deb.html https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-installation.html を参考に。

Open JDKのインストール

sudo apt update
sudo apt install openjdk-8-jre-headless

PGPキーのインストール

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

APT repositoryのインストール

sudo apt install apt-transport-https

sources listの追加

OSS版をインストールしたかったのでこちら

echo "deb https://artifacts.elastic.co/packages/oss-6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list

Elasticsearch/Kibana/Metricbeatのインストール

sudo apt update
sudo apt install elasticsearch-oss kibana-oss metricbeat-oss

設定ファイルの編集

Elasticsearchの設定

/etc/elasticsearch/elasticsearch.yml
## localhost以外からのアクセスを許可する
network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
transport.tcp.port: 9300

## JavaScriptからのCORSアクセスを許可する
http.cors.enabled: true
http.cors.allow-origin: "*"

Kibanaの設定

/etc/kibana/kibana.yml
## localhost以外からのアクセスを許可する
server.host: "0.0.0.0"

ElasticsearchとKibanaのサービス有効化・開始

sudo systemctl enable elasticsearch.service
sudo systemctl enable kibana.service

sudo systemctl start elasticsearch.service
sudo systemctl start kibana.service

接続確認1

http://ubuntu.local:9200にアクセス レスポンスがかえって来たら成功。

{
"name" : "fXjgLKE",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "WGnyRmUuSZemH70_ABZ3pg",
"version" : {
"number" : "6.5.4",
"build_flavor" : "oss",
"build_type" : "deb",
"build_hash" : "d2ef93d",
"build_date" : "2018-12-17T21:17:40.758843Z",
"build_snapshot" : false,
"lucene_version" : "7.5.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}

Kibanahttp://ubuntu.local:5601にアクセス。Kibanaの画面が表示されたら成功。

Metricbeatの設定

Kibanaにダッシュボードを追加

metricbeat setup --dashboards

Metricbeatのサービス有効化・開始

sudo systemctl enable metricbeat.service

sudo systemctl start metricbeat.service

接続確認2

Metricbeatのデータが上手くElasticsearchに入れば、Kibanaでこんな画面が見れます

Screenshot_2019-01-03 [Metricbeat System] Host overview - Kibana.png

JavaScriptで可視化

Google Charts ( https://developers.google.com/chart/?hl=ja ) でグラフ化します。

ElasticsearchのREST APIで検索します。Aggregationでいい感じに平均値を取得します。

POST http://ubuntu.local:9200/metricbeat-*/_search

リクエスト
{
"size": 0,
"query": {
"bool": {
"filter": {
"range": {
"@timestamp": {
"gte": "now-7d"
}
}
},
"must": [{
"match": {
"metricset.name": "cpu"
}
}, {
"match": {
"beat.hostname": "ubuntu"
}
}]
}
},
"aggs": {
"date_histogram": {
"date_histogram": {
"field": "@timestamp",
"interval": "10m"
},
"aggs": {
"system_cpu_total_pct": {
"avg": {
"field": "system.cpu.total.pct"
}
}
}
}
}
}
レスポンス
{
"took" : 16,
"timed_out" : false,
"_shards" : {
"total" : 4,
"successful" : 4,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 9239,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"date_histogram" : {
"buckets" : [
{
"key_as_string" : "2019-01-01T14:50:00.000Z",
"key" : 1546354200000,
"doc_count" : 59,
"system_cpu_total_pct" : {
"value" : 1.2820169491525424
}
},
{
"key_as_string" : "2019-01-01T15:00:00.000Z",
"key" : 1546354800000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.7167333333333333
}
},
{
"key_as_string" : "2019-01-01T15:10:00.000Z",
"key" : 1546355400000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.6058666666666668
}
},
{
"key_as_string" : "2019-01-01T15:20:00.000Z",
"key" : 1546356000000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.5145166666666667
}
},
{
"key_as_string" : "2019-01-01T15:30:00.000Z",
"key" : 1546356600000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.5042166666666666
}
},
{
"key_as_string" : "2019-01-03T02:10:00.000Z",
"key" : 1546481400000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.09896666666666668
}
},
{
"key_as_string" : "2019-01-03T02:20:00.000Z",
"key" : 1546482000000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.10701666666666668
}
},
{
"key_as_string" : "2019-01-03T02:30:00.000Z",
"key" : 1546482600000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.09681666666666668
}
},
{
"key_as_string" : "2019-01-03T02:40:00.000Z",
"key" : 1546483200000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.13956666666666667
}
},
{
"key_as_string" : "2019-01-03T02:50:00.000Z",
"key" : 1546483800000,
"doc_count" : 27,
"system_cpu_total_pct" : {
"value" : 0.09644444444444444
}
}
]
}
}
}

このJSONをいい感じに変換して、Google Chartsで折れ線グラフにしてみます。

スクリーンショット (86).png

できました。

ソースはこんな感じで

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" src="app.js"></script>

</head>
<body>
<div id="chart" style="width: 900px; height: 500px"></div>
</body>
</html>
app.js
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawChart);

function drawChart() {

var url = 'http://ubuntu.local:9200/metricbeat-*/_search'
var data = {
"size": 0,
"query": {
"bool": {
"filter": {
"range": {
"@timestamp": {
"gte": "now-7d"
}
}
},
"must": [{
"match": {
"metricset.name": "cpu"
}
}, {
"match": {
"beat.hostname": "ubuntu"
}
}]
}
},
"aggs": {
"date_histogram": {
"date_histogram": {
"field": "@timestamp",
"interval": "10m"
},
"aggs": {
"system_cpu_total_pct": {
"avg": {
"field": "system.cpu.total.pct"
}
}
}
}
}
}

fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
return response.json()
}).then(function (response) {
var data = []
data.push(['日付', 'CPU使用率'])

for (const date_histogram of response.aggregations.date_histogram.buckets) {
var key = date_histogram.key
var value = date_histogram.system_cpu_total_pct.value
data.push([new Date(key), value * 100])
}
return data
}).then(function (response) {
var data = google.visualization.arrayToDataTable(response)

var options = {
title: 'CPU使用率',
hAxis: {
format: 'M/d H:mm'
},
legend: {
position: 'bottom'
}
};

var chart = new google.visualization.AreaChart(document.getElementById('chart'));

chart.draw(data, options);
})
}

参考サイト

初心者のためのRest APIから覚えるElasticsearch https://qiita.com/_bsoo/items/d880831e644175782ee0

elasticsearchでlocalhost以外からのアクセスを許可する方法 https://qiita.com/fuku2014/items/c2e2ffc07da5e2d2ba05

· 約3分
moritalous
お知らせ

過去にQiitaに投稿した内容のアーカイブです。

我が子の小学校で、「ツイタもん」が導入されました。

児童見守り安心システム ツイタもん https://tsuitamon.jp/

学校の門を通ると、「ツイタもん」とメールが来ます。 今どきなサービスですが、毎日メールが来ると、そのうち気にしなくなりそうです。 そこで、万が一、門を通ってないときだけ「ツイテないもん」と連絡が来る仕組みを考えました。

仕組み

仕組みとしては、子供が学校に行くまでの時間に、 「ツイテないもん」通知を行うスケジュール を有効にし、「ツイタもん」メールが来たらこの 「ツイテないもん」通知を行うスケジュール を無効にします。 学校についたら、スケジュールはキャンセルされて通知は実行されず、学校についてなければ、通知スケジュールに従って通知されるわけです。

これをIFTTTとAWSのLambdaやCloudWatch Eventsを組み合わせて実現します。

構成

全体構成

ツイテないもん.png

学校についた場合

ツイテないもん-ついた場合.png

学校についてない場合

ツイテないもん-ついてない場合.png

Lambdaの処理

CloudWatch Eventsを無効にするLambda

超適当 CloudWatch Eventsのイベント名は環境変数にセットしました。 無効ではなく有効にする場合はdisable_ruleenable_ruleになります。

import os
import boto3

def lambda_handler(event, context):
# TODO implement
event_name = os.environ.get("EVENT_NAME")

client = boto3.client('events')

response = client.disable_rule(
Name=event_name
)

return response

ツイテないもん通知を行うLambda

超適当

import requests
import os

def lambda_handler(event, context):
requests.post(os.environ.get("REQUEST_URL"))
return 'Hello from Lambda'

· 約11分
moritalous
お知らせ

過去にQiitaに投稿した内容のアーカイブです。

いい感じのチュートリアルを見つけたのでやってみました。 構成図も書いてみました。

例: AWS CLI を使用して IPv4 VPC とサブネットを作成 https://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-subnets-commands-example.html

完成形

Step3.png

環境

Windows 10 AWS CLI 1.15.10

AWS CLIのプロファイルを作成

qiitaという名前のプロファイルを作成。リージョンは東京にしました。

aws configure --profile qiita
AWS Access Key ID [None]:           <--- Access Keyを入力
AWS Secret Access Key [None]: <--- Secret Access Keyを入力
Default region name [None]: <--- ap-northeast-1を入力
Default output format [None]: <--- 未入力
aws configure list --profile qiita
      Name                    Value             Type    Location
---- ----- ---- --------
profile qiita manual --profile
access_key ****************PLCA shared-credentials-file
secret_key ****************rObp shared-credentials-file
region ap-northeast-1 config-file ~/.aws/config

ステップ 1: VPC とサブネットを作成する

AWS CLI を使用して VPC およびサブネットを作成するには

  • 10.0.0.0/16 CIDR ブロックを持つ VPC を作成します。
aws ec2 create-vpc --cidr-block 10.0.0.0/16 --profile qiita
{
"Vpc": {
"VpcId": "vpc-29b62c4e",
"InstanceTenancy": "default",
"Tags": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-4850cf20",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"Ipv6CidrBlockAssociationSet": [],
"State": "pending",
"DhcpOptionsId": "dopt-b3268cd6",
"CidrBlock": "10.0.0.0/16",
"IsDefault": false
}
}
  • 前の手順の VPC IDを使用して、10.0.1.0/24 CIDR ブロックを持つサブネットを作成します。
aws ec2 create-subnet --vpc-id vpc-29b62c4e --cidr-block 10.0.1.0/24 --profile qiita
{
"Subnet": {
"AvailabilityZone": "ap-northeast-1d",
"AvailableIpAddressCount": 251,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-29b62c4e",
"State": "pending",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-30eeea18",
"CidrBlock": "10.0.1.0/24",
"AssignIpv6AddressOnCreation": false
}
}
  • VPC で、10.0.0.0/24 CIDR ブロックを持つ 2 番目のサブネットを作成します。
aws ec2 create-subnet --vpc-id vpc-29b62c4e --cidr-block 10.0.0.0/24 --profile qiita
{
"Subnet": {
"AvailabilityZone": "ap-northeast-1d",
"AvailableIpAddressCount": 251,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-29b62c4e",
"State": "pending",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-45ede96d",
"CidrBlock": "10.0.0.0/24",
"AssignIpv6AddressOnCreation": false
}
}

構成図

Step1.png

ステップ2のカスタムルートテーブルを作ってないと、デフォルトのルートテーブルが作成されるようです。

ステップ2: サブネットをパブリックにします。

サブネットをパブリックサブネットにするには

  • インターネットゲートウェイを作成する.
aws ec2 create-internet-gateway --profile qiita
{
"InternetGateway": {
"Tags": [],
"Attachments": [],
"InternetGatewayId": "igw-9eda9dfa"
}
}
  • 前のステップの ID を使用して、VPC にインターネットゲートウェイをアタッチします。
aws ec2 attach-internet-gateway --vpc-id vpc-29b62c4e --internet-gateway-id igw-9eda9dfa --profile qiita

  • VPC に対してカスタムルートテーブルを作成します。
aws ec2 create-route-table --vpc-id vpc-29b62c4e --profile qiita
{
"RouteTable": {
"Associations": [],
"RouteTableId": "rtb-67c92101",
"VpcId": "vpc-29b62c4e",
"PropagatingVgws": [],
"Tags": [],
"Routes": [
{
"GatewayId": "local",
"DestinationCidrBlock": "10.0.0.0/16",
"State": "active",
"Origin": "CreateRouteTable"
}
]
}
}
  • インターネットゲートウェイへのすべてのトラフィック (0.0.0.0/0) をポイントするルートテーブルでルートを作成します。
aws ec2 create-route --route-table-id rtb-67c92101 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-9eda9dfa --profile qiita
{
"Return": true
}
  • ルートが作成され有効になっていることを確認するには、ルートテーブルを記述して結果を表示できます。
aws ec2 describe-route-tables --route-table-id rtb-67c92101 --profile qiita
{
"RouteTables": [
{
"Associations": [],
"RouteTableId": "rtb-67c92101",
"VpcId": "vpc-29b62c4e",
"PropagatingVgws": [],
"Tags": [],
"Routes": [
{
"GatewayId": "local",
"DestinationCidrBlock": "10.0.0.0/16",
"State": "active",
"Origin": "CreateRouteTable"
},
{
"GatewayId": "igw-9eda9dfa",
"DestinationCidrBlock": "0.0.0.0/0",
"State": "active",
"Origin": "CreateRoute"
}
]
}
]
}
  • ルートテーブルは現在、サブネットには関連付けられていません。サブネットからのトラフィックがインターネットゲートウェイにルーティングされるよう、ルートテーブルを VPC のサブネットに関連付ける必要があります。最初に、describe-subnets コマンドを使用してサブネット ID を取得します。--filter オプションを使用して新しい VPC のサブネットだけを返し、--query オプションを使用してサブネット ID と CIDR ブロックだけを返します。
aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-29b62c4e" --query 'Subnets[*].{ID:SubnetId,CIDR:CidrBlock}' --profile qiita
"Subnets[*].{ID:SubnetId,CIDR:CidrBlock}"

queryすると結果が出ない。。Windowsだとだめなのかな

aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-29b62c4e" --profile qiita
{
"Subnets": [
{
"AvailabilityZone": "ap-northeast-1d",
"AvailableIpAddressCount": 251,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-29b62c4e",
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-30eeea18",
"CidrBlock": "10.0.1.0/24",
"AssignIpv6AddressOnCreation": false
},
{
"AvailabilityZone": "ap-northeast-1d",
"AvailableIpAddressCount": 251,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-29b62c4e",
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-45ede96d",
"CidrBlock": "10.0.0.0/24",
"AssignIpv6AddressOnCreation": false
}
]
}
  • カスタムルートテーブルに関連付けるサブネット、例えば subnet-b46032ec を選択できます。このサブネットはパブリックサブネットになります。
aws ec2 associate-route-table  --subnet-id subnet-30eeea18 --route-table-id rtb-67c92101 --profile qiita
{
"AssociationId": "rtbassoc-b44659d2"
}
  • サブネット内で起動されたインスタンスがパブリック IP アドレスを自動的に受信できるよう、オプションで、サブネットの動作に対処しているパブリック IP を変更できます。これを行わない場合は、インターネットからインスタンスにアクセスできるよう、起動後に Elastic IP アドレスをインスタンスに関連付ける必要があります。
aws ec2 modify-subnet-attribute --subnet-id subnet-30eeea18 --map-public-ip-on-launch --profile qiita

もう一度サブネットの情報を取得

aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-29b62c4e" --profile qiita
{
"Subnets": [
{
"AvailabilityZone": "ap-northeast-1d",
"AvailableIpAddressCount": 251,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-29b62c4e",
"State": "available",
"MapPublicIpOnLaunch": true,
"SubnetId": "subnet-30eeea18",
"CidrBlock": "10.0.1.0/24",
"AssignIpv6AddressOnCreation": false
},
{
"AvailabilityZone": "ap-northeast-1d",
"AvailableIpAddressCount": 251,
"DefaultForAz": false,
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-29b62c4e",
"State": "available",
"MapPublicIpOnLaunch": false,
"SubnetId": "subnet-45ede96d",
"CidrBlock": "10.0.0.0/24",
"AssignIpv6AddressOnCreation": false
}
]
}

subnet-30eeea18MapPublicIpOnLaunchtrueになってますね。

構成図

Step2.png

ルートテーブルが2つになって、インターネットにアクセスできるサブネットとできないサブネットができました。

ステップ 3: サブネット内にインスタンスを起動する

パブリックサブネット内のインスタンスを起動して接続するには

  • キーペアを作成して、--query オプションと --output テキストオプションを使用し、.pem 拡張機能でプライベートキーをファイルに直接パイプします。 ※これもqueryが上手くいかない。。。
aws ec2 create-key-pair --key-name MyKeyPair --output text --profile qiita
ff:5b:2d:43:fa:cd:1e:f2:30:8a:fd:7a:38:6a:48:70:bc:ff:99:d1     -----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAnqussaU7076k4d56v4Wz5PpZDCfgKKTWTtCsoBD3nzyR6moFRzFAlZ2qi1Tq
(省略)
EZss5GqDXov5B23iXcK9E9iRSnyPNVxDHmM240eHOMKTZkoLog+jnEQhG9Y6pTaHJAM=
-----END RSA PRIVATE KEY----- MyKeyPair

-----BEGIN RSA PRIVATE KEY-----から-----END RSA PRIVATE KEY-----までをコピーしてテキストファイルに保存します。

  • VPC にセキュリティグループを作成し、SSH でどこからでもアクセスできるようにするルールを追加します。
aws ec2 create-security-group --group-name SSHAccess --description "Security group for SSH access" --vpc-id vpc-29b62c4e --profile qiita
{
"GroupId": "sg-1846be60"
}
aws ec2 authorize-security-group-ingress --group-id sg-1846be60 --protocol tcp --port 22 --cidr 0.0.0.0/0 --profile qiita

  • 作成したセキュリティグループとキーペアを使用して、パブリックサブネット内でインスタンスを起動します。出力内のインスタンスのインスタンス ID をメモしておきます。

※AMI IDはここでわかります。 https://aws.amazon.com/jp/amazon-linux-ami/

aws ec2 run-instances --image-id ami-ceafcba8   --count 1 --instance-type t2.micro --key-name MyKeyPair --security-group-ids sg-1846be60 --subnet-id subnet-30eeea18  --profile qiita
{
"Instances": [
{
"Monitoring": {
"State": "disabled"
},
"PublicDnsName": "",
"StateReason": {
"Message": "pending",
"Code": "pending"
},
"State": {
"Code": 0,
"Name": "pending"
},
"EbsOptimized": false,
"LaunchTime": "2018-04-30T02:17:53.000Z",
"PrivateIpAddress": "10.0.1.119",
"ProductCodes": [],
"VpcId": "vpc-29b62c4e",
"StateTransitionReason": "",
"InstanceId": "i-0b192396791d0afa0",
"ImageId": "ami-ceafcba8",
"PrivateDnsName": "ip-10-0-1-119.ap-northeast-1.compute.internal",
"KeyName": "MyKeyPair",
"SecurityGroups": [
{
"GroupName": "SSHAccess",
"GroupId": "sg-1846be60"
}
],
"ClientToken": "",
"SubnetId": "subnet-30eeea18",
"InstanceType": "t2.micro",
"NetworkInterfaces": [
{
"Status": "in-use",
"MacAddress": "0e:ca:57:b1:d0:d8",
"SourceDestCheck": true,
"VpcId": "vpc-29b62c4e",
"Description": "",
"NetworkInterfaceId": "eni-b22fa5ac",
"PrivateIpAddresses": [
{
"Primary": true,
"PrivateIpAddress": "10.0.1.119"
}
],
"SubnetId": "subnet-30eeea18",
"Attachment": {
"Status": "attaching",
"DeviceIndex": 0,
"DeleteOnTermination": true,
"AttachmentId": "eni-attach-a9d214cf",
"AttachTime": "2018-04-30T02:17:53.000Z"
},
"Groups": [
{
"GroupName": "SSHAccess",
"GroupId": "sg-1846be60"
}
],
"Ipv6Addresses": [],
"OwnerId": "781749372177",
"PrivateIpAddress": "10.0.1.119"
}
],
"SourceDestCheck": true,
"Placement": {
"Tenancy": "default",
"GroupName": "",
"AvailabilityZone": "ap-northeast-1d"
},
"Hypervisor": "xen",
"BlockDeviceMappings": [],
"Architecture": "x86_64",
"RootDeviceType": "ebs",
"RootDeviceName": "/dev/xvda",
"VirtualizationType": "hvm",
"AmiLaunchIndex": 0
}
],
"ReservationId": "r-0aedd8269b2d255bd",
"Groups": [],
"OwnerId": "781749372177"
}
  • インスタンスに接続するには、そのインスタンスが running 状態になっている必要があります。インスタンスを記述してその状態を確認し、パブリック IP アドレスを書き留めておきます。
aws ec2 describe-instances --instance-id i-0b192396791d0afa0 --profile qiita
{
"Reservations": [
{
"Instances": [
{
"Monitoring": {
"State": "disabled"
},
"PublicDnsName": "",
"State": {
"Code": 16,
"Name": "running"
},
"EbsOptimized": false,
"LaunchTime": "2018-04-30T02:17:53.000Z",
"PublicIpAddress": "18.182.20.38",
"PrivateIpAddress": "10.0.1.119",
"ProductCodes": [],
"VpcId": "vpc-29b62c4e",
"StateTransitionReason": "",
"InstanceId": "i-0b192396791d0afa0",
"EnaSupport": true,
"ImageId": "ami-ceafcba8",
"PrivateDnsName": "ip-10-0-1-119.ap-northeast-1.compute.internal",
"KeyName": "MyKeyPair",
"SecurityGroups": [
{
"GroupName": "SSHAccess",
"GroupId": "sg-1846be60"
}
],
"ClientToken": "",
"SubnetId": "subnet-30eeea18",
"InstanceType": "t2.micro",
"NetworkInterfaces": [
{
"Status": "in-use",
"MacAddress": "0e:ca:57:b1:d0:d8",
"SourceDestCheck": true,
"VpcId": "vpc-29b62c4e",
"Description": "",
"NetworkInterfaceId": "eni-b22fa5ac",
"PrivateIpAddresses": [
{
"PrivateIpAddress": "10.0.1.119",
"Primary": true,
"Association": {
"PublicIp": "18.182.20.38",
"PublicDnsName": "",
"IpOwnerId": "amazon"
}
}
],
"SubnetId": "subnet-30eeea18",
"Attachment": {
"Status": "attached",
"DeviceIndex": 0,
"DeleteOnTermination": true,
"AttachmentId": "eni-attach-a9d214cf",
"AttachTime": "2018-04-30T02:17:53.000Z"
},
"Groups": [
{
"GroupName": "SSHAccess",
"GroupId": "sg-1846be60"
}
],
"Ipv6Addresses": [],
"OwnerId": "781749372177",
"PrivateIpAddress": "10.0.1.119",
"Association": {
"PublicIp": "18.182.20.38",
"PublicDnsName": "",
"IpOwnerId": "amazon"
}
}
],
"SourceDestCheck": true,
"Placement": {
"Tenancy": "default",
"GroupName": "",
"AvailabilityZone": "ap-northeast-1d"
},
"Hypervisor": "xen",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"Status": "attached",
"DeleteOnTermination": true,
"VolumeId": "vol-06f8f3fc34c17685d",
"AttachTime": "2018-04-30T02:17:54.000Z"
}
}
],
"Architecture": "x86_64",
"RootDeviceType": "ebs",
"RootDeviceName": "/dev/xvda",
"VirtualizationType": "hvm",
"AmiLaunchIndex": 0
}
],
"ReservationId": "r-0aedd8269b2d255bd",
"Groups": [],
"OwnerId": "781749372177"
}
]
}

構成図

Step3.png

インターネット側へのアクセスが可能で、外部の任意のIPアドレスからのSSH接続が可能なインスタンスが起動しました。

手順 4: クリーンアップ

  • インスタンスを終了
aws ec2 terminate-instances --instance-id i-0b192396791d0afa0 --profile qiita
{
"TerminatingInstances": [
{
"InstanceId": "i-0b192396791d0afa0",
"CurrentState": {
"Code": 32,
"Name": "shutting-down"
},
"PreviousState": {
"Code": 16,
"Name": "running"
}
}
]
}
  • セキュリティグループを削除する:
aws ec2 delete-security-group --group-id sg-1846be60 --profile qiita

  • サブネットを削除する:
aws ec2 delete-subnet --subnet-id subnet-30eeea18 --profile qiita

aws ec2 delete-subnet --subnet-id subnet-45ede96d --profile qiita

  • カスタムルートテーブルを削除する:
aws ec2 delete-route-table --route-table-id rtb-67c92101 --profile qiita

  • VPC からのインターネットゲートウェイのデタッチ:
aws ec2 detach-internet-gateway --internet-gateway-id igw-9eda9dfa --vpc-id vpc-29b62c4e --profile qiita

  • インターネットゲートウェイの削除:
aws ec2 delete-internet-gateway --internet-gateway-id igw-9eda9dfa --profile qiita

  • VPC の削除:
aws ec2 delete-vpc --vpc-id vpc-29b62c4e --profile qiita

終わりに

次はCloudFormationに挑戦しようと思います。

· 約6分
moritalous
お知らせ

過去にQiitaに投稿した内容のアーカイブです。

[2018/9/2更新]


俺とか言ってごめんなさい。

MNISTを元に学習したモデルを使って、私の文字を認識させました。 全部ちゃんと認識できるんですよね?

ルール

  • 正しく認識する
    →MNISTの勝ち
  • 正しく認識しない
    →私の勝ち(字がヘタって言われている気もしますが。。)

学習モデルの生成

kerasにサンプルコードがあったのでそのまま利用。

mnist_cnn.py https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py

生成したモデルを保存する1行だけ追加しました。

model.save('mnist_model.h5')

学習結果はこちら。見方はよくわかりません。99%正解するってことでしょうか。 詳しい人ヘルプ!

  from ._conv import register_converters as _register_converters
Using TensorFlow backend.
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
60000/60000 [==============================] - 513s 9ms/step - loss: 0.2750 - acc: 0.9163 - val_loss: 0.0586 - val_acc: 0.9806
Epoch 2/12
60000/60000 [==============================] - 559s 9ms/step - loss: 0.0894 - acc: 0.9734 - val_loss: 0.0464 - val_acc: 0.9850
Epoch 3/12
60000/60000 [==============================] - 688s 11ms/step - loss: 0.0658 - acc: 0.9803 - val_loss: 0.0370 - val_acc: 0.9880
Epoch 4/12
60000/60000 [==============================] - 688s 11ms/step - loss: 0.0542 - acc: 0.9834 - val_loss: 0.0309 - val_acc: 0.9895
Epoch 5/12
60000/60000 [==============================] - 693s 12ms/step - loss: 0.0464 - acc: 0.9858 - val_loss: 0.0318 - val_acc: 0.9889
Epoch 6/12
60000/60000 [==============================] - 674s 11ms/step - loss: 0.0417 - acc: 0.9874 - val_loss: 0.0294 - val_acc: 0.9903
Epoch 7/12
60000/60000 [==============================] - 654s 11ms/step - loss: 0.0365 - acc: 0.9889 - val_loss: 0.0292 - val_acc: 0.9900
Epoch 8/12
60000/60000 [==============================] - 665s 11ms/step - loss: 0.0345 - acc: 0.9893 - val_loss: 0.0287 - val_acc: 0.9908
Epoch 9/12
60000/60000 [==============================] - 772s 13ms/step - loss: 0.0322 - acc: 0.9902 - val_loss: 0.0270 - val_acc: 0.9910
Epoch 10/12
60000/60000 [==============================] - 684s 11ms/step - loss: 0.0306 - acc: 0.9907 - val_loss: 0.0295 - val_acc: 0.9908
Epoch 11/12
60000/60000 [==============================] - 748s 12ms/step - loss: 0.0282 - acc: 0.9912 - val_loss: 0.0272 - val_acc: 0.9911
Epoch 12/12
60000/60000 [==============================] - 657s 11ms/step - loss: 0.0259 - acc: 0.9918 - val_loss: 0.0252 - val_acc: 0.9916
Test loss: 0.025242764521988738
Test accuracy: 0.9916

予測

以下のコードにて、予測させました。features.argmax()を予測した文字としてます。

## coding:utf-8

import keras
import numpy as np
from keras.models import load_model
from keras.preprocessing.image import array_to_img, img_to_array,load_img
import os
import re

model = load_model('mnist_model.h5')

def list_pictures(directory, ext='jpg|jpeg|bmp|png|ppm'):
return [os.path.join(root, f)
for root, _, files in os.walk(directory) for f in files
if re.match(r'([\w]+\.(?:' + ext + '))', f.lower())]

for picture in list_pictures('./tegaki/'):
X = []
img = img_to_array(
load_img(picture, target_size=(28, 28), grayscale=True))
X.append(img)

X = np.asarray(X)
X = X.astype('float32')
X = X / 255.0

features = model.predict(X)

print('----------')
print(picture)
print(features.argmax())
print('----------')

手書き文字の作成

iPadのGoogle Keepアプリで手書きのメモを作成。pngになったファイルを取得。こんな感じ。

スクリーンショット (304).png

MNISTの画像は黒背景に白文字のようなので、ペイントで加工しました。

Windows 7のペイントで画像の色を反転させる方法 https://121ware.com/qasearch/1007/app/servlet/relatedqa?QID=013654

画像のサイズは1694x2048ですがload_imgのときに画像サイズを変更しているので、そのまま利用しました。

試合開始

手書き画像予測結果勝敗
1.png1MNISTの勝ち
2.png2MNISTの勝ち
3.png3MNISTの勝ち
4.png4MNISTの勝ち
5.png5MNISTの勝ち
6.png6MNISTの勝ち
7.png1私の勝ち
8.png5私の勝ち
9.png4私の勝ち

試合結果

6勝3敗でMNISTの勝ち~ でも、3勝もしちゃった。。。 (7と1、8と5、9と4が似てると言われれば似てるような気もしますが。)

試しに画像を予めペイントで28x28にして試しても結果は同じでした。ちゃんと読めますよね?

スクリーンショット (307).png

モデル生成のソースコードに(there is still a lot of margin for parameter tuning).とあるので、もっとすごいモデルを使わないといけないのかな?

終わりに

あれ、こんなもん? 「ディープラーニングで行うペン習字講座」を期待したのですが先は遠そうです。 まずは「MNISTに勝たせる7の書き方講座」からですね。