Programming Self-Study Notebook

勉強したことを忘れないように! 思い出せるように!!

本ブログに「お問い合わせフォーム」を設置しました!

f:id:overworker:20210425001348p:plain:w300


GoogleAdSense対策として、本ブログにお問い合わせフォームを設置したときの作業記録です。

手順1:「Google Chrome」での作業

1-1「お問い合わせフォーム」のテンプレート作成する

Googleアカウント(Gmail)にログインした状態で以下を選択します。

f:id:overworker:20210425002815p:plain:w400

私の場合は一番最後に表示されました。

f:id:overworker:20210425003112p:plain:w200
f:id:overworker:20210425004714p:plain:w400

私の場合は個人でブログを作成しているので、パーソナルを選択しました。

f:id:overworker:20210425005025p:plain:w400

新しいフォームを作成という画面になります。一番左の空白を選択してください。

f:id:overworker:20210425011540p:plain:w500

1-1.「お問い合わせフォーム」と入力します。
1-2.「お問い合わせフォーム」の説明を入力します。
2-1.「お名前」と入力します。
2-2.「記述式」を選択します。
2-3.「必須」をONにします。
2-4.ここをクリックすると、次の設定が開始します
3-※.メールアドレスの入力欄を作成します(「2-※」と同様の操作で実施可能です。)
4-※.お問い合わせ内容の入力欄を作成します(「2-※」と同様の操作で実施可能です。)
5.最後に右上の送信をクリックします。

f:id:overworker:20210425012724p:plain:w300

フォームの送信画面で一番右の<>を選択します。

最後にHTMLを埋め込むので下に書かれているURLをコピーします。(2-1で使います)
(ここではまだ閉じないでください。)

手順2:「はてなブログ」での作業

2-1:お問い合わせだけの記事を作成する。

まずはいつもの手順で「お問い合わせ」だけの記事を作成します。

項目 内容
タイトル お問い合わせ
内容 先ほどのURLのコピペ

2-2:サイドバーに「お問い合わせフォーム」を設定。

f:id:overworker:20210425014842p:plain:w200

管理画面上でデザインを選択します。

f:id:overworker:20210425015323p:plain:w200

工具アイコン→サイドバーを選択します。

f:id:overworker:20210425020114p:plain:w400

これでサイドバーにお問い合わせが追加されます。

仮想サーバがDiskFull時の対応方法

f:id:overworker:20200617233306p:plain:h250

環境

状況

  • 状況①:定期実行しているJobで不自然なログが出力されるようになった

  • 状況②:原因を解析するためにTeraTerm(ssh)でログイン、その後cdコマンドを実施してもエラーが発生する

f:id:overworker:20210331012400p:plain
$ cd auto-bash: ヒアドキュメント用一時ファイルを作成できません: デバイスに空き領域がありませんす

Linuxでdisk full、ディスクが一杯の状態であることを示している。

  • 状況③:Disk残量を確認する(DiskFullを確認する)
df -h --total
  • 以下は参考イメージです(記録し忘れたので、、、)
ファイルシス            サイズ  使用  残り 使用% マウント位置
/dev/mapper/centos-root   152G   20K  152G   100% /                  ←ココが枯渇していた
devtmpfs                  3.9G     0  3.9G    0% /dev
tmpfs                     3.9G     0  3.9G    0% /dev/shm
tmpfs                     3.9G  219M  3.7G    6% /run
tmpfs                     3.9G     0  3.9G    0% /sys/fs/cgroup
/dev/sda1                1014M  285M  730M   29% /boot
tmpfs                     783M   12K  783M    1% /run/user/42
/dev/sr0                  4.3G  4.3G     0  100% /run/media/root/CentOS 7 x86_64
total                     173G   20G  154G   12% -

対応方法

考え方

  • 手順①:サーバーの再起動を実施
    • 余計なpidファイルとか、tmpファイルが消える。
    • cdコマンドrmコマンドが利用可能になる
  • 手順②不要なディレクトリを削除して容量を確保する

手順1:サーバの再起動

reboot

rebootコマンドで以下のErrorが発生した

[ ~]$ reboot
User root is logged in on sshd.
User root is logged in on sshd.
User root is logged in on seat0.
Please retry operation after closing inhibitors and logging out other users.
Alternatively, ignore inhibitors and users with 'systemctl reboot -i'.
  • 1台のPC内で複数のTeraTermを起動し、並列でアクセスしている状態で、再起動コマンドを実行した際に発生したエラー表示
    • TeraTermが複数起動(かつ同一のマシンに接続)している場合は再起動できない

  • rebootコマンドを入力する接続以外は、切断することで解消されます

手順2:ディスクの使用状況を確認する

  • 少し空きが増えてることが確認できるはずです。
df -h --total

手順3:サイズが大きくなっているディレクトリを調べる

// 実行したディレクトリ、及び配下のディレクトリについて使用データサイズを抽出する
// (DiskFull位データがたくさんあると、算出に時間がかかると思います。)
du

// 合計値のみを表示する
du -s

