全力で怠けたい

怠けるために全力を尽くしたいブログ。

API Gateway のリージョン別カスタムドメイン名を設定するときにやったことのメモ。

API Gateway のリージョン別カスタムドメイン名を設定するときにやったことのメモ。

API Gateway のリージョン別カスタムドメイン名の設定

カスタムドメイン名の証明書の用意

API Gateway のエンドポイントタイプがリージョン別 API エンドポイントのカスタムドメイン名を作成するにはリージョン固有の ACM 証明書を指定する必要があるので パブリック証明書のリクエスト を参考にしてカスタムドメイン名の ACM 証明書を作成していく。

証明書を作成するにはユーザーがリクエストで指定したドメイン名の所有者または管理者であることを確認する必要があり、証明書をリクエストするときに E メールによる検証と DNS による検証のどちらかを選べる。ユーザーが DNS の設定を編集できるときは DNS 検証のほうがいろいろとメリットがあるので DNS を使用したドメインの所有権の検証 を参考にして DNS 検証を選んでいく。DNS 検証は Route 53 で DNS を管理しているときは DNS の設定がボタンを1つ押すだけで完了するので非常に簡単。

リージョンのカスタムドメイン名を設定

API Gateway でのリージョン別カスタムドメイン名の設定 を参考にしてリージョンのカスタムドメイン名の設定と API マッピング名を作成していく。 カスタムドメイン名の設定のなかでトラフィックAPI Gateway にルーティングするとこは ドメイン名を使用してトラフィックを Amazon API Gateway API にルーティングする を参考に。

Redash のログインページにアクセスすると `429 Too Many Requests` になるときにやったことのメモ。

サービスの運営で Redash を使っているんだけど、ブラウザーでログインページにアクセスすると 429 Too Many Requests が表示されるときにやったことのメモ。

ログインページにアクセスすると 429 Too Many Requests

ブラウザーで Redash のログインページにアクセスすると 429 Too Many Requests の表示になるようだった。 50 per 1 hour とも表示しているので API のレートリミットにひっかかってるとかっぽい。

f:id:ebc_2in2crc:20200502020005p:plain:w300

一応 curl でアクセスしてみるけどやっぱり 429 が返ってきているようだった。

$  curl --head http://localhost/login
HTTP/1.1 429 TOO MANY REQUESTS
Server: nginx/1.9.10
Date: Fri, 01 May 2020 17:02:34 GMT
Content-Type: text/html
Content-Length: 141
Connection: keep-alive

やったこと

見てみた

Redash の discuss にずばりな 429 Too Many Requests ってのがあって、そこを見てみると authentication.py がログインページのアクセス制限をしているっぽい。

@routes.route(org_scoped_rule("/login"), methods=["GET", "POST"])
@limiter.limit(settings.THROTTLE_LOGIN_PATTERN)
def login(org_slug=None):

settings.THROTTLE_LOGIN_PATTERNinit.pyREDASH_THROTTLE_LOGIN_PATTERN 環境変数の値を突っ込んでるので REDASH_THROTTLE_LOGIN_PATTERN 環境変数の値をいじればログインページへのアクセス制限を調整できそう。

THROTTLE_LOGIN_PATTERN = os.environ.get("REDASH_THROTTLE_LOGIN_PATTERN", "50/hour")

実際にやったこと

THROTTLE_LOGIN_PATTERN 環境変数の設定

ログインページのアクセス数が制限を超過しているのが原因なのだけど、ログインページのアクセス数を減らすことは難しそうだったので雑に制限を緩めることにした。 redash.env ファイルに REDASH_THROTTLE_LOGIN_PATTERN=1000/hour を追加して Redash を再起動したらログインページにアクセスするとちゃんとログインページが表示して、しつこくリロードしても 429 Too Many Requests は出なくなった。

アクセス情報を保存している Redis のキーを消す

Redash が運用中で再起動ができないとかって状況のときもあると思うけど、そんなときは Redash がアクセス情報を保存している Redis のキーを消しちゃえばログインページにアクセスできるようになる。 急場しのぎにすぎないけど覚えておいて損はなさそう。

