Ponz Dev Log

ゆるくてマイペースな開発日記

GCP BigQueryチュートリアルお触りメモ

GCPのData Engineer認定試験に向けて、データウェアハウスに分類されるBigQueryのチュートリアルを一周したのとドキュメントを読み漁った時のメモです。最近メモ続きで今回はコードは一行も出てきませんが、試験直前に見直すために書き残します。そろそろパイプラインとか自前で作ってみないと。。。

データロード方法

データを流し込むのは以下の方法がある。

データロードのTips

  • 直接ファイルをBQに入れると Upload -> Importの二段階が走って途中でこけると悲しい。GCS経由だと10倍程度早いようだ。
  • 圧縮データでロードする場合は、Avroが最適、次点がPurquet。圧縮率が高いのに、並列読み込みできるから。
  • CSVJSONファイルは、gzip圧縮よりも圧縮なしの方が早い。
  • 基本は文字コード UTF-8で入れること。ISO-8859-1でも読み込み可能だが、UTF-8に変換しながら読み込むため遅い。

テーブル構造

  • 構造化データを入れる
    • ただし、JSONのようにネストした形式のデータでもOK。この場合は、カラム名comitter.name,comitter.timestamp のようにドットつなぎ
    • スキーマは手動で定義するか、サポートされたファイルから読み込む場合は自動検出で定義可能。

ストリーム処理

  • ストリーミングの上限10.000行 / sec
  • ストリーミングインサートするときは、上記の上限に引っかからないようにDataflowを噛ませた方が良さそう。
  • DataflowならPub/Sub, GCS, JDBC(アプリ経由)のテンプレートが用意されているから使うハードルは低い。
  • バッチは強力な整合性、ストリーミングは結果整合性と整合性の性質が異なる。(チュートリアルでFluentd -> BQの場合は1分くらいラグがあった)

課金の話

  • 課金対象は、読み込んだ行数 で決まるので出力結果だけ絞っても金額は絞らない場合と変わらない。(よって、LIMIT句を加えても課金額は変わらない!!)
    • 全ての列を読み込む SELECT * は最低の所業。必要な列だけ取りなさい。
    • テーブルの中身を見るだけなら、プレビューを使おう。単に中身をチラ見するだけなのにクエリを投げるのは課金されるので無駄。
    • 特定の期間のデータのみクエリしたい場合は、時系列のパーティション属性(隠しフィールド扱い?)を使って、時系列パーティションでクエリを投げよう。
    • JOINが多い/共通のクエリがあるならば、事前に中間テーブルを作ろう。

権限設定周り

模擬試験でも出てきて焦ったところだけれども、この人にはこのデータセットは見せたくないとか権限設定は大事。

  • アクセス制御の基本はここを参照
  • 権限設定はプロジェクトレベルが適用されて、あとはデータセット単位(?)
  • 役割ごとに見せたいビューやデータセットを制限したい場合は、データセットを分けること。
  • データセットの権限付与と承認は新しいコンソール画面からじゃできない。"従来のUI”からのみ実行可能。

JavaScriptの2次元配列の展開・重複削除・集約をLodashを簡潔に書く

2018年末に書いたSlack Botを少しリファクタリングした時の話。2次元配列と配列要素の重複削除ってよく使いそうで意外とベストなやり方ってよく分からないですよね。自分の場合は2次元配列は mapforeach、重複削除は Set オブジェクトで実装していましたが、後からぱっと見て処理が訳わからんコードになりがちです。JSって flatMap ってないので気合いで書いちゃう。

以前書いたTrello/Slack/OpenWhiskで作ったBotでも同じような処理を実装しなければいけなくて、やっぱり読みづらいコードが爆誕してしまいました。正直コード書いてから1週間経った今でさえ分からんw

ponzmild.hatenablog.com

さて、こんなダメコードを書いていてはいけないと解決策を模索したところ辿り着いたのがLodash

lodash.com

ライブラリではよく中の実装で使われている印象があり今更かよ感が出ていますが、Lodashで関数を組み合わせて実装してみると思った以上に読みやすくなったのでBefore/Afterで見比べながら書き残します。

解決策

入力データ(Trello APIを呼び出した時のレスポンス)は以下のようなJSONです。

[
  {
    id: "dfhajsdfhalsdfhasrber",
    name: "task1",
    labels: [
      { id: "aaa", name: "hoge" },
      { id: "bbb", name: "fuga" }
    ]
  },
  {
    id: "ruweqioryqweryqweyr",
    name: "task2",
    labels: [
      { id: "aaa", name: "hoge" },
      { id: "ccc", name: "piyo" }
    ]
  }
]

この関数のアウトプットとしては、{name: "hoge", count: n} というオブジェクトの配列にしたい。

改善前

まずは年末の働かない頭で書いた以下のコードを見て欲しい。

