クラウドインフラ構築記

現在AWSの構築支援に携わっております。今注視しているのは、GKE、BigQuery、Google Dataflowなどサービスを展開しているGoolge Cloud Platformです。

2017年3月19日
から hiruta
Committed Use DiscountsとSustained use discountの比較 #gcpug はコメントを受け付けていません

Committed Use DiscountsとSustained use discountの比較 #gcpug

Committed Use DiscountsがGCPでも使えるようになりましたので、すでに利用できている継続利用割引(Sustained use discount)と比べて、どの位安価か調べてみました。

https://cloud.google.com/compute/docs/instances/signing-up-committed-use-discounts?hl=en_US&_ga=1.230413599.2091612383.1481360112

Standardインスタンスタイプで比較(月単位、単位ドル)

n1-standard-1 n1-standard-2 n1-standard-4 n1-standard-8 n1-standard-16 n1-standard-32 n1-standard-64
 vCPU 1 2 4 8 16 32 64
Memory 3.75 7.5 15 30 60 120 240
commitment 28.03 56.05 114.60 224.21 448.41 895.83 1,793.65
Sustained use discount 31.17 62.74 125.08 249.77 499.14 997.87 1,995.34
full 44.53 89.06 178.12 356.24 712.48 1424.96 2,849.92
 Difference -3.14 -6.69 -10.48 -25.56 -50.73 -102.04 -1,055.69
※AWS相当タイプの1年前払いなし 46.72 76.01 151.18 302.35 603.85  N/A 2417.10

n1-standard-1程度ではCommitted Use Discountsでなくても、いいのでは。

継続割引の段階でも、AWSより安価でしたが、さらに安くなっている。

高スペックになればほど、Committed Use Discountsのメリットが享受できるとみられます。

2017年3月18日
から hiruta
Google Cloud Video Intelligence API を使ってみました。 #gcpug はコメントを受け付けていません

Google Cloud Video Intelligence API を使ってみました。 #gcpug

Video Intelligence APIのPrivate Beta使えるようになったので、少し感想を。

.MOV、.MPEG4、.MP4、.AVIの動画フォーマットは対応しているとのこと

顔認識、ラベル認識、そして、動画のシーンの区切りを認識できるようです。

  • Face detection