$ redis-cli keys *redash.login*
1) "LIMITER/xxx.xxx.xxx.xxx/redash.login/50/1/hour"
$ redis-cli del "LIMITER/xxx.xxx.xxx.xxx/redash.login/50/1/hour"
(integer) 1

参考サイト

rename コマンドでよく使うオプションのメモ。

reaname コマンドでわりとよく使うオプションのメモ。

rename コマンドのバージョン。

$ rename --man
NAME
    rename - renames multiple files

VERSION
    version 1.601
# 省略

普段は Mac で作業することが多いので rename コマンドは brew で入れたやつを使ってる。

$ brew install rename

rename コマンドのオプション

rename コマンドはファイル名を変更するコマンド。

普段は mv コマンドで事足りるんだけど拡張子とかを一括で変更したいときが面倒くさい。 たとえば JPEG ファイルの拡張子が .jpg.jpeg が混在していて .jpeg に揃えたいときに ls *.jpg | sed -e 's/.jpg//' | xargs -n1 -I{} mv {}.jpg {}.jpeg みたいに打つのがすごく面倒くさい。実際のとこはコマンド履歴を呼び出すだけなんだけど、やりたいこととやってることがパッとリンクしないしやっぱり面倒くさい。 Windows なら ren *.jpg *.jpeg で一発なのに。

たしかこんな経緯で便利そうなコマンドを探してて rename コマンドを見つけたんだけど、rename コマンドはかなり便利なのでわりとよく使うオプションをメモしておく。

-h, --help, --man オプション: ヘルプ

-h オプション、--help オプションを指定すると rename コマンドの使い方を表示する……んだけど man rename が使えないときにしか使わない。

--man オプションを指定すると man rename するのと同じマニュアルが表示する……んだけど普通に man rename しちゃうので全然使わない。

基本的な使い方

基本的な使い方は man renameSYNOPSIS のとこに書いてある rename [switches|transforms] [files] のとおり。

[switches|transforms] でオプションと変換ルールを指定して [files] で変換対象のファイルを指定する。

たとえば hoge.txtfuga.txt に変換するときはこんな感じで rename コマンドを実行する。 -s hoge.txt fuga.txt が switches でコマンドの一番後ろの hoge.txt が files を指定している。

$ rename -s hoge.txt fuga.txt hoge.txt

これは以下の mv コマンドと同じ結果になる。

$ mv hoge.txt fuga.txt

rename コマンドは switches の指定が冗長に感じるけど -s hoge.txt fuga.txt という switches は「hoge.txt を fuga.txt にリネームする」という意味なので、今回のように対象のファイル名がはっきり分かっているときは -s hoge fuga と指定しても同じ結果を得ることができる。

$ rename -s hoge.txt fuga.txt hoge.txt
# ↑と↓は同じ結果になる
$ rename -s hoge fuga hoge.txt

実は rename コマンドの switches は Perl のコマンドを書けるのでさきほどの -s hoge fuga はこんな感じに書くこともできる。 いろいろな書き方ができるから Perl のコマンドをガシガシ書いてもいいしやりたいことのオプションを指定するでもいいし、やりたいことと状況に応じて自分の好きな書き方でファイル名を変更できるのが rename コマンドのいいところだと思う。

$ rename 's/hoge/fuga/' hoge.txt

-v, --verbose オプション: 詳細情報を出力する

rename コマンドはファイル名を変更しても何も出力しないけど -v オプションか --verbose オプションを指定するとファイル名を変更したとかの詳細情報を出力する。

自分は実際にどのファイルの名前が変わったのかとか気になるので使うことが結構よく使う。

$ rename -v -s hoge fuga hoge.txt
'hoge.txt' renamed to 'fuga.txt'

-n, --just-print, --dry-run: ドライラン

-n オプションか --just-print オプションか --dry-run オプションを指定するとドライランする。