function summarizeLabels(cards) {

  // 二次元配列でラベルを取り出して展開し、シンプルな文字列のみの配列にする ... (1)
  let labelLists = [];
  cards.map(card => {
    card.labels.forEach(label => labelLists.push(label.name));
  });

  // 配列内のラベル一覧を重複削除で取り出す ... (2)
  const labelSet = new Set(labelLists);

  // ラベルごとの件数を配列とラベル一覧から導出 ... (3)
  let labelResults = [];
  for (let targetLabel of labelSet) {
    const labelCount =
      labelLists.filter(cardLabel => cardLabel == targetLabel).length || 0;
    labelResults.push({ name: targetLabel, count: labelCount });
  }

  return labelResults;
}

やっていることとしては、以下3つ。文字に起こすと長いですね。

  1. まず label プロパティを取り出すと配列の中に配列が入れ子になった2次元配列の形になる。これは扱いづらいから展開しておく(1)。
  2. 次にキーを取り出すために(1)の配列を重複削除してキーのリストを取り出す(2)。
  3. 最後に(2)のキーのそれぞれに対して(1)の中で合致するラベルの数をカウントしてオブジェクトに突っ込む(3)。

いやー、、、 よ゛み゛つ゛ら゛い゛よ゛お゛

正直後で直したくないコードが見事に爆誕です。理解しづらい理由としては、2次元配列を展開していることを中から外に向かって処理を追わないと理解できない、Setってなんだっけ、filter関数と突っ込む先の配列定義が離れすぎて何の配列か分からない。こんなところでしょうか。

改善後

Lodashで関数チェーンを作り上げて直感的に書くことを試みます。最終的なアウトプットに値を集計する関数のみ自分で作成し、これ以外はLodashで定義された関数を使います。

const _ = require("lodash");

/**
 * 名称ごとの出現数を集計する.
 * @param {Object} stat 集計値
 * @param {String} name 集計キー ... 配列内の個々の値が入る
 */
const gatherNames = (stat, name) => {
  if (_.isUndefined(stat[name])) {
    stat[name] = { name: name, count: 0 };
  }
  stat[name].count++;
  return stat;
};

function summarizeLabels(cards) {
  const labelResults = _.chain(cards)
    .flatMap(_.property("labels")) // ... (1)
    .map(label => label.name)
    .reduce(gatherNames, {}) // ... (2)/(3)
    .values()
    .value(); // ... これを呼び出して初めて上記の関数チェーンが実行される
  return labelResults;
}

以前よりもコードが美しくなった気がします! 改善前のコードで分かりづらかった2次元配列の展開は _.flatMap() で一発で書けます。Lodashのメソッドもmap, reduceといった比較的聞き覚えのある名称なので理解しやすい。for文回さずシンプルに書けるところもポイント高いですね。 一番読みやすくなっているポイントは、処理を関数を組み合わせて関数チェーンで表現できていることでしょうか。

Lodashくん、、、君はすごいライブラリだったのか。。。色んなライブラリで多用される理由も納得です。

JavaScriptのクロージャって結局なんだよ

JavaScriptでは初歩的なコードでは現れないけれどふとした拍子に出てくる単語っていくつかいるような気がします。 特にカリー化、高階関数クロージャ、ファンクターあたり。関数型プログラミングを進めていたら最初の方に出てきて戸惑ったのが クロージャ ってやつです。走り書きでn番煎じですが調べて噛み砕いた結果の備忘録です。

結論

要は 関数 です。("スコープ" と書いてあることが多いけど、実際に指しているのは関数の模様)

関数の中でも、以下の特徴を持つ関数のようですね。

  1. 未実行の関数を返す関数である。
  2. 子の関数からアクセスできる変数を保持する。

ただの関数とは何が違うわけ?

上の(1)だけ見てもJavaで言うところのファクトリメソッド, JavaScriptだと関数ファクトリ(?)っぽいです。 半分合っていそうですが、違いはソースコードを元に見た方が早い。

let outerVar = "outerVar";

function makeInner(params) {
  const innerVar = "InnerVar";

  function inner() {
    console.log(`I can see: ${outerVar}, ${innerVar}, ${params}`);
  }

  return inner;  // 未実行の関数を返す
}

const inner = makeInner("params");
inner();  // --> I can see: outerVar, innerVar, params

上の例だと、makeInner 関数がクロージャになります。inner 関数を返していますね。この makeInner 実行時には inner() としていないから未実行です。(定義1)

また、クロージャ内のローカル変数は inner 宣言時には関数のスコープ外になっていますが消えません。(定義2)

こうやって親の関数から返却される子の関数から、子&親の関数内/関数の引数/グローバルスコープの変数にアクセスできるところが他の関数とは違うところ。 ただ、変数は残ってはいるもののあくまで 参照のみが残っているだけ であって値がそのまま保持されるわけではなさそう。

