Monthly Archives: 11月 2017

2017-11-29

PhpStorm(Intellij IDEA)のプラグイン作ってみる

GMOアドマーケティングのSSP開発チームのT.Kです。
コードレビューで処理を追いかける際にPhpStormを良く使いますが
ビューからコントローラへのジャンプが出来ず、不便に感じていました。
既存のプラグインで対応できるかもしれませんが、ブログの執筆を兼ねて
ビューから呼び出しコントローラを検索するプラグインを作ってみます。

環境構築
プラグインの開発はJavaとIntelliJ IDEAを使う必要があるので、公式からDLしてインストールします。

プロジェクトを作成
IntelliJ IDEAを起動したら、下記の手順でプロジェクトを作成します。

  • [File] -> [New] -> [Project] でプロジェクト作成画面を開く
  • [IntelliJ Platform Plugin] を選択して [Next] をクリック
    リストに[IntelliJ Platform Plugin]が無い場合は
    [File] -> [Settings] -> [Plugins] から [Plugin DevKit] を有効にしてください
  • [Project name] を入力して [Finish] をクリック

plugin.xmlを編集
プラグインの基本情報や依存関係などの設定ファイルです。
初期状態ではPHPStormで動作しないので、下記行のコメントを外します。

アクションを作成する
プロジェクトツリーのsrcディレクトリを右クリックして
[New] -> [Plugin DevKit] -> [Action] でアクション作成画面を開きます。

[Action ID] [Class Name] [Name] を入力します。

アクションの種類が大量にあり、全体を把握するには無理がありました。
今回はコンテキストメニューに追加したいので [PopupMenu] で検索し
[Groups] から [EditorPopupMenu(Editor Popup Menu)]
[Actions] から [EditorPopupMenu1(Editor Popup Menu Actions(1))] を選択しました。

[OK] をクリックするとクラスファイルが作成されます。
plugin.xmlを見ると <actions> に作成したアクションの情報が追加されています。

コードを書く
作成されたクラスファイル内のactionPerformedに処理を実装します。

動かしてみる
[Run] -> [Debug Plugin] から実行すると、 IntelliJ IDEA が別プロセスで起動します。

jarファイルの作成
[Build] -> [Prepare Plugin Module ‘<module name>’ for Deployment] で jar ファイルを作成します。

PhpStormにインストール
[File] -> [Settings] -> [Plugins] -> [Install plugin from disk] から作成した jarファイルをインストール
PhpStormを再起動すると反映されます。

PhpStormで動作確認
コンテキストメニューを開くと作成したプラグインの項目が追加されています。

実行すると検索結果が表示され、コントローラへのジャンプが楽になりました。

まとめ
Java初心者で最初は不安でしたが
IDEの補助と公開されているコードを参考に、最低限の機能は実装できました。
検索オプションでまだ不明な箇所があるので、引き続き調査&改良していきたいです。

2017-11-27

Go言語でGoogle Cloud StorageへのUploadとBigQueryで集計

GMOアドマーケティングに中途入社してまもないy.yです。

11/5(日)のGo Conferenceの内容についてまとめようと思っていたのですが

補欠からくり上がれなかったので今回はGo言語を使って

Google Cloud Storageへのアップロードをし、BigQueryでの集計手順について記載します。

 

本題に入る前にGo言語を選んだ理由

マスコットキャラクターのGopherくんが可愛かった 😀

Gopherくんはホリネズミという動物がモチーフらしいです。

どうでしょう?世界のミッキー○ウス並みにGopherくん可愛くないですか??

引用元:Gopherくん入門

@tentenのGopher by tenntenn CC BY 3.0

 

公式のGopherくんはきも可愛いですね 😀

引用元:The Go Blog

The Go Blog by Google CC BY 3.0

Gopherくんについて詳しく知りたい方は Gopherくん入門 へ!

 

Gopherくんが可愛いから選んだというのは冗談で

実際は下記の2点でGo言語を選択しました。

  1. いくつかの言語でパフォーマンスを計測した結果、Go言語のパフォーマンスが一番良かった。
  2. 並列処理でログをparseするのにGo言語が簡単だった。

 

ここから本題の手順を記載いたします。

  • 認証

 

  • Google Cloud Storageへのアップロード

ContentType 型:String

ContentTypeを指定します。

ChunkSize 型:Int

指定したサイズを上限にオブジェクトを分割してアップロードする指定。

1回のリクエストでアップしたい場合はCunkSizeを指定。

上限を指定しない場合は0または無指定。

オプションの詳細はこちら

容量の大きいObjectをUploadする際はネットワークに影響しないように制限した方がいいかもしれないですね。

 

  • BigQueryへLoad

AllowJaggedRows 型:bool

不正なレコードがあった場合、NULLとして扱うかエラーとして扱うかを選択します。

MaxBadRecords 型:Int

不正なレコード数を許容するレコード数を指定します。

Compression 型:String

Google Cloud StorageにuploadされたLoadするObjectの圧縮タイプを指定します。

FileDelimiter 型:String

Loadされるファイルのdelimiterを指定します。

オプションの詳細はこちら

圧縮されたファイルをLoadをする場合はCompression、CSV形式ではないファイルをLoadする場合はFileDelimiterを指定しましょう。

 

  • BigQueryで集計

UseLegacySQL 型:bool

オプションの詳細はこちら

LegacySQLを使用する場合はUseLegacySQLをtrueにしましょう。

 