※ 私はcdコマンドで対象ディレクトリへ移動しながらdu -sを実施しました

手順4:不要データ(ディレクトリごと)削除

rm -r (ディレクトリ名)

利用したUnixコマンド

reboot(サーバーを再起動する)

reboot

df(ディスクの残量を確認する)

df -h --total

duディレクトリ配下の容量を確認する)

// 詳細表示
du

// 合計値表示
du -s

rmディレクトリ配下をまとめて削除する)

rm -r (ディレクトリ名)

セマンティックバージョニングで迷った時のメモ書き

f:id:overworker:20210324234002p:plain:w400


開発中のプログラムのバージョン番号付けで迷うことがあったので、セマンティックバージョニングのリファレンスのを読んでみました。 その時に覚えておきたいと思った内容をノート代わりに記録しておきます。

概要

  • 基本的には3つの数の組み合わせでバージョンを管理する
  • バージョンナンバーは、左からメジャー.マイナー.パッチと呼ぶ。
  • バージョンを上げる際の決まり
    • APIの変更に互換性のない場合はメジャーバージョンを上げる
    • 後方互換性があり機能性を追加した場合はマイナーバージョンを上げる
    • 後方互換性を伴うバグ修正をした場合はパッチバージョンを上げる  - 3つの数字の組み合わせ部分以外に、プレリリースビルドナンバーなどのラベルを用いて形式を拡張する形で利用することができる。

導入

パブリックなAPIを宣言したら、それを変更する際にはルールに従ってバージョン番号を上げなければなりません。つまり、X.Y.Z(メジャー.マイナー.パッチ)のバージョン形式を遵守しなければなりません。

『セマンティック バージョニング仕様書 (SemVer)』より

前提

この文書における各キーワード
「しなければならない(MUST)」、
「してはならない(MUST NOT)」、
「要求されている(REQUIRED)」、
「することになる(SHALL)」、
「することはない(SHALL NOT)」、
「する必要がある(SHOULD)」、
「しないほうがよい(SHOULD NOT)」、
「推奨される(RECOMMENDED)」、
「してもよい(MAY)」、
「選択できる(OPTIONAL)」は、
RFC 2119に記載されている内容に従い解釈してください。

1.

セマンティック バージョニングを適用するソフトウェアはパブリックAPIを宣言しなければなりません(MUST)。このAPIはコード自体で表現されているかもしれませんし、明確に文書として存在してるかもしれません。どちらにせよ、正確かつ漏れがないようにするべきです(SHOULD)。

2.

通常のバージョンナンバーは、X.Y.Zの形式にしなければなりません(MUST)。このときX、Y、Zは非負の整数であり(MUST)、各数値の先頭にゼロを配置してはなりません(MUST NOT)。Xはメジャーバージョン、Yはマイナーバージョン、Zはパッチバージョンを表します。各バージョンは数値的にバージョンアップしなければなりません(MUST)。例:1.9.0 -> 1.10.0 -> 1.11.0。

3.

一度パッケージをリリースしたのなら、そのバージョンのパッケージのコンテンツは修正してはなりません(MUST NOT)。いかなる修正も新しいバージョンとしてリリースしなければなりません(MUST)。

  • 厳密にセマンティックバージョニングを運用するなら『タグのつけなおし』、は実施してはいけないということ。

4.

メジャーバージョンのゼロ(0.y.z)は初期段階の開発用です。いつでも、いかなる変更も起こりえます(MAY)。この時のパブリックAPIは安定していると考えるべきではありません(SHOULD NOT)。

  • 0.y.zは運用ルールが特別

5.

バージョン1.0.0はパブリックAPIを定義します。このリリース後のバージョンナンバーの上げ方に関しては、パブリックAPIがどのくらい変更されるのかによって決まります。

  • 1.0.0以降は運用ルールが厳密

6.

パッチバージョン Z (x.y.Z | x > 0)は、後方互換性を保ったバグ修正を取り込んだ場合のみ、上げなければなりません(MUST)。バグ修正とは間違った振る舞いを修正する内部の変更のことを指します。

7.

マイナーバージョン Y (x.Y.z | x > 0)は、後方互換性を保ちつつ機能性をパブリックAPIに追加した場合、上げなければなりません(MUST)。また、いかなるパブリックAPIも廃止予定としたのなら、上げなければなりません(MUST)。プライベートコード内での新しい機能の追加や改善を取り込んだ場合は、上げてもよいです(MAY)。その際にパッチレベルの変更も含めてもよいです(MAY)。マイナーバージョンを上げた際にはパッチバージョンを0にリセットしなければなりません(MUST)。

  • バグ修正等の機能に影響がない内容の変更を実施したとしてもマイナーバージョンを更新してよい。

8.

メジャーバージョン X (X.y.z | X > 0)は、パブリックAPIに対して後方互換性を持たない変更が取り込まれた場合、上げなければなりません(MUST)。その際にマイナーおよびパッチレベルの変更も含めてもよいです(MAY)。メジャーバージョンを上げた際には、パッチおよびマイナーバージョンを0にリセットしなければなりません(MUST)。

  • 一部のAPIを使えなくしたら、メジャーバージョンを上げる必要がある。