features = [enums.Feature.FACE_DETECTION]
operation = video_client.annotate_video(path, features

operation.result().annotation_results[0].
face_annotations
  • Label detection
video_service_request = video_service.videos().annotate(
body={
'inputUri': gcs_uri,
'features': ['LABEL_DETECTION']
})
response = video_service_request.execute()

labelData = response['response']['annotationResults'][0]['labelAnnotations']
  • Shot change detection

const request = {
inputUri: gcsPath,
features: ['SHOT_CHANGE_DETECTION']
};

video.annotateVideo(request)

const shotChanges = doneResponse[0].annotationResults[0].shotAnnotations;

の動画を、Cloud Video Intelligence API で解析したところ、44分ほどの動画でしたが、6分ほどで処理が完了。処理リージョンは、asia-east1を使用。

解析結果は以下jsonで返されます。

labelAnnotations[] ラベル認識結果一覧
labelAnnotations[].description ラベル認識結果
labelAnnotations[].languageCode
labelAnnotations[].locations[].segment.startTimeOffset ラベル認識された認識開始時間
labelAnnotations[].locations[].segment.endTimeOffset レベル認識された認識終了時間
labelAnnotations[].confiidence
labelAnnotations[].level
facelAnnotations[].segments.startTimeOffset 顔認識された認識開始時間
facelAnnotations[].segments.endTimeOffset 顔認識された認識終了時間
shotAnnotations[] シーンの変化
shotAnnotations[].startTimeOffset 認識開始時間
shotAnnotations[].endTimeOffset 認識終了時間

 

Cloud Vision APIとそう変わらない感じで使えるように見られます。画像と違って、処理に時間がかかることもあり、Botサービスで利用する場合、処理を受け付けた旨を返して、解析結果が出たら、結果を返す仕組みが必要と思われます。Line botのaccess tokenの有効期限は考慮は必要か。

2017年2月5日
から hiruta
Google Data Studioでカスタムクエリ #gcpja #gcpug はコメントを受け付けていません

Google Data Studioでカスタムクエリ #gcpja #gcpug

データのVisualizationツールであるGoogle Data Studioが完全に無料化されました。

ひっそり(?)カスタムクエリにも対応していました。

https://support.google.com/360suite/datastudio/answer/6370296?hl=en&ref_topic=6370347#custom_query

が、Standard SQLで、カスタイムクエリを作成すると、クエリは作成はできますが、レポートでグラフ部品を追加する際に、エラーとなります。

レポート上でグラフ部品を追加すると、

starts_widthはある文字で始めるフィールドでフィルタする際に使います。(Standard SQL)

legacy SQLだと、レポート上のグラフ表示は問題はないようです。

legacy SQLのみサポートしているのか。カスタムクエリのヘルプページ にもStandard SQLがダメだとは書いていないようです。

2017年1月22日
から hiruta
APIGateway + AWS Lambda とGoogle Cloud Functions のレスポンスタイムについて はコメントを受け付けていません

APIGateway + AWS Lambda とGoogle Cloud Functions のレスポンスタイムについて

AWS Lambdaには、直接HTTPアクセスすることができない。API Gatewayを使わないといけないので、レスポンス的にボトルネックになる場合があることを、先週のserverless meetup Tokyoであった。

直接HTTPでfunctionsをキックすることができるGoogle Cloud Functions (近々public beta)とのレスポンス時間をcurlにて計測してみた。

  • Google Cloud Functionsがus-central1(Council Bluffs, Iowa)なので、AWSのリージョンの中で近いus-east-2(オハイオ)で
  • 初期化処理がある初回は除く
  • curlコマンドで確認
  • Functions メモリ 256MB
  • Functionsは、hello worldレベル
API Gateway + Lambda Google Cloud Functions
 0.813  0.703
0.782  0.709 
0.775  0.775 
0.710  0.692 
0.600  0.733 
0.703  0.694 
0.774  0.748 
0.802  0.727 
0.582  0.426 
0.583  0.774 

さほどの差はありませんでしたが、若干Cloud Functionsの方がレスポンスは良かった。

2017年1月18日
から hiruta
Serverless Meetup Tokyo vol.2に参加しました。 #serverlesstokyo はコメントを受け付けていません

Serverless Meetup Tokyo vol.2に参加しました。 #serverlesstokyo

昨日Serverless Meetup Tokyo vol.2に参加しました。

Tune up AWS Lambda

Lambdaのパフォーマンスに関する話

知っておくべきこと

  • 同時実行数 ある時点にfunctionsが実行される数
    • ストリーム別
      •  シャードの数を大きくするとスケールしていく
      •  Lambdaの実行数は、シャードの数とイコール

セーフティガードとして、Limit = 100

    • それ以外
      •   一秒あたりのイベント数*実行時間

APIGatewayの時は秒間のリクエスト30s 30rps

同時実行数の制限緩和も可能だけど、実績がない場合は通らない。

実施にThrottleされているか確認

  • ライフサイクルコめコンテナ  Sandbox として動いている。dockerではない
    • 開始 コンテナ作成されて、コンテナ内にロード・展開(コールドスタート)
    • 終了
    • 再利用※時間が経っていない場合は、再利用される
      • 初期化処理は再利用されるのでパフォーマンス的なアドバンテージがある
      • 再利用されるとは保証するわけではない
  • パフォーマンス関連
    • メモリ設定

コンピューティング全体の設定なので、CPU必要な場合はあげるといい

    • バッチサイズ

 一度に取得する最大のレコード数

シャード数増やすことで同時処理数も増えるので、どちらがいいかはワークロード次第

  • Lambda functionを速くする方法
    • 定常的にリクエストする

ファンクションにたいしてPingするなり、ポーリングする処理を実装する

推奨の間隔は五分

    • コンピューティングリソースを増やす
    • 言語を変える

スピンアップの順番は、Java <  C# <  python < node.js

    • VPC使わない

ENIの生成、アタッチ処理は遅い

    • パッケージサイズを小さくする

Javaの場合、ProGuard等難読化ツールでパッケージを小さくできる

Lambdaの場合、使用するモジュールをコードに同封しないといけない。

    • グローバルスコープ
    • 同時実行性

インフラエンジニア”リング”レスアーキテクチャ

AzureFunctions 処理数1,200/ ピーク 3,700/分捌いている。

AzureFunctionsは、bashでコードを書ける。Functions内で、perlも使えてしまう。

Serverless AWS構成でセキュアなSPAを目指す

Cloudfront + Amazon S3に一応Serverless

API Gateway + Lambdaになってしまうので、レイテンシ問題がある

Google Cloud FunctionsとかAzureFunctionsだとHTTP(S) Trigger機能があるので、レイテンシでどの程度違うかは別途検証してもようと。

STSのCredential有効期限(最大1H)とCognito Token(最大24H)なので、気をつける

Json Web Token https://blog.kazu69.net/2016/07/30/authenticate_with_json_web_token/

Data + No-Ops

データ処理、No-Opsでできる

プラットフォーム作らないくてもいい

より良いソフトウェアを作るのに力を費やすのがいい

Googleでは、Billionユーザの大きなデータを日々受け取っている

BigQuery の外にあるデータも分析できる

https://cloud.google.com/bigquery/external-data-sources

Bigqueryでは、構造化したデータしか扱えないので、複雑な処理はGoogle Dataflow

2016年12月29日
から hiruta
Google Cloud FunctionsでLINE Botサーバーを立てる #gcpug #gcpja はコメントを受け付けていません

Google Cloud FunctionsでLINE Botサーバーを立てる #gcpug #gcpja

Cloud Functions でLINE Botサーバーを立ててみました。

LINE BOTアカウントの作成、LINE@MANAGERの設定は以下を参照

http://qiita.com/saitoryc/items/9f5833495d1e0453e052

AWS Lambdaの場合API Gatewayと併用しないといけないが、Google Cloud FunctionsだとHTTP Triger (HTTPS)でFunctionsを実行できるので、便利です。

LINE BOTサーバーはHTTPS通信できることが必要ですが、Cloud functions HTTP TriggerはHTTPSに対応済みなので、この点問題はありません。

実際のコードですが、Cloud Functions用の引数に変更する点と、HTTP通信でMessageAPIサーバに送信する際、Content-Lengthヘッダーを付与するようにしています。付与しないとMessageAPIサーバーからBad Requestと返ってきます。この点、LINE developersのドキュメントには記載されていません。


var gcloud = require('gcloud')({
projectId: process.env.GCP_PROJECT
});
var https = require('https');
var channel_access_token = '[ACCESS TOKEN]';

exports.linebot = function (req, res) {
var json = req.body;
json.events.forEach ( function(message,index){
events = message;
});
var postData = {
"replyToken" : events.replyToken,
"messages" : [
{
"type" : "text",
"text" : events.message.text
}
]
};
var options = {
hostname: 'api.line.me',
path: '/v2/bot/message/reply',
headers: {
"Content-type": "application/json; charset=UTF-8",
"Authorization": "Bearer " +channel_access_token,
"Content-Length": JSON.stringify(postData).length
},
method: 'POST',
};

var req = https.request(options, function(res){
res.on('data', function(chunk){
}).on('error', function(err){
console.log(err);
}).on('end', function(){
console.log('finish sending text message');
});
});
var sendData = JSON.stringify(postData);
req.write(sendData);
req.end();
};

Cloud Vision APIとかGoogleAPIと連携も可能かと思われます。

Content-Lengthで文字数をカウントする際、postData.lengthの代わりにBuffer.byteLength (postData)で文字数をカウントすることで日本語とかも送信が可能になりました。

2016年12月18日
から hiruta
ParquetデータをAmazon Athenaで検証してみました。 #jawsug #gcpug はコメントを受け付けていません

ParquetデータをAmazon Athenaで検証してみました。 #jawsug #gcpug

BigQueryで公開データとして公開されているNOAA Global Historical Climatology Network の天候データを、エクスポートして、Amazon Athenaで使用してみました。

Column-oriented フォーマットにカテゴリ分けされる Parquetに変換して検証してみました。

ParquentへのConvertはApache Drillを使用

0: jdbc:drill:zk=local> ALTER SESSION SET `store.format` = 'parquet'
. . . . . . . . . . . > ;
+-------+------------------------+
| ok | summary |
+-------+------------------------+
| true | store.format updated. |
+-------+------------------------+
1 row selected (1.655 seconds)

CTASクエリでの変換だと、VARCHARとして扱われてしまうので、カラム毎の型を設定しておく必要があります。それをしないと、Athenaでクエリ実行時、internal errorとなってしまいます。

0: jdbc:drill:zk=local> CREATE TABLE dfs.tmp.`/ghcnd_2016/` AS SELECT
. . . . . . . . . . . > id,
. . . . . . . . . . . > `date`,
. . . . . . . . . . . > `element`,
. . . . . . . . . . . > CAST(`value` AS FLOAT) AS `value`,
. . . . . . . . . . . > mflag,
. . . . . . . . . . . > qflag,
. . . . . . . . . . . > sflag,
. . . . . . . . . . . > `time`
. . . . . . . . . . . > FROM dfs.`/tmp/ghcnd_2016_ja.csvh`;
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
+-----------+----------------------------+
| Fragment | Number of records written |
+-----------+----------------------------+
| 0_0 | 174292 |
+-----------+----------------------------+
1 row selected (3.755 seconds)

気象観測所のデータはCTASクエリによる変換で済ませています。

ParquentのファイルをS3にアップロードし、Athenaのテーブルを作成します。

CREATE EXTERNAL TABLE IF NOT EXISTS athena_test_1.ghcnd_2016 (
id string,
date string,
element string,
value float,
mflag string,
qflag string,
sflag string,
time string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
'serialization.format' = '1'
) LOCATION 's3://athena-test-data01/parquent/ghcnd_2016/';
CREATE EXTERNAL TABLE IF NOT EXISTS athena_test_1.ghcnd_stations (
id string,
latitude float,
longitude float,
elevation float,
state string,
name string,
gsn_flag string,
hcn_crn_flag string,
wmoid int
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
'serialization.format' = '1'
) LOCATION 's3://athena-test-data01/parquent/ghcnd_stations/';

データ数は以下となっています。

ghcnd_2016 174292
ghcnd_stations 100820

Amazon Athenaの実行結果

Row-orientedのCSVファイルの結果。データスキャンサイズが、Column-orientedの場合に比べて、4倍。

BigQueryでの実行結果

BigQueryと比較して、2秒差、スキャンサイズがBigQueryの1/2の結果になりました。

 

2016年12月9日
から hiruta
Google Cloud Functions で環境変数を使うには(Tipsネタも) #gcpug はコメントを受け付けていません

Google Cloud Functions で環境変数を使うには(Tipsネタも) #gcpug

Google Cloud Platform(1)  Advent Calender 12/10分で書きました。

Runtime Configurationsはまだα版なので、今後仕様が変わる可能性があるかもしれません。

AWS Lambda、Azure Functionsとかでは、環境変数を扱えるので、Google Cloud Functionsでも使いたい願望が。

現状、Google Cloud functionsで環境変数を扱うことはできない。

ただ、Google Cloud FunctionsのEarly Access用Google Groupに環境変数を対応する予定があるか、聞いたところ、現状Runtime Configuration FundamentalsでGoogle Cloud Client libraryでは、対応しておらず、low-level APIのRuntime Configurationで行う必要がる。(Google Cloud Client libraryで対応してほしい。)

Runtime Configurationが対応しているGoogle APIはv1、v2には対応していないので注意。

https://cloud.google.com/deployment-manager/runtime-configurator/

Runtime Configの作成

gcloud alpha deployment-manager runtime-configs create functions-prod
gcloud alpha deployment-manager runtime-configs variables set TEST-KEY abcd1234efgh5678 --config-name functions-prod 

function auth (callback) {
var google = require('googleapis');
google.auth.getApplicationDefault(function (err, authClient) {
if (err) {
callback(err);
return;
}

if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped([
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/cloudruntimeconfig'
]);
}
callback(null, authClient);
});
}

