2018年振り返りと2019年の抱負
今年の年末エントリーです。
2018年は部署異動があったおかげで、仕事環境も私生活もガラッと変わった1年でした。 心のゆとりができたこともあってジムに通い始めたり技術書読んだりと社会人1〜2年目の時にはできなかったことにも手を出せて初めて社会人楽しいと思えた。ただ、色んなことに手を出し始めて手をつけられないことも多かったので、供養も兼ねて振り返りと来年の抱負を書き留めておきます。
2018年
[業務内]
上半期はテストフェイズ最後の期間なのにトラブルシューティングの嵐、嵐、嵐。 LinuxとETLツールとDBのログをひたすら読み解いてました。ログを読む力と問題の切り分け方法 + PMとのやり取りにある程度自信が結果的にはつきました。Jenkinsを使ったCICDも含めてインフラとミドルウェア周りに触れたいい経験だったと思いますよ。3月に一度倒れたので二度とやりたくない。
下半期は今どきのMicro ServicesでAPI開発、しかもAWSに取り組めたのは部門異動して本当に良かったと思える仕事でした。この期間内にAWSデベロッパーアソシエイトの認定が取れたことも大きな自信になったし、Javaの開発は1年半ぶりだったけど1年目に負けないように食らいついた。やっぱりロジックをひたすら考えてコーディングするのはめちゃくちゃ楽しい。 恥ずかしながらJUnitの使い方も1年目の新人よりも分かってなくてすごい焦ったのは今でも覚えていて、Udemyのコース1本をお盆休みかけてがっつりやったのは後ですごく役立った。 APIだけじゃなくて初物としてやらせてもらえたAWS Batchが一番楽しかった気がする。 それにとあるアプリ用にPythonのAPI開発, 入力チェックツールとしてNode.js使えて多言語だったのが飽きない理由の一つだったかもしれない。Node.jsバリバリのツール開発をやらせてもらえたのは感謝しかない。
[業務外 (社内)]
- 全社イベント向けアプリ(認証基盤連携 + Kubernetes + ログ基盤連携) 3〜4月
- Kubernetes @AWS 勉強会 (k8s + Codeシリーズ + Lambda) 6〜9月
- マネージャー向け案件管理アプリ (React/Redux ガッツリ + Carbon Design System) 10〜12月
業務外の社内開発も結構やってました。期間を見ると途切れることなくやってましたね、、、 上2つはk8s触れたし、最後のはReactガッツリで満足。インフラからフロントエンドまでまさにフルスタックで開発してました。
[個人開発]
- Spring Boot
- JAX-RS(Jersey)
- GraphQL
- 勉強会に参加したりしたけど, 案件の開発フェイズに入って時間が合わず途中で断念。来年こそは本格的に取り組む!
- Serverless(Lambda/OpenWhisk)
[気になったけど本格的に取り組めなかった技術たち]
来年はここからピックアップして取り組みたい。毎月テーマを決めていくつか取り組めば良かったなと反省です。
- GraphQL
- gRPC
- Go
- Scala
- クリーンアーキテクチャ
- 関数型プログラミング
- Serverless全般(OpenWhisk / Lambda / Spring Function)
- BlockChain (Ethereum / HyperLedger Fabric)
- Pupetter
- X Platform (Electoron / Flutter)
- MicroProfile
- Knative
- Istio
[書籍]
心に余裕ができてから少しずつ書籍を読めるようになった1年でもありました。読んでてよかった本をピックアップします。
- コンテナベース・オーケストレーション
- 入門Kubernetes
- DeploymentやService, Ingressだけじゃなく、Holizontal Pod Autoscalerを知れたのはサービスのスケーリングを考える上で助かった。
- リーダブルコード
- 話すように書き、無関係な細かい処理は外に出し、数週間後の自分がみて分かるコードを書くことは設計開発時の心構えになった。
- 2週間後の自分が見てわかるコードを書くが自分の戒めになった。
- React開発 現場の教科書
- 社内ワークの時に, アプリの構成の参考になった。DesignSystemやAtomicデザインは必見。
- JavaScript本格入門
- String/Number/Arrayといった基本型やPromiseのリファレンスとして最適。
- 漫画
- 100冊以上買って読んでましたw
- これはこれでまとめておけばよかったな。
2019年の抱負
技術面
1〜2ヶ月に1テーマ決めて取り組んだことをプログにまとめます。今のところ考えているテーマは、サーバレス(Knative/Istio/FaaS)、マイクロサービス(Micro Profile)、関数型プログラミング(JS/Scala)/クリーンアーキテクチャ、ブロックチェーン(Hyper Ledger)、自動化(Puppeteer/CICDプロダクト)あたりです。
あとはアウトプットとして
- ブログ記事
- 日本語記事を年間24本
- Mediumに英語記事6本
- 書籍まとめ
- 年間5本
生活面
技術面だけじゃなくて生活面も改善させます。疲れにくい身体を作るのは継続したい。12月はジム通いは後半サボっちゃったから今年は具体的に目標決めます。
- 体重
- 6月までに58kg
- 12月末までに60kgを目指す。
来年はもっと頑張れる一年にしたいと思います。それでは良いお年を。
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のリンクからどうぞ。