9.

プレリリースバージョンは、パッチバージョンの直後にハイフンとドットで区切られた識別子を追加することで表現してもよいです(MAY)。識別子は必ずASCII英数字とハイフン [0-9A-Za-z-] でなければなりません(MUST)。識別子は空であってはなりません(MUST NOT)。数値の識別子はゼロから始めてはなりません(MUST NOT)。プレリリースバージョンは関連する通常のバージョンよりも低い優先度です。プレリリースバージョンは、不安定であり、関連する通常のバージョンが示す要件と互換性を満たさない可能性があります。例:1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92。

10.

ビルドメタデータはパッチまたはプレリリースバージョンの直後にプラス記号とドットで区切られた識別子を追加することで表現してもよいです(MAY)。識別子は必ずASCII英数字とハイフン [0-9A-Za-z-] でなければなりません(MUST)。識別子は空であってはなりません(MUST NOT)。バージョンの優先度を決める際にはビルドメタデータは無視されなければなりません(MUST)。つまり、2つのビルドメタデータだけが違うバージョンは、同じ優先度ということです。例:1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85。

11.

バージョン同士をどのように比較するのかは優先度によって決まります。優先度はメジャー、マイナー、パッチ、プレリリース識別子の順番(ビルドメタデータは優先度に関して考慮しない)で分けて評価されなければなりません(MUST)。優先度は、各識別子を左から右に比較して最初の違いによって評価します。以下のように、メジャー、マイナー、パッチバージョンと常に数値的に比較します。例:1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。メジャー、マイナー、パッチが同じ場合、プレリリースバージョンを持っている方が通常のバージョンよりも低い優先度です。例:1.0.0-alpha < 1.0.0。同じ、メジャー、マイナー、パッチを持つプレリリースバージョンの優先度の決定は、ドットで区切れた識別子を左から右に、異なるところが見つかるまで比較し決定しなければなりません(MUST)。数値のみで構成される識別子は数値的に比較され、文字列やハイフンを含む識別子はASCIIソート順に辞書的に比較されます。数値的な識別子は常に数値的でない識別子よりも低い優先度です。もし先行する識別子が同じ場合、プレリリースのフィールドが小さいセットよりも大きいセットのほうが高い優先度です。例:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0。

参考文献

AWS Lambdaを少しでも速くする

f:id:overworker:20210304234231p:plain:h200f:id:overworker:20210312003225p:plain:h200

Lambdaのコールドスタート対策の調査をする中で、「AWS Summit Tokyo 2017全部教えます!サーバレスアプリのアンチパターンとチューニング」というセッションに到達しました。
上記スライド以外にもYouTubeの動画(約40分)があるようですのでご興味がある方は探してみてください。

遅くなる理由

  • プログラムの問題
  • コンピューティングリソースの不足
  • コールドスタート
  • アーキテクチャの問題
  • 同時実行数

プログラムの問題

  • Lambdaファンクションとして実装されているプログラムのロジックそのものの問題
    • 実際のところ、プラットフォーム側でできることはない
  • 各言語のベストプラクティス、最適化手法はそのまま当てはまる

遅く処理されるように書かれたコードは遅く処理されるので各言語で早く処理されるように記述してください』ということ。 (当然ですね (-_-;))

コンピューティングリソースの不足

メモリ設定
• 設定値としてはメモリとなっているが実際はコンピューティングリソース全体の設定
• メモリサイズと比例してCPU能力も割り当てられる
• メモリ設定はパフォーマンス設定と同義
• コストを気にしがちだが、メモリを増やすことで処理時間がガクンと減り、結果的にコストはそれほど変わらずとも性能があがることもある
少しずつ調整し、変更しても性能が変わらない値が最適値

以下の内容を断言してくれているので、安心してパラメータ設計できます。
- メモリサイズと比例してCPU能力も割り当てられる
- 少しずつ調整し、変更しても性能が変わらない値が最適値

コールドスタート

Lambdaファンクション実行時に起きていること

順番 内容 備考
1 (ENIの作成) VPCからアクセスする場合だけ
10秒~30秒かかる
CloudWatchメトリクスのDurationには含まれない
2 コンテナの作成 CloudWatchメトリクスのDurationには含まれない
3 デプロイパッケージのロード CloudWatchメトリクスのDurationには含まれない
4 デプロイパッケージの展開 CloudWatchメトリクスのDurationには含まれない
5 ランタイム起動・初期化 各ランタイムの初期化処理
グローバルスコープの処理
 - ハンドラー
 - コンストラクタ(java)
タイムアウトがある
CloudWatchメトリクスのDurationには含まれない
6 関数/メソッドの実行 ハンドラーで指定した関数/メソッドの実行
Duration値として計測している値
  • Lambdaは裏側ではコンテナが使用されている。
  • CloudWatchメトリクスのDurationには含まれない=支払い対象にならない
種類 特徴
コールドスタート 上記、①~⑥をすべて実行すること
ウォームスタート 上記、①~⑤を再利用することで省略して効率化

