kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Unsplash API (unsplash_rb) を試した

写真サービスだと Unsplash が大好きで,気分転換に見ることも多いし,発表資料の背景写真はほとんど Unsplash から引っ張ってきている.全ての写真を自由に使えるし,シンプルなサービスながら,非常にクオリティが高い.

Unsplash 関連ツール

公式で Chrome 拡張も提供されていて,Unsplash Instant を使うと,新規タブの背景写真を Unsplash からランダムに取得できるようになってオススメ!

chrome.google.com

あと,最近だと Trello と Unsplash の連携があり,Trello のタスクボードの背景写真を Unsplash から引っ張ってくることができるようになった.この機能も気に入ってて,定期的に背景写真を変えて Trello に飽きないように工夫している.

trello.com

Unsplash API

そんな Unsplash から API が提供されていることを最近知って,さらに Ruby ラッパーも公式で提供されていたため,少し試してみた.事前に Application ID を取得しておく必要がある.なぜ今まで知らなかったのだろう!

unsplash.com

github.com

サンプルコード

ザッと書いてみた.キーワード検索だけじゃなく,キュレーション検索もできるし,ランダム検索もできる.また,写真によっては Exif 情報も取れるし,ロケーションも取れる場合もある.他にもまだまだ多くのレスポンスが返ってくるので,詳しくはドキュメントを参照してもらえればと.あと,utm パラメータを付けないとダメなど,ある程度のガイドラインがあるため,実際にアプリケーションに組み込む場合は,確認しておく必要がありそう.

require 'unsplash'
require 'active_support'
require 'active_support/core_ext'

Unsplash.configure do |config|
  config.application_id = ENV['UNSPLASH_APPLICATION_ID']
  config.application_secret = ENV['UNSPLASH_SECRET']
  config.application_redirect_uri = 'https://example.com/callback'
  config.utm_source = 'example_app'
end

def info(photo)
  # Basic
  puts "===== #{photo.id} ====="
  puts photo.width
  puts photo.height

  # Exif
  if photo.exif.present?
    puts photo.exif.make
    puts photo.exif.model
    puts photo.exif.iso
  end

  # Location
  if photo.location.present?
    puts photo.location.city
    puts photo.location.country
  end

  # URL
  if photo.urls.present?
    puts photo.urls.raw
    puts photo.urls.full
    puts photo.urls.thumb
  end
end

# Find by id
photo = Unsplash::Photo.find('srDN5nHM35g')
info(photo)

# Search by keyword
search_results = Unsplash::Photo.search('mountain', page = 1, per_page = 3)
search_results.each do |photo|
  info(photo)
end

# Search curation ( latest, oldest, popular )
search_results = Unsplash::Photo.curated(page = 1, per_page = 3, 'popular')
search_results.each do |photo|
  info(photo)
end

# Search random
photo = Unsplash::Photo.random
info(photo)

Ruby 以外の公式ライブラリ

PHP と js も提供されていた!

github.com

github.com

Unsplash Team の Hiring も発見して,Rails Engineer ならリモート歓迎って書いてある.気になるなー!

unsplash.com

組織パフォーマンスを改善しよう!

今週,社内で「技術的負債」をテーマにしたイベントがあり,トーク枠で発表をしてきた.タイトルは「技術的負債を "なるべく" 作らないためのコツ」で,意図的に技術の話をせずに,エモ系のストーリーに仕上げた.

特に伝えたかった部分は最後の「組織パフォーマンス」を改善する Tips で,雑談の重要さ,質問の重要さ,相互理解の重要さ,表情の重要さなどを語った.その中でも「ノンバーバルなコミュニケーション」の Tips はイベント中も気になっていて,発表者がもっと気持ちよく話せるように反応しましょー!と,緊張をほぐすようなアプローチもした.

もっと「組織パフォーマンス」を改善していきましょ!!!

発表資料

関連記事