ここまででGoogle Cloud Storageへのアップロード、BigQueryでの集計手順は終わりです。

どういったオプションがあるのか確認するのに時間が多少かかりましたが

アップロード、集計までの処理はサクッと簡単に書くことができました。

Go言語に関してまだまだ初心者なのでまずは中級者を目指したいと思います。

以上、Google Cloud Storageのアップロードから BigQueryでの集計の手順でした。

 

エンジニア採用

弊社は、広告をより便利な物にしていく事を一緒に目指してくれるエンジニアを募集しています。

エンジニア採用 | GMOアドパートナーズ株式会社

GMOアドパートナーズグループのエンジニア採用サイトです。

 

2017-11-20

軽量アプリケーションサーバ NGINX Unitを触ってみる

こんにちは、GMOソリューションパートナー媒体開発本部のN.Sです。

先日NGINX社より軽量アプリケーションサーバNGINX Unitのベータ版リリースがありました。
各言語毎のアプリケーションサーバ運用を一本化出来るメリットがありそうですが、
今後の選択肢として、導入の手間、操作感、パフォーマンスはどうなの?という事で簡単に触ってみました。

NGINX Unitとは?

  • https://www.nginx.com/products/nginx-unit/
  • 2017.9.7に発表されたばかりのNGINX社製 軽量アプリケーションサーバ。
  • 2017.9.28現在でv0.1ベータ版、特徴は主に以下です。
    • RESTful APIやJSON経由でサービス無停止でリアルタイムに設定変更が出来る
    • 複数言語に対応(PHP, Python, Go対応、今後Java, Ruby, Node.jsにも対応予定
    • 将来的に既存の商用NGINX + NGINX Unit にGUI管理機能のNGINX Controllerを加えて統合プラットフォームを作る構想がある
      https://oss.sios.com/nginx-ch/nginxconf2017

 

CentOS7コンテナにNGINX Unitをインストールしてみる

NGINX Unit導入の前提環境は以下です。

  • Linux2.6以上
  • Python 2.6, 2.7, 3
  • PHP 5系、7系
  • Go 1.6以上

今回はテスト環境として以下を使用しました。

  • Dockerコンテナ環境構築
  • ホストOSは、ローカルPCにVagrant+ VirtualBoxで構築したCentOS7.4
  • コンテナ環境はCentOS 7.4.1708/Linux3.10.0 + NGINX Unit 0.1 + PHP5.4.45

今回行う導入・設定を実施済のDockerコンテナ環境は以下です。
とりあえず環境を見たい方はこちらをご覧ください。
※実行手順はリンク先の「起動方法」参照

https://hub.docker.com/r/oshou/docker-centos7-unit/

1. CentOS7コンテナ起動、コンソールログイン

管理者モードでCentOSプレーンのコンテナ起動起動、NGINX Unitで動かすサンプルアプリケーション用にport8300を通しておきます。

2. NGINX Unit用レポジトリ作成

CentOS7 or Ubuntu16.04TLSはunitインストールパッケージが提供されているので、今回はそちらを使います。

3. NGINX Unitインストール

4. 設定用ツール インストール

Unitデーモンの設定は、UNIXドメインソケットへのリクエストにより行うので、
curl(v7.40以上)をインストールします。
※v7.40以上でないとドメインソケット対応オプション –unix-socketが使えません。
CentOS7では以下手順で別途レポジトリを定義してインストールしました。
https://www.rootlinks.net/2017/09/21/update-curl-7-29-to-7-55-on-centos-7-with-city-fan-repo/

5. NGINX Unitデーモンの起動

デーモンの起動を確認します。
unitdは管理用のTCPポート等は存在せず、UNIXドメインソケット通信により設定を行います。

Unitの初期設定をしてみる

1. 設定用jsonファイルの作成

listeners(待機するTCPポート設定)とapplications(遷移先のアプリケーション設定)は必須なのでそれぞれ以下要領で指定します。
詳しいパラメータは下記を参照下さい。
https://unit.nginx.org/docs-configuration.html#listener-and-application-objects

2. 設定用jsonファイルをunitデーモンに投入

リクエストメソッド、設定用jsonファイル、socketファイル、配置先URLをそれぞれ指定してリクエストを行います。
socketファイルはデフォルトだと/var/run/control.unit.sockです。

設定は以上です!簡単ですね。
注意点としては以下です。

  • curlがv7.40以上になっている事(–unix-socketオプション指定でエラーが発生しない事)
  • socketファイルのパスが正しく指定されている事(デフォルトだと/run/control.unit.sock)
  • HTTPメソッドが正しく設定されている事

3. 設定反映の確認

それでは正しく動作しているか確認してみましょう。
設定内容は設定先URLにGETリクエストを送ることで確認できます。

反映直後から指定したTCPポートでリッスンされる事が確認出来ました。

DocumentRootの場所にphpinfo()表示用スクリプトを配置してみます。
http://[Docker親ホストIP]:8300/[スクリプト名]にアクセスして正しく表示された事が確認できました。

ちなみに複数サーバ設定時はlisteners, applicationsでそれぞれ並列表記します。
一覧性があり見やすいですね

一部設定を動的変更する場合はパラメータに対応した特定URLにPUTリクエストを送ります。
例えばworkersを20->30に変更する場合は、
http://localhostの/applications/sample_php/workers宛に更新データを-dオプションで送るだけで即反映されます。

 

簡易的なベンチマークを行ってみる

それではNGINXサーバ連携で置換え検討機会の多そうなphp-fpmと比較してみましょう。
テスト環境は以下です。

テスト環境

  •  比較環境
  • アプリケーションサーバは基本デフォルト設定、worker数MAX値だけ10で統一
  • サンプルスクリプトは以下
  • Apache Benchで計測
  • 以下で計測(同時接続数100、総リクエスト数10000、keepaliveを使用しない)

テスト結果

APサーバ スループット(req/s) 平均レスポンスタイム(ms/req) エラー率(%)
NGINX Unit 423.12 2.363 0
php-fpm 571.13 1.751 0

不本意ながらphp-fpmの方が早い!という結果が出てしまいました、、、
実施後の所感としては以下でした。

  • 同一ホストでコンテナ環境もミドル部分以外は統一しているため、他影響ではなくアプリサーバ側の性能差が取れていそう
  • ps aux等で見るとNGINX Unitは子プロセスのメモリ効率が悪い印象を受けた。RSS=実際に使用した物理メモリ がphp-fpmの約4倍だった。
    • php-fpm側が5.94MB、NGINX Unit側が26.04MB程度
  • php-fpmのpm.start-serverにあたるものが無いため初回コストがかかっている
  • 他Go、Python言語等でも性能差比較してみたい

まとめ

  • CentOS7、Ubuntu向けにパッケージ提供されているので導入は簡単、CentOS6系等は公式手順でソースインストールが必要
  • 比較的軽量でサクサク動く印象だが、本検証ではphp-fpmには及ばずでした。
    他言語でも比較して傾向を見たい所ですが、PHPに関してはメモリ効率部分で今後に期待したい所でした。
  • JSONベースの設定が使いやすい。
    一覧性が高く、config.jsonだけ抑えておけばOKな手軽さが良い。動的設定変更も可能。
    ただし、初回起動時に設定用JSONファイルを都度PUTリクエストする必要があるので注意
  • モニタリング、権限管理機能等は今後登場予定のNGINX Controller側で実装される(?)
    • https://oss.sios.com/nginx-ch/nginxconf2017
  • 複数言語でアプリケーションサーバを一本化、という事が出来そうですが、
    ベータ版という事であまり詳細なパラメータはまだ公開されていない模様。
    php-fpmで言う pm.start-server(初回起動時のワーカー数)やpm.max_requests (メモリリーク対応)、slowlog(スローログ取得)等にあたるものが今後出てくると嬉しい。

2017-11-16

TerraformでGCP環境を構築してみる

はじめまして。GMOアドマーケティングでインフラを担当しているa.sです。
今回はTerraformを用いて、GCP上に検証環境を構築する機会がありましたので、構築に伴う一連の作業をご紹介します。


構築内容


既存のオンプレミス環境から接続可能なKVSサーバ環境を構築します。
目的として、オンプレミス環境上に構築しているKVSサーバを物理的にスケールする作業のコストを
クラウド化することで下げたいというものです。

以下のような構成になります。


  • KVSサーバはGCPで提供されているCentOS7のイメージを使用して構築します。
  • オンプレミス環境とGCP環境の通信はVyOSとGCP上のVPN Gatewayで暗号化して行います。
  • KVSへの接続は内部ロードバランサを介して各KVSサーバにバランシングする設計としています。
  • Terraformのtfstateファイルの管理はGCS(Google Cloud Storage)上で行います。
  • Terraformで作成したインスタンスのミドルウェア等の管理は踏み台サーバ(bastion Server)上からansibleで行います(本ブログでは触れません)。

残念ながら、VPN環境は現時点では構築できていないため、その他のGCPリソースをTerraform化したもののご紹介となります。


Terraformを使用する事前準備


予め用意しておくもの

  • TerraformとCloud SDKをインストール可能な環境
    弊社ではCentOS7の環境で実施します。
  • GCPのプロジェクト
    GCPの環境を構築するためにGCP上でプロジェクトを作成しておきます。
  • 作成したGCPのプロジェクトでAPIを有効化
    こちらを参考に、作成したGCPプロジェクトで「Google Compute Engine API」を有効化しておきます。

Google Cloud Console上からTerraform用のサービスアカウントを作成する

TerraformとCloud SDKのAPI認証用にGoogle Cloud Console上からサービスアカウントを作成します。

1.Google Cloud Consoleログイン後、画面左側から「IAM & admin」を選択し、「Service accounts」を選択します。

2.遷移した画面上部にある「CREATE SERVICE ACCOUNT」を選択します。

3.「Service account name」に適当な名前を入力し、「Role」部で必要な権限を選択します。
今回はGCE(Google Compute Engine)及びGCSを操作するために、
「Compute Admin (beta)」及び「Storage Admin」を付与します。


鍵が必要になるので、json形式の鍵を選択して、「CREATE」を選択します。
この鍵は再ダウンロードが出来ないので、大切に保管します。
※鍵の再設定は可能なので、万が一鍵を紛失した際は再設定を行います。

何かと使えるのでGCP用のCloud SDKのインストールと認証
※本ブログではGoogle Cloud Storageのbucket作成にしか使いません

Terraform実行サーバでCloud SDKのインストール及び、認証作業を実施します。

公式ドキュメントの「yum(Red Hat と CentOS)」部を参考にしています。

1.リポジトリを登録します

2.yumでCloud SDKをインストールします

3.Cloud SDK及びTerraformを操作するユーザにスイッチし(任意)、作成したサービスアカウントのjsonを設置します

4.Cloud SDKで作成したサービスアカウント及びGCPのプロジェクトを認証します

5.認証した情報を確認します。

tfstateファイルをGoogle Cloud Storage上で管理するため、保存するためのバケットを作成する

Terraformはデフォルトだと「terraform.tfstate」という名前のファイルで管理対象のインフラの状態を保存しています。
Terraformはこのファイルに基づいて、インフラの構成の変更などを検知し、必要に応じてリソースの作成や削除、変更などを行っています。
チームでTerraformを運用する場合、各々でtfstateファイルの状態が異なると矛盾が生じてしまうため、今回の場合はGCS上にtfstateファイルを保持することで情報の一貫性を保ちます。

Cloud SDKインストール時に併せてインストールされるgsutilコマンドを用いてGCS上にtfstateファイルを保存しておくためのバケットを作成します。

gsutilコマンドの各オプションの意味は以下の通りです。

  • mb
    バケットを作成します
  • -p 
    作成するバケットの対象プロジェクト名を指定します
  • -c
    作成するストレージクラスを指定します
  • -l
    バケットロケーションを指定します
  • gs://example_tf-state-prod/
    「gs://バケット名/」として作成するバケットを指定します

Terraformのインストール

Terraformのインストールを行います。
今回はTerraform実行ユーザの「~/terraform」以下にインストールします。

インストール後、以下コマンドでバージョンが確認できればインストールに成功しています。


Terraformのコードを書く


Terraformの実行環境が整ったところで、ここからは実際にTerraformのコードを書いていきます。
Terraform構成の構文はHashiCorp Configuration Language、HCLという言語で記述します。
「*.tf」という拡張子を持つファイルにコードを書くことで、Terraformがそれをテンプレートとして自動的に認識します。

Terraform用に適当なディレクトリを作成して、その中に設定ファイルを作成していきます。
今回作成する「*.tf」ファイルの構成は以下の通りです。今回は分かりやすくするために各機能ごとにファイルを分けました。

以下からは個別に設定ファイルと、設定内容の詳細を記載します。

provider.tf

接続するプロバイダー(今回はGCP)を設定します。

  • provider
    接続先を設定します。今回はgoogleとなります
  • credentials
    認証情報を設定します。作成したサービスアカウントから発行されたjsonのkeyのパスを指定します
  • project
    対象のプロジェクトを設定します
  • region
    対象のリージョンを設定します

backend.tf

tfstateファイルをGCS上で管理するための設定です。

  • backend
    対象のバックエンドサービス(gcs)を指定します
  • bucket
    作成したバケットを指定します
  • path
    対象のtfstateファイルのパスを指定します
  • credentials
    認証情報を指定します。作成したサービスアカウントから発行されたjsonのkeyのパスを指定します

variables.tf

各設定ファイル内で使用する変数を設定します。
変数は “${var.変数名}” の形で使用します。

  • variable “region”
    「asia-northeast1」を変数”region”に登録します
  • variable “region_zone”
    「asia-northeast1-a」を変数”region_zone”に登録します
  • variable “bastion_ssh_keys”
    “bastion_ssh_keys”という変数に「exampleadmin」ユーザと、そのユーザ用の公開鍵(ssh-rsa 〜)を登録しています。
    ここで登録したユーザはsudo権限が与えられた状態でサーバに設定され、併せて公開鍵を登録しているので秘密鍵ログインが可能になります
  • variable “kvs_ssh_keys”
    「variable “bastion_ssh_keys”」と同様です

network.tf

カスタムVPCネットワークを設定します。

  • resource “google_compute_network” “example”
    ネットワークリソースを作成します
    name
    ネットワークの一意の名前を設定します。ここでは「example」としています
  • resource “google_compute_subnetwork” “subnet1”
    サブネットワークリソースを作成します
    ・name
    サブネットワークの一意の名前を設定します。ここでは「subnet1」としています
    ・ip_cidr_range
    作成するネットワークレンジを設定します。ここでは「192.168.10.0/24」を設定しています
    ・network
    このサブネットワークが属する親ネットワークを設定します。ここでは直前で作成した「example」ネットワークを設定しています
    ※「${google_compute_network.example.name}」とは、「google_compute_network」というリソースの中の「example」というリソースの中の「name」に当たるものという意味で、ここでは
    「resource “google_compute_network” “example”」内で設定されている「name = “example”」を指定しているということになります。
    ・description
    このサブネットワークの説明となります
    ・region
    このサブネットワークが属するリージョンを設定します

bastion.tf

GCEでbastion Serverを構築するための設定です。

  • resource “google_compute_address” “bastion01”
    bastion Serverに割り当てる静的グローバルIPアドレスリソースを設定します
    name
    一意の「bastion01」というリソース名を設定します
    region
    静的グローバルIPアドレスリソースを作成するリージョンを設定します。
  •  resource “google_compute_instance” “bastion01”
    作成するGCEインスタンスリソースの情報を設定します
    name
    一意の「bastion01」というリソース名を設定します
    machine_type
    作成するインスタンスのマシンタイプを設定します
    zone
    インスタンスを作成するゾーンを設定します
    tags
    インスタンスに付与するタグのリストを設定します
    boot_disk
    インスタンス作成に使用するOSイメージを設定します
    metadata_startup_script
    サーバ起動時に流すコマンドを設定できます
    ここではSSHのポートを10022で使用できるようにし、GCPのCentOS7のイメージはデフォルトUTCなためJSTに変更しています
    network_interface
    インスタンスに接続するネットワークを設定します
    ここではnetwork.tfで作成したネットワークからの静的プライベートIPを割り振り、
    「resource “google_compute_address” “bastion01” 」で作成した静的グローバルIPを割り振ります。
    metadata
    ここではSSH用の公開鍵を登録しています。個別にインスタンスに公開鍵を登録するため「block-project-ssh-keys」を有効化します。「sshKeys」には変数で登録した公開鍵を指定します

kvs.tf

GCEで3台のKVS Serverを構築するための設定です。3台とも同スペックで構築するためリソース名に変数を使って一つの設定で3台分のインスタンスを作成することも出来るのですが、このように1台1台個別に設定しないと後述の「instancegroupes.tf」で設定するインスタンスグループに登録できなかったためこのような記述となりました
静的グローバルIPアドレスリソースの設定が無いことを除いて、こちらの説明は「bastion.tf」と重複するため割愛します

firewall.tf

ファイアウォールルールを設定します。項目が多いためそれぞれピックアップして説明します。
「xxx.xxx.xxx.xxx/xx」となっている箇所は弊社固定IPになります。

  • resource “google_compute_firewall” “allow-icmp”
    「example」ネットワーク内の「bastion」タグが付いたリソースに対してソースIPからicmpを許可しています
  • resource “google_compute_firewall” “allow-tcp-10022”
    「example」ネットワーク内の「bastion」タグが付いたリソースに対してソースIPから10022番ポートを許可しています
  • resource “google_compute_firewall” “allow-tcp-8091”
    「example」ネットワーク内の「kvs」タグが付いたリソースに対してソースIPから8091番ポートを許可しています
  • resource “google_compute_firewall” “allow-internal”
    「example」ネットワーク内の「server」タグが付いたリソースに対してソースIPから全ての通信を許可しています
  • resource “google_compute_firewall” “allow-internal-lb”
  • resource “google_compute_firewall” “allow-health-check”
    これらの設定は内部ロードバランサ及びヘルスチェックのアクセスを、「example」ネットワーク内の「kvs」タグが付いたリソースに対して許可しています。内部ロードバランサからのアクセスを許可する設定は公式ドキュメントを参考にしています

instancegroupes.tf

内部ロードバランサから各インスタンスにバランシングさせるためには、対象のインスタンスをインスタンスグループとして登録する必要があります。今回は非マネージドインスタンスグループとして作成します。インスタンスグループに関して詳しくは公式ドキュメントをご参照下さい。

  • resource “google_compute_instance_group” “kvs-group”
    インスタンスグループを作成します。
    ・name
    インスタンスグループの名前を設定します
    ・description
    作成するインスタンスグループの説明です
    ・zone
    インスタンスグループを作成するゾーンを指定します
    ・instances
    インスタンスグループに登録するインスタンスを指定します
    今回はkvs.tfで作成するインスタンスを指定しますが、他のケースで使用する場合にも基本的には以下の形で指定の形で問題ないと思います
    ${google_compute_instance.インスタンス名.self_link}
    ※self_linkとは、作成されたリソースのURIを示します。基本的にTerraform側でGCP側から動的に取得してくれます。

internallb.tf

内部ロードバランサの設定を行います。ここでは実際の内部ロードバランサの設定とともに、ヘルスチェックと転送ルールも併せて設定しています。

  • resource “google_compute_health_check” “kvs-health-check”
    内部ロードバランサが使用するヘルスチェックリソースを設定します
    ・name
    ヘルスチェックリソースの一意の名前を設定します
    check_interval_sec
    ヘルスチェックの間隔を設定します
    timeout_sec
    接続失敗を判断するまでの秒数を設定します
    tcp_health_check
    ヘルスチェック接続先のポートを設定します
  • resource “google_compute_region_backend_service” “kvs-int-lb”
    内部ロードバランサを設定します
    name
    バックエンドサービスの名前を設定します
    protocol
    使用するプロトコルを設定します。ここではTCPを指定しています
    health_checks
    使用するヘルスチェックリソースを設定します。ここでは先程設定した「kvs-health-check」を指定しています
    timeout_sec
    接続要求が失敗したと判断するまで待機する時間を設定します
    session_affinity
    使用するアフィニティ機能を設定します。詳細はTerraformの公式ドキュメントと、GCPの公式ドキュメントを参照して下さい
    region
    バックエンドが存在するリージョンを設定します。ここでは「variables.tf」で設定した変数を利用しています
    backend
    作成する内部ロードバランサを利用するインスタンスグループを設定します
  • resource “google_compute_forwarding_rule” “kvs-int-lb-forwarding-rule”
    内部ロードバランサが利用する転送ルールを設定します
    name
    転送リソースの一意の名前を設定します
    load_balancing_scheme
    使用するロードバランシングのタイプを設定します。今回は内部ロードバランサなので「INTERNAL」を指定しています
    ports
    内部ロードバランサに使用するポートを設定します。このポート宛のパケットが、この転送ルールで指定したバックエンドサービス(kvs-int-lb)に転送されます
    region
    転送ルールを使用するリソースが存在するリージョンを設定します
    network
    負荷分散対象のネットワークを設定します。ここでは「network.tf」で作成した「example」ネットワークを指定します
    subnetwork
    負荷分散対象のサブネットワークを設定します。ここでは「network.tf」で作成した「subnet1」ネットワークを指定します
    backend_service
    転送ルールに一致したパケットの転送先のバックエンドサービスを設定します。ここでは先程作成した「kvs-int-lb」を指定します
    ip_address
    パケットを最初に受信する静的IPを設定します。この場合だとクライアント側からは「192.168.10.100:11210」宛にKVS用のパケットを送信することになります。

ここまででTerraformのコードの準備が出来ました。


Terraformの実行


コードの準備ができたら、実際にTerrafomを実行してGCP上にリソースを構築します。

コードの検証
先ずは 「terraform validate」コマンドを使用して作成したコードの構文チェックを行います。

実行した結果、何も表示されなければ構文に問題はありません。
エラーが出た場合はその内容に沿ってコードの修正を行う必要があります。

実行計画
構文に問題がなければ、次に「terraform plan」コマンドを実行してGCP上のリソースにどのような変更を加えるか、実行計画を確認します。このコマンドを実施しても実際のGCPリソースに変更は加えられません。

実行した内容を確認し、実際にコードの内容通りに変更が加えられるかどうかなどをチェックします。

適用
実行計画に問題がなければ、「terraform apply」コマンドを使用して実際にコードをGCPリソースに適用します。

実行した内容を確認し、エラーなどが出ていなければGCP上にリソースが作成されているはずです。
後は実際にGoogle Cloud Console上や、「terraform show」コマンドなどでリソースの情報を確認してみましょう。

 


Terraformで作成したリソースの削除


Terraformで作成したリソースを全て削除する場合は以下の通り実行します

リソースの削除計画の確認
先ず「terraform plan -destroy」コマンドを使用してどのリソースを削除するのかを確認しておきます。このコマンドを実施しても実際のGCPリソースに変更は加えられません。

実行した内容を確認し、削除対象に問題がないことを確認します。

リソースの削除
terraform destroy」コマンドを使用して実際に削除処理を行います。実行後確認プロンプトが出てくるはずなので、「yes」を入力して実行を進めます。

実行した内容を確認し、エラーが出ていないことと、対象リソースが削除されていることを確認します。
また、Google Cloud Console上でも同様にリソースが削除されていることを確認できると思います。

まとめ

今回はGCP上のリソースをTerraformで作成する場合の一連の作業と、各設定ファイルの詳細、リソースを削除するまでをご紹介しました。
Terraformはまだ検証のみの使用であるため、ご紹介できた機能はごく一部だと思いますが、同じようにGCPリソースをTerraformで管理を始めたような方に少しでもご参考になれば幸いです。

2017-11-14

GitHubのWebhook活用

2017年7月からGMOアドマーケティングのSSP開発チームにJoinしたK.Mです。
先日、試用期間も無事終え落ち着きました。
GMOアドパートナーズグループには、住宅補助手当という
オフィスビル近隣に住んでいる人が対象となる福利厚生があるので、
そろそろオフィスビル近くに引越かと考えています。

早速本題です。

Webhookってなに?

Webhookとは特定の条件を満たした際に他のアプリケーション/URLへリクエストする仕組みとなります。
SSP開発チームでは今回紹介するGitHubの他にSlackのWebhookも活用しています。

活用事例

SSP開発チームはGitHubのレビュー機能を利用したGitHubフローで開発しています。
Pull Request = レビュー依頼ではないため、レビュー依頼はラベル機能を利用していますが、
レビューNGとなった場合、主に3つ問題がありました。

  • Pull Requestの一覧上のレビュー結果が見辛い
  • ラベルが放置され、レビュー依頼中なのか、修正中なのかの判断がつかない
  • ラベルが放置されガチだったため、”[WIP]”とタイトルに付けるPRが散見された

上記のような問題を抱えていたため、
GitHubのWebhookを利用し、レビュー結果を元にラベルの張替を実現しました。
ラベル張替をWebhookに任せる事で、以下のメリットがありました。

  • ラベルがついていない = 開発/修正中
  • ラベルがついている = レビュー依頼中/レビュー完了
  • “[WIP]”が消えました

実装コード例

Webhook設定

去年の10月に追加されたPullRequestReviewEventを利用します。
まず、GitHub側のWebhook設定を行います。
Webhookを適用したいリポジトリのページから Settings > Webhooks と遷移し、 Add webhook から新規にWebhookを追加します。
今回は Let me select individual events. を選択し、 Pull request review のみにチェックを入れます。

Access Token取得

ラベル張替用のAccess Tokenを生成します。
アカウント情報の Settings > Developer settings > Personal access tokens にアクセスし、 Generate new token から新規にトークンを発行します。
利用しているリポジトリに応じ public_reporepo にチェックを入れます。

リクエスト先の設定例

SSP開発チームではPHP、JavaScript、Ruby、Goで開発を行っていますが、
今回はPHPでの実装例となります。

GitHubのdeveloperガイドに記載ありますが、GitHubからみたPull Requestはissueと大差ありません。

Labels, assignees, and milestones

その事を踏まえた上で、下記実装を行いました。

まとめ

ラベルの張替は対応時間としては微々たるものですが、日々の業務で開発者全員にちょっとした気遣いを強いるものでした。
そのちょっとした気遣いを自動化する事で意識せずに済むようになったためチーム内で好評でした。

リクルーティング

GMOアドマーケティングではBigQuery、機械学習など新しい技術に興味のあるエンジニアに限らず、
開発効率の向上に積極的なエンジニアを募集しています。

エンジニア採用 | GMOアドパートナーズ株式会社

GMOアドパートナーズグループのエンジニア採用サイトです。

 

2017-11-09

機械学習入門者がKerasでマルチレイヤーパーセプトロンのサンプルを読む

こんにちは。
GMOアドマーケティング、機械学習入門者のT.Mです。

はじめに

ゼロから作るDeep Learningを読み終え、
実際に何か作るにあたって何をしたらよいか調べていたところ
ニューラルネットワークのライブラリであるKerasを知り触ってみました。
いきなりKerasのサンプルソースを見てもさっぱり分からなかったので、
ゼロから作るDeep Learningで学習した内容とKerasドキュメントを参照しながら
見ていきたいと思います。

Kerasについて

Kerasについては公式ドキュメントを参照ください。
TensorFlow上で動く、ニューラルネットワークをより簡単に書けるようにした
ライブラリという認識です。

サンプルソース

Keras公式のサンプルソースから、
ゼロから作るDeep Learningでも5章までガッツリと書かれていたMLP(マルチレイヤーパーセプトロン)のサンプルを見ていきます。

サンプルソースを読む

サンプルソースから引用しながら見ていきます。
Kerasのライセンス表記です。

Copyright (c) 2015, François Chollet.
Copyright (c) 2015, Google, Inc.
Copyright (c) 2017, Microsoft, Inc.
Copyright (c) 2015 – 2017, the respective contributors.
Released under the MIT license
https://github.com/fchollet/keras/blob/master/LICENSE

最初の部分ですが、MNISTのデータをロードし、ニューラルネットワークに取り込めるようにデータを変換しています。

どのようなニューラルネットワークなのかを定義しています。
Sequentialモデルはニューラルネットワークの各層を順番につなげたモデルを表します。
add()で層を追加していきます。
https://keras.io/ja/getting-started/sequential-model-guide/

最初の層として追加しています。
どんな層かというと、Dense()で定義されています。
このDenseは、全結合ニューラルネットワークになります。
この1行だけで1つのニューラルネットワークを表しています。
https://keras.io/ja/layers/core/#dense
Kerasのソースの方にも、
https://github.com/fchollet/keras/blob/master/keras/layers/core.py#L729
Just your regular densely-connected NN layer.
とあり、
Dense implements the operation:
output = activation(dot(input, kernel) + bias)
と、ゼロから作るDeep Learningにも出てきたA・W+Bというニューラルネットワークになります。

このDenseの引数を見ると、下記の通りになっています。

  • units・・・出力の数
  • activation・・・活性化関数。reluを指定しています。
    https://keras.io/ja/activations/#relu
    活性化関数については、この記事も参照ください。
  • input_shape・・・最初の層のときにだけ指定します。入力層の形を指定します。MNISTで扱う28×28=784のデータのことを表しています。

ドロップアウトの層になります。
ドロップアウトは、ゼロから作るDeep Learningの6章にも出てきました。
過学習を避けるために出力結果を間引くようになります。
引数はレートを指定します。

第2層目のニューラルネットワークです。
出力の次元数は512、活性化関数は前回と同じくreluです。

またドロップアウトを指定しています。

最後に出力層として、次元数10(0〜9の数字なので)、活性化関数はSoftmaxを指定しています。
ここまでがSequentialモデルで定義したニューラルネットワークになります。

次に、compileメソッドは訓練の定義をします。
https://keras.io/ja/models/sequential/#compile

  • loss・・・損失関数を指定します。ここでは、categorical_crossentropyが指定されています。
    MNISTのような多クラス分類では、categorical_crossentropyを使用します。
  • optimizer・・・最適化アルゴリズムを指定します。RMSpropを指定しています。
    https://keras.io/ja/optimizers/#rmsprop
    ゼロから作るDeep Learningには出てこない最適化アルゴリズムです。
    書籍で出てきた内容としては、SGD、Adagrad、Adamがあります。
  • metrics・・・評価関数を指定します。通常はmetrics=[‘accuracy’]を指定するとのこと。
    https://keras.io/ja/metrics/

fitは、ニューラルネットワークの訓練を行います。
https://keras.io/ja/models/sequential/#fit

  • 第1引数、第2引数・・・入力データとなります。
  • batch_size・・・バッチサイズを指定します。
  • epochs・・・訓練を行う回数を指定します。
  • verbose・・・指定する数値により実行ログの出す内容が変わります。
  • validation_data・・・評価用のデータを指定します。
  • 戻り値・・・訓練の損失値と評価関数値が返ってきます。

evaluateは、損失値を計算します。
https://keras.io/ja/models/sequential/#evaluate

  • 第1引数、第2引数・・・評価用の入力データを指定します。
  • verbose・・・進行状況の表示を指定します。0は出しません。
  • 戻り値・・・テストデータの損失値を返します。

まとめ

いかがだったでしょうか?
最初はどこから手を付けたらよいか分かりませんでしたが、
ゼロから作るDeep Learningで学習した知識をベースに
Kerasのドキュメントを参照することでほんの少し読めるようになったと思います。
次は自分でニューラルネットワークを作っていきたいです。

2017-11-02

あなたが選ぶなら、どのエンジニアの職種?

GMOアドマーケティングのKMです。気が付けば、IT業界20年です(笑)
エンジニアの人は自分の得意分野って把握している?キャリアプランは?
エンジニアを目指す人や理解したい人も参考になればと思い職種について書きます。

IT(Information Technology: 情報技術)エンジニアも様々な職種があり、
GMOインターネットグループでも、大きく分けて下記5つがあります。
http://recruit.gmo.jp/engineer/guide/

🙂 アプリケーションエンジニア
😎 インフラエンジニア
😐 データベースエンジニア
😮 スマホアプリエンジニア
😛 フロントエンドエンジニア

メガネしてチェックのシャツ来ているイメージですが、
27職種に細かく分けて求人している会社もあり、
職種や適性については実は様々なんです。

今回は、大きく分けた上記5職種について説明しますが、
非エンジニアの方は、スマホを使っている気持ちで、
下記を読んで頂けるとイメージが湧くと思います。

■職種

・アプリケーションエンジニア 🙂 
→アプリケーションとは、コンピュータで、使用者の業務に応じて作成したプログラムを意味するので、使用者の目的や要件を汲み取って、利用シーン、利用される為の運用まで考えて、理想的に自動で動く仕組み(システム)を作るエンジニア。
★適性は、人がやる仕事を自動化したいとか、物作りや部品化が好きな方、
システムが直近から中長期に使われて、ビジネスと共に成長していくイメージを行う事が好きな方。

♥ 嬉しい事:世の中に広く使われる事。
× 悲しい事:作った物が使われず、無駄になる事。
○【トリセツ】:良い企画を出して優先順位を間違えないであげましょう。

・インフラエンジニア 😎 
→システムが動作する為のネットワークやハードウェア(機器)の環境構築及び
通信やシステムの正常稼働を監視する設定などを行うエンジニア。
★適性は、新しい機器の操作や、システムが稼働する構成を考える事が好きな方。
システムが稼働するベースとなる機器を設定するので慎重な面もあるとベスト。

♥ 嬉しい事:アプリケーションエンジニアと連携して開発したり、原因を特定しづらい、トラブルシューティングで問題を見つけた時。
× 悲しい事:障害を未然に防ぐ、あまり表に出ないので評価されない事もある。
○【トリセツ】:機器の故障、障害など昼夜問わず発生するので、消防士にように守ってくれる事、理解して感謝しましょう。

・データベースエンジニア 😐 
→大量データを高速に集計したり、最適化の為の分析を行うエンジニア。
★適性は、整理整頓好きで、合理的な効率化が好きなタイプ。

♥ 嬉しい事:求める結果が、効率良く検索でき早く返却される事。
× 悲しい事:検索結果が要求された速度で得られない事。
○【トリセツ】:F1のように限界まで効率化に対する意識や、お願いしたデータを素早く抽出してくれたり、意味を持たないデータを、価値ある法則を導き出す事ができるので、尊敬してあげましょう。

・スマホアプリエンジニア 😮 
→ブラウザで見るサイトではなく、専用のiPhone/Androidアプリを作る
エンジニア。
★適性は、ゲームなどアプリでしか実現できない事や利便性に関心があり、
その為なら、新しい言語を習得する事を苦にしないタイプ。

♥ 嬉しい事:Webでは実現できない高度な機能を開発し、世の中に広く使われる事。
× 悲しい事:制約が多く、実現したい事が実現できない。
○【トリセツ】:むしろ複雑な事を相談して、頼りにしましょう。きっと解決してくれます。

・フロントエンドエンジニア 😛 
→ユーザーへ見せる画面表示を担当するエンジニア。
★適性は、他人に対する見え方、見せ方に関心があり、
ユーザーに気持ち良く使ってもらう為に導線に配慮したり、
工業デザインを意識して画面が考えられるタイプ。

♥ 嬉しい事:自分が作った機能がサクサクと動いて、意図通りユーザーが使ってくれる事。
× 悲しい事:画面でJavaScriptエラーが発生し、うまく動かない時。
○【トリセツ】:目的を明確に伝えて、きっと素敵なインターフェースを一緒に考えてくれる筈。

ITは情報技術なので、情報の伝達や連携という意味でコミュニケーションやチームワークが必要な一方、自動車作りのように、電力供給からネジ作り等の専門性も必要で職種が分かれています。
上記で隣接する職種は関連する事が多いので、2つ以上の職種を兼任しているエンジニアもいますし、上3つの職種の知識が多い人を、バックエンドエンジニアと総称する事もあります。

システムは、VR、ロボット、自動運転、IoT等、社会のニーズが常に発生していますが、どれも上記、職種のエンジニアが活躍しているので、どの職種を選択するかは、適性や好みと、仕事の「イメージが湧くか 」で良い思います。海外のエンジニアは殆どが理系のようですが、日本でもその傾向はありまして、仕事内容から内向的な方がスティーブ・ジョブズのようにいい物を作る印象です。

最後に
弊社は、現在、広告をより便利な物にしていく事を、一緒に目指してくれるエンジニアを募集しています。
https://www.wantedly.com/companies/gmo-am/projects

尚、どの職種も、以下のような工程がありますので、次回説明したいと思います。
「要件定義」、「設計」、「開発」、「テスト」、「稼働」、「運用」