※ ①~⑤は基本的に毎回同じ内容が実行される。

コールドスタートが起こる条件

簡単に言うと、利用可能なコンテナがない場合に発生
• そもそも1つもコンテナがない状態
• 利用可能な数以上に同時に処理すべきリクエストが来た
• コード、設定を変更した
 • コード、設定を変更するとそれまでのコンテナは利用できない

安定的にリクエストが来ているならば、コールドスタートはほとんど発生しない

コールドスタートを速くする

コンピューティングリソースを増やす
• コンピューティングリソースの割当を増やすことで初期化処理自体も速くなる
  ランタイムを変える
• 例えばAWS Lambdaに限らず、JVMの起動は遅い
• ただし、一度温まるとコンパイル言語のほうが速い傾向

  • Javaコンパイル言語)はコールドスタートでは遅いがウォームスタートでは速い。

パッケージサイズを小さくする
• サイズが大きくなるとコールドスタート時のコードのロードおよびZipの展開に時間がかかる
• 不要なコードは減らす
• 依存関係を減らす
 • 不要なモジュールは含めない
 • 特にJavaは肥大しがち
JavaだとProGuardなどのコード最適化ツールを使って減らすという手もある
 • 他の言語でも同様のものはある  

VPCは必要でない限り使用しない
• 使うのはVPC内のリソースにどうしてもアクセスする必要があるときだけ
VPCアクセスを有効にしているとコールドスタート時に10秒から30秒程度余計に必要になる
 

同期実行が必要な箇所やコールドスタートを許容できない箇所ではなるだけ使わない
VPC内のリソースとの通信が必要なのであれば非同期にする
RDBMSのデータ同期が必要なのであればDynamoDB StreamsとAWSLambdaを使って非同期に
 

Javaの場合は以下も検討
POJOではなくバイトストリームを使う
• 内部で利用するJSONリアライゼーションライブラリは多少時間がかかるので、バイトストリームにしてより軽量なJSONライブラリを使ったり最適化することも可能
https://github.com/FasterXML/jackson-jr
http://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-typestream.html
• 匿名クラスをリプレースするようなJava8の機能を利用しない
(lambda、メソッド参照、コンストラクタ参照など)
  初期化処理をハンドラの外に書くとコールドスタートが遅くなるので遅延ロードを行う

import boto3
client = None
def my_handler(event, context):
  global client
  if not client:
    client = boto3.client("s3")
  # process

アーキテクチャの問題

同期でInvokeすると同時実行数の制限に引っかかってつまりがち
• 非同期呼び出しの場合、許可された同時実行数内で順次処理をし、バーストも許容されている
• 同期呼び出しの場合、許可された同時実行数を超えた時点でエラーが返されてしまう
• 非同期の場合はリトライされる
  できるだけ非同期でInvokeするのがスケーラビリティの観点ではオススメ
• その処理、本当にレスポンス必要ですか?
• 特にAmazon API Gatewayとの組み合わせの場合、PUT系の処理をAWSLambdaで直接処理するのではなく、サービスプロキシとして構成してAmazon SQS、Amazon Kinesisに流すなどする

Think Parallel
AWS Lambdaの最大限活かすにはいかに並列処理を行うか

1つあたりのイベントを小さくして同時に並列で動かせるようなアーキテクチャにする
• 1回のInvokeでループさせるのではなく、ループ回数分Lambdaファンクションを非同期Invokeする
• 長時間実行のLambdaファンクションが減るので、同時実行数の制限にも引っかかりにくくなる

同時実行数

  • DynamoDB、kinesisの場合はシャードで計算する。

Limit Increaseについて

標準では1000、実績がない状態でいきなり数千とか数万を申請しても通らない
• 実際にThrottleされているかどうかの確認を
• Throttleされているかなどはメトリクスで確認可能
• サービスローンチなどの場合は、余裕をもって担当セールス、SAにご相談を

Limit Increaseしても性能上のボトルネックが解消しないこともある
• ストリーム系の場合、シャード数を増やしたりバッチサイズを調整したりしないと変わらない
• そもそもファンクションの実行に時間がかかっている場合、レイテンシは改善しない

アンチパターン

AWS LambdaでRDBMS使いがち問題

AWS Lambda + RDBMSアンチパターンな理由
• コネクション数の問題
AWS Lambdaはステートレスなプラットフォームであるため、コネクションプールの実装は難しい
AWS Lambdaがスケールする、つまりファンクションのコンテナが大量に生成された場合に、各コンテナからDBへコネクションが張られることになり、耐えられないケースがある
VPCコールドスタートの問題
VPCのコールドスタートが発生する場合、通常のコールドスタートに比べて10秒程度の時間を必要とする

ベストプラクティス
Amazon DynamoDBを使う
• 何らかの理由でRDBMSとの連携が必要な場合はDynamoDB StreamsとAWS Lambdaを利用して非同期にする

IP固定したがり問題

