Trello APIとSlackで今週の頑張りをめちゃくちゃ褒めるボットを作る
モチベーション
仕事のタスク管理って基本めんどくさいですよね。僕はTrelloで仕事(+一部の業務外のToDo)のタスクを管理しているんですが、Trelloは期限やチェックリスト, コメント残しにカレンダーと機能が豊富でとても便利です。 ただ、年末の自分の評価シートを書いている時に、この案件に入ってから何かしら自分の作業効率って上がっているのかしらとふと思いました。その時は結局分からずじまいで悲しくなったので、できれば定量的に(週ごとに捌いたタスク数とか、修正にかかった時間とか)改善が把握できるBotが欲しいと思いつきました。あわよくば、モチベーションもあげたい。。。じゃあ今週頑張ったかを褒めちぎるBotを作ろう!!
実現したいこと
今回実現したいことを列挙するとこんな感じです。シンプルに2つだけにします。
- 今週の完了したタスク数, タスク名をTrelloの完了リストから取得する
- 完了済みタスク数と褒め言葉をSlackで自分宛に投げる
自分のスケジュール(毎週の進捗ミーティングやら検証環境へのリリースタイミング)や面倒くさがりの性格を考えて、自分でSlackコマンドを打つんじゃなくてスケジュール起動でSlack Botから通知を飛ばすようにしました。
Botの構成
構成図は割とシンプルになりました。
上の構成図の技術要素も並べるとこんな感じ。 極力労力をかけず/コードを書かずにサービスを組み合わせて実現させることを第一に実装します。
- Node.js
- スピード重視で慣れている言語で作ります。TypeScriptは使いません。
- Trello API
- 公式から出ているAPIでタスクを取得します。
- Slack
- 業務でも使ってるコミュニケーションツール。特定のタイミングで頑張った成果と褒め言葉を自分に投げる先です。
- 一番手軽なWebhook経由でメッセージを投稿させます。
- IBM Cloud Functions
- こちらもスピード重視でCloudFoundryやIBM Kubernetes Serviceよりも手軽に上記の要素を実現できる方法として採用。
- Slackにメッセージを飛ばすパッケージが事前に用意されていたので、
- Serverless Framework
- Continuous Delivery @IBM Cloud
できたもの
金曜22時になったら頑張りを通知してくれるようになりました!!
ソースコードはこちらに置いていますので、ご参考まで。 github.com
実装のポイント
実際にコードを書いたのは、Trelloから完了済みカードを取ってきて整形するところだけです。Trelloの特定のリストからカードを一式取ってくるだけなので、難しくはありません。以下実際のコードです。
("use strict"); const axios = require("axios"); const qs = require("querystring"); /** * Trelloのカードを操作する. */ class TrelloClient { constructor(params) { this.baseUrl = params.TRELLO_URL || "https://api.trello.com/1"; this.apiKey = params.TRELLO_API_KEY || "API KEY"; this.token = params.TRELLO_TOKEN || "TOKEN"; this.listId = params.TRELLO_LIST || "LIST_ID"; } /** * 完了済みタスクの一覧を取得する. * @param {String} listId 完了リストのID * @returns {Promise} 完了済みタスクのJSON配列 */ getCompletedTasks() { const reqParams = qs.stringify({ key: this.apiKey, token: this.token, fields: "id,name,labels" }); const TRELLO_URL_GET_COMPLETED_TASKS = `${this.baseUrl}/lists/${ this.listId }/cards?${reqParams}`; return axios.get(TRELLO_URL_GET_COMPLETED_TASKS).then(response => { return response.data || {}; }); } } module.exports = TrelloClient;
params
オブジェクトの各パラメータは serverless.yml に定義した値が渡ってきます。後は呼び元のメインの関数内でこのクラスをnewして使えば終わりです。全体で100行ちょっとしかないので軽いですね。
TrelloのAPIを叩く部分しか書か必要がない理由は、Slackへメッセージを投稿する部分は事前定義済みSlackパッケージを使うからです。atachmentsを使ったカラフルな凝ったメッセージ使えないですが、文字列連結すればいける範囲だったので無理せずそのまま使いました。
ハマりポイント
ContinuousDeliveryでServerless Frameworkを使ったデプロイするときは、CDのバージョンに注意
NPMの環境を指定してもNode.jsはv0.10系です。IBM SDKだとv6系しか入ってないのでなるべくv8系以上にしたいところ。v0.10系だと serverless
パッケージがpostinstall時にでこけます。以下の記事を参考にしてNVMを使えば良さそうとのことだったので、v8系をNVM経由でインストールして解決。
developer.ibm.com
Serverless Frameworkからデプロイするときに認証エラーになる
Serverless Frameworkは .wskprops
ファイルを参照してIBM Cloud Functionsにアクセスするようなのですが、どうも ibmcloud login
でログインしても上手く生成されないようです。以下のようにして .wskprops
を生成したらデプロイできるようになりました。
Deploy shellscrpit to work with IBM Cloud Function ...
これで来年の改善具合が見える化できるので楽しみです :)
AWS認定 デベロッパーアソシエイトに合格してきました
TL; DR
遅ればせながら、9月末にAWS認定 デベロッパーアソシエイト試験(2018/6リリース)に合格しました!
認定取るためにとにかくサービスを弄り舐め回しましたし、普段は触らないであろうサービスに色々触るいい機会になりました。 実案件の設計と開発どっちにも役立ちそうな内容を学べたので受ける価値ありです。
AWS認定って何?
AWSが公式にやってる認定試験。(関東近郊だと開催日平日なのが辛いです笑)
役割別認定
専門知識認定
- 高度なネットワーキング
- ビッグデータ
- セキュリティ
デベロッパーアソシエイトは認定されると, 認定試験公式ページ曰く以下の能力を持っていることを証明できるみたいですね。
AWS 認定デベロッパー – アソシエイト試験は AWS プラットフォームでのアプリケーションの開発と保守についての技術的な専門知識を認定します。 この試験では以下について理解していることが求められます。
試験ではどんなこと聞かれたの?
テーマ
AWSのサービスの知識,各サービスの使い方,ベストプラクティスについて聞かれます。 ほとんどがセキュリティと可用性を高めるには?という設問です。単純な知識問題の比率はかなり低め。
また、突然Pythonのコードが出てきたりするので、一度はチュートリアルに沿ってコードを書いておくと吉でしたね。 むしろドキュメントを見ながら実装できることを前提にしている節が見受けられます。
設問例
出題パターンはある程度決まっているので、脊髄反射で解けるやつを求めて分からんやつは飛ばして次に行く。 2時間あっという間に終わります。。。
EC2からS3にアクセスしたいけど、権限がなくて処理がアベンドした。問題の解決策のうち素早くかつ最も安全なものは?
API Gateway, Lambda, RDSからなるAPIを作ったけど、人気が出たからRDSへの負荷が高くなってしまった。ほとんどが読み取りだけど、処理がハングしないための対策は?
CodeCommitに変更がプッシュされる度にツール通知を受け取りたい。どうする? (SNS, SESと絡めて)
…
出題内容
めちゃくちゃ広いです。出題されたテーマ的にはセキュリティ,コンピューティング,データストアあたりが多め。
ただし、先にも書いたように出題範囲が上記の通りセキュリティと可用性の設問が多かったので、主要なサービス+セキュリティ/可用性向上に関係しようなサービスを押さえておけばいいなと思いました。
セキュリティ ★
- アクセス制御: IAM
- 暗号化; KMS
コンピューティング ★
- EC2
- Auto Scaling
- ECS
- Lambda
- AWS Batch
ネットワーク
- VPC
- Elastic Load Balancer ★
- CloudFront ★
- Route53
ストリーミング
データストア ★
- RDS
- DynamoDB
- S3
- Elasticache
アプリケーション統合
メッセージング ★
- SQS
- SNS
開発ツール / CDCI ★
実際どんな対策したの?
AWSのドキュメント見ながらやるのが7割。 - とにかくサービスを使う. - どうなったらサービスがエラーを返すか、使う側がコケるかというエラー系を押さえておくとなお良し。
知識系の問題はオンラインの動画見て補完するので3割。
- ホワイトペーパーを読もう! とありますが、1年以上前のものであれば日本語化されているものの最近のやつだと英語版しかありません。英語読むのが辛い人は、字面だけ追ってもすぐ夢の世界に行くことは間違いありません。できれば動画を見つつ手を動かせるコースが望ましいです。
- 費用はかかりましたが、A CLOUD GURUのコースは受けけて正解でした。
まとめ
認定試験を取るまで私の場合は3週間ほどかかりましたが、2~4weekくらいあれば十分かなと思います。 ミソはとにかくサービスを触ること。これに尽きます。
AWSの各サービスを舐める (3) - Amazon S3
AWSのサービス舐めるシリーズその3。今回はS3です。
Kubernetesの検証の時にお世話になったので、今回はちょっとしたメモ程度で。
以前どんなことに使ったかは過去記事をご参照ください。
特徴と制約
ほぼ無限にオブジェクトを格納できる
- ただし、バケット数の上限は100個/アカウント.
- 1オペレーション(PUT)で格納できるファイルサイズ上限は5GB.
- 複数回に分けて格納した場合は格納できるファイルサイズ(1ファイル)の上限は5TB.
ストレージのタイプ
高頻度(ミリ秒単位でパフォーマンスが求められる)のアクセス
- STANDARD ... デフォルトの設定
- RRS ... 非推奨
低頻度のアクセス
- STANDARD_IA ... AZにコピーして保存
- ONEZONE_IA ...
ほとんどアクセスしないアーカイブ
- Amazon Glacierを使う. S3のライフサイクル管理で一定期間経ったらS3 --> Glacierに移動させることができる.
イベント通知
ファイルの格納はもちろんですが、静的ファイルホスティングやイベント通知はかなり使い勝手が良さそうですね。 イベント通知のとこは別のアプリ(オンライン, 定刻起動のジョブとか)でS3にファイル置く -> Lambdaキックとかパイプライン組めそうなので、次回にやってみて記事に載せようと思います
AWSの各サービスを舐める (2) - DynamoDB
AWS舐めるシリーズその2。 今回はAmazon DynamoDBです。前回は文字ばかりだったので、チュートリアルを元にプログラム(Node.js)からも操作してみます。
ちなみに、ローカルマシンのTerminalから弄るので、アクセスキーとシークレットキーを使ってます。Elastic BeanstalkやECS, Lambadaから弄る時はIAMでロールを作ってから操作しましょう。
DynamoDB
テーブル作成
テーブルを作成してみます。
aws configure
で設定していない時は認証失敗して以下のように弾かれるんですね。うまくいったときはdata
に結果が全て入っていると。
正直プログラムからテーブル作るよりもCloudFormationでテーブル作成したほうが冪等性の担保とソース管理がしやすいので個人的にはこっちの方が好みです。
// 認証失敗 { "message": "The security token included in the request is invalid.", "code": "UnrecognizedClientException", "time": "2018-08-19T09:03:53.473Z", "requestId": "SVANMBETVBO11DHOKS8A45GRTVVV4KQNSO5AEMVJF66Q9ASUAAJG", "statusCode": 400, "retryable": false, "retryDelay": 41.39762357028852 } // 認証成功 Created table. Table description JSON: { "TableDescription": { "AttributeDefinitions": [ { "AttributeName": "title", "AttributeType": "S" }, { "AttributeName": "year", "AttributeType": "N" } ], "TableName": "Movies", "KeySchema": [ { "AttributeName": "year", "KeyType": "HASH" }, { "AttributeName": "title", "KeyType": "RANGE" } ], "TableStatus": "CREATING", "CreationDateTime": "2018-08-19T09:04:50.440Z", "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "ReadCapacityUnits": 10, "WriteCapacityUnits": 10 }, "TableSizeBytes": 0, "ItemCount": 0, "TableArn": "arn:aws:dynamodb:ap-northeast-1:284677944563:table/Movies", "TableId": "b5086ea3-11b7-4f0c-b0aa-933e2be38079" } }
テーブルに初期データをロード
次にサンプルのデータをロードします。WCU=10なので、1件ずつデータをロードするときは理論値としては10 * 1KB 書き込み/sec できるはず。
全部で4612件(3632KB)のJSONを1件ずつArray.forEach
で突っ込んでいると、結果的には途中まで進んだところで ProvisionedThroughputExceededException
で弾かれるようになりました。200件ほどエラーで弾かれていますね。
$ node MovieLoadData.js ... PutItem succeeded: Of Human Bondage Unable to add movie 200 Cartas . Error JSON: { "message": "The level of configured provisioned throughput for the table was exceeded. Consider increasing your provisioning level with the UpdateTable API.", "code": "ProvisionedThroughputExceededException", "time": "2018-08-19T09:21:50.335Z", "requestId": "OG9EONR7I6GNIRCSL57FKR8CTRVV4KQNSO5AEMVJF66Q9ASUAAJG", "statusCode": 400, "retryable": true } $ aws dynamodb describe-table --table Movies # ロードされた項目数が表示される. ... "TableSizeBytes": 1991251, "ItemCount": 4365, ...
CRUD操作
SDKにはCRUD用のAPIが用意されているので、ありがたく使わせてもらいます。 実際のプロジェクトで使うなら生のSDKをそのまま書くんじゃなくて、プロジェクト共通のUtilityとしてラップした関数を作って提供してあげたほうが各開発者には優しいかも。
以下チュートリアルのコードほぼそのままですが、 UpdateExpression
, ExpressionAttributeValues
のところが自然言語のようなJPAっぽくて気持ちわるいですね。
const AWS = require("aws-sdk"); // ここのconfigは環境変数で外出ししたほうがベター AWS.config.update({ region: "ap-northeast-1", endpoint: "https://dynamodb.ap-northeast-1.amazonaws.com" }); const docClient = new AWS.DynamoDB.DocumentClient() const table = "Movies"; const year = 2015; const title = "The Big New Movie"; const params = { TableName: table, Key: { "year": year, "title": title }, UpdateExpression: "set info.rating = :r, info.plot=:p, info.actors=:a", ExpressionAttributeValues: { ":r": 5.5, ":p": "Everything happens all at once.", ":a": ["Larry", "Moe", "Curly"] }, ReturnValues: "UPDATED_NEW" }; console.log("Updating the item..."); docClient.update(params, (err, data) => { if (err) { console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2)); } else { console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2)); } });
検索操作
Query
Scan
- テーブル全体の項目を返す。
- デフォルトだとテーブル全体で1MB読みこむ。1MB以上あっても1MBしか読みこまない(全部返すんじゃないんかい)
- 結果セットのフィルタリングができますが、全部読み込んでからフィルタリングで不要なデータを捨てる挙動みたいですね。
- ベストプラクティスとしては、
Limit
宣言で読みこむ件数にキャップをかけること。
使ってみた感想としては、AWS上で使うNoSQLとしては面白い選択肢ですね。
テーブルサイズに上限がないとはいえキャパシティユニットのキャパプラをしておかないとすぐスロットルするから、AutoScalingを有効化するのが最初は無難かもしれません。 あとはユースケースを見極めてテーブル設計すればRDBよりも素早いレスポンスで使えそう。
AWSの各サービスを舐める (1) - IAM, EC2, RDS
今年の目標としてAWS 認定デベロッパー - アソシエイト(2018 June)を取ることを目標にしたので、 A CLOUD GURUのコースに沿って各サービスを舐めて回ることにしました。
気になるやつはGetting Startedをなぞって「へー( ˙꒳˙ )」となるばかりだったので、これを機に使いこなしたいし。 最初の方から割と基本的なことが分かってなかったなと思うことが多いので、しばらくはブログ記事が備忘録になるかと思います笑
今回はタイトルにある、IAM, EC2, RDSのまとめです。
IAM
用語
ユーザー
- AWSを利用する人
グループ
- ユーザーの論理的なまとまり
- グループに所属するユーザー全員に対してアクセス権限(できること/できないことを規定するもの)を設定・適用できる。
ポリシー
ロール
ベストプラクティス
個々の利用者にユーザー/アクセスキーを作る
- ルートキーは漏れるとやばいので、まずは消せ。
- 1つのアクセスキーは使いまわさない。使い回していると万が一キーを漏れた時に影響範囲が全員になってしんどい。
- 1User, 1AccessKey / person
権限はロールを使う
- 同時に言うべきは、アクセスキー/シークレットキーを直接使わないこと。
- ロールに適切な権限をつけることで、ユーザーだけでなくリソースそのものが他のリソースにアクセスするのも安全。
最低限の権限から始める
- いきなりFull Accessが必要か?
- 必要に応じて権限をゆるくするのが安全。
EC2
永続ストレージ(EBS)
RDS
- RDBのマネージドサービス
対象は6種類。Aurora以外はFree Teerもあるみたい。
可用性を高めるには、MultiAZ or Backup or SnapShot
パフォーマンスを高めるには Read Replica
RDSで作られるDBのインスタンスはリージョン固有になる。
- セキュリティグループもリージョンにひもづく
- EC2等の他のリソースからアクセスする場合はセキュリティグループのInBound/OutBoundで穴を開けておくこと。
次はS3やLambdaあたりを舐めまわそうかな。
AWS Lambda with Node.js を叩いてKubernetesにアプリをデプロイしてみる
Kubernetesへのアプリのデプロイ方法を検討したことがあったのでちょっとまとめてみる。
AWS CodePipelineからKubernetesにビルドしたDockerイメージをデプロイするときは、Lambdaでやるパターンがあるみたいですね。
また、ECSだとCodeDeployでデプロイ先にECSクラスターを選べるので楽チン。ただ、AWSのマネージドサービスではKubernetesを直接選ぶことができなさそうだったので、今回もLambdaで実行する方法を検討してみました。
※ 注釈 -----------------------------------------------
上記のデプロイ方法を検討したのが2018年5月ごろなので、EKSのことは考えていません。 2018年6月初めにAmazon EKSが出てきて、公式ではリソース作成にCloudFormationを多用する方法を用いているので、CodeBuildでCloudFormationのテンプレートを作る --> CodeDeployでCloudFormation経由でデプロイ実行の流れもできそうな気がします。
----------------------------------------------- 注釈 ここまで
いろんな記事を舐めてみた限りクライアントライブラリはPythonのを使うって投稿多いけど、Node.jsでやった例が少なそう。(Node.jsのユースケースとして適しているかは別の話)
ただ、公式のNode.jsのKubernetesクライアントライブラリはドキュメントが貧弱なのが難点です。。。
クライアントライブラリを使えないとすれば、別のAPIを使う他ない。Kubernetesにはオブジェクト操作用にREST APIが用意されているので、これを利用するやり方にしてます。
どう実装したかソースを見たい方はGitHubのリンクからどうぞ。
Amazon EKSがGAになったので触った所感
AWSでKubernetesのマネージドサービス Amazon EKS がGAになりました。 今まではAWSでk8sをいじるときはkops経由でクラスターを作って、権限設定してと手間がかかっていましたが、EKSはどれくらい楽になるのかなという観点で触ってみました。
全体的に
AWSのWebコンソール側はめっちゃシンプルで発展途上とさえ感じられるレベル。
今の所、使えるのは US West (Oregon) (us-west-2) or US East (N. Virginia) (us-east-1) のみ。
- 東京リージョン早く来てほしい!
リソースの用意は基本はCLI(aws-cli/kubectl) & CloudFormationでやる。
- クラスターのみWebから作成できる。
クラスターの作成
ネットワーク関連は自分で用意しないといけない。
Get Startedの例だとVPC/SecurityGroupをCloudFormation経由でやらせていました。クラスターの作成も含めてCloudFormationでやったほうが早そう...
ノードの作成
ワーカーノードも自分で作成する。
- クラスターとワーカーの紐付けを後から実施する形みたい。Configmapを編集して適用する。
Auto Scaling グループを設定してあげるので、最小・最大・希望ノード数の範囲で自動で増減できます。
- KubernetesのPodのスケールは HolizontalPodAutoscalerで出来るけど、ノードのスケールまで出来るのは可用性を高めるのに良さげ。
Kubernetesにアプリケーションを乗せる
通常のKubernetesの使い方同様に、ReplicationController, Service ect...を作成すればOK。
LoadBalancerはアクセスできるようになるまで10minくらい待つので気長にお茶でも飲んで待つ。
ハマりポイント
自分がハマったポイント集。
それとMFAでカッチリユーザー権限を設定している人は、事前に
aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from-token
でtokenを取得すること- An error occurred (InvalidClientTokenId) when calling the GetSessionToken operation: The security token included in the request is invalid.
もしInvalidClientTokenIdで弾かれる場合はkubeconfigから-r 行および <role-arn> 行を消すと通る。Roleをここで決めておきたいのに。。。
- could not get token: InvalidClientTokenId: The security token included in the request is invalid.
雑感
認証・認可を上手にIAMとKubernetesのRBACを統合しようとしているなと感じます。AWSでKubernetesを立てるメリットの1つではないでしょうか。
ただ、ドキュメントを見る限りEKSでのIAMの立ち位置は"認証"であって、認可はまだRBAC側で設定するみたいです。
Kubernetesのリソースアクセスの制御は、ConfigMapにIAMユーザー/ロール/アカウントを追加する必要がありますが、新しいユーザーやロールが追加されるたびに毎度毎度ConfigMapを手で書き換えるのは中々メンテナンスが大変そう。。。ここをGUIや自動化出来るとさらに使いやすいですね。
他にも最初からリソース操作はかなり CloudFormationやkubectl に頼っています。
- kopsと比較するとVPC/セキュリティグループ/Auto Scaling/Nodeの設定を細かく出来る一方で手作業となる部分が多いので、"とりあえず作って壊す" には少しハードルが高い印象を受けます。
認可の仕組みやVPC、CloudFormationあたりをもう少し探っていきたいと思います。ここら辺が明確になれば、ECSとの差別化要素も見えてきそうです。