(let outerVar ~ makeInnerクロージャの宣言まで同じ)

// クロージャから内部の関数を引数を渡して生成する前でも後でも参照する値は変更可能
// outerVar = "Outer2"; // inner() --> outerVar=Outer2
const inner = makeInner("params");
// outerVar = "Outer3"; // inner() --> outerVar=Outer3
inner();  // --> I can see: outerVar, innerVar, params

2番目の例の通り、途中で書き変わると最終的にクロージャから返却される関数の実行結果は変わるようですね。

参考

developer.mozilla.org

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ (impress top gear)

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ (impress top gear)

Gradleを使ってIBM Cloud Functions with Javaの関数を実装する

あけましておめでとうございます。新年一発目はサーバーレスです。 昨年はNode.jsしかほとんど触らなかったIBM Cloud Functions(OpenWhisk)をJavaで実装します。

ただし、公式のチュートリアルだと自力でgsonにCLASSPATH通してデプロイしてねと雑にしか書いていないので、こちらのブログのチュートリアルを使います。

www.ibm.com

とはいっても、作り方は2ステップで簡単です。 ブログ記事そのままですが、書き初めとうことで基本を押さえに行きます。

Javaの関数を書く

ポイントは2つ押さえておけばOKです。

  1. 実行する関数(厳密にはエントリーポイントとなるメソッドを指します)の名前は main 固定です。(別名にしてもいいけど仕組みに乗っかった方が楽)
  2. どうやらリクエストとレスポンスのJSONパーサーはgsonを使うことが推奨されています。(これ以外のJSONパーサーは使えないのかは未検証です)

簡単なHello worldは以下のようになります。

package com.example;

import com.google.gson.JsonObject;

public class Hello {

  public static JsonObject main(JsonObject args) {
    // リクエストを受け取る
    String name = args.getAsJsonPrimitive("name").getAsString();
    // レスポンスを返す
    JsonObject response = new JsonObject();
    response.addProperty("greeting", "Hello " + name + "!");
    return response;
  }
}

JARに固めてデプロイする

gsonはIBM Cloud側で提供されているので依存関係にJARとして含めなくても良いのですが、これ以外にもライブラリを含めたいとかありますよね?DIするならgoogle-guiceとか、HTTPクライアントにOkHttp使いたいとか諸々。そんな時は公式のチュートリアルのようにいちいちクラスパスを通すのは時間の無駄なのでGradleで一気にまとめます。(Jarに固めればいいので、Mavenでもできるはず)

上のHello worldの例だと最小限の記述で以下のように書けます。単純に依存関係のJARの取得先と何を入れるのかを書くだけ。

apply plugin: 'java'
version = '1.0'
repositories {
    mavenCentral()
}
dependencies {
    compile 'com.google.code.gson:gson:2.8.5'
}

あとは ibmcloud fn action create hello-wsk-java build/libs/hello-wsk-java-1.0.jar --main com.example.Hello でデプロイするだけ! ちょっとした関数を書くにはJavaを使うのは億劫ですが、かなり簡単にできるんですね。

2018年振り返りと2019年の抱負

今年の年末エントリーです。

2018年は部署異動があったおかげで、仕事環境も私生活もガラッと変わった1年でした。 心のゆとりができたこともあってジムに通い始めたり技術書読んだりと社会人1〜2年目の時にはできなかったことにも手を出せて初めて社会人楽しいと思えた。ただ、色んなことに手を出し始めて手をつけられないことも多かったので、供養も兼ねて振り返りと来年の抱負を書き留めておきます。

2018年

[業務内]

  • オンプレのオープン系システムの運用(上半期)
  • AWSAPI開発(下半期)

上半期はテストフェイズ最後の期間なのにトラブルシューティングの嵐、嵐、嵐。 LinuxとETLツールとDBのログをひたすら読み解いてました。ログを読む力と問題の切り分け方法 + PMとのやり取りにある程度自信が結果的にはつきました。Jenkinsを使ったCICDも含めてインフラとミドルウェア周りに触れたいい経験だったと思いますよ。3月に一度倒れたので二度とやりたくない。