Amazon API GatewayAWS Lambdaから別システムや外部APIにアクセスする際のソースIPアドレスを固定したい署名や証明書などで担保すべき
IPアドレスを固定するということはスケーラビリティを捨てることにもつながる
AWS LambdaではVPCを利用してNATインスタンスを使うという方法もなくはないが…
VPCのコールドスタート問題
• 自前のNATインスタンスの場合、その可用性、信頼性、スケーラビリティを考慮する必要がある

サーバレスに夢見がち問題

サーバレスであれば全く運用が必要ない、インフラ費用が10分の1になる
• サーバの管理は不要だが運用は必要
• コスト効率が高いため、サーバを並べて同様のことを実装するよりは安くなる可能性が高いが、リクエスト数が多い場合などはそれなりの費用になる
• インフラ費用だけでなく、トータルコストで考える必要がある
• 複雑なことをやろうとすると、設計・開発コストがあがる可能性も大きい
シンプルに使うべきものはシンプルに使いましょう

監視しなくていいと思ってる問題

Serverless != Monitorless
処理の異常を検知して対応するのはユーザの仕事
• 適切にログ出力を行い、適切にモニタする
ベストプラクティス
• CloudWatchのメトリクスを利用(Errors, Throttles)
• CloudWatchのカスタムメトリクス
• CloudWatch Logsへのログ出力とアラーム設定

その他

通常の他のサービスと同様に障害発生を前提として実装をする
• リトライ
• Dead Letter Queueの活用(非同期の場合)
冪等性はお客様のコードで確保する必要がある
AWS Lambdaで保証しているのは最低1回実行することであり1回しか実行しないことではない
• 同一イベントで同一Lambdaファンクションが2回起動されることがまれに発生する
Amazon DynamoDBを利用するなどして冪等性を担保する実装を行うこと

  • 最低1回実行されることは保証されている。
  • 1回しか実行されないことは保証されていない

参考文献

全部教えます!サーバレスアプリのアンチパターンとチューニング

AWS S3について調べてみた

f:id:overworker:20210304234231p:plain:h200f:id:overworker:20210314003943p:plain:h200

参考資料

全般

保存データの制限

  • 格納可能なデータの総量とオブジェクトの数には制限はない
  • 個別の Amazon S3 オブジェクトのサイズは、最低 0 バイトから最大5テラバイトまで
  • 1 つの PUT にアップロード可能なオブジェクトの最大サイズは 5ギガバイト

ストレージクラスの種類

  • S3 標準
    :高頻度アクセスの汎用ストレージ用
  • S3 Intelligent-Tiering
    :未知のアクセスパターンまたはアクセスパターンが変化するデータ用
  • S3 標準 – 低頻度アクセス
    :S3 標準 – IA
  • S3 1 ゾーン – 低頻度アクセス
    :S3 1 ゾーン – IA、長期間使用するが低頻度アクセスのデータ用:
  • Amazon S3 Glacier
    :S3 Glacier
  • Amazon S3 Glacier Deep Archive
    :S3 Glacier Deep Archive、長期アーカイブおよびデジタル保存用:
  • S3 Outposts
    :データレジデンシーの要件を満たすオンプレミスのオブジェクト保存用)

データ編成

  • キーベースのオブジェクトストア
  • データを格納する場合、後にデータを取得するために使用することのできる独特なオブジェクトキーを割り当てる
  • キーは任意の文字列にすることができる
  • 階層的属性を模して構築することができる
  • S3 オブジェクトタグを用いて、お使いのすべての S3 バケットプレフィックスにわたってデータを編成できる

データのやり取り

信頼性(アベイラビリティー)

トラフィックが急激に増加した場合のパフォーマンス

  • 従量制の料金設定と無制限の容量により、負荷上昇によってコストが変わることはなく、サービスが干渉を受けることもない。
  • Amazon S3 の莫大な規模により、負荷を均等に配分することができる。
  • 個別のアプリケーションが、トラフィックのスパイクによる影響を受けることはない。

トラフィックが急激に増加した場合のパフォーマンス

  • 従量制の料金設定と無制限の容量により、負荷上昇によってコストが変わることはなく、サービスが干渉を受けることもない。
  • Amazon S3 の莫大な規模により、負荷を均等に配分することができます。これによって個別のアプリケーションが、トラフィックのスパイクによる影響を受けることはありません。

データのライフサイクル

  • ライフサイクル全体でデータを管理する機能が搭載されている
  • S3 ライフサイクルポリシーを設定すると、データは別のストレージクラスに自動的に移行されます
    • アプリケーションに変更を加える必要はない

1つのバケットに異なるストレージクラスのオブジェクト

  • 1 つのバケットに S3 標準、S3 Intelligent-Tiering、S3 標準 – IA、S3 1 ゾーン – IA で保存された各オブジェクトを混在させることができる

データを格納する AWS リージョンの決定について

  • 特定のアプリケーションに合わせて考慮すべきいくつかの要素があります。以下の条件を満たすリージョンにデータを格納することもできます。
    • データアクセス遅延を減らすため、お客様のカスタマー、データセンター、または他の AWS リソースに近い。
    • 地理的冗長性および災害対策の目的のため、他の運用リージョンから離れている。
    • 特定の法的および規制要件を満たすことができる。
    • ストレージコストを削減できる。より低額なリージョンを選択してコストを抑えることができます。

