2020年11月12日木曜日
AWS ECRのライフサイクルポリシーを設定して自動クリーンアップ
今回は軽く、AWS ECR (Elastic Container Registry) の小ネタです。
AWSでコンテナを使って何かする場合ECRにコンテナイメージを保存しておくことが多いと思いますが、日ごろからイメージをよくビルド&プッシュしているとどんどんイメージが増えていきますね。
イメージサイズがものすごく大きいとかでなければそれほど料金を食うわけでもないのですが、まず使わない古いイメージをずっと保存しておくこともないよなーと思ったのでそのあたりを設定してみました。
ECRではライフサイクルポリシーという機能があり、いろいろな条件を定めてイメージを自動クリーンアップすることができるんですね。
Amazon ECRのライフサイクルポリシーでコンテナイメージのクリーンアップ | Amazon Web Services ブログ
設定できる条件は
- タグ
- イメージ数
- プッシュされてからの経過日数
今回は、「タグが latest
ではない」かつ「プッシュされて90日以上」の条件に合うイメージを削除するポリシーを設定してみました。
AWSコンソールで設定する場合は、ECRのコンソールでリポジトリを選択して左のメニューの Lifecycle Policy
をクリックすると設定画面があります。
「テストルールの編集」ボタンを押すとポリシーを適用した結果が確認できる(実際に保存されているイメージには何もしない)テスト用ページに移動するので、まずはそこで試してみるのがいいですね。
さて、ライフサイクルポリシーは「ルール」を優先順位つきで好きな数設定することで構成します。ルール作成画面はこうなっていて、一致条件は「イメージをプッシュしてから」「次の数値を超えるイメージ数」が選べます。
今回作りたい条件は「タグが latest
ではない」かつ「プッシュされて90日以上」ということで、
- タグ付け済("latest")、次の数値を超えるイメージ数(1)
- すべて、イメージをプッシュしてから(90日)
という2つのルールを作ってこのようになります。
ルールを作ればあとは自動でそれに従ってイメージが毎日掃除されるので、とても楽ですね😊
ここまではコンソールで操作してきましたが、リポジトリが多い場合やコンソール面倒だと言う場合はもちろんCLIが使えます。
put-lifecycle-policy — AWS CLI 2.1.0 Command Reference
まずは先ほどのルールをJSON化して policy.json
とでもファイルを作ります。
{
"rules": [
{
"rulePriority": 1,
"description": "keep latest image",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["latest"],
"countType": "imageCountMoreThan",
"countNumber": 1
},
"action": {
"type": "expire"
}
},
{
"rulePriority": 2,
"description": "expire images older than 90 days",
"selection": {
"tagStatus": "any",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 90
},
"action": {
"type": "expire"
}
}
]
}
今回は全リポジトリに適用したかったのでシェルスクリプトを作りました。
#!/bin/sh
# ECRリポジトリにライフサイクルポリシーを設定する
for REPO in $(aws ecr describe-repositories --query "repositories[*].{name:repositoryName}" --output text)
do
echo "repository: $REPO"
aws ecr put-lifecycle-policy --lifecycle-policy-text "file://policy.json" --repository-name $REPO
done
これで一括適用ができますね💪
比較的簡単に設定ができるので、「うわっ…ECRのイメージ、多すぎ…?」と気づいた際には設定してみてはいかがでしょうか。
ちなみにterraformだとaws_ecr_lifecycle_policy
リソースで設定できるようです。
aws_ecr_lifecycle_policy | Resources | hashicorp/aws | Terraform Registry
2019年2月21日木曜日
Alexaスキルを作ろう - 第2回
SPECというサービスのバックエンド開発などを行っています。
今回は前回の続きで、Alexaスキルの作成について書いていきます。
今回は、前回作成したスキルから呼び出されるLambdaを作成します。
まずAWSコンソールにログインして、Lambda - 関数の作成に行きます。
そこから「一から作成」、「設計図」などが選べます。
「設計図」でalexaを検索すると、
それぞれのスキルタイプに合わせたsdkが用意されています。
使用したいタイプのsdkがある場合は、それを使用しましょう。
今回はとても単純なスキルを作成したので、「一から作成」を選択します。
いろいろな言語が選べますが、今回はNode.jsで作成しました。
関数を作成すると、シンプルなレスポンスを返す関数が書かれているので、その中身を変更します。
今回作成したスキルは、「言葉を逆さまにする」です。
シンプル...!
コードを記述します。
exports.handler = async (event) => { const word = event.request.intent.slots.word.value; const response = { "version": "1.0", "response": { "outputSpeech": { "type": "PlainText", "text": word.split('').reverse().join('') }, "shouldEndSession": false }, "sessionAttributes": {} }; return response; };
こんな感じになりました。
responseの形式について、詳しくは応答の形式を参考にしてください。
「intent.slots.word」の部分の「word」は前回設定した「スロット名」に対応します。
次にこのLambdaを呼び出すトリガーを設定します。
「トリガーの追加」から、「Alexa Skills Kit」を選択して、スキルID(alexa developer consoleを参照)を設定します。
alexa developer consoleでテストしてみましょう。
前回、スキルの呼び出し名とサンプル発話を設定しました。
テスト画面で、
「<スキルの呼び出し名>を開いて、<サンプル発話>おはよう」と入力すると‥
ちゃんと逆さまにして返してくれましたね!
シンプルなスキルですが動くと面白いと思います。
今回はここまでにします。
次回は実機でのテストとスキルの公開について書ければと思います。
ありがとうございました!
2018年12月25日火曜日
[第一回]SansanとHubSpotの連携
こんにちは、シタテルエンジニアの工です!
今回は、SansanとHubSpotの連携の仕方について書いていきます 🚀
はじめに
シタテルでは、衣服生産をSCS、マーケティング・営業の部分をHubSpotを使って管理しています。
HubSpotを導入する際に、Sansanの情報をHubSpotに同期したいという要望があったので、SansanのAPIとHubSpotのAPIを組み合わせて同期処理を実装しました。
AWSLambdaを使って、定期的に同期処理を実行しています。
HubSpot公式にもSansanとハブスポットの連携の仕方という記事も公開されていますので参考にしてみてください。
Sansanの名刺情報をHubSpotにインポートする
使うもの
余談ですが実装したときAWSLambdaにはRubyの選択肢がなかったのですが、今は使用できるみたいですね。
普段はRubyを使うことが多いので、次にLambdaを使うときはRubyで実装してみたいです。
Sansanの情報を取得
handler.js
const axios = require('axios')
const moment = require('moment')
axios.defaults.headers.common['X-Sansan-Api-Key'] = process.env.SANSAN_API_KEY
axios.defaults.headers.get['Content-Type'] = 'application/json'
module.exports.importSansanData= async (event, context, callback) => {
var updatedFrom = moment().subtract(2, 'hours').format("YYYY-MM-DDTHH:mm:ss")+"Z"
var updatedTo = moment().format("YYYY-MM-DDTHH:mm:ss")+"Z"
await axios.get(`https://api.sansan.com/v2.0/bizCards?updatedFrom=${updatedFrom}&updatedTo=${updatedTo}&range=all`)
.then(function (response) {
importHubspot(response)
callback(null, response.data)
})
.catch(function (error) {
callback(error)
});
};
詳しくはこのあたりを参考にしてください。
AWSLambdaとServerlessを使ってみる[第1回]
AWSLambdaとServerlessを使ってみる[第2回]
日時取得のところがとてもブサイクです... 😢
なぜかタイムゾーンZにしないとうまくいかなっかった 🤔
本当は+09:00
に設定したい。
var updatedFrom = moment().subtract(2, 'hours').format("YYYY-MM-DDTHH:mm:ss")+"Z"
var updatedTo = moment().format("YYYY-MM-DDTHH:mm:ss")+"Z"
HubSpotにインポート
取得したSansanデータをインポート。
propertyは数が多いのでほとんど割愛して記載します。
handler.js
function importHubspot (response) {
response.data.data.forEach(createContact)
}
function createContact (value, index) {
var properties = [
{
property: 'email',
value: value.email
},
{
property: 'firstname',
value: value.firstName
},
{
property: 'lastname',
value: value.lastName
}
]
axios.post(`https://api.hubapi.com/contacts/v1/contact?hapikey=${process.env.HUBSPOT_API_KEY}`, {
properties: properties,
})
.then(function (response) {
console.log(response.data)
})
.catch(function (error) {
console.error(error.response.data)
});
}
上の例はひとつひとつPOSTしていますが、こちらのAPI使えば1回のPOSTでまとめてCreateできます。
Create or update a group of contacts | Contacts API
CloudWatchでスケジュールを設定
serverless.ymlにスケジュールを設定します。
2時間おきにインポート 🚀
serverless.yml
functions:
importSansanData:
handler: handler.importSansanData
events:
- schedule: cron(0 */2 * * ? *)
これで2時間おきに、Sansanの名刺情報がHubSpotのコンタクトに同期されます!👏
最後に、deploy 🚀
serverless deploy -v
まとめ
今回はSansanとHubSpotのAPIを使って、Sansanの名刺情報をHubSpotのコンタクトにインポートする方法について書きました。
SCSと外部サービスとの連携は今後もどんどん加速していくと思います!マーケティング・営業 -> 衣服生産 -> 請求
この流れがシステムでシームレスに実現できるように開発中です 💻
2018年12月21日金曜日
金沢で開催された IVS CTO Night & Day に参加してきました!
こんにちは!
シタテル株式会社CTOの和泉です。
12月17〜19の3日間、金沢で開催された IVS CTO Night and Day 2018 Winter powered by AWS に参加してきました。
どんな会なのか? 詳しくはこちら!
CTO Night and Day 2017
(リンク先は昨年のレポートです)
新旧大小さまざまな企業のCTOがずらり100人以上。
前夜祭に始まり、AWSの最新技術や文化紹介、選ばれた15社の技術やマネジメント紹介(登壇しました)、先輩CTOとの公開メンタリング、ダンスパーティーまで盛りだくさん。
「CTOがいなくなって8ヶ月がたった話」「CTOの休み方」など、CTOにまつわる、CTOならではの話題や悩み相談が随所で繰り広げられていました。
事業を進めていくのは本当にエネルギーが必要で、でも皆さん熱量高く真摯に取り組んでおられて本当に刺激になりました。
40名を超える方と名刺を交換して事業について意見交換させていただいて素晴らしい出会いがたくさんありました。
そして、本当にAWSの運営の方々のホスピタリティが半端ない!
私も事前に伝えていた事業内容に対してこの人が最適だろうという方を紹介いただいて、有意義なディスカッションが出来ました。
来年もできたら参加したい!頑張ろう!とめちゃくちゃテンションが上りました。
反省
話すのに忙しすぎて写真を全然撮っていませんでした、、、
2018年12月20日木曜日
プロジェクトごとに環境変数/クレデンシャルを管理する
sitateruでサービス・プロダクトを担当している北爪です。
インフラを見ることもあり、今日はShellでの環境変数の扱い方について書きます。
プロジェクトごとに環境変数/クレデンシャルを管理する
複数のプロジェクトに関わっているときに、プロジェクトごとの環境変数やAWSのkey/secretsなど環境変数に設定し管理する必要があることがあります。
Shellを使って管理する一つの方法を記述します。
準備
プロジェクトごとにクレデンシャルフェイルを作る
クレデンシャルファイル置き場を作ります
$ mkdir ~/.crds/
プロジェクトごとにプロジェクトファイルを作ったディレクトリ以下に置きます。
ディレクトリはinvisibleファイルにしておきます。
$ touch ~/.crds/pj-1
ファイルに必要なクレデンシャルを記述します
export AWS_ACCESS_KEY_ID==XXXXX
export AWS_SECRET_ACCESS_KEY==XXXXX
export AWS_DEFAULT_REGION=ap-northeast-1
export TF_VAR_secret_key=XXXXX
export TF_VAR_rds_password=XXXXX
読み込みと切り替え
設定した環境変数群を以下の方法でプロジェクトごとに読み込みます。
リセットはされないので、別プロジェクトに変える際は、あらたにshellを立ち上げるようにします。
プロジェクトのクレデンシャルを読み込む
source コマンドをつかってシェルに読み込めば(dot operatorでもOK)
$ source ~/.crds/pj-1
or
$ . .~/.crds/pj-1
別のプロジェクトのクレデンシャルを読み込む
複数のプロジェクトファイルを作ることで、クレデンシャルを別で読み込むことができます。
$ source ~/.crds/pj-2
Tips
初期読み込みが必要な場合は、 bashrcやzshrcなどに、読み込みコマンドを記述しておけます
まとめ
クレデンシャルファイルを特定のディレクトリに作り、基本コマンドで呼び出すだけです。一覧性も高く、管理しやすくなります。
2018年12月13日木曜日
ec2のインスタンスログインを簡単に管理する ~EC2 with Peco ~
sitateruでサービス・プロダクトを担当している北爪です。
インフラを見ることもあり、ec2サーバーのアドレス管理についてCLIで行う方法を紹介します。
目的
ec2のインスタンスはアドレスが構築するたびに変わり、負荷や新しいプロジェクトが立ち上がると増えたり減ったりします。
そのため、動的にサーバーアドレスを取得する必要があります。
AWS consoleに入ることなく、awsコマンドからサーバーリストを取得し、CLI filterのpecoを使って、SSHまでおこないます。
使い方
Command+\
でpecoを起動
やじるしの ↑↓
か、キーワードで絞る
SSHするサーバーを選んでEnterを押す
SSHコマンドがはかれる
準備
zshを使っているのを前提に説明します。
必要ソフトのインストール
Shellの設定
ec2 コマンドを作る
AWS CLIから、ec2をリスト化するコマンドを作成し、shellに設定します。(zshrc)
alias ec2="aws ec2 describe-instances --query 'Reservations[].Instances[].{PublicDnsName:PublicDnsName,InstanceId:InstanceId,Tags:Tags[?Key==\`Name\`].Value|[0],InstanceType:InstanceType,State:State.Name}' --output table"
peco-ec2コマンドを作る
zshrc
にpeco-ec2
をつくります- ログインユーザーをdeployにしています
function peco-ec2 () {
local selected=$(ec2 | peco --query "$LBUFFER")
if [ -n "$selected" ]; then
BUFFER="ssh deploy@$(echo $selected | awk 'match($0, /ec2.*\.amazonaws\.com/) {print substr($0, RSTART, RLENGTH)}')"
zle accept-line
fi
zle clear-screen
}
- さらに、好きなキーにバインドします。
- ここでは、
Command-\
につけています
zle -N peco-ec2
bindkey '^\' peco-ec2
まとめ
ec2をリスト化し、すぐにそこからsshを選べるようにしました。
2018年12月12日水曜日
Alexaスキルを作ろう
こんにちは。シタテルでエンジニアをしている熊谷です。
主にSPECというサービスのバックエンド開発(Rails)を行っています。
少し前にAlexaスキルの作成を試したので、その流れを簡単に説明していきます。
手順
1.Amazonアカウントを用意する
すでにamazon.co.jpの開発者アカウントがある場合は、それを使います。
お買い物用のAmazonアカウントを使用して、開発を開始できます。
Amazon Developerから、サインインして、情報を入力すると、開発用アカウントが登録されます。
※ 画像のページで、ログインをして進みます。[Amazon Developerアカウントを作成]から進むと、amazon.com用のアカウントになってしまい、US向けのスキルになってしまうようです。
2.Alexa Developer Consoleにアクセス
3.[スキルの作成]をクリックし、スキル名などを入力する
4.スキルのページで、[呼び出し名]を設定する
5.エンドポイントを設定する
- AWS Lambdaが推奨されているので、Lambdaでエンドポイントを作成するのが良いと思います。
- リクエスト、レスポンスはJSON形式で送信します。
- 作成したLambdaのARNを指定します。
6.インテントを作成する
- [インテントを追加]をクリックし、カスタムインテントを作成します。
7.作成したインテントのページで、スキルの発話時に使用する、スロット(変数のようなもの)を設定する
- スロットには、日付、数値、検索クエリー(文字列)などの型を指定できます
8.インテントを設定する
- 作成したインテントの設定で、サンプル発話を登録します。
- サンプル発話には上で作成したスロットを
{スロット名}
のような形で使用できます。
これで簡単なスキルを作成できました!
今回はざっくりした流れの紹介なので、ここまでにしたいと思います。
次回はLambdaの内容や、作成したスキルの公開、テストなどを説明していこうと思います。
2018年12月7日金曜日
CircleCIでAWS ECSに自動デプロイする(おまけで環境面の切り替えも)
こんにちは、シタテルの茨木です。
今回はCircleCIでDockerをビルドし、そのままAWS ECR/ECSにデプロイする為の設定例を紹介します。
Nuxt.jsアプリ用に作ったものですが、言語やAPサーバが違っても共通の部分がほとんどです。
PRマージからの自動デプロイ、いいですよね。
https://circleci.com/docs/2.0/ecs-ecr/
https://github.com/CircleCI-Public/circleci-demo-aws-ecs-ecr
基本的にはCircleCI公式ガイドの上記リンクを参考にしていますが、元ネタはterraform前提だったりでなかなか大仰です。(下記に説明漏れがあったら原典を見てください…)
今回紹介するのはリンク先のスクリプト類を簡素化し、少し機能を追加(リポジトリ名からデプロイ先の環境面を切り替えできるように)したものです。
以下で省略しているけれど必要なモノ
- ECS/ECRの設定
これだけで別の記事が書けてしまうので割愛します
ecsTaskExecutionRoleの割り当てとか忘れがちですかね
- githubリポジトリ
言わずもがな。CircleCIとの接続設定はされているものとします
- Dockerfile
リポジトリのルートに。Dockerfileの書き方は解説しません
- requirements.txt
リポジトリのルートに。awscliを使えるようにします
https://github.com/CircleCI-Public/circleci-demo-aws-ecs-ecr/blob/master/requirements.txt
- CircleCIの環境変数設定
github上にaccess_keyを晒さなくていいように、入れておきます
https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project
この手順で設定した環境変数はCircleCIのジョブから参照できます
.circleci/config.yml:build
version: 2
jobs:
~省略~
build:
docker:
- image: circleci/node:10-stretch
steps:
- checkout
- setup_remote_docker
- run:
name: Setup common environment variables
command: |
echo 'export ECR_REPOSITORY_NAME="YOUR-ECR-REPO-NAME"' >> $BASH_ENV
echo 'export FULL_IMAGE_NAME="${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${ECR=REPOSITORY_NAME}:${CIRCLE_SHA1}"' >> $BASH_ENV
- run:
name: Build image
command: |
docker build -t $FULL_IMAGE_NAME .
- run:
name: Save image to an archive
command: |
mkdir docker-image
docker save -o docker-image/image.tar $FULL_IMAGE_NAME
- persist_to_workspace:
root: .
paths:
- docker-image
~省略~
さっそくですがビルドジョブです。
- YOUR-HOGEHOGE箇所はご自身のECS/ECRの設定に合わせて置き換えてください
- image: circleci/node:10-stretch
node:10を使っていますが、これはビルドする対象がNuxt.jsアプリだからですね。Dockerビルド時に必要なモノに合わせて修正してください
.circleci/config.yml:deploy
~省略~
deploy:
docker:
- image: circleci/python:3.6.1
environment:
AWS_DEFAULT_OUTPUT: json
steps:
- checkout
- setup_remote_docker
- attach_workspace:
at: workspace
- restore_cache:
key: v1-{{ checksum "requirements.txt" }}
- run:
name: Install awscli
command: |
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
- save_cache:
key: v1-{{ checksum "requirements.txt" }}
paths:
- "venv"
- run:
name: Load image
command: |
docker load --input workspace/docker-image/image.tar
- run:
name: Setup target environment variables
command: |
echo 'export TARGET=`echo $CIRCLE_BRANCH | sed -e s/develop.*/dev/ -e s/release.*/stg/ -e s/master/prd/`' >> $BASH_ENV
source $BASH_ENV
- run:
name: Setup common environment variables
command: |
echo 'export ECR_REPOSITORY_NAME="YOUR-ECR-REPO-NAME"' >> $BASH_ENV
echo 'export ECS_CLUSTER_NAME="YOUR-ECS-CULSTER-NAME-PREFIX${TARGET}"' >> $BASH_ENV
echo 'export ECS_SERVICE_NAME="YOUR-ECS-SERVICE-NAME-PREFIX${TARGET}"' >> $BASH_ENV
- run:
name: Push image
command: |
. venv/bin/activate
eval $(aws ecr get-login --region ap-northeast-1 --no-include-email)
docker push $AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/$ECR_REPOSITORY_NAME:$CIRCLE_SHA1
- run:
name: Deploy
command: |
. venv/bin/activate
export AWS_DEFAULT_REGION="ap-northeast-1"
export ECS_TASK_FAMILY_NAME="YOUR-ECS-TASK-NAME-PREFIX${TARGET}"
export ECS_CONTAINER_DEFINITION_NAME="YOUR-ECS-CONTAINER-DEF-NAME-PREFIX${TARGET}"
export EXECUTION_ROLE_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:role/ecsTaskExecutionRole"
bash ./deploy.sh
~省略~
デプロイジョブです。
- ブランチ名から環境名へ
echo 'export TARGET=`echo $CIRCLE_BRANCH | sed -e s/develop.*/dev/ -e s/release.*/stg/ -e s/master/prd/`' >> $BASH_ENV
ブランチ名に応じた値(developブランチなら"dev")を環境変数に入れています。これをsuffixとして使い、デプロイ先のクラスタ名等に反映しています
- YOUR-HOGEHOGE箇所はご自身のECS/ECRの設定に合わせて置き換えてください
余談ですが、ECSはクラスタ・サービス・タスク・タスク定義といろいろ設定しないといけないのですが、なかなか直感的にわかりにくくてイマイチな印象です
.circleci/config.yml:workflows
~省略~
workflows:
version: 2
build-deploy:
jobs:
- build:
filters:
branches:
only:
- develop
- /release\/.*/
- master
- deploy:
requires:
- build
filters:
branches:
only:
- develop
- /release\/.*/
- master
この辺はよしなに
deploy.sh
#!/usr/bin/env bash
set -eo pipefail
# more bash-friendly output for jq
JQ="jq --raw-output --exit-status"
deploy_cluster() {
make_task_def
register_definition
if [[ $(aws ecs update-service --cluster $ECS_CLUSTER_NAME --service $ECS_SERVICE_NAME --task-definition $revision | \
$JQ '.service.taskDefinition') != $revision ]]; then
echo "Error updating service."
return 1
fi
# wait for older revisions to disappear
# not really necessary, but nice for demos
for attempt in {1..30}; do
if stale=$(aws ecs describe-services --cluster $ECS_CLUSTER_NAME --services $ECS_SERVICE_NAME | \
$JQ ".services[0].deployments | .[] | select(.taskDefinition != \"$revision\") | .taskDefinition"); then
echo "Waiting for stale deployment(s):"
echo "$stale"
sleep 30
else
echo "Deployed!"
return 0
fi
done
echo "Service update took too long - please check the status of the deployment on the AWS ECS console"
return 1
}
make_task_def() {
task_template='[
{
"name": "%s",
"image": "%s.dkr.ecr.%s.amazonaws.com/%s:%s",
"essential": true,
"portMappings": [
{
"containerPort": 80
}
],
"environment": [
{
"name": "TARGET",
"value": "%s"
}
]
}
]'
task_def=$(printf "$task_template" $ECS_CONTAINER_DEFINITION_NAME $AWS_ACCOUNT_ID $AWS_DEFAULT_REGION $ECR_REPOSITORY_NAME $CIRCLE_SHA1 $TARGET)
}
register_definition() {
if revision=$(aws ecs register-task-definition --requires-compatibilities FARGATE --cpu 256 --memory 1024 --network-mode awsvpc --execution-role-arn $EXECUTION_ROLE_ARN --container-definitions "$task_def" --family $ECS_TASK_FAMILY_NAME | $JQ '.taskDefinition.taskDefinitionArn'); then
echo "New deployment: $revision"
else
echo "Failed to register task definition"
return 1
fi
}
deploy_cluster
デプロイジョブから呼び出すスクリプトです。
task_templateの内容を色々弄るとカスタマイズできます
設定可能な項目はこちら
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/create-task-definition.html
ここでは、environmentで環境変数TARGETを設定しています
ECSがdocker runする際に引数として付与され、docker内のアプリから環境変数として参照可能になります
実際には、nuxt.config.js内でTARGETを参照し、APIサーバの向け先を切り替えたり等しています
以上、ご参考になれば幸いです。
2018年11月30日金曜日
AWSLambdaとServerlessを使ってみる[第2回]
こんにちは、シタテルエンジニアの工です!
AWSLambdaとServerless第2回に入っていきます!
前回は、AWSLambdaとserverlessについてさらっと確認して
serverlessでServiceをcreateするところまでをやってきました。
AWSLambdaとServerlessを使ってみる[第1回]|sitateru tech blog
今回は実際にSansan OpenAPIを利用して名刺情報を取得してみます 🚀
SansanAPI
公式ドキュメント Sansan Open API
名刺API 名刺Set取得(期間指定)
を使ってみます。
SansanAPIを利用するにはAPI Keyが必要です。
取得方法はこちらを参考にしてください。
作る
前回createしたServiceを利用して作っていきます。
現在この2ファイルが作成されている状態です。
- serverless.yml
- 各種設定を書いていきます
- handler.js
- 処理を書いていきます
axiosインストール
今回は、httpリクエストにaxiosを使用します。
$ npm install axios
インストールされました
.
├── handler.js
├── node_modules
│ ├── axios
├── package-lock.json
└── serverless.yml
serverless.yml
環境変数の設定
lambdaには環境変数を設定することができます。
SansanAPIKeyを環境変数として設定してみます。
serverless.yml
# you can define service wide environment variables here
environment:
SANSAN_API_KEY: xxx
環境変数を利用する場合は、このように取得できます。
process.env.SANSAN_API_KEY
handler.js
それでは処理を書いていきます。
lambdaの非同期処理とcallbackについてはこちらを参考にしてください。
名刺情報はお見せできないので、取得した件数を出力してみます。
'use strict';
const axios = require('axios')
axios.defaults.headers.common['X-Sansan-Api-Key'] = process.env.SANSAN_API_KEY
axios.defaults.headers.get['Content-Type'] = 'application/json'
module.exports.hello = async (event, context, callback) => {
var updatedFrom = "2018-11-26T01:00:00Z"
var updatedTo = "2018-11-27T21:00:00Z"
await axios.get(`https://api.sansan.com/v2.0/bizCards?updatedTo=${updatedTo}&range=all&entryStatus=completed`)
.then(function (response) {
callback(null, response.data.data.length)
})
.catch(function (error) {
callback(error)
});
};
deploy
cliでdeployします。
serverlessを使わない場合、serviceを手動でzipにしてawsにdeployする必要があるのでとても面倒です...
$ serverless deploy -v
deployが完了したら情報が出力されます。
...
Serverless: Stack update finished...
Service Information
service: hello-sansan
stage: dev
region: us-east-1
stack: hello-sansan-dev
api keys:
None
endpoints:
None
functions:
hello: hello-sansan-dev-hello
lambdaの関数のところにも表示されています。
環境変数も設定されています。
実行
こちらもcliで実行します。
$ sls invoke -f hello
16
件数が取得できました。
おわりに
今回はlambdaからSansanOpenAPIを利用して名刺情報をゲットしてみました!
lambdaはサーバーのこと気にせずに処理だけ書けば良く、serverlessはcliでごにょごにょできるし、とても便利です!
sitateruではlambdaを使って、SansanとHubSpotの同期を自動化しています。
どこかのタイミング第3回としてserverless-offlineを使用したlambdaの開発についても書こうと思います。
2018年11月22日木曜日
AWSLambdaとServerlessを使ってみる[第1回]
こんにちは、シタテルエンジニアの工です!
AWS Lambdaを触る機会がありましたので、ServerlessFrameworkと一緒にいじいじしてみました!
シリーズで、
Serverlessをインストール
AWSLambdaでSansanの名刺データを取得してみる
serverless-offlineでAWSLambdaをローカルで実行
なんかを書いていこうと思います!
さらっとAWSLamdaとServerlessFrameworkについて
AWS Lambdaとは
AWS Lambda はサーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービスです。
つまり、流行りのサーバーレス
てやつで、サーバーを準備しなくてよいので、ちょっとした処理の実行など大変助かります。
しかも、LambdaはNode.js (JavaScript)、Python、Java (Java 8 互換)、C# (.NET Core)、 Goに対応しています!
様々な言語に対応しているので学習コストもかからないのがいいですね。
シタテルでは、HubSpotとSansanのデータ同期や、SlackCommandでリリースPRを作るなどで使っています。
Serverlessとは
The Serverless Framework is an open-source CLI for building and deploying serverless applications.
つまり、サーバーレスアプリケーションの開発を手助けをしてくれるやつです!
AWS Lambda単体で開発してみるとわかるのですが、ローカルでの開発やビルド、デバッグやらが面倒です。
このServerless Frameworkを使えばそのあたりのもやもやを解消してくれます!
作ってみる
Serverless Framework - AWS Lambda Guide - Introduction こちらがAWS用のServerlessFramework公式ドキュメントです。 基本的にこちらの内容に沿って進めていきます、
今回は、Sansanの名刺データを取得してみます。
まずはServerlessFrameworkをインストール
$ npm install -g serverless
$ serverless -v
1.33.2
正しくバージョンが表示されていたら、インストール完了です!
Serviceを作る
Serviceはプロジェクトのようなもの。
今回は、nodejsで作っていきますので、aws-nodejs
を指定。
その他の言語を使いたい方はこちらを参考に。
$ serverless create --template aws-nodejs --path hello-sansan
実行すると
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/mogura/work/sitateru/lambda/hello-sansan"
_______ __
| _ .-----.----.--.--.-----.----| .-----.-----.-----.
| |___| -__| _| | | -__| _| | -__|__ --|__ --|
|____ |_____|__| \___/|_____|__| |__|_____|_____|_____|
| | | The Serverless Application Framework
| | serverless.com, v1.33.2
-------'
Serverless: Successfully generated boilerplate for template: "aws-nodejs"
このような構成で、Serviceができました!
hello-sansan
├── handler.js
└── serverless.yml
次は、実際に処理を書いていきます。
が、長くなりそうなので今回はここまでに。
おわりに
今回は、ServerlessFrameworkでserviceを作るところまでをやってみました。
次回は、実際にAWSLamdaでSansanから名刺データを取得するとことまでをやっていきます! 🚀
2018年11月14日水曜日
リリース作業を少し楽にした開発(Slack+Lambda+Golang)
こんにちは、シタテルの鶴巻です。
devops&インフラ担当です。
シタテルのプロダクトのリリース作業を少し楽にするために、
Slack+Lambda+Golangを用いて開発した話をします。
リリースの流れ
シタテルでは、GitフローやGitHubフローを採用しています。
また、本番環境へのデプロイは、以下の流れで実施しています。
- developブランチからreleaseブランチを作成
- ステージング環境でreleaseブランチをデプロイ&動作確認
- 本番環境にデプロイ
ちなみに、1.でreleaseブランチを作成すると、CircleCIによって2.のステージング環境へのデプロイは自動で行われます。
地味に面倒なリリース作業
ステージング環境へのデプロイは自動化されているとはいえ、小さな手作業が合間に発生し、地味に面倒でした。
具体的には以下のような作業です。
- developブランチからreleaseブランチの作成
- ローカルPCでdevelopブランチを最新の状態にpullして、releaseブランチ作成してGitHubにpush
- releaseブランチのプルリクエスト作成
- GitHubのUIをポチポチ
- リリースタグの作成
- 前回のリリース以降でマージされたプルリクエストを見て、リリース内容を記述
手作業はSlackからコマンドを叩くだけにしました
Slackから以下のコマンドを叩くだけで、地味に面倒くさかった作業を自動で行うようにしました。
/release <repository> <release branch>
実際には、以下の内容を実施するGolangプログラムをLambdaで実行しています。
- 対象のリポジトリをクローンし、developブランチからreleaseブランチを作成し、GitHubにpush
- releaseブランチのプルリクエストを作成
- 前回のリリース以降にマージされたプルリクエストのタイトルのリストを記述したリリースタグのドラフトを作成
構成
Slack -> API Gateway -> Lambda01(同期) -> Lambda02(非同期) -> GitHub
- Slackからコマンドを叩くと、Lambda01にリクエストを送信します。
- Lambda01は、Lambda02に対象レポジトリとブランチ名を付与してリクエストを送信します。
- Lambda02で作業を実行します。
Lambdaを2つ使用している理由
Slackはリクエスト送信後3秒でタイムアウトするためです。
実行したいプログラムは3秒以上かかるため、実際の作業は非同期で実施する必要がありました。
そのため、Lambda01はLambda02に処理を投げて、Slackに200を返し、実際の処理はLambda02で実施します。
Lambda01はLambda02を非同期実行で呼び出すので、リクエストをキューに入れた後は、Lambda01は関数を終了することができます。
Lambdaの呼び出しタイプ(同期・非同期)
Lambdaは、呼び出しタイプ(InvocationType)を指定することで、同期実行や非同期実行を選択することができます。
例:InvocationTypeで"Event"を指定することで、非同期実行でLambdaを呼び出せます。
input := &lambda.InvokeInput{
FunctionName: aws.String("xxxx"),
Payload: jsonBytes,
InvocationType: aws.String("Event"),
}
※同期実行は"RequestResponse"を指定します
今回使用したGitHub操作のためのGoライブラリ
- go-git https://github.com/src-d/go-git
- インメモリでgitクローンするために使用
- go-github https://github.com/google/go-github
- google製
- プルリク作成やリリースタグ作成に使用
その他ハマったポイント
- APIGatewayの統合リクエストのマッピングテンプレートを使いこなせず。デバッグのやり方もわからず、使うのを諦めました。
まとめ
- 少しの手間が自動化されるだけで、すごく楽になります。これからももっとやっていきたいです。
- GitHub操作のライブラリはとても便利でした。
- シタテルのサービスはRails + vue.jsが主ですが、自分の好きなGo言語を使えたので楽しかったです。
参考
2018年10月31日水曜日
s3の操作はaws-cliよりs3cmd使うほうが便利
こんにちは!
シタテルで エンジニアをしている建山です。
主に工場向けのマイオペというシステムの開発を行っています。
シタテルではファイルをawsのs3でホスティングしています。
直接s3のファイルを操作することは少ないのですが、やはり時々は発生します。
そんなときにはaws-cli
を使うこともできるのですが、s3cmd
を使うとより簡単なコマンドでS3を操作できます。
いくつかよく使うコマンドをまとめました。
ディレクトリのファイル権限を操作
s3cmd setacl -r --acl-private s3://バケット名/ディレクトリ名/
-r
は再帰的に配下すべてやってくれる--acl-private
はprivate権限にする--acl-public
はpublic権限にする
※バケットも指定できる
ディレクトリの中身を参照
s3cmd ls s3://バケット名/ディレクトリ名/
バケットの情報をみる
s3cmd info s3://バケット名
これ以外にもファイル/ディレクトリアップロードや削除などいろいろなことができます。
コマンドのインストール
インストールはmacの場合、
brew install s3cmd
でできます。
コマンドを使う前に、AWSのアクセスキー等を設定 する必要があります。
s3cmd --configure
ぜひ、お試ししてみてください。
2018年10月30日火曜日
AWS Loft Tokyoに行ってきました
こんにちは!
シタテルで エンジニアをしている熊谷です。
主にSPECというサービスのバックエンド開発(Rails)を行ってます。
今回は、話題のAWS Loft Tokyoに行って来たのでレポートします。