function getVariable(configName, variableName, callback) {
var google = require('googleapis');
var config = google.runtimeconfig('v1beta1');

var fullyQualifiedName = 'projects/' + process.env.GCLOUD_PROJECT +
'/configs/' + configName +
'/variables/' + variableName;

auth(function(err, authClient) {
config.projects.configs.variables.get({
auth: authClient,
name: fullyQualifiedName
}, function(err, variable) {
if (err) {
callback(err);
return;
}
// decode the value as values are saved as base64-encoded strings
callback(null, Buffer.from(variable.value, 'base64').toString());
});
});
}

exports.myFunction = function (req, res) {
getVariable('functions-prod', 'TEST-KEY', function(err, stripeKey) {

// do something involving "stripeKey"

res.send('OK');
});
};

GoogleAPIs Node.js clientは8.0.0で確認。

また、Functionsでエラーになった場合、ErrorReportingと連携できるようになっています。

screencapture-console-cloud-google-errors-13056176819937875897-1481114893469

 

functions.env 変数でRuntime Configの環境変数を取れるようになるらしい。

As an FYI for anyone using the Firebase tools for Cloud Functions, the functions.env variable is built using Runtime Config as well.

Tipsネタをいくつか。

GCSトリガーでfunctionsを実行する際、lacks permissionとか発生するケースが。