ファイル名の変更をミスると結構悲惨だと思うので、複雑な swithes を指定したり rename コマンドを本番環境で使うときは必ずドライランして意図するとおりの結果になることを確かめてから実際にファイル名を変更するようにしている。

$ ls hoge.txt
hoge.txt

$ rename -n -s hoge fuga hoge.txt
'hoge.txt' would be renamed to 'fuga.txt'

$ ls hoge.txt
hoge.txt

-s, --subst オプション: 置換

ここまで何も書かずに -s オプションを使ってきたけど -s オプションか --subst オプションを指定すると単純な置換ができる。

rename -s from to files みたいな感じで -s オプションか --subst オプションのすぐあとに置換元の文字列と置換前の文字列を指定する。 たぶん一番よく使うオプションだと思う。

$ rename -v -s hoge fuga hoge.txt
'hoge.txt' renamed to 'fuga.txt'

-S, --subst-all オプション: 全置換

-S オプションか --subst-all オプションは -S from to にみたいに指定すると変換対象のファイル名から見つかったすべての fromto に置換する。

たとえば変換対象のファイル名が hoge-hoge.txt のときに -S hoge fuga みたいな switches を指定するとファイル名のすべての hogefuga に置換するので変換後のファイル名は fuga-fuga.txt になる。

$ rename -v -S hoge fuga hoge-hoge.txt
'hoge-hoge.txt' renamed to 'fuga-fuga.txt'

ちなみに、さっきの -s オプションと --subst-s from to にみたいに指定すると変換対象のファイル名から最初に見つかった fromto に置換する。 つまり変換対象のファイル名が from を複数含むときは最初に見つかった from だけ to に置換して2個め以降の from は置換しない。

たとえば変換対象のファイル名が hoge-hoge.txt のときに -s hoge fuga みたいな switches を指定するとファイル名の最初の hoge だけ fuga に置換して2個めの hoge は置換しないので変換後のファイル名は fuga-hoge.txt になる。

$ rename -v -s hoge fuga hoge-hoge.txt
'hoge-hoge.txt' renamed to 'fuga-hoge.txt'

-x, --remove-extension オプション: 拡張子を取り除く

-x オプションか --remove-extension オプションを指定するとファイル名の末尾の拡張子を取り除く。

$ rename -v -x hoge.txt.bak
'hoge.txt.bak' renamed to 'hoge.txt'

-s オプションとかでも同じことはできるけど、やりたいことが「拡張子を取り除く」だけのときは -x オプションを使うほうが短く書けるし直感的なのでだいたい -x オプションを使ってる。

$ rename -v -s .bak '' *.bak
'hoge.txt.bak' renamed to 'hoge.txt'

$ rename -v 's/.bak\z//' *.bak
'hoge.txt.bak' renamed to 'hoge.txt'

-a, --append オプション: 文字列をファイル名の末尾に追加する

-a オプションか, --append オプションを指定すると文字列をファイル名の末尾に追加する。

$ rename -v -a .old hoge.txt
'hoge.txt' renamed to 'hoge.txt.old'

Perl のコマンドとかでも同じことはできるけど、やりたいことが「文字列を追加する」だけのときは -a オプションを使うほうが短く書けるし直感的なのでだいたい -a オプションを使ってる。

$ rename -v 's/\z/.old/' hoge.txt
'hoge.txt' renamed to 'hoge.txt.old'

c: 文字列をファイル名の先頭に追加する

-A オプションか --prepend オプションを指定すると文字列をファイル名の先頭に追加する。

$ rename -v -A [wip] hoge.txt
'hoge.txt' renamed to '[wip]hoge.txt'

Perl のコマンドとかでも同じことはできるけど、やりたいことが「文字列を追加する」だけのときは -A オプションを使うほうが短く書けるし直感的なのでだいたい -A オプションを使ってる。

$ rename -v 's/\A/[wip]/' hoge.txt
'hoge.txt' renamed to '[wip]hoge.txt'

-p, --mkpath, --make-dirs オプション: ディレクトリがないときに作成する