Amazon S3 のイベント通知

  • Amazon S3 のイベント通知は、PUT、POST、COPY、DELETE といった Amazon S3 のアクションに対する応答として送信できる。
  • 通知メッセージは、Amazon SNSAmazon SQS を使用して送信したり、または AWS Lambda に直接送信したりできる。

Amazon S3 イベント通知を使用するコスト

  • Amazon S3 を用いてイベント通知を行うための追加料金はない
  • イベント通知を配信するための Amazon SNS または Amazon SQS の使用料金、または AWS Lambda 機能を実行するためのコストのみ必要

セキュリティ

データのセキュリティ

  • 作成時は、リソースの所有者のみがその作成した Amazon S3 リソースにアクセスできる。
  • Amazon S3 はユーザー認証をサポートし、データへのアクセスをコントロールしている。
  • バケットポリシーやアクセスコントロールリスト (ACL) などのアクセスコントロールカニズムを使用して、選択的にユーザーおよびユーザーのグループに権限を付与することができる。
  • Amazon S3 コンソールでは、パブリックにアクセス可能なバケットがハイライトされ、パブリックにアクセスされたアクセス元が示される。
  • また、バケットポリシーやバケット ACL への変更によりバケットがパブリックにアクセス可能になった場合、警告が出される。
  • パブリックにアクセスしたくないすべてのアカウントとバケットに対して、ブロックパブリックアクセスを有効にする必要がある。

  • HTTPS プロトコルを使用して、SSL エンドポイント経由で Amazon S3 にデータを安全にアップロードまたはダウンロードできる。

  • セキュリティの強化が必要な場合には、サーバー側の暗号化 (SSE) オプションを使用して、保存されているデータを暗号化できる。
  • 受信ストレージ要求に暗号化情報が含まれない場合、保存する前にオブジェクトを自動的に暗号化するよう Amazon S3 バケットを設定できる。
  • 固有の暗号化ライブラリを使用して、Amazon S3 に保存する前にデータを暗号化することもできる。

データへのアクセスのコントロール

  • Amazon S3 のリソースに対して、4 つのアクセスコントロールカニズムを使用することができる。

  • IAM により、複数の従業員がいる組織は、単一の AWS アカウントのもとに複数のユーザーを作成し、管理することができる。

  • IAM ポリシーにより、ユーザーが行うすべてを完全にコントロールしながら、お客様は Amazon S3 バケットやオブジェクトに対して細かく分けられたコントロールを IAM ユーザーに付与することができる。
  • バケットポリシーを使用すれば、書き込み特権を Amazon S3 リソースのサブセットに付与するといったような、Amazon S3 リソースに対する全リクエストに幅広く適用する規則を、お客様が定義できます。HTTP 参照子や - IP アドレスといったリクエストの側面を基にして、お客様がアクセスを制限することもできます。
  • ACL を使用すれば、特定のユーザーに対し、個々のバケットとオブジェクトに対する権限 (たとえば READ、WRITE、FULL_CONTROL) を、お客様が付与できる。
  • クエリ文字列認証を使用すれば、限定された時間にのみ有効な、Amazon S3 オブジェクトへの URL をお客様が作成できる。

Amazon S3 向け Amazon VPC エンドポイントとは何ですか?

  • Amazon S3 向け Amazon VPC エンドポイントは、Amazon グローバルネットワークを介して S3 へ接続できる VPC 内の論理エンティティ。
  • S3 の VPC エンドポイントには、ゲートウェイ VPC エンドポイントとインターフェイス VPC エンドポイントの 2 種類がある。
  • ゲートウェイエンドポイントは、Amazon ネットワークを介して VPC から S3 にアクセスするためにルートテーブルで指定するゲートウェイ
  • インターフェースエンドポイントは、プライベート IP を使用して、VPC 内、オンプレミス、または別の AWS リージョンから S3 にリクエストをルーティングすることにより、ゲートウェイエンドポイントの機能を拡張する。