「組織パフォーマンス」を改善する Tips はコーチングの文脈からもインスパイアされていて,コーチングを学ぶならまずこの本から読むのが良いのではないかなと思う.

kakakakakku.hatenablog.com

プレゼンのコツは最近まとめたので,参考になれば!

kakakakakku.hatenablog.com

CyberAgent Developers Blog

会社ブログも書いた!

developers.cyberagent.co.jp

Apex の --env オプションを使って Lambda を複数環境にデプロイする

最近仕事で必要になり,CircleCI + Apex を使って,Lambda を複数環境 (prd / stg / dev など) にデプロイできる仕組みを作ったので,実現したかったこと,工夫したことなどを紹介したいと思う.ちなみに,以前も似たような事例で CloudWatch Events + Lambda + CircleCI + Apex を使ったアーキテクチャを紹介したが,これはあくまで開発ツールの位置付けなので,複数環境の考慮が必要なく,単純に apex deploy を実行するだけの非常にシンプルな構成になっていた点が異なる.

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

エイリアスは採用しなかった

「実践 AWS Lambda」にも書いてある通り,Lambda にはエイリアスという機能があり,特定のバージョンに prd / stg / dev など,任意のエイリアスを付けて識別することができる.単純にバージョンと環境を紐付けるだけなら便利だと思うが,今回は以下の要件を満たしたいと考えていて,エイリアスで環境を識別するアプローチは採用しなかった.プロダクションで Lambda を使う場合,基本的には以下の要件はあると思う.

  • 環境ごとに異なる環境変数を設定する
  • 環境ごとに制御した IAM ロールを設定する
  • 環境ごとに異なるコンピューティングリソースを設定する

kakakakakku.hatenablog.com

複数環境デプロイ

公式ドキュメントにも記載がある通り,Apex は複数環境 (Multiple Environments) のデプロイに対応している.特に難しいことはなく,環境ごとの設定ファイルを用意して --env オプションを指定することで,環境別にデプロイを行うことができる.なお,環境ごとの設定ファイルには大きく2種類あり,粒度によって使い分けることができる.

  • project.json … 複数の Lambda 関数で共通して参照する設定ファイル
  • function.json … Lambda 関数ごとに参照する設定ファイル

今回作ったデプロイフローはザッと以下のようになる.

f:id:kakku22:20170620212838j:plain

事前作業

環境ごとに IAM ロールが必要になるため,事前に作成しておく.今回サンプルとして prd / stg / dev を作成した.

  • arn:aws:iam::00000000000:role/prd-myfunc_lambda_function
  • arn:aws:iam::00000000000:role/stg-myfunc_lambda_function
  • arn:aws:iam::00000000000:role/dev-myfunc_lambda_function

IAM ポリシーの設定は割愛するが,公式ドキュメントに Lambda のポリシーテンプレートが公開されていて,様々なユースケースを網羅しているため,非常に便利!

docs.aws.amazon.com

Apex ディレクトリ構造

Apex ディレクトリ構造は以下のようになる.project.*.json はルートディレクトリに配置して,function.*.json は Lambda 関数のメイン処理と同じディレクトリに配置している.なお,今回は2個の Lambda 関数をデプロイできるようにした(ランタイムは Python).

├── circle.yml
├── functions
│   ├── myfunc1
│   │  ├── function.dev.json
│   │  ├── function.prd.json
│   │  ├── function.stg.json
│   │  ├── main.py
│   │  └── requirements.txt
│   └── myfunc2
│       ├── function.dev.json
│       ├── function.prd.json
│       ├── function.stg.json
│       ├── main.py
│       └── requirements.txt
├── project.dev.json
├── project.prd.json
└── project.stg.json

project.*.jsonfunction.*.json

設定項目としては同じで,粒度が異なるだけなので,今回は project.dev.json を例に載せる.