実は rename コマンドはファイル名を変更するだけでなくてファイルを別のディレクトリに移動することができてすごく便利なんだけど、移動先のディレクトリがないときはエラーになる。

-p オプションか --mkpath オプションか --make-dirs オプションを指定すると移動先のディレクトリがないときは rename コマンドが自動的に作ってくれる。

$ ls
hoge.txt

$ rename -v -p -s hoge hoge-files/hoge hoge.txt
'hoge.txt' renamed to 'hoge-files/hoge.txt'

$ ls hoge-files
hoge.txt

参考ページ

既存の RDS の パラメータグループから CloudFormation テンプレートを簡単に作るやり方のメモ。

AWS コンソールから作成した RDS の DB パラメータグループ (DBParameterGroup) のパラメータから CloudFormation テンプレートを簡単に作るやり方のメモ。

AWS のリソースは Cloudmation で管理したいけど、古から伝わる AWS コンソールをポチポチして作成した既存の RDS のパラメータグループのパラメータを1つ1つ目で見ながらテンプレートに転記していく……のは面倒くさいし時間がかかるしなにより間違いが混入しやすいからやりたくない。

=> AWS CLI で DB パラメータグループのパラメーターを取得しちゃえばいい。

RDS の DB パラメータグループから CloudFormation テンプレートを作る

RDS の DB パラメータグループのパラメータは describe-db-parameters で取得できるので、取得結果をいじって CloudFormation テンプレートにしちゃえばいい。

AWS CLI のバージョン。

$ aws --version
aws-cli/1.16.300 Python/2.7.16 Linux/4.14.171-136.231.amzn2.x86_64 botocore/1.13.36

前準備: DB パラメータグループを作る

やり方の手順の前準備として DB パラメータグループを作っておく。

DB パラメータグループのファミリーは何でもいいけど今回は MySQL 5.7 ファミリーの DB パラメータグループを作っておく。

$ aws rds create-db-parameter-group \
    --db-parameter-group-name my-db-parameter-group \
    --db-parameter-group-family mysql5.7 \
    --description 'My DB Parameter Group'

あとでパラメーターの設定値を出力するためにどれでもいいのでパラメーターの設定値を変えておく。 今回は MySQL 5.7 の DB パラメータグループはデフォルトではスロークエリログを出さない設定なので、スロークエリログを出す設定の slow_query_log=1 にしておく。

$ echo '{
    "Parameters": [
        {
            "ApplyMethod": "immediate",
            "Description": "Enable or disable the slow query log",
            "DataType": "boolean",
            "IsModifiable": true,
            "AllowedValues": "0,1",
            "Source": "user",
            "ParameterValue": "1",
            "ParameterName": "slow_query_log",
            "ApplyType": "dynamic"
        }
    ]
}' > input.json

$ aws rds modify-db-parameter-group \
    --db-parameter-group-name my-db-parameter-group \
    --cli-input-json file://input.json
{
    "DBParameterGroupName": "my-db-parameter-group"
}

DB パラメータグループのパラメータの取得

describe-db-parameters で DB パラメータグループのパラメータを取得できる。

$ aws rds describe-db-parameters --db-parameter-group-name my-db-parameter-group --source user > output.json

describe-db-parameters の出力はこんな感じの JSON になっているので、

$ cat output.json
{
    "Parameters": [
        {
            "ApplyMethod": "immediate",
            "Description": "Enable or disable the slow query log",
            "DataType": "boolean",
            "IsModifiable": true,
            "AllowedValues": "0,1",
            "Source": "user",
            "ParameterValue": "1",
            "ParameterName": "slow_query_log",
            "ApplyType": "dynamic"
        }
    ]
}

jq でいい感じに整形する。

$ cat output.json | jq -r '.Parameters[] | .ParameterName + ": " + .ParameterValue'
slow_query_log: 1

DB パラメータグループのテンプレートを作る

DB パラメータグループのテンプレートを作ってさっき出力したパラメータを Parameters のところにコピペする。