バケットとアクセスポイントの違いは何ですか?

  • バケットはオブジェクトの論理ストレージコンテナであり、アクセスポイントはバケットとそのコンテンツへのアクセスを提供します。
  • アクセスポイントは、Amazon リソースネーム (ARN)、ホスト名 (https://[access_point_name]-[account ID].s3-accesspoint.[region].amazonaws.com 形式)、アクセスコントロールポリシー、ネットワークオリジンコントロールを持つバケット用に作成された個別の Amazon リソースです。

アクセスポイントを使用する理由

  • S3 Access Points を使用すると、特定のアプリケーション向けに用意されたポリシーを使用して共有データセットへのアクセスを許可するアクセスポイントをアプリケーションに合わせて作成できる。

アクセスポイントの管理

  • アクセスポイントの追加、表示、削除も、S3 コンソールおよび CLI によるアクセスポイントポリシーの編集できる。
  • さらに、CloudFormation テンプレートを使用してアクセスポイントがご利用いただけるようにもなる。
  • AWS CloudTrail ログを使用すると、「アクセスポイントの作成」や「アクセスポイントの削除」のようなアクセスポイントオペレーションのモニタリング、監査が可能。
  • AWS SCP をサポートする AWS Organizations を使用すると、アクセスポイントの使用量を制御できる。

参考資料

aws.amazon.com

Gitのフック(hook)について調べてみた

f:id:overworker:20200817161353p:plain:h150


概要

hookとは

  • 特定のアクションが発生した時にカスタムスクリプトを叩く方法

hookの種類

大きく分けて二つのグループがある

  • クライアントサイド
    • コミットワークフローフック
    • Eメールワークフローフック
    • その他のクライアントフック
  • サーバーサイド

hookの準備(インストール)

  • git initで新しいリポジトリを初期化する時には、Gitに同梱されているスクリプトのサンプルがhooksディレクトリ(一般的なプロジェクトでは、.git/hook)に格納されます。

hookの使い方

Gitに同梱されているスクリプトのサンプルがこのhooksディレクトリに格納されます。サンプルの多くはそのままでも十分有用ですし、また、各スクリプトの入力値に関するドキュメントもついています。サンプルは全てシェルスクリプトで書かれており、その中の一部ではPerlも使われています。ですが、どんなスクリプトでも、実行可能かつ適切に命名されてさえいれば、問題なく動きます。RubyPython などで書くこともできます。これら同梱のフックスクリプトを使用する場合は、ファイル名の末尾が .sample となっていますので適宜リネームしてください。

フックスクリプトを有効にするには、Gitディレクトリの hooks サブディレクトリに、実行可能なファイルを適切な名前(拡張子は使えません)で配置すれば、以降そのファイルが呼び出されます。 ここでは重要なフックファイル名をいくつか取り上げます。

hookの種類(一部紹介)

クライアントサイドフック

コミットやマージといったクライアントでの操作の際に実行されます。

コミットワークフローフック

pre-commit フック

コミットメッセージが入力される前に実行されます。 これは、いまからコミットされるスナップショットを検査したり、何かし忘れた事がないか確認したり、テストが実行できるか確認したり、何かしらコードを検査する目的で使用されます。 このフックがゼロでない値を返すと、コミットが中断されます。また、この検査は git commit --no-verify で飛ばすこともできます。 ここではコーディングスタイルの検査(lintを実行するなど)や、行末の空白文字の検査(デフォルトのフックがまさにそうです)、新しく追加されたメソッドのドキュメントが正しいかどうかの検査といったことが可能です。

prepare-commit-msg フック

コミットメッセージエディターが起動する直前、デフォルトメッセージが生成された直後に実行されます。 このフックでは、デフォルトメッセージを、コミットの作者の目に触れる前に編集できます。 このフックにはパラメータがあり、その時点でのコミットメッセージを保存したファイルへのパス、コミットのタイプ、さらにamendされたコミットの場合はコミットの SHA-1 をパラメータとして取ります。 このフックは普段のコミットにおいてはあまり有用ではありませんが、テンプレートが用意されているコミットメッセージ・mergeコミット・squashコミット・amendコミットのような、デフォルトメッセージが自動生成されるコミットにおいて効果を発揮します。 コミットメッセージのテンプレートと組み合わせれば、プログラムで情報を動的に挿入できます。

commit-msg フック

開発者の書いたコミットメッセージを保存した一時ファイルへのパスをパラメータに取ります。 このスクリプトがゼロ以外の値を返した場合、Git はコミットプロセスを中断します。これを使えば、コミットを許可して処理を進める前に、プロジェクトの状態やコミットメッセージを検査できます。 この章の最後のセクションでは、このフックを使用してコミットメッセージが要求された様式に沿っているか検査するデモンストレーションを行います。

post-commit フック

コミットプロセスが全て完了した後には、post-commitフックが実行されます。 このフックはパラメータを取りませんが、git log -1 HEAD を実行することで直前のコミットを簡単に取り出すことができます。 一般的にこのスクリプトは何かしらの通知といった目的に使用されます。

Eメールワークフローフック

Eメールを使ったワークフロー用として、三種類のクライアントサイドフックを設定できます。 これらはすべて git am コマンドに対して起動されるものなので、ふだんのワークフローでこのコマンドを使っていない場合は次のセクションまで読み飛ばしてもかまいません。 git format-patch で作ったパッチを受け取ることがあるなら、ここで説明する内容の中に有用なものがあるかもしれません。

applypatch-msg フック

これは引数をひとつ(コミットメッセージを含む一時ファイル名)だけ受け取ります。 このスクリプトがゼロ以外の戻り値で終了した場合、Git はパッチの処理を強制終了させます。 このフックを使うと、コミットメッセージの書式が正しいかどうかを確認したり、スクリプトで正しい書式に手直ししたりできます。

pre-applypatch フック

少々ややこしいのですが、このフックはパッチが 適用された後 、コミットが作成される前に実行されます。そのため、このフックでは、スナップショットの内容を、コミットする前に調べることができます。 このスクリプトを使えば、テストを実行したり、ワーキングツリーの調査をしたりといったことが行えます。 なにか抜けがあったりテストが失敗したりした場合はスクリプトをゼロ以外の戻り値で終了させます。そうすれば、git am はパッチをコミットせずに強制終了します。

post-applypatch フック

このフックは、コミットが作成された後に実行されます。 これを使うと、特定のグループのメンバーや、プルしたパッチの作者に対して、処理の完了を伝えることができます。 このスクリプトでは、パッチの適用を中断させることはできません。

その他のクライアントフック

pre-rebase フック

何かをリベースする前に実行され、ゼロ以外を返せばその処理を中断できます。 このフックを使うと、既にプッシュ済みのコミットのリベースを却下できます。 Git に同梱されているサンプルの pre-rebase フックがこの処理を行いますが、このフックの前提となっている条件のなかには読者のワークフローに合わないものもあるでしょう。

post-rewrite フック

既存のコミットを書き換えるコマンド、例えば git commit --amend や git rebase を実行した際に実行されます(ただし git filter-branch では実行されません)。 引数はひとつで、コミットの書き換えを行ったコマンドを引数に取ります。また、書き換えを行ったファイルのリストを stdin から受け取ります。 このフックは post-checkout や post-merge といったフックと同じ用途に使えます。

post-checkout フック

git checkout が正常に終了すると、post-checkout フックが実行されます。これを使うと、作業ディレクトリを自分のプロジェクトの環境にあわせて設定できます。 たとえば、バージョン管理対象外の巨大なバイナリファイルを作業ディレクトリに取り込んだり、ドキュメントを自動生成したりといった処理が行えます。

post-merge フック

merge コマンドが正常に終了したときに実行されます。 これを使うと、Git では追跡できないパーミッション情報などを作業ツリーに復元できます。 作業ツリーに変更が加わったときに取り込みたい Git の管理対象外のファイルの存在確認などにも使えます。

pre-push フック

git push を実行した際、リモート参照が更新された後、オブジェクトの転送が始まる前に実行されます。 このフックはリモートの名前と場所を引数に取ります。また、これから更新する参照のリストを stdin から受け取ります。 このフックは、プッシュを行う前に、更新される参照を検査するのに使用できます(ゼロ以外の値を返すとプッシュが中断されます)。

pre-auto-gc フック

Git は通常の操作の一環として、時折 git gc --auto を実行してガベージコレクションを行います。 pre-auto-gc フックは、ガベージコレクションが実行される直前に呼び出されます。このフックは、ガベージコレクションが実行されることを通知したり、タイミングが悪い場合にガベージコレクションを中断したりするのに使用できます。

サーバーサイドフック

プッシュされたコミットの受け取りといったネットワーク操作の際に実行される

システム管理者としてプロジェクトのポリシーを強制させる際には、クライアントサイドフックに加え、いくつかのサーバーサイドフックを使うこともできます。 これらのスクリプトは、サーバへのプッシュの前後に実行されます。 pre フックをゼロ以外の値で終了させると、プッシュを却下してエラーメッセージをクライアントに返すことができます。つまり、プッシュに関して、好きなだけ複雑なポリシーを設定できるということです。

pre-receive フック

クライアントからのプッシュを処理するときに最初に実行されるスクリプトが pre-receive です。 このスクリプトは、プッシュされた参照のリストを標準入力から受け取ります。ゼロ以外の値で終了させると、これらはすべて却下されます。 このフックを使うと、更新内容がすべてfast-forwardであることをチェックしたり、プッシュによって変更されるファイルや参照に対するアクセス制御を行ったりできます。

update フック

update スクリプトは pre-receive スクリプトと似ていますが、プッシュしてきた人が更新しようとしているブランチごとに実行されるという点が異なります。 複数のブランチへのプッシュがあったときに pre-receive が実行されるのは一度だけですが、update はブランチ単位でそれぞれ一度ずつ実行されます。 このスクリプトは、標準入力を読み込むのではなく三つの引数を受け取ります。参照 (ブランチ) の名前、プッシュ前を指す参照の SHA-1、そしてプッシュしようとしている参照の SHA-1 です。 update スクリプトをゼロ以外で終了させると、その参照のみが却下されます。それ以外の参照はそのまま更新を続行します。

post-receive フック

post-receive フックは処理が終了した後で実行されるもので、他のサービスの更新やユーザーへの通知などに使えます。 このフックは、 pre-receive フックと同じデータを標準入力から受け取ります。 サンプルのスクリプトには、リストをメールしたり、継続的インテグレーションサーバーへ通知したり、チケット追跡システムを更新したりといった処理が含まれています。コミットメッセージを解析して、チケットのオープン・修正・クローズなどの必要性を調べることもできます。 このスクリプトではプッシュの処理を中断させることはできませんが、クライアント側ではこのスクリプトが終了するまで接続を切断できません。このスクリプトで時間のかかる処理をさせるときには十分注意しましょう。

参考文献

Git - Git フック