下半期は今どきのMicro ServicesでAPI開発、しかもAWSに取り組めたのは部門異動して本当に良かったと思える仕事でした。この期間内にAWSデベロッパーアソシエイトの認定が取れたことも大きな自信になったし、Javaの開発は1年半ぶりだったけど1年目に負けないように食らいついた。やっぱりロジックをひたすら考えてコーディングするのはめちゃくちゃ楽しい。 恥ずかしながらJUnitの使い方も1年目の新人よりも分かってなくてすごい焦ったのは今でも覚えていて、Udemyのコース1本をお盆休みかけてがっつりやったのは後ですごく役立った。 APIだけじゃなくて初物としてやらせてもらえたAWS Batchが一番楽しかった気がする。 それにとあるアプリ用にPythonAPI開発, 入力チェックツールとして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
    • Javaの勉強やり直しとして取り組んだ。業務外のイベントアプリや案件管理アプリの時にアプリのデバッグに役立ったかな。
  • JAX-RS(Jersey)
    • 2018年下半期の案件でJavaを使うことになったので、設計フェイズの余裕のある時に取り組んだ。フレームワークはまさしくJerseyがベースだったので開発フェイズ以降に戸惑うことが少なかったのが嬉しかったところ。
  • GraphQL
    • 勉強会に参加したりしたけど, 案件の開発フェイズに入って時間が合わず途中で断念。来年こそは本格的に取り組む!
  • Serverless(Lambda/OpenWhisk)
    • きっかけは ServerlessConfに行ってきたところから。
    • Webサービスだけじゃなくてアナリティクスや機械学習、巨大なデータセットのETLにまでサーバーレスを使ってることが衝撃だった。
    • しかもAWS一強じゃなくてAzure Functionもプレゼンやユースケースを見てすごく魅力的に見えた。あまり他の人が使ってないこの領域が自分の軸になるかもと可能性を感じた分野でした。

[気になったけど本格的に取り組めなかった技術たち]

来年はここからピックアップして取り組みたい。毎月テーマを決めていくつか取り組めば良かったなと反省です。

[書籍]

心に余裕ができてから少しずつ書籍を読めるようになった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の構成

構成図は割とシンプルになりました。

f:id:accelerk:20181231004654p:plain
Botの構成図

上の構成図の技術要素も並べるとこんな感じ。 極力労力をかけず/コードを書かずにサービスを組み合わせて実現させることを第一に実装します。

  • Node.js
    • スピード重視で慣れている言語で作ります。TypeScriptは使いません。
  • Trello API
    • 公式から出ているAPIでタスクを取得します。
  • Slack
    • 業務でも使ってるコミュニケーションツール。特定のタイミングで頑張った成果と褒め言葉を自分に投げる先です。
    • 一番手軽なWebhook経由でメッセージを投稿させます。
  • IBM Cloud Functions
    • こちらもスピード重視でCloudFoundryやIBM Kubernetes Serviceよりも手軽に上記の要素を実現できる方法として採用。
    • Slackにメッセージを飛ばすパッケージが事前に用意されていたので、
  • Serverless Framework
    • 関数のデプロイや依存するリソース管理に時間をかけたくないので、宣言的にリソース定義とデプロイするためのツールとして使用します。
    • IBM Cloud Functionsと連携する方法は自分の記事参照。 qiita.com
  • Continuous Delivery @IBM Cloud
    • TrelloやSlackのURL/Tokenを扱う以上、これらの情報をいちいち環境変数に指定してデプロイするのは面倒。
    • GitHubソースコードがコミットされることを検知してCI/CDパイプラインからリリースをかけます。
    • スケジュール起動や事前にIBM Cloud側で用意されているSlackパッケージはServerless Frameworkで定義してデプロイします。

できたもの

金曜22時になったら頑張りを通知してくれるようになりました!!

f:id:accelerk:20181231005204p:plain
Botから成果と褒め言葉が送られる

ソースコードはこちらに置いていますので、ご参考まで。 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 プラットフォームでのアプリケーションの開発と保守についての技術的な専門知識を認定します。 この試験では以下について理解していることが求められます。

  • アプリケーションについて適切な AWS サービスを選択する
  • アプリケーションと AWS サービスが相互にやり取りするための AWS SDK を取得する
  • アプリケーションによって使用される AWS サービスのパフォーマンスを最適化するためのコードを記述する
  • コードレベルのアプリケーションのセキュリティ(IAM ロール、認証情報、暗号化など)

試験ではどんなこと聞かれたの?

テーマ

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
  • アプリケーション統合

  • メッセージング ★

  • 開発ツール / CDCI ★

    • CodeCommit
    • CodBuild
    • CodePipeline
    • Elastic Beanstalk
    • AWS SDK

実際どんな対策したの?

AWSのドキュメント見ながらやるのが7割。 - とにかくサービスを使う. - どうなったらサービスがエラーを返すか、使う側がコケるかというエラー系を押さえておくとなお良し。

知識系の問題はオンラインの動画見て補完するので3割。

  • ホワイトペーパーを読もう! とありますが、1年以上前のものであれば日本語化されているものの最近のやつだと英語版しかありません。英語読むのが辛い人は、字面だけ追ってもすぐ夢の世界に行くことは間違いありません。できれば動画を見つつ手を動かせるコースが望ましいです。

まとめ

認定試験を取るまで私の場合は3週間ほどかかりましたが、2~4weekくらいあれば十分かなと思います。 ミソはとにかくサービスを触ること。これに尽きます。