edit object default permission でcloud functions用Service Account (Service Account名はCloud functionからBigQueryに登録した際にエラーメッセージの中から見つけました)を登録することで解決。以前はこの設定なくてもうまくいっていたんだけど。

error_2

Google Cloud Clinent library for node.jsのバージョンによって、発生しました。発生したバージョンは、0.35.0。Google Cloud Client library は、0.44もでているようだが、使えないバージョンもあるので、注意が要。動作がOKだったバージョンは、0.28.0でした。

error_3

12/9 の0:00ごろ?WEB Consoleでcloud functionsのインライン編集に対応していました。新規でfunctionsを作成すると、現仕様のサンプルコードが自動生成されます。下記はCloud Vision APIでLabel Detectionを使う例になります。package.jsonの編集にも対応していて、便利です。

inlineditor

 

2016年12月5日
から hiruta
Amazon AthenaのPartitioningについて #jawsug #gcpug はコメントを受け付けていません

Amazon AthenaのPartitioningについて #jawsug #gcpug

https://cloud.google.com/storage/docs/public-datasets/landsat からダウンロードできるデータで、Amazon Athenaをつかって、クエリを実行してみました。

テーブル構成は以下の通りです。

CREATE EXTERNAL TABLE athena_test.landsat_data_csv (
SCENE_ID STRING,
PRODUCT_ID INT,
SPACECRAFT_ID STRING,
SENSOR_ID STRING,
DATE_ACQUIRED DATE,
COLLECTION_NUMBER STRING,
COLLECTION_CATEGORY STRING,
SENSING_TIME timestamp ,
DATA_TYPE STRING,
WRS_PATH INT,
WRS_ROW INT,
CLOUD_COVER decimal ,
NORTH_LAT decimal,
SOUTH_LAT decimal,
WEST_LON decimal,
EAST_LON decimal,
TOTAL_SIZE decimal,
BASE_URL STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
ESCAPED BY '\\'
LINES TERMINATED BY '\n'
LOCATION 's3://athena-test-data01/csv/';

単一のCSVでは、Partitioningでデータスキャンする容量を減らすことは不可。(Partitioningのために、S3上でフォルダが分かれてファイルが配置されていないといけないため)

Amazon Athenaの課金は、スキャンするサイズによるので、課金にもろ響きます。Athena破産の可能性も。

screencapture-console-aws-amazon-athena-home-1480936289615

データスキャンした容量は、968MB (CSVのファイルサイズと同じなので、全スキャン)が読まれます。

screencapture-bigquery-cloud-google-results-cms-production-1225-bquijob_780f3acf_158cebfd84f-1480937513091

一方、同じクエリでBigQueryで実行させるとほとんどスキャンされないで結果が返る。

BigqueryのようなことがAthenaでできると思ったら、間違いです。

2016年12月4日
から hiruta
GCPUG Shonan vol.9 (re:dash、Data Studio)によるVisualization #gcpug はコメントを受け付けていません

GCPUG Shonan vol.9 (re:dash、Data Studio)によるVisualization #gcpug

GCPUG Shonan vol.9が本日ありました。お題は、BigQueryのデータのre:dash、DataStudioによるVisualization(可視化)でした。

サンプルデータのBigQueryへのインポート

 bq load --source_format=CSV --field_delimilter=',' --skip_loading_rows=1 --max_bad_records=1000 redash_shonan_handon.taxi gs://bq_shonan_handon/taxi.csv ./schema.json

Cloud Launcherにより、re:dashインスタンスの作成

※re:dash自体は、mac os x上のDocker上にも作ることは可能です。

IAMの設定だけでは、BigQuery Userの権限を与えておいても、re:dashでSELECT SQLすら権限がないよとなっていまいます。

Error running query: { "error": { "errors": [ { "domain": "global", "reason": "accessDenied", "message": "Access Denied: Table XXXXXXXXXXXXXXXXXXX:billing.201612: The user bqclient@XXXXXXXXXXXXXXXXXXX.iam.gserviceaccount.com does not have permission to query table XXXXXXXXXXXXXXXXXXX:billing.201612." } ], "code": 403, "message": "Access Denied: Table XXXXXXXXXXXXXXXXXXX:billing.201612: The user bqclient@XXXXXXXXXXXXXXXXXXX.iam.gserviceaccount.com does not have permission to query table XXXXXXXXXXXXXXXXXXX:billing.201612." } }

BigQueryのdatasetにおいて、Share datasetで最低Service Account名で権限を付与する必要があります。

screencapture-bigquery-cloud-google-queries-cms-production-1225-1480852442942

BigQueryの権限付与もIAMで一括して行ってほしい。

re:dash自体、0.12.0+b2449 (Cloud Launcherのばーじょんは少し古い)となっており、発展途上なところもあり、使い勝手的に?なところもあります。

Google Data Studio ( FREE版はレポートは5つまで)の紹介。re:dashはSQL(legacy SQL/Standard SQL)で組み立てるのが、Data Studioは、クエリの組み立てのカスタマイズは高くない。ただ、緯度経度情報があれば、MAPのコンポーネントがあるので、地図上にBigqueryのデータをplotすることは可能。コンポーネントについては揃っているように見えました。

(おまけ)re:inventで発表されたAmazon Athenaについて

Amazonが、BigQueryを意識して作ったと思いますが、Partitioning しないとCOUNTでもすべてのデータをスキャンしていまうこと。Partitioning Data することで、スキャンする量を制限はできそうですが。

Colossusの仕組みをAthenaで実現するのは不可能ではと思われる。