ポン酢まいるど開発記

開発のことから、ITにまつわることの感想まで、マイルドに書きます

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くらいあれば十分かなと思います。 ミソはとにかくサービスを触ること。これに尽きます。

AWSの各サービスを舐める (3) - Amazon S3

AWSのサービス舐めるシリーズその3。今回はS3です。
Kubernetesの検証の時にお世話になったので、今回はちょっとしたメモ程度で。 以前どんなことに使ったかは過去記事をご参照ください。

特徴と制約

  • レコードを格納するようなDBではなく、ファイル(CSV, JSON, Image, etc...)を格納するオブジェクト・ストレージ

  • ファイルの保存だけでなく、HTML/CSS/JSのファイルを置いてウェブサイトホスティングができます。

    • フロントエンドアプリ(React, Vue.js, Angularとか)ならバンドルして置くだけで良さげ。
    • PHPやNode.js, Javaのようなサーバーサイドスクリプトはおいてもアプリは動かない。

    • リージョンによって、ホスティングするときのサイトのエンドポイント名の命名規則が若干違うらしいです。

      • <bucket-name>.s3-website-<AWS-region>.amazonaws.com
      • <bucket-name>-s3-website-<AWS-region>.amazonaws.com

docs.aws.amazon.com

  • ほぼ無限にオブジェクトを格納できる

    • ただし、バケット数の上限は100個/アカウント.
    • 1オペレーション(PUT)で格納できるファイルサイズ上限は5GB.
    • 複数回に分けて格納した場合は格納できるファイルサイズ(1ファイル)の上限は5TB.

ストレージのタイプ

  • 高頻度(ミリ秒単位でパフォーマンスが求められる)のアクセス

    • STANDARD ... デフォルトの設定
    • RRS ... 非推奨
  • 低頻度のアクセス

    • STANDARD_IA ... AZにコピーして保存
    • ONEZONE_IA ...
  • ほとんどアクセスしないアーカイブ

    • Amazon Glacierを使う. S3のライフサイクル管理で一定期間経ったらS3 --> Glacierに移動させることができる.

イベント通知

  • バケットに対して特定のオペレーションをかけたときにAWSの他のサービスに通知送信・起動ができるみたい.
  • 通知先は、SNS, SQS, Lambdaの3種類
    • Lambdaの直接キックもできる。

ファイルの格納はもちろんですが、静的ファイルホスティングやイベント通知はかなり使い勝手が良さそうですね。 イベント通知のとこは別のアプリ(オンライン, 定刻起動のジョブとか)でS3にファイル置く -> Lambdaキックとかパイプライン組めそうなので、次回にやってみて記事に載せようと思います

AWSの各サービスを舐める (2) - DynamoDB

AWS舐めるシリーズその2。 今回はAmazon DynamoDBです。前回は文字ばかりだったので、チュートリアルを元にプログラム(Node.js)からも操作してみます。

docs.aws.amazon.com

ちなみに、ローカルマシンの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宣言で読みこむ件数にキャップをかけること。

docs.aws.amazon.com


使ってみた感想としては、AWS上で使うNoSQLとしては面白い選択肢ですね。

テーブルサイズに上限がないとはいえキャパシティユニットのキャパプラをしておかないとすぐスロットルするから、AutoScalingを有効化するのが最初は無難かもしれません。 あとはユースケースを見極めてテーブル設計すればRDBよりも素早いレスポンスで使えそう。

AWSの各サービスを舐める (1) - IAM, EC2, RDS

今年の目標としてAWS 認定デベロッパー - アソシエイト(2018 June)を取ることを目標にしたので、 A CLOUD GURUのコースに沿って各サービスを舐めて回ることにしました。

気になるやつはGetting Startedをなぞって「へー( ˙꒳​˙ )」となるばかりだったので、これを機に使いこなしたいし。 最初の方から割と基本的なことが分かってなかったなと思うことが多いので、しばらくはブログ記事が備忘録になるかと思います笑

今回はタイトルにある、IAM, EC2, RDSのまとめです。

IAM

用語

  • ユーザー

    • AWSを利用する人
  • グループ

    • ユーザーの論理的なまとまり
    • グループに所属するユーザー全員に対してアクセス権限(できること/できないことを規定するもの)を設定・適用できる。
  • ポリシー

    • AWSリソースに対するアクセス権限の設定の論理的なセット
    • 実態はJSON文書
    • AWSで用意されたものだけじゃなく、自分で各リソースへのアクセス権限を設定可能
      • MFAの強制とかは自分でポリシーを作らないとダメっぽい
  • ロール

    • 名前の通り、AWSのアカウントにおける役割のこと。ユーザーまたはAWSリソースに対して付与する。
    • このロールにはポリシーを最大10個までつけることで権限を持つことができる。

