AWS CloudFormation の組込み関数 Ref と Sub について
仕事柄、様々な AWS CloudFormation テンプレートを参照することがありますが、あるテンプレートを見ていた時、ふと、「あれ?ここで使っているは 組込み関数は Subでなくて Refでもいいんじゃない?」と気づくことがありました。
その時の経験から、組込み関数 Ref と Sub についてまとめてみたいと思います。
AWS CloudFormation の組込み関数については、次のドキュメントもあるので、あわせてご参照ください。
組み込み関数リファレンス | AWS CloudFormation ユーザーガイド
まず、次のCloudFormation テンプレートのサンプルをみてみましょう。 これは、Amazon S3 バケットをパラメータで指定した名前で 作成するテンプレートです。
Parameters: BucketName1: Description: 'Bucket Name #1' Type: String Default: 'tnobe-sample1-bucket-1' BucketName2: Description: 'Bucket Name #2' Type: String Default: 'tnobe-sample1-bucket-2' Resources: MyBucket1: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName1 # Ref関数で参照 MyBucket2: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${BucketName2} # Sub関数で参照
このテンプレートでは、Parameters セクションのパラメータ名を Ref 関数と Sub 関数で参照して、S3のバケット名に指定しています。 Ref 関数では、そのままパラメータ名 (BucketName1) を指定していますが、Sub 関数では、${BucketName2}と、$ { }で囲んでいます。
記述方法は異なりますが、どちらもパラメータの値を参照することができます。
次に、2つ目のサンプルをみてみましょう。
Parameters: BucketName1: Description: 'Bucket Name #1' Type: String Default: 'tnobe-sample2-bucket-1' BucketName2: Description: 'Bucket Name #2' Type: String Default: 'tnobe-sample2-bucket-2' Resources: MyBucket1: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName1 Tags: - Key: Region Value: !Ref 'AWS::Region' # 疑似パラメータをRef関数で参照 MyBucket2: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${BucketName2} Tags: - Key: Region Value: !Sub ${AWS::Region} # 疑似パラメータをSub関数で参照
2つ目のテンプレートでは、AWS::Region という疑似パラメータを Ref 関数と Sub 関数で参照して、S3バケットのタグの値を設定しています。
疑似パラメータとは、事前に定義されているパラメータで、例えば AWS::Region であれば、そのテンプレートでCloudFormationスタックを作成するAWSのリージョンのIDが自動的に設定されます。
次のドキュメントに他の疑似パラメータの記載もあるので、参考にしてください。
擬似パラメータ参照 | AWS CloudFormation ユーザーガイド
この2つ目のサンプルでも、Ref 関数では、そのまま疑似パラメータ (AWS::Region) をそのまま指定していますが、Sub 関数では、${AWS::Region}と、$ { }で囲んでいます。
記述方法は異なりますが、疑似パラメータであっても、Ref 関数でも Sub 関数でも値を参照することができます。
では、3つ目のサンプルをみてみましょう。
Parameters: BucketId1: Description: 'Bucket Id #1' Type: String Default: '1' BucketId2: Description: 'Bucket Id #2' Type: String Default: '2' Resources: MyBucket1: Type: AWS::S3::Bucket Properties: # Ref関数で参照した値を他の文字列と連結したい場合 BucketName: !Join - '' - - 'tnobe-sample3-bucket-' - !Ref BucketId1 MyBucket2: Type: AWS::S3::Bucket Properties: # Sub関数で参照した値を他の文字列と連結したい場合 BucketName: !Sub 'tnobe-sample3-bucket-${BucketId2}'
3つ目のサンプルでは、文字列 tnobe-sample3-bucket- と、パラメータの値を連結して、バケット名に設定したいという意図があります。
この場合、Ref 関数を使う方法と Sub 関数を使う方法では、記述方法が異なることがわかります。
Ref 関数の場合は、他の文字列と連携つするために、 Join という関数を使っています。
一方、Sub 関数の場合は、文字列の中に、${BucketId2} が埋め込ている形で記述します。
この場合だと、Ref関数 + Join 関数の記述より、Sub 関数の方がシンプルに記述できますね。
まとめ
Amazon Linux 2 に microk8s をインストールする方法
先日、Amazon Linux 2 に minikube をインストールする方法という記事を書きましたが、今回は microk8s をインストールする方法をまとめていきます。
インストール手順は、 Canonical 社の microk8s の Getting Start のページに記載されていますが、まず推奨される環境を用意します。
Getting Startのページでは次のような環境が推奨されています。
- 最低 20G のディスク空き容量
- 最低 4G のメモリ
そのため、EC2 インスタンスのインスタンスタイプは t3.medium を選択して、EBS のストレージ容量も 余裕をもって 30GB に設定することにしました。 t3.medium は、AWSの無料利用枠ではないためご注意ください。
また、EC2インスタンスに接続した後のシェルを bash にしておきましょう。
そのため、もし Systems Manager の Session Manager で接続した場合は、次の例のコマンドを実行して、シェルをbash
にして、かつホームディレクトリに移動しておくとよいでしょう。
sudo su - ssm-user
インスタンスに接続したら、さっそく microk8s をインストールしたいところですが、Amazon Linux 2 の場合は、まずは snapd
をインストールする必要があります。
snapdのリポジトリをダウンロードします。
cd /etc/yum.repos.d/
sudo wget https://people.canonical.com/~mvo/snapd/amazon-linux2/snapd-amzn2.repo
次に /etc/yum.conf
を開きます。
sudo vi /etc/yum.conf
そして、一番最後に下記を追記して保存します。
exclude=snapd-*.el7 snap-*.el7
これで、snapd をインストールできるようになります。
cd sudo yum install -y snapd sudo systemctl enable --now snapd.socket
snapd のインストールが完了したら、いよいよ microk8s をインストールします。
sudo snap install microk8s --classic --channel=1.24
注意: 実行後、次のようなエラーが表示された場合は、1,2分待ってから再度実行して下さい。
error: too early for operation, device not yet seeded or device model not acknowledged
インストールが完了すると、次のようなメッセージが表示されます。
microk8s (1.24/stable) v1.24.0 from Canonical installed
次に、OSユーザーを microk8sグループ に追加するなどの処理を行います。
sudo usermod -a -G microk8s $USER sudo chown -f -R $USER ~/.kube
設定を反映させるため、新たにセッションを開始します。
sudo su - $USER
microk8sのステータスを確認しておきましょう。
microk8s status --wait-ready
これで、microk8s を使用する準備が整いました。
ただ、microk8s では、Kubernetes を操作するのに microk8s kubectl
を使うため、次のような alias
を設定しておくことにします。
alias kubectl='microk8s kubectl'
では、シンプルな Deployment を作成して確認みましょう。
kubectl create deployment nginx --image=nginx
kubectl get pods
kubectl get deploy
microk8s を問題なくインストールできていれば、Pod のステータスは Running になっているはずです。
bash
を使う、snapd
のインストールが必要、という点に注意すれば、minikube よりもシンプルに使えそうだというのが個人的な感想です!
モダンなJavaScriptのお勉強:テンプレート文字列編
今回は、テンプレート文字列を試してみます。
ES2015から、テンプレート文字列を使用して、文字列を構成できるようになっています。
例えば文字列を連結する場合、従来は次のような方法で行っていました。
const firstName = "のべ"; const lastName = "てつお"; const address = "京都"; const printFormat="氏名: " + firstName + " " + lastName + "\n" + "住所: " + address; console.log(printFormat);
結果:
氏名: のべ てつお 住所: 京都
テンプレート文字列を使うと、次のように記述できます。
const firstName = "のべ"; const lastName = "てつお"; const address = "京都"; const printFormat= `氏名: ${firstName} ${lastName} \n住所: ${address}`; console.log(printFormat);
結果:
氏名: のべ てつお 住所: 京都
同じ結果にできましたね。
テンプレート文字列では、 `
つまりバッククォートで文字列を囲みますが、その中の ${ }
で囲んだ部分には JavaScript の変数や処理結果を埋め込むことができます。
上の例の ${firstName}
では、firsrName 変数を埋め込んでいるのでその値が出力できます。
たくさんの +
演算子を使って連結するよりもシンプルで、可読性も向上できそうですね。
${ }
で囲んだ部分には JavaScriptの処理も書けるので、試しに次のようなコードを実行してみましたが、期待通り 1100円と出力できました。
function getTaxRate() { return 0.1; } const productPrice = 1000; const priceFormat= `税込み価格 ${productPrice + (productPrice * getTaxRate())} 円`; console.log(priceFormat);
結果:
税込み価格 1100 円
まとめ
- テンプレート文字列を使うことで、
+
演算子を用いた文字列の連結によりもシンプルで読みやすいコードを記述できます。 - テンプレート文字列は、
`
(バッククォート)で囲みます。この中で、${ }
で囲まれた部分には JavaScriptを記述し、変数や動的な値を出力できます。
Amazon Linux 2 に minikube をインストールする方法
この記事に記載されている方法は、minikube 1.26 以降のバージョンでは適用できませんのでご注意ください。 詳細は、下記の v1.26.0 のリリース情報をご参照ください。
Releases · kubernetes/minikube · GitHub
こちら minikube start の内容を参考に実施しました。 minikube start の記載だけでは不十分な箇所があったので、迷わずインストールできるよう手順をこの記事に書いていきます。
この時、minikube start に記載されている次の要件を満たすため、インスタンスタイプは t3.small で EBSボリュームの容量も 20 GB 以上にしておきます。(このスペックは AWS の 無料枠 ではありませんのでご注意ください。)
- 2 CPUs or more
- 2GB of free memory
- 20GB of free disk space
インスタンスが作成されたら、接続します。 私は Session Manager で接続しましたが、ssh を使って ec2-user で接続してもかまいません。
接続後、次の手順を実施していきます。
Docker をインストールする
sudo yum update -y sudo amazon-linux-extras install -y docker sudo systemctl enable docker sudo systemctl start docker
OSユーザーをdockerグループに追加
次の例では OSユーザーを ssm-user にしています。
sudo gpasswd -a ssm-user docker
この後、いったんログアウトして、もう一度ログインします。
minikube のインストール
いよいよ minikube をインストールします。
conntrack
のインストールも必要です。
curl -LO https://github.com/kubernetes/minikube/releases/download/v1.25.2/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube sudo yum install -y conntrack
minikubeの起動
インストールが終了したら、起動します。
次の例では --vm-driver=none
で起動しています。
minikube start --vm-driver=none
kubectl の設定
次の例では、minikube の handbook の kubectl の内容を参考に、シンボリックリンクを使って kubectl を使うようにしています。
sudo ln -s $(which minikube) /usr/local/bin/kubectl
kubectl を試してみます。
kubectl get all
結果の例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2m
これで、完了です。 一度手順が確立できれば、簡単に、いつでもすぐに再構築できますね。
モダンなJavaScriptのお勉強:分割代入編
今回は、分割代入 についてまとめます。
代入とは、変数への値を設定することです。 例えば、JavaScript で次のようなオブジェクトがあるとします。
const customer = { id: 1, name: "のべ", email: "xxx@nobelabo.net" };
この customer オブジェクトから name と email プロパティを取り出して変数に格納したいとします。 分割代入を使わない場合は、次のようになります。
let name = customer.name; let email = customer.email; console.log(name); console.log(email);
結果:
のべ xxx@nobelabo.net
2つの変数を別々に用意して、それぞれ、オブジェクト名.プロパティ名 を指定して代入していますが 分割代入を使うと、もっとシンプルに変数に値を代入できます。 では、分割代入を使って同じことをやってみましょう。
let { name, email } = customer; console.log(name); console.log(email);
結果:
のべ xxx@nobelabo.net
いかがでしょう?
変数宣言で、{ }
で囲って複数の変数を指定しています。
これらの変数に、customer のプロパティ名と一致している値が代入されています。
この例では { name, email }
という順で指定していますが、{ email, name }
のように順番が変わっても大丈夫です。
少しシンプルにできましたね。
次に、変数名を代入元のオブジェクトのプロパティ名と違うものにする方法をみてみましょう。
let { name: customerName, email: customerEmail } = customer; console.log(customerName); console.log(customerEmail);
結果:
のべ xxx@nobelabo.net
変数宣言時に、{プロパティ名: 任意の変数名 }
とすることで実現できますね!
この分割代入ですが、オブジェクトだけでなく配列でも使用できます。
配列の場合は、変数を [ ]
で囲みます。
const colors = ["Red", "Blue", "Yello"]; let [ red, blue ] = colors; console.log(red); console.log(blue);
結果:
Red Blue
ただし配列の分割代入の場合、配列の要素順にしか値を代入できません。 例えば、次のようなコードにすると、blue 変数には 文字列 "Red" が、red 変数には 文字列 "Blue" が代入されますのでご注意ください。
const colors = ["Red", "Blue", "Yello"]; let [ blue, red ] = colors; console.log(red); console.log(blue);
結果:
Blue Red
まとめ
- オブジェクトの分割代入では、
{ }
内でオブジェクトのプロパティ名を指定すれば、順序に関わらず代入できることがわかりました。- プロパティ名と同じ変数名にすることも、任意の変数名にすることもできましたね。
- 配列の分割代入では、
{ }
内で任意の変数名を指定して代入できますが、あくまで配列の要素順で代入されることに注意しましょう!
モダンなJavaScriptのお勉強:変数宣言編
これまでは、普通に var を使って変数宣言していましたが、ECMAScript 2015 で追加された let や const を使って、その違いを確認してみます。
var の場合
例えば、次のような宣言をしてみます。
var message = "Hello";
この変数 message は、値の変更がでます。変数だから当然と言えば当然かもですが。
message = "Hi";
console.log(message);
結果
Hi
また、同じ変数名で再度宣言することもできます。
var message = "ハロー"; console.log(message);
結果
ハロー
let の場合
letの場合は、値の変更は可能ですが、同じ変数名での再宣言は不可になります。
まず let で宣言します。
let message = "Hello";
その後、値を変更します。次のコードは正常に実行できます。
message = "Hi";
console.log(message);
結果
Hi
ただし、次のように再宣言するコードはSyntaxErrorになり、実行できません。
let message = "ハロー"; // SyntaxError console.log(message);
const の場合
constは、値の変更も、同じ変数名での再宣言も不可になります。
いわゆる 定数 の扱いですね。
const で宣言してみます。
const message = "Hello"; console.log(message);
その後、値を変更します。次のコードはSyntax Errorにはなりませんが、実行時にエラーになります。
message = "Hi";
console.log(message);
発生したエラーは、TypeError: Assignment to constant variable
でした。
また、let と同じく次のように再宣言するコードはSyntaxErrorになり、実行できません。
const message = "ハロー"; // SyntaxError console.log(message);
const は、値の変更が不可という事がわかりましたが、1つ注意点があります。
値が不可なのは、文字列 ( String ) や 数値 ( Number) や 真偽 ( Boolean) などのプリミティブ型であり、オブジェクトのプロパティや配列の要素は変更できます。
オブジェクトのプロパティの例をみてみましょう。
次のコードは const でオブジェクトを宣言していますが、そのプロパティは変更可能です。
const member1 = { id: 1, name: "Neco", address: "Tokyo" }; member1.address = "Osaka"; console.log(member1);
結果
{ id: 1, name: 'Neco', address: 'Osaka' }
配列の要素の例もみてみましょう。このコードでも const で宣言した配列の要素を変更しています。
const mode = ["PLAY", "STOP"] mode.push("PAUSE"); console.log(mode);
結果
[ 'PLAY', 'STOP', 'PAUSE' ]
まとめ
var と違い、let と const は同じ変数名での再宣言は不可であることがわかりました。
再宣言は、コードが混乱する元になりがちなので、基本的に let か const での変数宣言が良さそうです。
また、let か const の使い分けは、変数として扱うか、定数として扱いかで考えればいいですね。
AWS Certified Database - Specialty (DBS-C01) のお勉強:RDSのまとめ
AWS Certified Database - Specialty (DBS-C01) 試験を受ける予定。勉強したことのまとめを書いていきます。なお、私個人のメモなので、基礎から体系的に整理しているわけではないのは、ご容赦ください!
今回は、RDSについてのメモです。
RDS
AWSのリレーショナル・データベースのマネージドサービス。マネージドサービスなので、下記はAWSの管理となり、ユーザーはデータベースを使用するアプリケーションの最適化に注力できるというメリットがある。
- データベース用のインフラ(サーバーやストレージ)のプロビジョニング
- データベースのインストール
- データベースの冗長化を容易に行える機能の提供
- データベースのスケーラビリティを高める機能の提供
- データベースのバックアップ、リストアを容易に行える機能の提供
- データベースのメンテナンスを容易に行える機能の提供
RDSで利用できるデータベースのエンジン
- Aurora
- MySQL
- PostgreSQL
- MariaDB
- Oracle
- SQL Server
RDSの可用性
- マルチAZ構成
- プライマリで使用するデータベースと、プライマリで障害発生時に切り替えるスタンバイのデータベースを異なるAZに作成し、プライマリからスタンバイへデータを同期的にレプリケーションする構成。
- リードレプリカ
- リードレプリカ(読み込み専用データベース)を作成し、通常時は読み込みで使用するが、障害発生時にプライマリに昇格させる
RDSのスケーラビリティ
- インスタンスクラス(EC2でいうインスタンスタイプ)を変更してスケールアップ
- ストレージ容量の拡張
- 手動または自動で拡張可能。
- ただし、ストレージ容量の縮小は不可
- リードレプリカ(読み込み専用データベース)
- 0~5個作成可能
- 他のリージョンでも作成可能
- ただしSQL Serverは不可
- リードレプリカは自動バックアップが有効でないと作成できない。
- プライマリのデータベース停止時は、リードレプリカを削除する必要あり。
RDSのバックアップ/リストア
- 自動バックアップ
- バックアップウィンドウでスケジューリングして日次でスナップショットを取得
- トランザクション・ログは5分毎に取得
- 保持日数 0~35まで指定可能。デフォルト7
- AWS内部管理のS3に格納される
- バックアップウィンドウで指定した期間で実施
- マルチAZ構成の場合、スタンバイ側に対して実施される
- 手動でスナップショット取得
- 保持日数 指定ないので、自動では削除されない
- 取得したスナップショットのコピーや共有
- 他のリージョンへコピー可能
- ただし、パラメータグループやセキュリティグループはコピーされない
- 他のアカウントと共有可能
- 任意のS3バケットへのエクスポートが可能
RDSのメンテナンス
- パッチ適用やデータベースのバージョン更新
- メンテナンスウィンドウでスケジューリング(週次、30分の枠)
- マネジメントコンソールから[今すぐ適用]または[次のメンテナンスウィンドウで適用]を選択できる。
- 重要でないメンテナンスは、放置することで無期延期扱いできる
- 重要なメンテナンスは、無期延期できない
- マルチAZ構成の場合、まずスタンバイ側で適用、スタンバイ側をプライマリに昇格させた後に、元プライマリ側に適用する
- データベースの静的パラメータ変更は、「メンテナンス」ではないので、メンテナンス・ウィンドウで自動適用できない。手動での再起動が必要になるケースもある。
RDSのセキュリティ
- VPCのセキュリティグループでネットワークアクセスの制御
- データ保管時の暗号化
- データベース作成時の設定可能
- 既存データベースを暗号化する場合は、スナップショットを取得、そのスナップショットを暗号化を指定してコピー、そのスナップショットからリストアする
- データ転送時の暗号化
- AWSより証明書取得
- データベース認証・認可
- データベース側の機能で設定
- AuroraとMySQLとPostgreSQLはIAM認証を設定可能
- 監査ログ
- 各データベースの機能で取得し、CloudWatch Logsへ転送可能