AWSTemplateFormatVersion: "2010-09-09"
Description: DB Parameter Group
Resources:
  DBParameterGroup:
    Type: "AWS::RDS::DBParameterGroup"
    Properties:
      Family: mysql5.7
      Description: My DB Parameter Group
      Parameters:
        # ↓さっき出力したパラメータ
        slow_query_log: 1

以上。

参考ページ

URL から HTML の <a> タグにする url-anchor コマンドを作った。

URL から HTML の <a> タグにする url-anchor コマンドを作った。

url-anchor コマンドって?

url-anchor コマンドは URL を与えると URL とページのタイトルを HTML の <a> タグにする。

デフォルトの動作は与えた URL とページのタイトルを HTML の <a> タグにするけど、オプションを指定すると Markdown のリンクと reStructuredText のリンクにすることもできる。

使い方

URL から HTML の <a> タグにする。

$ url-anchor https://google.com/
<a href="https://google.com/">Google</a>

URL から Markdown のリンクにする。

$ url-anchor -m https://google.com/
[Google](https://google.com/)

URL から reStructuredText のリンクにする。

$ url-anchor -r https://google.com/
`Google <https://google.com/>`_

Docker

普通に docker container run する。 コマンドの実行が終わったらコンテナを削除したいので --rm オプションを付けてる。

$ docker container run --rm ebc2in2crc/url-anchor https://google.com/
<a href="https://google.com/">Google</a>

便利な使い方 (Mac のみ)

クリップボードを使う便利な使い方。

  1. URL をクリップボードにコピーしておく。
  2. 以下のコマンドを実行すると実行結果をクリップボードにコピーしてくれる。
$ url-anchor $(pbpaste) | pbcopy

エイリアスにしておくとかシェル関数にしておくとさらに便利。 自分はこんな感じのエイリアスにしてる。

alias ura='url-anchor    $(pbpaste) | pbcopy && pbpaste'
alias urm='url-anchor -m $(pbpaste) | pbcopy && pbpaste'

インストール方法

Homebrew

$ brew tap ebc-2in2crc/tap
$ brew install url-anchor

Developer

$ go get -u github.com/ebc-2in2crc/url-anchor/...

手動でのインストール

https://github.com/ebc-2in2crc/url-anchor/releases からダウンロードした zip ファイルを展開した中にあるファイルをパスの通ったディレクトリに入れる。

動機

Twitter結城浩さんのツイートを見たのが url-anchor コマンドを作るきっかけ (だと思う。たぶん) ブラウザーでページを見てるときとかはブラウザー拡張機能で同じようなことができるんだけど、結構 CLI で作業してることが多いので同じようなことが CLI でできたら便利だなーと思って作った。

まとめ

バグとかあると思うし「おそいよ!」とか「こーしたら使いやすくなる」とかあったらイシュー作ったり声かけてもらえると嬉しいです!

du コマンドでよく使うオプションのメモ。

du コマンドでわりとよく使うオプションのメモ。

普段は AWS の EC2 インスタンスに入って使うことが多いのでこのエントリーを書くときも EC2 インスタンスに入って du コマンドを実行した結果とかをメモっている。

du コマンドのバージョン。

$ du --version
du (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Torbjörn Granlund, David MacKenzie, Paul Eggert,
and Jim Meyering.

du コマンドのオプション

du コマンドはディスクの使用量を表示するコマンド。

自分はちょいちょい使うわりにはオプションとかよく覚えてなくて使うたびにググったりが多い気がするのでよく使うオプションをメモしておく。

コマンドの動作は以下のディレクトリ構造とそれぞれ 1MiB のサイズの dat ファイルを配置して確認いく。

$ tree
.
├── fuga
│   ├── fuga-1.dat
│   └── fuga-2.dat
├── hoge
│   ├── hoge-1.dat
│   └── hoge-children
│       ├── hoge-children-1.dat
│       ├── hoge-children-2.dat
│       ├── hoge-children-3.dat
│       ├── hoge-children-4.dat
│       └── hoge-children-5.dat
└── piyo
    ├── piyo-1.dat
    ├── piyo-2.dat
    └── piyo-3.dat

--help オプション: ヘルプ

--help オプションを指定すると du コマンドの使い方を表示する……んだけど man du が使えないときにしか使わない。

$ du --help
Usage: du [OPTION]... [FILE]...
  or:  du [OPTION]... --files0-from=F
Summarize disk usage of each FILE, recursively for directories.

Mandatory arguments to long options are mandatory for short options too.
  -0, --null            end each output line with 0 byte rather than newline

# 省略

オプションなし

du コマンドをオプションなしで実行するとカレントディレクトリ配下のサイズを再帰的に集計して表示する。

$ du
5120    ./hoge/hoge-children
6144    ./hoge
2048    ./fuga
3072    ./piyo
11264   .

-d, --max-depth オプション: 集計するディレクトリの階層を指定

-d オプションか --max-depth オプションで集計するディレクトリの階層を指定する。

du --max-depth 1 するとカレントディレクトリとカレントディレクトリ直下のディレクトリそれぞれのサイズをディレクトリごとに集計する。

$ du --max-depth 1
6144    ./hoge
2048    ./fuga
3072    ./piyo
11264   .

du --max-depth 0 を指定するとカレントディレクトリのサイズだけ集計する (= 階層がゼロ)

$ du --max-depth 0
11264   .

FILE: サイズを集計するディレクトリかファイル

オプションじゃないんだけど FILE についても書いておく。

$ du --help
Usage: du [OPTION]... [FILE]...
  or:  du [OPTION]... --files0-from=F

FILE はサイズを集計するディレクトリかファイルを指定する。

たとえば du fuga と指定すると fuga ディレクトリのサイズを集計するし du piyo と指定すると piyo ディレクトリのサイズを集計する。

$ du fuga
2048    fuga/

$ du piyo
3072    piyo

du fuga piyo みたいに FILE を複数指定すると fuga ディレクトリと piyo ディレクトリそれぞれのサイズを集計する。

$ du fuga/ piyo/
2048    fuga/
3072    piyo/

du みたいに FILE を指定しないときは du . みたいにカレントディレクトリを指定するのと同じ。

$ du
5120    ./hoge/hoge-children
6144    ./hoge
2048    ./fuga
3072    ./piyo
11264   .

$ du .
5120    ./hoge/hoge-children
6144    ./hoge
2048    ./fuga
3072    ./piyo
11264   .

-s, --summarize オプション: ディレクトリの合計サイズだけ表示

-s オプションか --summarize オプションを指定すると指定したディレクトリのサイズだけを表示する……と書くとなんのことやらだけど、ようはサブディレクトリごとのサイズは表示しなくなるということ。 => --summarize オプションは --max-depth 0 を指定するのと同じ

たとえば du . みたいに --summarize オプションを指定しないとカレントディレクトリとカレントディレクトリ配下のディレクトリそれぞれのサイズが表示されるけど、

$ du .
5120    ./hoge/hoge-children
6144    ./hoge
2048    ./fuga
3072    ./piyo
11264   .

du --summarize . みたいに --summarize` オプションを指定するとカレントディレクトリのサイズだけ表示する。

$ du --summarize .
11264   .

-B, --block-size オプション: サイズの単位を指定

-B オプションか --block-size オプションでサイズの単位を指定する。 -B オプションか --block-size オプションを指定しないときは K (KiB) を指定するのと同じ。

$ du --summarize .
11264   .

$ du --summarize --block-size K .
11264K  .

$ du --summarize --block-size M .
11M .

-B オプションか --block-size オプションは以下を指定できる。

指定できる値 表示単位
KB キロバイト (KB)
K キビバイト (KiB)
MB ガバイト (MB)
M メビバイト (MiB)
GB ギビバイト (GB)
G ギビバイト (GiB)
TB テビバイト (TB)
T テビバイト (TiB)

実は -B オプションか --block-size オプションは数字なら何でも指定できる。面倒くさいからやらないけど……

$ du --summarize --block-size KB .
11535kB .

$ du --summarize --block-size 1000 .
11535   .

$ du --summarize --block-size K .
11264K  .

$ du --summarize --block-size 1024 .
11264   .

-k, -m オプション: --block-size オプションの短縮形

-k オプションと -m オプションはそれぞれ --block-size K--block-size M を指定するのと同じ。

$ du -k --summarize .
11264   .

$ du -m --summarize .
11  .

-h, --human-readable オプション: 人間が読みやすくするやつ

-h オプションか, --human-readable オプションを指定するとサイズに応じた単位で表示する。

個人的にはディレクトリのサイズでソートしちゃうことが多いのであまり使わないオプション。

$ du --human-readable --summarize .
11M .

CloudFormation の Fn::Cidr 組み込み関数の使い方のメモ。

AWS の CloudFormation の Fn::Cidr 関数 を使うとサブネットとかの CIDR ブロックを動的に指定することができて便利なので使い方をメモ。

Fn::Cidr 関数を使わないとき

Fn::Cidr 関数を使わないときは CIDR ブロックはベタ書きのハードコーディングする感じになる。

たとえば 10.0.0.0/16 の16ネットマスクの CIDR ブロックを VPC に割り当てて、その VPC のサブネットを2つ作ってそれぞれのサブネットは 10.0.x.0/24 の24ネットマスクの CIDR ブロックを割り当てるときはこんなテンプレートを書く感じ。

AWSTemplateFormatVersion: "2010-09-09"
Description: Example of Cidr function
Resources:
  ExampleVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16

  ExampleSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.0.0/24
      VpcId: !Ref ExampleVPC

  ExampleSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.1.0/24
      VpcId: !Ref ExampleVPC

別にこれでもいいんだけど VPC の CIDR ブロックが変わったりすると VPC だけじゃなくてサブネットの CIDR ブロックも変えないといけなくて面倒くさい。

Fn::Cidr 関数を使うとき

Fn::Cidr 関数を使うと CIDR ブロックはベタ書きのハードコーディングしなくていい。

たとえば 10.0.0.0/16 の16ネットマスクの CIDR ブロックを VPC に割り当てて、その VPC のサブネットを2つ作ってそれぞれのサブネットは 10.0.x.0/24 の24ネットマスクの CIDR ブロックを割り当てるときはこんなテンプレートを書く感じ。 サブネットの CIDR ブロックのところがベタ書きじゃなくなっているのが分かると思う。

AWSTemplateFormatVersion: "2010-09-09"
Description: Example of Cidr function
Resources:
  ExampleVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16

  ExampleSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Select [0, !Cidr [!GetAtt ExampleVPC.CidrBlock, 2, 8]]
      VpcId: !Ref ExampleVPC

  ExampleSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Select [1, !Cidr [!GetAtt ExampleVPC.CidrBlock, 2, 8]]
      VpcId: !Ref ExampleVPC

でも、さっきよりはいい感じなんだけど VPC の CIDR ブロックが変わったりすると VPC の CIDR ブロックのところを変えないといけないのが面倒くさい。

なので、実際の開発では VPC の CIDR ブロックは↓みたいにパラメーターにしてテンプレート外部からもらうのがよさそう。

AWSTemplateFormatVersion: "2010-09-09"
Description: Example of Cidr function
Parameters: 
  VPCCidrBlock: 
    Type: String
    Default: 10.0.0.0/16

Resources:
  ExampleVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCidrBlock

  ExampleSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Select [0, !Cidr [!GetAtt ExampleVPC.CidrBlock, 2, 8]]
      VpcId: !Ref ExampleVPC

  ExampleSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Select [1, !Cidr [!GetAtt ExampleVPC.CidrBlock, 2, 8]]
      VpcId: !Ref ExampleVPC

CIDR ブロックはパラメーターにしてテンプレート外部からもらうと Resources セクションのベタ書きの CIDR ブロックが消えてすっきりするしメンテナンスもしやすくなっていい感じ。

参考ページ