ベストプラクティス

  • 個々の利用者にユーザー/アクセスキーを作る

    • ルートキーは漏れるとやばいので、まずは消せ。
    • 1つのアクセスキーは使いまわさない。使い回していると万が一キーを漏れた時に影響範囲が全員になってしんどい。
    • 1User, 1AccessKey / person
  • 権限はロールを使う

    • 同時に言うべきは、アクセスキー/シークレットキーを直接使わないこと
    • ロールに適切な権限をつけることで、ユーザーだけでなくリソースそのものが他のリソースにアクセスするのも安全。
  • 最低限の権限から始める

    • いきなりFull Accessが必要か?
    • 必要に応じて権限をゆるくするのが安全。

EC2

  • 仮想マシン

    • 仮想マシンスペックは汎用的なインスタンスだけでなく、I/O, メモリ, GPU特化のインスタンスもある。
    • OSやM/Wの入ったマシンイメージから作成する。
      • コミュニティイメージにはWAS入りのやつとかもあるので、探せばニッチなやつも見つかりそう。
    • 開発用のマシンが欲しいなら取り敢えずt2.microインスタンスを用意しておけば良さそう。
  • 永続ストレージ(EBS)

    • 自在にEC2に付け外しできるストレージ
    • SSD/HDDから選べる(その中でも更にボリュームサイズやスループットの性能で分類がある)
    • EC2にEBSのストレージをアタッチしてファイルシステムも作れるけど、それならEFS使ったほうが早くね?というのが素直な疑問。
    • 暗号化はもちろん、スナップショットも簡単に取れる。
      • スナップショットから仮想マシンイメージも作れる(!?)

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でやるパターンがあるみたいですね。

aws.amazon.com

また、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クライアントライブラリはドキュメントが貧弱なのが難点です。。。

github.com

クライアントライブラリを使えないとすれば、別のAPIを使う他ない。Kubernetesにはオブジェクト操作用にREST APIが用意されているので、これを利用するやり方にしてます。

どう実装したかソースを見たい方はGitHubのリンクからどうぞ。

github.com

Amazon EKSがGAになったので触った所感

AWSでKubernetesのマネージドサービス Amazon EKS がGAになりました。 今まではAWSでk8sをいじるときはkops経由でクラスターを作って、権限設定してと手間がかかっていましたが、EKSはどれくらい楽になるのかなという観点で触ってみました。

www.atmarkit.co.jp

全体的に

  • AWSのWebコンソール側はめっちゃシンプルで発展途上とさえ感じられるレベル。

    • クラスター情報の参照くらいしかできない最低限のものなので、これからGUIで各種操作できるようにできるのかな?
  • 今の所、使えるのは US West (Oregon) (us-west-2) or US East (N. Virginia) (us-east-1) のみ。

    • 東京リージョン早く来てほしい!
  • リソースの用意は基本はCLI(aws-cli/kubectl) & CloudFormationでやる。

クラスターの作成

  • ネットワーク関連は自分で用意しないといけない。

  • 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との差別化要素も見えてきそうです。

npm v6が自動的に脆弱性を見つけるようになった

Node 10.0と合わせて自分のMacのnpmもv6にバージョンアップさせました。 色々いじってた時に脆弱性を教えてくれるようになったので、メモとして残します。

例えばnpm install でnodemonを入れると、以下のように脆弱性があるよと警告を親切に出してくれます。

f:id:accelerk:20180514234607p:plain

画像のインストラクション通り、npm auditで詳細が見られるようです。 素直にコマンドを叩くとこんな図のようにどのパッケージの何がマズイのか表示されるようになります。

f:id:accelerk:20180514234132p:plain

ガイドはNPM公式から出てます。 ガイドを見る限り、npm installを叩くと同時に npm auditも叩かれるみたいです。 もしパッケージインストール時に npm auditを叩かないようにしたい場合は、--no-auditフラグをつければOK。

今回のnodemonの例でやると、以下のようになる。

npm install nodemon --no-audit

また、npmのインストール全体を通して npm auditさせないようにするためには以下のように設定してあげればいいみたいです。

npm set audit false

docs.npmjs.com

Nodeだけじゃなくてnpmも進化してるって発見ですね。 セキュリティ周りをこうやって補強するのを助けてくれるのは嬉しい限りです。最近はGitHubもpackage.jsonから脆弱性アラートを出してくれるようになっているみたいなので、ちゃんとセキュリティ周りは固めておきたいね。