{
  "name": "dev-myfunc",
  "description": "dev-myfunc",
  "memory": 128,
  "timeout": 5,
  "role": "arn:aws:iam::00000000000:role/dev-myfunc_lambda_function",
  "environment": {
    "XXX": "xxx",
    "YYY": "yyy",
    "ZZZ": "zzz"
  }
}

このように設定することで,今回の要件を全て満たすことができた.

  • 環境ごとに異なる環境変数を設定する
  • 環境ごとに制御した IAM ロールを設定する
  • 環境ごとに異なるコンピューティングリソースを設定する

デプロイする

残るはデプロイするだけとなる.

$ apex deploy --env prd
$ apex deploy --env stg
$ apex deploy --env dev

CircleCI で自動デプロイ

今回も CircleCI で自動デプロイをできるようにした.以下にサンプルの circle.yml を載せておく.これで,プルリクを出すと dev / stg 環境にデプロイされて,master にマージをすると dev / stg / prd 環境にデプロイされる.便利!なお,テストを書かないと CircleCI でエラーになるため,今回は echo を設定して回避している.

machine:
  timezone: Asia/Tokyo

dependencies:
  post:
    - curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sudo sh
    - apex version

deployment:
  prd:
    branch: master
    commands:
      - pip install --requirement functions/myfunc1/requirements.txt --target functions/myfunc1
      - pip install --requirement functions/myfunc2/requirements.txt --target functions/myfunc2
      - apex deploy --env dev
      - apex deploy --env stg
      - apex deploy --env prd
  stg_dev:
    branch: /^(?!master$).*$/
    commands:
      - pip install --requirement functions/myfunc1/requirements.txt --target functions/myfunc1
      - pip install --requirement functions/myfunc2/requirements.txt --target functions/myfunc2
      - apex deploy --env dev
      - apex deploy --env stg

test:
  override:
    - echo 'ok'

まとめ

  • Apex 本当に便利!
    • API Gateway / DynamoDB なども必要なら Serverless Framework や AWS SAM なども候補になる
  • Apex の --env オプションを使うと Lambda を複数環境にデプロイすることができる
  • 環境変数,IAM ロール,コンピューティングリソースを環境ごとに設定ファイルで変えることもできる

コントリビュート

公式ドキュメントを見ていたら --env の部分が -env になっていて,検索できずハマったので,修正のプルリクを投げたらすぐにマージしてもらえた!やった!

github.com

任意のパラメータを格納できる EC2 Systems Manager「パラメータストア」を試したら便利だった

re:Invent 2016 で発表されたけど,オンプレ関連だと勝手に思い込んでいて,今まで試していなかった Amazon EC2 Systems Manager の中に「パラメータストア」というサービスがあり,試してみたらこれが非常に便利だった.簡単に言うと,任意のパラメータをパラメータストアに格納することができて,アプリケーションと環境変数を完全に切り離すことができてしまうというもの.The Twelve-Factor App を実現できるぞ!

パラメータストアとは?

  • 任意のパラメータをパラメータストアに格納することができる
  • データタイプは3種類ある
    • String
    • String List
    • Secure String (パラメータを KMS で暗号化して格納する)
  • ._ を使うと,パラメータをグルーピングできる
  • IAM Role でアクセスできるパラメータグループを制御できる

docs.aws.amazon.com

パラメータストアに格納してみた

サンプルとして,4個のパラメータをパラメータストアに格納してみた.なお,キーと値は同じにした.

  • パラメータグループとして prdstg を用意した
  • KMS の挙動を確認するため StringSecure String を用意した

f:id:kakku22:20170610180222p:plain

パラメータストアからパラメータを取得する

aws ssm get-parameters コマンドを使うと,簡単にパラメータを取得することができる.

$ aws ssm get-parameters --name 'stg.user_id'
{
    "InvalidParameters": [],
    "Parameters": [
        {
            "Type": "String",
            "Name": "stg.user_id",
            "Value": "stg.user_id"
        }
    ]
}

Secure String の場合は,デフォルトだと KMS で暗号化された値が返ってくる(今回は例として xxxxx とした).

$ aws ssm get-parameters --name 'stg.user_pass'
{
    "InvalidParameters": [],
    "Parameters": [
        {
            "Type": "SecureString",
            "Name": "stg.user_pass",
            "Value": "xxxxx"
        }
    ]
}

よって,Secure String の場合は --with-decryption オプションを付ける必要がある.ちなみに --with-decryption オプションは Secure String 以外の場合は無視されるため,String のときにも付けておけば,コマンドが統一できて良さそう.

$ aws ssm get-parameters --name 'stg.user_pass' --with-decryption
{
    "InvalidParameters": [],
    "Parameters": [
        {
            "Type": "SecureString",
            "Name": "stg.user_pass",
            "Value": "stg.user_pass"
        }
    ]
}

ちなみに aws ssm get-parameters コマンドの詳細は以下にまとまっている.

パラメータストアから取得した値を環境変数に設定する

こんな感じでスクリプトを用意すれば,簡単に The Twelve-Factor App を実現できる.便利!

$ USER_ID=$(aws ssm get-parameters --name 'stg.user_id' | jq -r '.Parameters[].Value')
$ echo ${USER_ID}
stg.user_id

$ USER_PASS=$(aws ssm get-parameters --name 'stg.user_pass' --with-decryption | jq -r '.Parameters[].Value')
$ echo ${USER_PASS}
stg.user_pass

IAM Role でアクセスできるパラメータグループを制御する

まず prd.* にアクセスできる IAM ポリシーと stg.* にアクセスできる IAM ポリシーを用意して,IAM ロールに紐付けた.

  • policy-ssm-prd
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:Describe*",
                "ssm:Get*",
                "ssm:List*"
            ],
            "Resource": [
                "arn:aws:ssm:ap-northeast-1:111111111111:parameter/prd.*"
            ]
        }
    ]
}
  • policy-ssm-stg
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:Describe*",
                "ssm:Get*",
                "ssm:List*"
            ],
            "Resource": [
                "arn:aws:ssm:ap-northeast-1:111111111111:parameter/stg.*"
            ]
        }
    ]
}

次に IAM ロールをアタッチしたインスタンスを起動して動作確認をした.以下の例は stg からパラメータストアにアクセスした状態で,prd.* グループのパラメータにはアクセスできなかった.このように設定することで,別環境の設定が誤って取得されるリスクが無くなる.

$ aws ssm get-parameters --name 'stg.user_id'
{
    "InvalidParameters": [],
    "Parameters": [
        {
            "Type": "String",
            "Name": "stg.user_id",
            "Value": "stg.user_id"
        }
    ]
}
$ aws ssm get-parameters --name 'prd.user_id'

An error occurred (AccessDeniedException) when calling the GetParameters operation: User: arn:aws:sts::111111111111:assumed-role/ec2-ssm-stg/i-22222222222222222 is not authorized to perform: ssm:GetParameters on resource: arn:aws:ssm:ap-northeast-1:111111111111:parameter/prd.user_id

簡単に図にすると,このようになる.

f:id:kakku22:20170610180308j:plain

re:Invent 2016 動画

パラメータストア以外にもいろいろ機能があるので,試してみないと!

www.youtube.com

env-injector

パラメータストアから環境変数に自動的に設定をしてくれる env-injector というツールを先輩の id:okzk が実装していた.これは便利!

$ ENV_INJECTOR_PREFIX=prd env-injector printenv | egrep 'user_id|user_pass'
user_id=prd.user_id
user_pass=prd.user_pass

$ ENV_INJECTOR_PREFIX=stg env-injector printenv | egrep 'user_id|user_pass'
user_id=stg.user_id
user_pass=stg.user_pass

env-injector の詳細は以下の記事を参照で!

okzk.hatenablog.com

まとめ

  • Amazon EC2 Systems Manager の中にはたくさんのサービスがあった
  • 「パラメータストア」は非常に便利でパラメータの格納を AWS に任せられる
  • IAM Role でアクセスできるパラメータグループを制御することもできる
  • クレデンシャル / データベース接続情報などの一般的なユースケース以外にも「パラメータストア」を活用できるアイデアがたくさんありそう

Lambda を軸にサーバレスを解説した「実践 AWS Lambda」を読んだ

AWS Summit Tokyo 2017 の先行発売でゲットした「実践 AWS Lambda」をさっそく読んだ.Lambda の解説だけではなく,サーバレスの文脈で導入事例が増えてきたアーキテクチャ(ユースケース)の紹介がされていたり,サーバレスのデプロイツールとして AWS SAM の紹介がされていたりして,非常に良書だった.Amazon を見ると,一般発売は明日 6/9 になっていたので,気になる人はすぐに買うと良いのでは!

実践AWS Lambda ~「サーバレス」を実現する新しいアプリケーションのプラットフォーム~

実践AWS Lambda ~「サーバレス」を実現する新しいアプリケーションのプラットフォーム~

Chapter 3 AWS Lambdaの使い方

3-7 バージョニングとエイリアス

Lambda 関数の ARN にバージョンを付与して識別できるのは知らなかった.また,エイリアスを付けて運用できるのも知らなかった.実際に運用している Lambda 関数を見てみたところ,確かにバージョンなしの ARN もあったし,バージョンありの ARN もあった.ちなみに Lambda 関数は Apex でデプロイをしているため,Apex の実装を確認したら自動的に current エイリアスを付与するようになっていた.おおお!

  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample
  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample:$LATEST
  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample:50
  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample:current

docs.aws.amazon.com

3-10 環境変数の利用

暗号化ヘルパーを使うと,環境変数を KMS で暗号化できるのを知った.今のところ,暗号化が必要な環境変数を使っていないため,普通に Apex の project.json でベタ打ちして運用していた.

docs.aws.amazon.com

Chapter 4 プログラミングモデル

4-5 Lambda関数作成時のポイント

特定の言語に依存せず,対応言語全て (Node.js / Python / Java / C#) の解説があるのは素晴らしかった.また Lambda の特性に合ったアーキテクチャに関しては,AWS Summit Tokyo 2017 で講演があった内容とも似ていた.

speakerdeck.com

Chapter 8 サーバレスアプリケーション開発のデプロイ

個人的に1番良かったのは AWS SAM の紹介がされていた点だった.今まで Lambda のデプロイなら Apex を使って,API Gateway が必要なときは Serverless Framework を使っていたけど,AWS から公式に提供された AWS SAM はずっと気になっていてまだ使ったことが無かった.現状サポートされているリソースは Lambda と API Gateway と DynamoDB とのことだが,CloudWatch Events もサポートされると良いなと思う.Apex もここはサポートしていなくて,自動化できなかった.

github.com

本書には記載がなかったけど,AWS SAM で Tracing を設定すれば X-Ray も合わせてデプロイとのこと.気になる!

www.slideshare.net

誤植

初版だからかもしれないけど,typo 系の誤植があって少し気になった.実際に5箇所を発見したため,マイナビに報告をしておいた.確認してもらえれば,以下のサポートサイトに反映されるのかな?と期待している.

book.mynavi.jp

まとめ

  • Lambda を軸にサーバレス全体の理解を改めて整理できた
  • 実際に Lambda + API Gateway + DynamoDB を使うチュートリアルも紹介されていて未経験者にも参考になる内容だった
  • AWS SAM の紹介があり Lambda の運用まで考慮された解説範囲の広さだった

関連記事

先週参加した AWS Summit Tokyo 2017 の参加レポートも参照してもらえればと!

kakakakakku.hatenablog.com

実際に運用している Lambda + Apex の事例も前にまとめていて参照してもらえればと!

kakakakakku.hatenablog.com