- 投稿日:2020-06-23T23:52:53+09:00
AWS CLI で EKS クラスターの IAM OIDC ID プロバイダーを作成
$ CLUSTER_NAME=example-eks-cluster $ ISSUER_URL=$(aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text) $ JWKS_FQDN=$(curl -sS $ISSUER_URL/.well-known/openid-configuration | jq -r '.jwks_uri' | perl -pe 's/^https:\/\/(.+?)\/.+$/${1}/') $ CERTIFICATE_BODY=$(openssl s_client -servername $JWKS_FQDN -showcerts -connect $JWKS_FQDN:443 < /dev/null) $ CERTIFICATE_START=$(echo $CERTIFICATE_BODY | grep -n 'BEGIN CERTIFICATE' | sed -e 's/:.*//g' | tail -n 1) $ CERTIFICATE_END=$(echo $CERTIFICATE_BODY | grep -n 'END CERTIFICATE' | sed -e 's/:.*//g' | tail -n 1) $ echo $CERTIFICATE_BODY | head -$CERTIFICATE_END | tail -$(expr $CERTIFICATE_END - $CERTIFICATE_START + 1) > /tmp/certificate.crt $ ROOT_CA_FINGERPRINT=$(openssl x509 -in /tmp/certificate.crt -fingerprint -noout | perl -pe 's/^SHA1 Fingerprint=(.+)$/${1}/' | perl -pe 's/\://g') $ rm -f /tmp/certificate.crt $ aws iam create-open-id-connect-provider --url $ISSUER_URL --thumbprint-list $ROOT_CA_FINGERPRINT --client-id-list sts.amazonaws.com { "OpenIDConnectProviderArn": "arn:aws:iam::999999999999:oidc-provider/oidc.eks.ap-northeast-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
- 投稿日:2020-06-23T23:34:48+09:00
あらためてEPELリポジトリの使い方をまとめてみた
1. はじめに
RHEL系ディストリビューションにおける、拡張パッケージのリポジトリ「EPEL」を使っている人は多いだろう。筆者もこれまでの記事で何度か紹介してきた。ところがクラウドでは状況が微妙に異なる。そこで使い方をまとめることにした。
1-1. TL;DR
- クラウドでは、デフォルトで有効になっていることや、独自のインストールコマンドが提供されていることがある
- 記事で毎回EPELの使い方を説明するのは無駄
1-2. 前提条件
- RHEL系Linuxディストリビューション。FedoraやCentOS、Amazon Linux、Oracle Linuxなど
2. EPELとは
EPELを使う手順は簡単だ。すぐにインストールしたいときは「3. EPELリポジトリを有効にする」に進んでほしい。ここではEPELの概要や使用するうえでの注意事項を説明する。
2-1. もっとも有名なサードパーティー・リポジトリEPEL
EPEL(Extra Packages for Enterprise Linux)は、Fedoraプロジェクトの有志がビルドした、Red Hat Enterprise Linux (RHEL) 系Linuxディストリビューション向けオプションパッケージ群だ。LinuxのメディアやYumリポジトリに含まれないパッケージ入手先の第1候補になる。
EPELのように、ディストリビューション本家以外が提供するリポジトリを「サードパーティー・リポジトリ」と呼ぶ。EPEL以外にも、以下のリポジトリも有名である。
2-2. なぜサードパーティー・リポジトリが必要か?
理由は簡単で「使いたいアプリケーションが標準のYumリポジトリに含まれていない」もしくは「含まれていてもバージョンが古い」からだ。これはディストリビューションのサポート上の理由だ。
- ディストリビューションベンダーは製品をサポートする責任があるので、標準リポジトリに含めるパッケージを制限している
- 互換性の問題で、同一メジャーバージョン内で新しいバージョンを取り入れられない
これらの問題は、RHEL7までのSoftware Collections(SCL)や、RHEL8のAppStreamで改善するが、すべての問題が解決するわけではない。
2-2-1. ソースからインストールする?
これらの問題が起きたときソースからビルドする人もいるだろう。ソースコードからのインストールは否定しないが、パッケージ管理ステムのメリットが損なわれる。十分な理由のあるときだけに限ったほうがいいだろう。
ソースからビルドしたときのデメリット
- 依存関係を保ったシステム管理が難しくなる
- ソースRPMからビルドしたバイナリRPMはサポート対象外になる
2-2-2. 互換性の話
以下の表は、RHELバージョンごとのkernelとglibcのバージョンをまとめたものだ。同一メジャーバージョン内では、アップデートパッケージを適用してもパッケージのバージョンは変わらない。
ディストリビューション kernel glibc RHEL6 2.6.32 2.12 RHEL7 3.10.0 2.17 RHEL8 4.18.0 2.28 Amazon Linux 2 4.14 2.26 RPMパッケージは以下のように命名される。kernelやglibcなどのコアコンポーネントの場合、
yum update
を実行して変わるのはバージョン以降に付与したリリース番号である。
ここまでしつこく書く理由は、kernelやglibcなどのコアコンポーネントは、アプリケーションの動作保証で極めて重要だからだ。だから出どころの分からない野良リポジトリを使ってはいけないし、RHEL6用のRPMパッケージをRHEL7にインストールするような強引なことはしてはいけない。
余談
筆者が経験したホラーストーリーがある。とある障害の支援でRHEL6の設定を確かめていたときの出来事だ。いくつかの基本コマンドが動かない。おかしいと思い、以下のコマンドでRed Hat以外のパッケージを探すと、たくさん出てきた。VenderがRedHat以外のパッケージを表示するコマンドrpm -qa --qf "%{name} %{vendor}\n" | grep -v "Red Hat"それもglibcなどのコアコンポーネントがFedoraやScientific Linuxになっている。それもリリース番号違いでなくバージョン番号違い。本来インストールできないものを
nodeps
やforce
でインストールしたようだ。そんな強引なことをしたら、正常動作しなくて当然だ。逆に動いていたことが不思議でならない。3. EPELリポジトリを有効にする
EPELを使用するには
epel-release
パッケージをインストールすればよい。ただし使用するクラウドサービスやLinuxディストリビューションによって以下の注意事項がある。EPELのWebサイトも見てほしい。
- RHEL7では
optional
リポジトリやextras
リポジトリを有効にする必要がある- RHEL8では
codeready-builder
リポジトリを有効にする必要がある- AWSのAmazon Linux 2ではEPELを有効にする専用のコマンドがある
- Oracle Cloud InfrastructureのOracle Linux 7では、専用のEPELリポジトリがデフォルトで有効になっている
3-1. EPELを有効にする(基本)
「クラウドでRHELやCentOSを使うとき」や「オンプレミス環境」では
epel-release
をインストールする。これが基本になる。8系Linux OS
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y7系Linux OS
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y6系Linux OS
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm -y3-2. EPELを有効にする(AWS)
Amazon Linux 2ではEPELを有効にする専用のコマンドが用意されている。AWSでもRHELやCentOSでは、前述の方法を利用する。
sudo amazon-linux-extras install epelインストールに成功すると「amzn2extra-epel」と「epel」リポジトリが追加される。
$ yum repolist enabled repo id repo name status amzn2-core/2/x86_64 Amazon Linux 2 core repository 19791 amzn2extra-docker/2/x86_64 Amazon Extras repo for docker 28 amzn2extra-epel/2/x86_64★ Amazon Extras repo for epel 1 epel/x86_64★ Extra Packages for Enterprise Linux 7 - x86 13141+192 repolist: 32961amzn2extra-epelリポジトリのパッケージ数が1なのが気になる。調べてみるとepel-releaseだけが含まれていた。
repoファイルの定義を確認すると、EPELのミラーサイトを参照しており、クラウド内にAWS独自のミラーサイトがあるわけではない。ログを確認するとcloudfrontから取得している。
/etc/yum.repos.d/epel.repo[epel] name=Extra Packages for Enterprise Linux 7 - $basearch #baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch★ミラーサイトを取得 failovermethod=priority3-2. EPELを有効にする(Oracle Cloud Infrastructure)
Oracle Cloud InfrastructureのOracle Linux 7では「ol7_developer_EPEL」という専用のEPELリポジトリが用意してある。そのため追加作業は不要だが、他のOSでは前述の方法を利用する。
EPELリポジトリが有効になっているか、次のコマンドで確認するといいだろう。
$ yum repolist repo id repo name status ol7_UEKR5/x86_64 Latest Unbreakable Enterprise Kernel Rele 217 ol7_addons/x86_64 Oracle Linux 7Server Add ons (x86_64) 433 ol7_developer/x86_64 Oracle Linux 7Server Development Packages 1349 ol7_developer_EPEL/x86_64★これ Oracle Linux 7Server Development Packages 32336 ol7_ksplice Ksplice for Oracle Linux 7Server (x86_64) 7356 ol7_latest/x86_64 Oracle Linux 7Server Latest (x86_64) 18986 ol7_oci_included/x86_64 Oracle Software for OCI users on Oracle L 321 ol7_optional_latest/x86_64 Oracle Linux 7Server Optional Latest (x86 13984 ol7_software_collections/x86_64 Software Collection Library release 3.0 p 14564 repolist: 89546repoファイルの定義を確認すると、リージョンごとに用意したOracle独自のEPELを参照している。
/etc/yum.repos.d/oracle-epel-ol7.repo[ol7_developer_EPEL] name=Oracle Linux $releasever Development Packages ($basearch) baseurl=http://yum$ociregion.oracle.com/repo/OracleLinux/OL7/developer_EPEL/$basearch/ol7_developer_EPELからインストールした
pwgen
パッケージを確認すると、ビルドホスト(Build Host)やベンダ(Vendor)が「fedora」ではない。そのためEPELからソースパッケージを取得して再ビルドしていることが分かる。$ rpm -qi pwgen Name : pwgen Version : 2.08 Release : 1.el7 ★中略 Source RPM : pwgen-2.08-1.el7.src.rpm Build Date : Tue Aug 14 22:24:07 2018 Build Host : x86-ol7-builder-01.us.oracle.com ★ Relocations : (not relocatable) Vendor : Oracle America ★ URL : http://sf.net/projects/pwgen Summary : Automatic password generation ★以下省略重要
「EPELからソースパッケージを取得してビルド」という手順を踏んでいることから、EPELとol7_developer_EPELは厳密には同じバイナリではない。またバージョン等のタイムラグの可能性がある。依存性などの原因でol7_developer_EPELにあるパッケージのインストールに失敗するときは、EPELに切り替えてみよう。
4. さらなるEPELの使いこなし
4-1. EPELの有効化/無効化を切り替える
EPELに限らず追加のリポジトリを使用するときは、「常時有効にする」「一時的に有効にする」の二通りの方法がある。EPELを使い始めたら常時有効にするのが一般的だが、EPELのパッケージを明示的に区別したいときは「一時的に有効にする」ことで区別できる。
常時有効にする
yum repolist
で表示されるときは有効になっている。またrepoファイルはenabled=1
になっている。一時的に有効にする
この方法ではEPELを無効化しておき、必要なときだけ有効化する。
- EPELを無効化する。これでyumを実行してもEPELのパッケージは利用できない。
sudo yum-config-manager --disable epel2.EPELにあるパッケージをインストール/アップデートするときだけ
--enablerepo
オプションで有効化する。sudo yum --enablerepo=epel install <パッケージ名>4-2. トラブルシュート
余力のあるとき執筆予定
5. まとめ
- 標準リポジトリにないパッケージがあるときはEPELを探そう
- 野良リポジトリは使わないこと。使うときは人柱覚悟で
- RPMパッケージの依存性を崩すような強引なことはしないこと
- AWSではEPELを有効にする独自コマンドが提供されている
- Oracle Cloud InfrastructureのOracle Linux 7では独自のEPELリポジトリが提供されている
- 投稿日:2020-06-23T22:59:53+09:00
【AWS】AmazonLinuxのyumができない場合の対処
はじめに
AmazonLinux構築中に
yum update
ができない事象が発生しました。
この場合の原因と対処についてアウトプットしていきたいと思います。事象
AmazonLinuxにて
yum update
を実施したところ、下記画面にて止まることを確認。[root@ip-192-168-5-129 ec2-user]# yum -y update Loaded plugins: extras_suggestions, langpacks, priorities, update-motd環境
自宅環境
項目 説明 自宅PC Windows10 ターミナル TeraTerm クラウド環境
項目 説明 PublicCloud AWS OS Amazon Linux 2 AMI (HVM), SSD Volume Type ※自宅PC→構築したEC2に接続できるようにVPC設定済み
原因
「DNSホスト名」と「DNS解決」が有効化されていない。
対策
「DNSホスト名」と「DNS解決」の有効化
手順
DNS解決の編集
- 対象VPCを右クリックし、「DNS解決の編集」をクリック
- 「DNS解決」の有効化に☑を入れ、OKをクリック
- 「DNS解決が更新されました」と表示されることを確認
DNSホスト名の編集
- 対象VPCを右クリックし、「DNSホスト名の編集」をクリック
-「DNSホスト名」の有効化に☑を入れ、OKをクリック
-「DNSホスト名が更新されました」と表示されることを確認
AmazonLinuxにて
yum update
実施実行できることを確認。
[root@ip-192-168-5-129 ec2-user]# yum -y update Loaded plugins: extras_suggestions, langpacks, priorities, update-motd amzn2-core | 3.7 kB 00:00 amzn2extra-docker | 3.0 kB 00:00 (1/5): amzn2-core/2/x86_64/group_gz | 2.5 kB 00:00 (2/5): amzn2-core/2/x86_64/updateinfo | 218 kB 00:00 (3/5): amzn2extra-docker/2/x86_64/updateinfo | 69 B 00:00 (4/5): amzn2extra-docker/2/x86_64/primary_db | 68 kB 00:00 (5/5): amzn2-core/2/x86_64/primary_db | 41 MB 00:01 Resolving Dependencies --> Running transaction check ---> Package amazon-linux-extras.noarch 0:1.6.10-1.amzn2 will be updated ---> Package amazon-linux-extras.noarch 0:1.6.11-1.amzn2 will be an update ---> Package amazon-linux-extras-yum-plugin.noarch 0:1.6.10-1.amzn2 will be updated
- 投稿日:2020-06-23T22:44:19+09:00
【AWS初心者】AWS Batchで作られるEC2インスタンスがECSクラスターに入らない!ハマったのでメモ
はじめに
タイトルの通り、"AWS Batchで作られるEC2インスタンスがECSクラスターに入らない!"というハマり方をしました。
今後同じようになった人の解決の助けになればと思います。1つ目のハマったところ → 原因: AWS Batchで選択しEC2たインスタンスタイプが東京リージョン未対応だったため
現象
AWS BatchにてCompute environments、Job queue, Job definitionsを作成しJob実行後、"RUNNABLE"の状態で止まったままでした。
このとき、EC2インスタンスはできていませんでした。AutoScalingGroupの設定を見ると下記スクショのようなエラーメッセージが出ていることがわかりました。エラーメッセージテキスト
a user request created an AutoScalingGroup changing the desired capacity from 0 to 1.
an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 1原因と解決
これはAWS Batchで選択しEC2たインスタンスタイプ(a1系)が東京リージョン未対応だったことが原因でした。
[EC2]東京リージョンで構築可能なインスタンスタイプのアベイラビリティーゾーン別一覧表の記事を参考に対応しているインスタンスタイプを選ぶようにAWS Batchのompute environmentsを再設定するとこのエラーが解決され、次実行時にはEC2インスタンスが作成されました。
2つの目のハマったところ → 原因: Compute environmentsで選択したサブネットが外部ネットワークに接続できない状態だった
現象
1つ目の問題を解決でき、EC2インスタンスができましたが、そのEC2インスタンスがAWS Batchが管理するECSクラスター内に入らずBatchのジョブがRUNNABLEのままという状況になっていました。
原因と解決
調査
公式のAWS Batch ジョブ が RUNNABLE ステータスで止まっているのはなぜですか?の記事を確認しましたが、この記事上の項目はすべて問題なしとわかり、
それでもインスタンスが Amazon ECS クラスターに参加していない場合は、インスタンスに接続します。次に、 Docker デーモン と Amazon ECS コンテナーエージェントのステータスを確認します。
この手順を実施しました。
AWS Batchが作成したEC2インスタンスは Amazon ECS コンテナーエージェントなるDockerコンテナを自身に立ち上げこれが動くことがECSクラスターで動くことを意味していると知りました。
踏み台サーバを経由しAWS Batchが立ち上げたEC2インスタンスへSSHしDockerコンテナの状況を確認しました。
$ docker psこれを確認すると、Dockerコンテナが作られては無くなっていることがわかりました。
そこで立ち上がっているときにコンテナ内のログを確認すると下記のようなエラーが出ているとわかりました。
$ docker logs -f ecs-agent level=info time=2020-06-22T13:06:09Z msg="Loading configuration" module=agent.go level=info time=2020-06-22T13:06:09Z msg="Image excluded from cleanup: amazon/amazon-ecs-agent:latest" module=parse.go level=info time=2020-06-22T13:06:09Z msg="Image excluded from cleanup: amazon/amazon-ecs-pause:0.1.0" module=parse.go level=info time=2020-06-22T13:06:09Z msg="Amazon ECS agent Version: 1.36.2, Commit: 0e4174f6" module=agent.go level=info time=2020-06-22T13:06:09Z msg="Creating root ecs cgroup: /ecs" module=init_linux.go level=info time=2020-06-22T13:06:09Z msg="Creating cgroup /ecs" module=cgroup_controller_linux.go level=info time=2020-06-22T13:06:09Z msg="Event stream ContainerChange start listening..." module=eventstream.go level=info time=2020-06-22T13:06:09Z msg="Loading state!" module=state_manager.go level=info time=2020-06-22T13:06:10Z msg="Registering Instance with ECS" module=agent.go level=info time=2020-06-22T13:06:10Z msg="Remaining mem: 3725" module=client.go level=error time=2020-06-22T13:06:31Z msg="Unable to register as a container instance with ECS: RequestError: send request failed\ncaused by: Post https://ecs.ap-northeast-1.amazonaws.com/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)" module=client.go level=error time=2020-06-22T13:06:31Z msg="Error registering: RequestError: send request failed\ncaused by: Post https://ecs.ap-northeast-1.amazonaws.com/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)" module=agent.go明らかにネットワークの問題っぽい文言。
sudo yum update
を実行すると実行がされない。。ネットワークの問題なのが確定です。ECSインスタンスがクラスターに登録されないの記事に出会い、ネットワークの様子を見ると私の場合はルーティングテーブルの箇所が悪く、AWS BatchのCompute environmentsが持つサブネットが外部ネットワークにつながらないものだったことが原因とわかりました。
ポイント
- AWS Batchが作成するEC2インスタンスはPublic IPを割り当てられない
- インターネットゲートウェイをルーティングテーブルに持つサブネットに入っていてもそのEC2がPublic IPを持っていないとインターネットにはつながらない
解決方法
そのため、公式のパブリックサブネットとプライベートサブネットを持つ VPC (NAT)の記事を参考にNATゲートウェイがTargetになるルーティングテーブルを作成。そのルーティングテーブルを持つサブネットを作成し、そのサブネットをAWS BatchのCompute environmentsに紐付けると無事にJobが走るようになりました。
参考
- 投稿日:2020-06-23T22:26:44+09:00
Next.jsを使って、医師国家試験の勉強ノートを公開するブログを作った話
Next.jsを使って、医師国家試験の勉強ノートを公開するブログを作った話
表題の通りです。まずは完成品とレポジトリのURLをどうぞ。
サイト:https://chilvary-beta.vercel.app
GitHub:https://github.com/yokonao/chilvary-beta
作ったきっかけ
アーキテクチャ
アーキテクチャっていうのは大げさすぎるかもしれません。
- ローカルPCで書いたMarkdownファイルを作成
- MarkdownファイルをAWS S3にアップロード
- S3のデータを引っ張ってきて、静的サイトとしてビルド
Next.jsとは全く関係ありませんが、Markdownファイルのバージョン管理とアップロードは完全自動化しています。作業終了後Alfredをちょっと立ち上げてAppleScriptを起動すればアップロードが完了するようにしました。(AppleScriptでgit pushしてgithub actionsでS3にアップロード)。この話はまた別でしたい。
メリット
- SPAなのでページ遷移はほぼ0秒
- 超優秀なMarkdownエディタTyporaの力を借りることができる
参考:https://qiita.com/4_mio_11/items/223326c3289f6b2c2a07
実際の記事データ
こんな感じになります。
クエスチョンバンク(QB)を解きながら、疑問に思った点を調べてMarkdownファイルにまとめる。国試の勉強は長期戦なので、1年後の自分に向けて書いてます。
スタイルに関しては、Typoraのテーマで使用されているcssファイルとBulmaを併用してます。記事をローカルで作成した時とほぼ同じ見た目で公開しつつ、ヘッダーなどを作る際はBulmaのコンポーネントを利用できるになっています。
チュートリアルから進化している点
S3のディレクトリ構成が完成品のブログにそのまま反映されています。説明が難しいですがサイトを一度巡回していただければ、意図が伝わるはず...
本当に手元で作成したフォルダがそのままwebサイトになるイメージです。
Next.jsのすごいところ
このwebサイト、markdownファイルの中身をNext.jsに渡してあげれば成立するので以下のような拡張もできると思います。
データの置き場所をS3からデータベースにする
Markdown形式で記事をアップロードできるwebアプリを作成してS3を介してつなぐ
メディアサイトのようなものを作成しようとすると、認証機能など難しい点も出てくるでしょう。しかし、ローカルで作成した文書をSPAとして公開できるサイトをこれだけ簡単に自分で1から作れてしまうのは、Next.js様様かな、と感じます。もちろんGitHub Pagesなどもっと楽な選択肢もありますが、SPAや自由にカスタマイズできるというメリットは十分あると思います。
個人的には自分で見返す際もページ遷移に時間をとられないのでストレスフリーで気持ちいいです。普段やる気にならない勉強も記事作成という遊び感覚でできるようになりましたし。
## 今後
現在は、ビルド時に全てのページを静的に作成しているので、記事を追加・変更する際は再ビルドが必要になります。
しかし最近、Next.jsは静的なwebサイトに動的なページ更新機能を搭載できるようになりました。Incremental Static Regenerationというやつです。この機能を使いたかったのですが、現在はバグが存在するようなので実現できませんでした。
Next.jsのレポジトリではこのバグに関するissueに最優先事項のラベルがつけられていたので、修正がきたら導入したいと思っています。これさえ導入できれば、Markdownファイルの保存から公開までがほぼ自動化できる...
補足
Incremental Static Regenerationについては以下のサイトの説明が超わかりやすいです。(英語ですけど...)
https://arunoda.me/blog/what-is-nextjs-issg
件のバグのissue
- 投稿日:2020-06-23T22:26:44+09:00
Next.jsを使って医師国家試験の勉強ノートを公開するブログを作った話
Next.jsを使って医師国家試験の勉強ノートを公開するブログを作った話
表題の通りです。まずは完成品とレポジトリのURLをどうぞ。
サイト:https://chilvary-beta.vercel.app
GitHub:https://github.com/yokonao/chilvary-beta
作ったきっかけ
next.jsの公式チュートリアル(URLは以下)をやったら、構築の容易さとSPAのページ遷移の速さに感動したので。これで自分のブログ作ったら超便利じゃない?と思いました。単純なページ公開だけならバックエンドなしでも可能です。
https://nextjs.org/learn/basics/create-nextjs-app?utm_source=next-site&utm_medium=homepage-cta&utm_campaign=next-websiteアーキテクチャ
アーキテクチャっていうのは大げさすぎるかもしれません。
- ローカルPCで書いたMarkdownファイルを作成
- MarkdownファイルをAWS S3にアップロード
- S3のデータを引っ張ってきて、静的サイトとしてビルド
Next.jsとは全く関係ありませんが、Markdownファイルのバージョン管理とアップロードは完全自動化しています。作業終了後Alfredをちょっと立ち上げてAppleScriptを起動すればアップロードが完了するようにしました。(AppleScriptでgit pushしてgithub actionsでS3にアップロード)。この話はまた別でしたい。
メリット
- SPAなのでページ遷移はほぼ0秒
- 超優秀なMarkdownエディタTyporaの力を借りることができる
参考:https://qiita.com/4_mio_11/items/223326c3289f6b2c2a07
実際の記事にはどんなこと書いてんの?
クエスチョンバンク(QB)を解きながら、疑問に思った点を調べてMarkdownファイルにまとめる。国試の勉強は長期戦なので、1年後の自分に向けて書いてます。
スタイルに関しては、Typoraのテーマで使用されているcssファイルとBulmaを併用してます。記事をローカルで作成した時とほぼ同じ見た目で公開しつつ、ヘッダーなどを作る際はBulmaのコンポーネントを利用できるになっています。
チュートリアルから進化している点
S3のディレクトリ構成が完成品のブログにそのまま反映されています。説明が難しいですがサイトを一度巡回していただければ、意図が伝わるはず...
本当に手元で作成したフォルダがそのままwebサイトになるイメージです。
Next.jsのすごいところ
このwebサイト、markdownファイルの中身をNext.jsに渡してあげれば成立するので以下のような拡張もできると思います。
データの置き場所をS3からデータベースにする
Markdown形式で記事をアップロードできるwebアプリを作成してS3を介してつなぐ
メディアサイトのようなものを作成しようとすると、認証機能など難しい点も出てくるでしょう。しかし、ローカルで作成した文書をSPAとして公開できるサイトをこれだけ簡単に自分で1から作れてしまうのは、Next.js様様かな、と感じます。もちろんGitHub Pagesなどもっと楽な選択肢もありますが、SPAや自由にカスタマイズできるというメリットは十分あると思います。
個人的には自分で見返す際もページ遷移に時間をとられないのでストレスフリーで気持ちいいです。普段やる気にならない勉強も記事作成という遊び感覚でできるようになりましたし。
今後
現在は、ビルド時に全てのページを静的に作成しているので、記事を追加・変更する際は再ビルドが必要になります。
しかし最近、Next.jsは静的なwebサイトに動的なページ更新機能を搭載できるようになりました。Incremental Static Regenerationというやつです。この機能を使いたかったのですが、現在はバグが存在するようなので実現できませんでした。
Next.jsのレポジトリではこのバグに関するissueに最優先事項のラベルがつけられていたので、修正がきたら導入したいと思っています。これさえ導入できれば、Markdownファイルの保存から公開までがほぼ自動化できる...
補足
Incremental Static Regenerationについては以下のサイトの説明が超わかりやすいです。(英語ですけど...)
https://arunoda.me/blog/what-is-nextjs-issg
件のバグのissue
- 投稿日:2020-06-23T22:12:59+09:00
【AWS;Lambda入門】第二弾;jsonファイルから文章抽出してS3保存♬
前回は、以下のコードでs3://バケットに配置されたmp3ファイルをtranscribeしてテキストに変換して、jsonファイルをOutputBucketNameのS3;バケットに配置した。
今回は、このjsonファイルを呼び出して、テキスト変換された文章を抽出しようと思います。わざわざ前回コードを出したのは、今回もコードが似ているからです。s3 = boto3.client('s3') transcribe = boto3.client('transcribe') def lambda_handler(event, context): bucket = event['Records'][0]['s3']['bucket']['name'] key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8') try: transcribe.start_transcription_job( TranscriptionJobName= datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '_Transcription', LanguageCode='ja-JP', Media={ 'MediaFileUri': 'https://s3.ap-northeast-1.amazonaws.com/' + bucket + '/' + key }, OutputBucketName='lamoutput' ) ... raise eということで、以下のコードで実施できました。
S3;バケットに保存する方法は参考のとおりにしています。
【参考】
①【AWS Lambdaの基本コードその2】 S3へのファイル保存
②Boto3 で S3 のオブジェクトを操作する(高レベルAPIと低レベルAPI)
参考①のコメントを残しています。ほぼまんまなコードで動きました。
異なるのは、先日のjsonファイルの取り扱い方を取り入れている部分です。
まず、Libは以下のとおり、# ①ライブラリのimport import boto3 import urllib.parse from datetime import datetime import json以下は、参考②から真似してclientを定義しています。
print('Loading function') # ②Functionのロードをログに出力 s3 = boto3.resource('s3') # ③S3オブジェクトを取得 client = s3.meta.clientlambda_handlerの入りのbucket, keyの取得は、上記のtranscribeのコードと全く同一です(当然ですが。。)。
# ④Lambdaのメイン関数 def lambda_handler(event, context): bucket = event['Records'][0]['s3']['bucket']['name'] key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')以下は、参考②と同じコードでjsonファイルから、response['Body']を読込ます。
ところが、ここで躓きました。
つまり、このbody.decode('utf-8')とすれば日本語の文章が表れると思っておりました。が、現実は結構なjson likeな(文字列)が出現。
当初は、これは文字列と気づかず、jsonファイルだと思いました。
ということで、文字列と気づき、さらにjson.loadsでjsonファイルに変換できることが分かり、...やっと以下のコードにたどり着きました。
つまり、bodyは文字列です。response = client.get_object(Bucket=bucket, Key=key) body = response['Body'].read()文字列をjsonファイルに変換します。
dec = json.loads(body)そして、jsonファイルなるがゆえに以下のように日本語文章が簡単に抽出できました。
con_el=dec["results"]["transcripts"][0]["transcript"] print('contents=',con_el)
contents= こんにちは 東京 横浜 も 少し 曇り です 声 は 水木 さん です
最後に以下のように指定したs3;バケットにkeyのような時刻入りの.txtとして保存できます。bucket = 'muauanpub' # ⑤バケット名を指定 key = 'test_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt' # ⑥オブジェクトのキー情報を指定 file_contents = con_el # 'Lambda test' # ⑦ファイルの内容 obj = s3.Object(bucket,key) # ⑧バケット名とパスを指定 obj.put( Body=file_contents ) # ⑨バケットにファイルを出力 returnまとめ
・音声ファイルを変換したjsonファイルから文章抽出してs3バケットに保管できた
・これで二段階になっていますが、mp3ファイルをs3バケットに置くと、自動的にそのテキスト変換された文章そのものがs3バケットに保存されるようになりました。
・一応、Teraterm→ec2→s3バケット転送...s3バケットからダウンロード⇒表示は出来ました・あと、このs3バケットに音声ファイルを転送するアプリとs3バケットのテキストファイルを表示するアプリが出来るとより使いやすい音声ファイル-テキスト変換アプリが出来そうです(Web化)
・変換時間が長くともどちらのLambda関数も非同期起動なので、お金にも時間にも優しいアプリになりそうです
- 投稿日:2020-06-23T21:29:55+09:00
TerraformでAWS VPCを作成する
TerraformでAWS VPCを作成するコード
実行環境
- Windows 10 Home (1919)
- Git Bash (git version 2.25.1.windows.1)
- AWS CLI (aws-cli/2.0.3 Python/3.7.5 Windows/10 botocore/2.0.0dev7)
- Terraform (v0.12.26)
作成する構成
まっさらな環境にVPCを1つ作成
main.tf
main.tfprovider "aws" { profile = "prj01-profile" region = "us-west-2" } resource "aws_vpc" "prj01VPC" { cidr_block = "10.10.0.0/16" instance_tenancy = "default" tags = { Name = "prj01VPC" CostGroup = "prj01" } }公式サイトのマニュアルはこちら
AWS: aws_vpc - Terraform by HashiCorp実行
実行前の状態確認
$ aws ec2 describe-vpcs --region=us-west-2 { "Vpcs": [] }VPCは1つも存在していないことを確認。
前提
$ aws configure list --profile prj01-profile Name Value Type Location ---- ----- ---- -------- profile prj01-profile manual --profile access_key ****************FCES shared-credentials-file secret_key ****************4Idw shared-credentials-file region us-west-2 config-file ~/.aws/config前提としてaws cliのprofileは作成済み。
まずinit
$ ../terraform.exe init Initializing the backend... Initializing provider plugins... - Checking for available provider plugins... - Downloading plugin for provider "aws" (hashicorp/aws) 2.67.0... The following providers do not have any version constraints in configuration, so the latest version was installed. To prevent automatic upgrades to new major versions that may contain breaking changes, it is recommended to add version = "..." constraints to the corresponding provider blocks in configuration, with the constraint strings suggested below. * provider.aws: version = "~> 2.67" Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.次にplan
$ ../terraform.exe plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_vpc.prj01VPC will be created + resource "aws_vpc" "prj01VPC" { + arn = (known after apply) + assign_generated_ipv6_cidr_block = false + cidr_block = "10.10.0.0/16" + default_network_acl_id = (known after apply) + default_route_table_id = (known after apply) + default_security_group_id = (known after apply) + dhcp_options_id = (known after apply) + enable_classiclink = (known after apply) + enable_classiclink_dns_support = (known after apply) + enable_dns_hostnames = (known after apply) + enable_dns_support = true + id = (known after apply) + instance_tenancy = "default" + ipv6_association_id = (known after apply) + ipv6_cidr_block = (known after apply) + main_route_table_id = (known after apply) + owner_id = (known after apply) + tags = { + "CostGroup" = "prj01" + "Name" = "prj01VPC" } } Plan: 1 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.確認ポイント
- 今回は新規作成なので、全て「+」になっていること
- changeとdestroyが「0」になっていること
- その他エラーや警告が発生していないこと確認できたのでapply
$ ../terraform.exe apply An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_vpc.prj01VPC will be created + resource "aws_vpc" "prj01VPC" { + arn = (known after apply) + assign_generated_ipv6_cidr_block = false + cidr_block = "10.10.0.0/16" + default_network_acl_id = (known after apply) + default_route_table_id = (known after apply) + default_security_group_id = (known after apply) + dhcp_options_id = (known after apply) + enable_classiclink = (known after apply) + enable_classiclink_dns_support = (known after apply) + enable_dns_hostnames = (known after apply) + enable_dns_support = true + id = (known after apply) + instance_tenancy = "default" + ipv6_association_id = (known after apply) + ipv6_cidr_block = (known after apply) + main_route_table_id = (known after apply) + owner_id = (known after apply) + tags = { + "CostGroup" = "prj01" + "Name" = "prj01VPC" } } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_vpc.prj01VPC: Creating... aws_vpc.prj01VPC: Still creating... [10s elapsed] aws_vpc.prj01VPC: Creation complete after 13s [id=vpc-085c4a097408d438d] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.確認ポイント
- Apply complete!と表示されること
- added, changed, destroyedが想定通りであること(今回は1,0,0であること)実行後の確認
$ aws ec2 describe-vpcs --region=us-west-2 { "Vpcs": [ { "CidrBlock": "10.10.0.0/16", "DhcpOptionsId": "dopt-0ebee8b328487036e", "State": "available", "VpcId": "vpc-085c4a097408d438d", "OwnerId": "679788997248", "InstanceTenancy": "default", "CidrBlockAssociationSet": [ { "AssociationId": "vpc-cidr-assoc-05db0b29ba54e1edc", "CidrBlock": "10.10.0.0/16", "CidrBlockState": { "State": "associated" } } ], "IsDefault": false, "Tags": [ { "Key": "CostGroup", "Value": "prj01" }, { "Key": "Name", "Value": "prj01VPC" } ] } ] }成功!
失敗パターン
providerにregionを指定しないと
main.tfprovider "aws" { profile = "prj01-profile" }$ ../terraform.exe plan provider.aws.region The region where AWS operations will take place. Examples are us-east-1, us-west-2, etc. Enter a value:上記のようにリージョンの指定を求められてしまうため、main.tf等に記載しておく方が良い。
- 投稿日:2020-06-23T20:10:48+09:00
【AWS】GithubからCodePipelineでECS/Fargateにデプロイする方法
【AWS】GithubからCodePipelineでECS/Fargateにデプロイする方法
CodePipelineを使ってECS/Fargateにnginx,phpコンテナをデプロイする方法をまとめます。
目次
構築イメージ
動作環境・前提条件
【動作環境】
OS : macOS 10.14.6
【前提条件】
VPC,サブネットは作成済STEP1. ECRの作成とイメージのプッシュ
ECR(Amazon Elastic Container Registry)とはDocker Hubのようなコンテナイメージを保管するAWS上のレジストリのことです.
ECRの作成
複数のイメージコンテナをデプロイするため、レジストリも複数作成します.
リポジトリ名は任意で構いませんが、後ほどdockerイメージとタグ付けを行うため,管理しやすいようdockerfileで定義したコンテナ名と同じ名前をつけています.
イメージのプッシュ
次にそれぞれのリポジトリ名をクリックし、リポジトリに入り、
プッシュコマンドの表示
を押します.表示されたコマンドを手元のMACのターミナルで実行します.
実行後、ECRにlatestタグが付いたイメージがアップロードされます.
STEP2. タスク定義ファイルとAppspecファイルの作成
タスク定義ファイル
AWSのチュートリアルでは
taskdef.json
と記載されていますが、
複数コンテナを同じタスクに登録する場合,この時点ではテンプレートを作成し、codebuildの際にtaskdef.jsonを作成するように設定します.taskdef-template.json{ "executionRoleArn": "arn:aws:iam::アカウントID:role/ecsTaskExecutionRole", "containerDefinitions": [{ "name": "nginx", "image": "<IMAGE_NGINX_NAME>", "essential": true, "portMappings": [{ "hostPort": 80, "protocol": "tcp", "containerPort": 80 }] }, { "name": "php", "image": "<IMAGE_PHP_NAME>", "essential": true, "portMappings": [{ "hostPort": 9000, "protocol": "tcp", "containerPort": 9000 }] } ], "requiresCompatibilities": [ "FARGATE" ], "networkMode": "awsvpc", "cpu": "256", "memory": "512", "family": "ecs-task" }Appspecファイル
AppspecファイルはCodeDeployの際に実行されます.
appspec.ymlversion: 0.0 Resources: - TargetService: Type: AWS::ECS::Service Properties: TaskDefinition: <TASK_DEFINITION> #<TASK_DEFINITION>は変えずにそのままにする LoadBalancerInfo: ContainerName: "nginx" ContainerPort: 80作成したタスク定義ファイルとAppspecファイルをプロジェクト直下のフォルダに保存し、githubにpushします.
STEP3. アプリケーションロードバランサーとターゲットグループを作成する
アプリケーションロードバランサとターゲットグループをAWSチュートリアルに沿って作成します.
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html#tutorials-ecs-ecr-codedeploy-loadbalSTEP4. ECSクラスターとサービスを作成する
ECSクラスターとサービスも上記リンクの
STEP4
と同じように作成します.参考までに作成したサービス作成ファイルを掲示します.
create-service.json{ "taskDefinition": "ecs-task", "cluster": "ecs-cluster01", "loadBalancers": [{ "targetGroupArn": "AWSのサイトで確認したtargetgroupのArnを入力", "containerName": "nginx", "containerPort": 80 }], "desiredCount": 1, #タスク実行数を定義しています. "launchType": "FARGATE", "schedulingStrategy": "REPLICA", "deploymentController": { "type": "CODE_DEPLOY" }, "networkConfiguration": { "awsvpcConfiguration": { "subnets": [ "subnet-0fXXXXXのようなsubnet IDを記載", "subnet-0fXXXXXのような2つ目のsubnet IDを記載" ], "securityGroups": [ "security gropuのIDを記載" ], "assignPublicIp": "ENABLED" } } }こちらもプロジェクトフォルダに保存し、ローカルPCのターミナルからコマンドを実行,サービスを作成します.
*ecs-test-serviceはサービス名のため任意の名前を付けられますaws ecs create-service --service-name ecs-test-service --cli-input-json file://create-service.jsonSTEP5. CodeDeployアプリケーションとデプロイグループを作成
こちらもAWSチュートリアルに従って作成していきます
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html#tutorials-ecs-ecr-codedeploy-cluster注釈
まずは動かして動作を確かめる場合はチュートリアル通りで問題ないです。
ただチュートリアルだと
すぐにトラフィックを再ルーティング
となっておりデプロイした新しいターゲットグループに対してすぐにユーザがアクセスできるようになっています。またデフォルトでは1時間後に、古いリビジョンが消去されるようになっているため、こちらも運用ポリシーに沿って変更します。
こちらではどちらも1日と設定しています。
STEP6. CodeBuildを作成
CodeBuildを実行するためにBuildspecファイルを作成し、プロジェクトフォルダのルートに保存します.そして、GithubにPushします.
buildspec.ymlversion: 0.2 phases: pre_build: commands: - IMAGE_URI_WEB=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME_WEB - IMAGE_URI_PHP=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME_PHP - $(aws ecr get-login --no-include-email --region ${AWS_DEFAULT_REGION}) build: commands: - docker-compose -f docker-compose-production.yml build - docker tag src_web:$IMAGE_TAG $IMAGE_URI_WEB:$IMAGE_TAG - docker tag src_php:$IMAGE_TAG $IMAGE_URI_PHP:$IMAGE_TAG post_build: commands: - docker push $IMAGE_URI_WEB:$IMAGE_TAG - docker push $IMAGE_URI_PHP:$IMAGE_TAG #taskdef-templateで定義したIMAGE_URIを環境変数で置き換えています. - cat taskdef-template.json | sed -e s@\<IMAGE_WEB_NAME\>@$IMAGE_URI_WEB:$IMAGE_TAG@ -e s@\<IMAGE_PHP_NAME\>@$IMAGE_URI_PHP:$IMAGE_TAG@ > taskdef.json artifacts: files: - appspec.yaml - taskdef.jsonその後、AWSの管理画面からCodeBuildの作成を選択します。
作成時に環境変数を設定する画面があるためにそこにリポジトリ名などを入れます。
そして、ソースとしてGithubを選択します.アーティファクトも不要です.
ポイント1. 特権を付与
そしてBuildの作成を実行します.
ポイント2. CodeBuildにポリシーを付与
codebuild作成後、CodeBuildがECRにアクセスできるようにCodeBuildのサービスロールに
AmazonEC2ContainerRegistryPowerUser
ポリシーをアタッチします.STEP7. CodePipelineを作成
最後にCodePipelineの作成を選択し、ソースにはGithub, ビルドステップではSTEP5で作成したCodeBuildを選択します。
デプロイステップではAmazon ECS(ブルー/グリーン)を選択し、
Source Artifactでtaskdef.jsonとappspec.ymlを選択します。
タスク定義の動的な更新イメージ - オプショナル
は入力不要です。動作確認
作成が完了するとCodePipelineがスタートします。
ここでDeployのところでステータスが処理中になります。
そのため、ロードバランサのDNS:8080(テスト用のリスナー)にアクセスに新しくデプロイしたシステムが問題なく動くか確認します。
問題なさそうであればDeploy画面からトラフィックの再ルーティングをクリックすると、
新システムにトラフィックが流れ始めます。その後、CodeDeployで設定した待機時間をすぎると古いタスクが停止されCodeDeployが成功となります。
実際にAWSの管理画面からECSを選択し、タスクが実行されていることを確認します。
そしてブラウザからロードバランサが持つ、パブリックDNSに対してアクセスし、PHPの画面が表示されれば成功です。
その後、githubに対して新たなバージョンをpushするとcodepiplineが実行されます.
- 投稿日:2020-06-23T17:15:38+09:00
Railsアプリに独自ドメインを与えてAWSに上げても表示されない問題
「自分のアプリを独自ドメインにしてAWSに上げたろー」
ということで以下の記事を参考に自分のアプリに独自ドメインを付与しました。
https://mel.onl/onamae-domain-aws-route-53/しかし3日待っても全く表示されない。AWSの紹介ページが表示されるだけ・・・
そこで色々調べた結果、Nginxの設定が必要であるとわかった。Nginxの設定
EC2で
[USERNAME|~]$ cd /etc/nginx/conf.d/ [USERNAME|conf.d]$ sudo vi 〇〇.conf (#自分のアプリケーション名)〇〇.confで
server_name 〇〇.com;(#アプリの独自ドメインに変更してください)保存して終了。再起動する。
[USERNAME|〇〇(アプリ名)]$ sudo nginx -s reloadこれで行けるはず!
参考文献
https://qiita.com/naoki_mochizuki/items/5a1757d222806cbe0cd1#nginx%E3%81%AE%E8%B5%B7%E5%8B%95
- 投稿日:2020-06-23T16:59:19+09:00
AWSハンズオン実践メモ 〜スケーラブルウェブサイト構築編〜
はじめに
AWSでWeb三層モデルを体系的に構築した事が無かった為、AWS公式のハンズオン(スケーラブルウェブサイト構築編)を実践しました。
本記事は自身のハンズオン学習メモとして投稿します。目次
ハンズオンの目的
WordPressを具体例に、
- Amazon EC2
- Amazon Virtual Private Cloud (VPC)
- Amazon Relational Database Service (RDS)
- Elastic Load Balancing (ELB)
を利⽤し、スケーラブルなWebシステムを構築する。
WordPressを使ったブログサイトの構築を通じて、スケーラブルな Web システム構築を学んでいただけるウェビナーシリーズです。主に取り扱う AWS サービスは Amazon EC2、Amazon RDS、ELB の3つです。また、作って終わりではなく、実際にEC2インスタンス1台を停止させ、その状態でもブログサイトにアクセスできることも確認します。
(https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/?trk=aws_blog より引用)本編
※全てマネジメントコンソールから実施。
Amazon VPCの作成
- VPC作成
- Subnet作成(Private、PublicをAZ-A、AZ-Cに1つずつ)
- ルートテーブルの関連付け(PublicのデフォルトゲートウェイをIGWに設定)
Amazon EC2の作成
- PublicのAZ-AにEC2インスタンスを作成。ユーザーデータを利用しWordPressをインストール
- SecurityGroup作成・設定
- EC2にSSH(EC2 Instance Connect (ブラウザベースの SSH 接続)を利用)
EC2 Instance Connectを使えばSSHの鍵を作成せずに接続出来るのか。。。
参考:EC2のSSHアクセスをIAMで制御できるEC2 Instance Connectが発表されましたAmazon RDSの作成
- SecurityGroup作成
- Subnetグループ作成
- RDS作成
ELBの作成
- SecurityGroup作成
- ALB作成(ターゲットグループ作成、ヘルスチェック設定)
- DNS名で接続
WordPress初期設定
初期設定を行い、アクセス。特筆すべき事はなし
AMIの作成と、そのAMIから2つ⽬のEC2インスタンス作成
- AMI作成(既にデプロイしているEC2のAMIを作成)
- AMIからEC2作成
- ターゲットグループに新規EC2追加
EC2(Web)とRDS(DB)のマルチAZ化
- RDSをマルチAZに変更
構築したアーキテクチャの可⽤性確認
- EC2のうち1台を停止し、Webページにアクセス。問題なくアクセス出来る事を確認
- RDSをフェールオーバーさせ、webページにアクセス。フェールオーバー中の数分はアクセス出来ないが、その後アクセス出来るようになる事を確認
作成した AWS リソースの削除
粛々と削除。特筆すべきことはなし。
おわりに
AWSでweb三層モデルを体系的に構築したのは初めてだったので、いい経験になった。
また、AWSの資格勉強のおかげで、GUIで行うレベルの設定パラメータについては理解できている事が分かった。
- 投稿日:2020-06-23T16:45:40+09:00
AWSのEC2内でDockerコマンドを使えないときの対処法【目的:load遂行】
はじめに
ローカルにあるファイルをEC2へ送りたかったのですが、dockerコマンドが使えませんでした。
[ec2-user@ip-xxx-xx-xx-xx ~]$ docker load < dockerfiles.tar -bash: docker: command not found色々試行錯誤しながら、EC2環境にdockerをインストールすることで解決できたので共有したいと思います。
手順
[ec2-user@ip-xxx-xx-xx-xx ~]$ sudo yum install -y dockerEC2環境にDockerをインストール。EC2環境で上記コマンドを叩きます。「完了しました!」が最後に表示されたら成功。
[ec2-user@ip-xxx-xx-xx-xx ~]$ sudo service docker startdockerを起動させます(EC2インスタンスを再起動させたときはDockerが停止してしまうので、インスタンスを再起動したときは毎回このコマンドを使います)。
さあ、もう使えるだろうと思い、手始めにdockerイメージの一覧でも見るかとコマンドを叩くと
[ec2-user@ip-xxx-xx-xx-xx ~]$ docker imagesGot permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%43j432jd34fFdocker.sock/v1.26/images/json: dial unix /var/run/docker.sock: connect: permission deniedエラーが発生。
dockerグループにec2-userを追加してなかったんですね。では追加します。
[ec2-user@ip-xxx-xx-xx-xx ~]$ sudo usermod -a -G docker ec2-userそして一度EC2から抜けます。
[ec2-user@ip-xxx-xx-xx-xx ~]$ exitまたEC2内に入ります。
nakajimakoutanoMacBook-ea:Desktop nakajimakouta$ ssh -i xxxxxxx.pem ec2-user@ホスト名そしてdocker imagesコマンドを叩くと無事に動きました。
[ec2-user@ip-xxx-xx-xx-xx ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE本来の目的であった「ローカルにあるファイルをEC2へ送りたい」をできるかどうか試すと
[ec2-user@ip-xxx-xx-xx-xx ~]$ docker load < Dockerfile.tar Loaded image ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[ec2-user@ip-xxx-xx-xx-xx ~]$ docker run -it xxxxxxxxxxxxx sh/ # $ ls bin dev etc home lib media mnt opt proc root run sbin srv sys Dockerfile←これ tmp usr var成功です。無事にDockerfileをEC2内へ送ることができました。
参考記事
- 投稿日:2020-06-23T16:24:27+09:00
CDKを使ってWordpressをFargate+EFS環境に移行する
概要
AWS ECS Fargate1.4.0がついにEFS(Elastic File System)をサポートしました。
これまではコンテナ内にボリュームをマウントしていたため、タスク数が増えたり、タスクがリフレッシュされるとマウントしていたデータが消えてしまっていたので、Wordpressのようなローカルにファイルを保持するようなアプリケーションにFargateは適用できませんでした。
EFSを利用することで、データを永続的に保持することが可能になるため、WordpressでもFargateを利用することができます。
今回は、CDKを利用してWordpressが稼働するインフラ環境を構築しました。
インフラ構築
1. セキュリティグループを定義
RDS、EC2、EFSのセキュリティグループを作成します。
export class SystemStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc = ec2.Vpc.fromLookup(this, 'VpcForSystem', { vpcName: 'vpc' }); // RDS用のセキュリティグループ // ポート3306番のTCP通信のみを許可 const dbSecurityGroup = new ec2.CfnSecurityGroup(this, 'RDSSecurityGroup', { groupDescription: 'RDS Secutiry Group', tags: 'wordpress-rds-sg', securityGroupIngress: [ { ipProtocol: 'tcp', cidrIp: '0.0.0.0/0', fromPort: 3306, toPort: 3306, } ], vpcId: vpc.vpcId, }); // EC2用のセキュリティグループ // ポート22番のSSH通信のみを許可(踏み台用) const ec2SecurityGroup = new ec2.CfnSecurityGroup(this, 'EC2SecurityGroup', { groupDescription: 'EC2 Secutiry Group', securityGroupIngress: [ { ipProtocol: 'tcp', cidrIp: '0.0.0.0/0', fromPort: 22, toPort: 22, } ], tags: 'wordpress-ec2-sg', vpcId: vpc.vpcId, }); // EFS用のセキュリティグループ // ポート3306番のTCP通信のみを許可 const efsSecurityGroup = new ec2.CfnSecurityGroup(this, 'EFSSecurityGroup', { groupDescription: 'EFS Secutiry Group', tags: 'wordpress-efs-sg', securityGroupIngress: [ { ipProtocol: 'tcp', cidrIp: '0.0.0.0/0', fromPort: 2049, toPort: 2049, } ], vpcId: vpc.vpcId, }); } }2. EC2の作成
ローカルからRDSやEFSにアクセスするための踏み台のインスタンスを作成します。
export class Ec2Stack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const instance = new ec2.Instance(this, 'Instance', { instanceType: new ec2.InstanceType('t2.micro'), machineImage: ec2.MachineImage.latestAmazonLinux(), vpc, allowAllOutbound: true, instanceName: 'wordpress-bastion', keyName: 'wordpress-key', securityGroup: ec2.SecurityGroup.fromSecurityGroupId(this, 'Ec2SecurityGroupId', cdk.Fn.importValue('Ec2-SecurityGroup-GroupId')), }); instance.addUserData( 'yum -y update', 'rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm', 'yum -y install --enablerepo=mysql57-community mysql-community-client php-mysqlnd', 'yum -y install amazon-efs-utils', `mkdir -p /mnt/efs/${FileSystemId}`, `mount -t efs ${cdk.Fn.importValue(FileSystemId}:/ /mnt/efs/${FileSystemId}` ); } }3. RDSの作成
export class RdsStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, stackUtil: StackUtil, props?: cdk.StackProps) { super(scope, id, props); // Parameter Group const parameterGroup = new rds.ParameterGroup(this, 'ParameterGroup', { description: 'DB Parameter Group', family: 'mysql5.7', parameters: { 'character_set_connection': 'utf8', 'character_set_database': 'utf8', 'character_set_results': 'utf8', 'character_set_server': 'utf8', 'character_set_client': 'utf8', }, }); // Instance const databaseInstance = new rds.DatabaseInstance(this, 'DbInstance', { allocatedStorage: 20, autoMinorVersionUpgrade: false, backupRetention: cdk.Duration.days(7), cloudwatchLogsRetention: logs.RetentionDays.TWO_MONTHS, copyTagsToSnapshot: true, engine: rds.DatabaseInstanceEngine.MYSQL, engineVersion: '5.7', instanceClass: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO), instanceIdentifier: 'wordpress-rds', licenseModel: rds.LicenseModel.GENERAL_PUBLIC_LICENSE, masterUsername: 'wp_admin', masterUserPassword: this.node.tryGetContext('rds-password'), multiAz: false, parameterGroup, securityGroups: [ ec2.SecurityGroup.fromSecurityGroupId(this, 'DbSecurityGroup', cdk.Fn.importValue(DBSecurityGroupId)), ], storageEncrypted: false, storageType: rds.StorageType.GP2, enablePerformanceInsights: false, vpc, }); } }4. ALBの作成
export class LbStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, stackUtil: StackUtil, externalProps: IExternalProperties, props?: cdk.StackProps) { super(scope, id, props); // VPC const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { vpcName: stackUtil.getVpcName() }); // Security Group for LB const lbSecurityGroup = new ec2.SecurityGroup(this, 'LbSecurityGroup', { securityGroupName: stackUtil.getName('LB-SG'), description: 'Security group for Loadbalancer.', vpc, allowAllOutbound: true, }); lbSecurityGroup.addIngressRule(ec2.Peer.ipv4('0.0.0.0/0'), ec2.Port.tcp(80), ''); lbSecurityGroup.addIngressRule(ec2.Peer.ipv4('0.0.0.0/0'), ec2.Port.tcp(443), ''); stackUtil.addTagToResource(lbSecurityGroup, 'LB-SG'); // Application Load Balancer const alb = new elbv2.CfnLoadBalancer(this, 'LoadBalancer', { name: 'wordpress-alb', type: 'application', scheme: 'internet-facing', subnets: vpc.publicSubnets.map(c => c.subnetId), securityGroups: [ lbSecurityGroup.securityGroupId, ], }); // Target Group for ALB const targetGroup = new elbv2.ApplicationTargetGroup(this, 'TargetGroup', { deregistrationDelay: cdk.Duration.seconds(15), healthCheck: { healthyThresholdCount: 3, healthyHttpCodes: '200-299,301,302,303,304', interval: cdk.Duration.seconds(90), path: '/', protocol: elbv2.Protocol.HTTP, timeout: cdk.Duration.seconds(60), unhealthyThresholdCount: 3, }, port: 80, protocol: elbv2.ApplicationProtocol.HTTP, targetGroupName: 'wordpress-tg', targetType: elbv2.TargetType.IP, vpc, }); // HTTPリクエストの場合は、HTTPSにリダイレクト new elbv2.CfnListener(this, 'ListenerHttp', { port: 80, protocol: elbv2.Protocol.HTTP, loadBalancerArn: alb.ref, defaultActions: [ { type: 'redirect', redirectConfig: { port: '443', protocol: elbv2.Protocol.HTTPS, statusCode: 'HTTP_301' } }, ], }); new elbv2.CfnListener(this, 'ListenerHttps', { port: 443, protocol: elbv2.Protocol.HTTPS, loadBalancerArn: alb.ref, certificates: [ { certificateArn: '[LBの証明書ARN]', }, ], defaultActions: [ { targetGroupArn: targetGroup.targetGroupArn, type: 'forward', }, ], }); } }5. EFSの作成
export class EfsStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const fileSystem = new efs.FileSystem(this, 'FileSystem', { vpc, fileSystemName: 'wordpress-efs', performanceMode: efs.PerformanceMode.GENERAL_PURPOSE, securityGroup: ec2.SecurityGroup.fromSecurityGroupId(this, 'EfsSecurityGroup', cdk.Fn.importValue('EfsSecurityGroupd')), }); } }6. System Managerのパラメータストアにパラメータ定義
Fargateのコンテナから環境変数を参照するために、System Managerのパラメータストアにパラメータを定義しておきます。
export class SsmStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new ssm.StringParameter(this, 'WpDbHostParameter', { description: 'Wordpress DB Host', parameterName: '/wordpress/db_host', stringValue: '[RDSのDBエンドポイント]', }); new ssm.StringParameter(this, 'WpDbPortParameter', { description: 'Wordpress DB Port', parameterName: '/wordpress/db_port', stringValue: '[RDSのDBポート]', }); new ssm.StringParameter(this, 'WpDbPasswordParameter', { description: 'Wordpress DB Password', parameterName: '/wordpress/db_password', stringValue: 'password', }); new ssm.StringParameter(this, 'WpDbNameParameter', { description: 'Wordpress DB Name', parameterName: '/wordpress/db_name', stringValue: 'wordpress', }); new ssm.StringParameter(this, 'WpDbUserParameter', { description: 'Wordpress DB User', parameterName: '/wordpress/db_user', stringValue: 'wp_admin', }); } }7. ECSの作成
ECSのリソースを作成します。
注意すべき点は、2020年6月現在Fargateのlatestバージョンは1.3.0ですが、1.3.0ではEFSをサポートしていないため、1.4.0を指定する必要があります。
また、CDK及びCloudformationではまだ、インフラコードからFargateとEFSの連携ができないため、手で作成する必要があります。
タスク定義をインフラコードで作成した後、コンソールから「新しいリビジョン」を選択し、EFSの追加、コンテナ上でEFSをマウントします。
コンテナパスは/var/www/htmlにします。export class EcsStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, stackUtil: StackUtil, props?: cdk.StackProps) { super(scope, id, props); // Load ECS Cluster const cluster = new ecs.CfnCluster(this, 'Cluster', { clusterName: 'wordpress-cluster', }); // Task Execution Role const executionRole = new iam.Role(this, 'TaskExecutionRole', { roleName: 'wordpress-taskexecution-role', assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy'), ], inlinePolicies: { 'INLINE': new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:GetParameter', 'ssm:GetParameters', 'ssm:GetParameterHistory', 'ssm:GetParametersByPath', ], resources: [ `arn:aws:ssm:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:parameter/*`, ], }), new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:DescribeParameters', ], resources: [ '*', ], }), ], }), }, }); // Task Role const taskRole = new iam.Role(this, 'TaskRole', { roleName: 'wordpress-task-role', assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), inlinePolicies: { 'INLINE': new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:GetParameter', 'ssm:GetParameters', 'ssm:GetParameterHistory', 'ssm:GetParametersByPath', ], resources: [ `arn:aws:ssm:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:parameter/*`, ], }), new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:DescribeParameters', ], resources: [ '*', ], }), ], }), }, }); // Task Definition let taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', { cpu: 256, executionRole, family: 'wordpress-taskdefinition', memoryLimitMiB: 512, taskRole, }); // Container let containerDefinition = new ecs.ContainerDefinition(this, 'wordpress', { image: ecs.ContainerImage.fromRegistry('wordpress:latest'), taskDefinition, cpu: 256, environment: { REGION: cdk.Aws.REGION, }, logging: ecs.LogDriver.awsLogs({ streamPrefix: 'wordpress', logGroup, }), memoryReservationMiB: 512, secrets: { WORDPRESS_DB_HOST: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbHostParameterName', `/wordpress/db_host`), ), WORDPRESS_DB_PORT: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbPortParameterName', `/wordpress/db_port`), ), WORDPRESS_DB_PASSWORD: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbPasswordParameterName', `/wordpress/db_password`), ), WORDPRESS_DB_NAME: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbNameParameterName', `/wordpress/db_name`), ), WORDPRESS_DB_USER: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbUserParameterName', `/wordpress/db_user`), ), } }); containerDefinition.addPortMappings({ containerPort: 80, hostPort: 80, protocol: ecs.Protocol.TCP, }); // Service const fargateService = new ecs.CfnService(this, 'EcsService', { serviceName: 'wordpress-service', cluster: cluster.clusterArn, desiredCount: 1, launchType: ecs.LaunchType.FARGATE, loadBalancers: [ { containerName: 'wordpress' containerPort: 80, targetGroupArn: cdk.Fn.importValue('LbTgArn'), }, ], deploymentConfiguration: { maximumPercent: 200, minimumHealthyPercent: 100, }, networkConfiguration: { awsvpcConfiguration: { securityGroups: [ systemSecurityGroup.securityGroupId, ], subnets: vpc.publicSubnets.map(c => c.subnetId), assignPublicIp: 'ENABLED', }, }, platformVersion: '1.4.0', // TODO: latest healthCheckGracePeriodSeconds: 30, taskDefinition: taskDefinition.taskDefinitionArn, }); } }まとめ
Fargateを利用することでログの可視化(Cloudwatch)や、セキュリティ強化のためにWAFを導入したり、死活監視でXrayを使ったりなど、アーキテクチャの幅が広がりそうです。
- 投稿日:2020-06-23T16:24:27+09:00
CDKでWordpressをFargate+EFS環境に移行する
概要
AWS ECS Fargate1.4.0がついにEFS(Elastic File System)をサポートしました。
これまではコンテナ内にボリュームをマウントしていたため、タスク数が増えたり、タスクがリフレッシュされるとマウントしていたデータが消えてしまっていたので、Wordpressのようなローカルにファイルを保持するようなアプリケーションにFargateは適用できませんでした。
EFSを利用することで、データを永続的に保持することが可能になるため、WordpressでもFargateを利用することができます。
今回は、CDKを利用してWordpressが稼働するインフラ環境を構築しました。
インフラ構築
1. セキュリティグループを定義
RDS、EC2、EFSのセキュリティグループを作成します。
export class SystemStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc = ec2.Vpc.fromLookup(this, 'VpcForSystem', { vpcName: 'vpc' }); // RDS用のセキュリティグループ // ポート3306番のTCP通信のみを許可 const dbSecurityGroup = new ec2.CfnSecurityGroup(this, 'RDSSecurityGroup', { groupDescription: 'RDS Secutiry Group', tags: 'wordpress-rds-sg', securityGroupIngress: [ { ipProtocol: 'tcp', cidrIp: '0.0.0.0/0', fromPort: 3306, toPort: 3306, } ], vpcId: vpc.vpcId, }); // EC2用のセキュリティグループ // ポート22番のSSH通信のみを許可(踏み台用) const ec2SecurityGroup = new ec2.CfnSecurityGroup(this, 'EC2SecurityGroup', { groupDescription: 'EC2 Secutiry Group', securityGroupIngress: [ { ipProtocol: 'tcp', cidrIp: '0.0.0.0/0', fromPort: 22, toPort: 22, } ], tags: 'wordpress-ec2-sg', vpcId: vpc.vpcId, }); // EFS用のセキュリティグループ // ポート3306番のTCP通信のみを許可 const efsSecurityGroup = new ec2.CfnSecurityGroup(this, 'EFSSecurityGroup', { groupDescription: 'EFS Secutiry Group', tags: 'wordpress-efs-sg', securityGroupIngress: [ { ipProtocol: 'tcp', cidrIp: '0.0.0.0/0', fromPort: 2049, toPort: 2049, } ], vpcId: vpc.vpcId, }); } }2. EC2の作成
ローカルからRDSやEFSにアクセスするための踏み台のインスタンスを作成します。
export class Ec2Stack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const instance = new ec2.Instance(this, 'Instance', { instanceType: new ec2.InstanceType('t2.micro'), machineImage: ec2.MachineImage.latestAmazonLinux(), vpc, allowAllOutbound: true, instanceName: 'wordpress-bastion', keyName: 'wordpress-key', securityGroup: ec2.SecurityGroup.fromSecurityGroupId(this, 'Ec2SecurityGroupId', cdk.Fn.importValue('Ec2-SecurityGroup-GroupId')), }); instance.addUserData( 'yum -y update', 'rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm', 'yum -y install --enablerepo=mysql57-community mysql-community-client php-mysqlnd', 'yum -y install amazon-efs-utils', `mkdir -p /mnt/efs/${FileSystemId}`, `mount -t efs ${cdk.Fn.importValue(FileSystemId}:/ /mnt/efs/${FileSystemId}` ); } }3. RDSの作成
export class RdsStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, stackUtil: StackUtil, props?: cdk.StackProps) { super(scope, id, props); // Parameter Group const parameterGroup = new rds.ParameterGroup(this, 'ParameterGroup', { description: 'DB Parameter Group', family: 'mysql5.7', parameters: { 'character_set_connection': 'utf8', 'character_set_database': 'utf8', 'character_set_results': 'utf8', 'character_set_server': 'utf8', 'character_set_client': 'utf8', }, }); // Instance const databaseInstance = new rds.DatabaseInstance(this, 'DbInstance', { allocatedStorage: 20, autoMinorVersionUpgrade: false, backupRetention: cdk.Duration.days(7), cloudwatchLogsRetention: logs.RetentionDays.TWO_MONTHS, copyTagsToSnapshot: true, engine: rds.DatabaseInstanceEngine.MYSQL, engineVersion: '5.7', instanceClass: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO), instanceIdentifier: 'wordpress-rds', licenseModel: rds.LicenseModel.GENERAL_PUBLIC_LICENSE, masterUsername: 'wp_admin', masterUserPassword: this.node.tryGetContext('rds-password'), multiAz: false, parameterGroup, securityGroups: [ ec2.SecurityGroup.fromSecurityGroupId(this, 'DbSecurityGroup', cdk.Fn.importValue(DBSecurityGroupId)), ], storageEncrypted: false, storageType: rds.StorageType.GP2, enablePerformanceInsights: false, vpc, }); } }4. ALBの作成
export class LbStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, stackUtil: StackUtil, externalProps: IExternalProperties, props?: cdk.StackProps) { super(scope, id, props); // VPC const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { vpcName: stackUtil.getVpcName() }); // Security Group for LB const lbSecurityGroup = new ec2.SecurityGroup(this, 'LbSecurityGroup', { securityGroupName: stackUtil.getName('LB-SG'), description: 'Security group for Loadbalancer.', vpc, allowAllOutbound: true, }); lbSecurityGroup.addIngressRule(ec2.Peer.ipv4('0.0.0.0/0'), ec2.Port.tcp(80), ''); lbSecurityGroup.addIngressRule(ec2.Peer.ipv4('0.0.0.0/0'), ec2.Port.tcp(443), ''); stackUtil.addTagToResource(lbSecurityGroup, 'LB-SG'); // Application Load Balancer const alb = new elbv2.CfnLoadBalancer(this, 'LoadBalancer', { name: 'wordpress-alb', type: 'application', scheme: 'internet-facing', subnets: vpc.publicSubnets.map(c => c.subnetId), securityGroups: [ lbSecurityGroup.securityGroupId, ], }); // Target Group for ALB const targetGroup = new elbv2.ApplicationTargetGroup(this, 'TargetGroup', { deregistrationDelay: cdk.Duration.seconds(15), healthCheck: { healthyThresholdCount: 3, healthyHttpCodes: '200-299,301,302,303,304', interval: cdk.Duration.seconds(90), path: '/', protocol: elbv2.Protocol.HTTP, timeout: cdk.Duration.seconds(60), unhealthyThresholdCount: 3, }, port: 80, protocol: elbv2.ApplicationProtocol.HTTP, targetGroupName: 'wordpress-tg', targetType: elbv2.TargetType.IP, vpc, }); // HTTPリクエストの場合は、HTTPSにリダイレクト new elbv2.CfnListener(this, 'ListenerHttp', { port: 80, protocol: elbv2.Protocol.HTTP, loadBalancerArn: alb.ref, defaultActions: [ { type: 'redirect', redirectConfig: { port: '443', protocol: elbv2.Protocol.HTTPS, statusCode: 'HTTP_301' } }, ], }); new elbv2.CfnListener(this, 'ListenerHttps', { port: 443, protocol: elbv2.Protocol.HTTPS, loadBalancerArn: alb.ref, certificates: [ { certificateArn: '[LBの証明書ARN]', }, ], defaultActions: [ { targetGroupArn: targetGroup.targetGroupArn, type: 'forward', }, ], }); } }5. EFSの作成
export class EfsStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const fileSystem = new efs.FileSystem(this, 'FileSystem', { vpc, fileSystemName: 'wordpress-efs', performanceMode: efs.PerformanceMode.GENERAL_PURPOSE, securityGroup: ec2.SecurityGroup.fromSecurityGroupId(this, 'EfsSecurityGroup', cdk.Fn.importValue('EfsSecurityGroupd')), }); } }6. System Managerのパラメータストアにパラメータ定義
Fargateのコンテナから環境変数を参照するために、System Managerのパラメータストアにパラメータを定義しておきます。
export class SsmStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new ssm.StringParameter(this, 'WpDbHostParameter', { description: 'Wordpress DB Host', parameterName: '/wordpress/db_host', stringValue: '[RDSのDBエンドポイント]', }); new ssm.StringParameter(this, 'WpDbPortParameter', { description: 'Wordpress DB Port', parameterName: '/wordpress/db_port', stringValue: '[RDSのDBポート]', }); new ssm.StringParameter(this, 'WpDbPasswordParameter', { description: 'Wordpress DB Password', parameterName: '/wordpress/db_password', stringValue: 'password', }); new ssm.StringParameter(this, 'WpDbNameParameter', { description: 'Wordpress DB Name', parameterName: '/wordpress/db_name', stringValue: 'wordpress', }); new ssm.StringParameter(this, 'WpDbUserParameter', { description: 'Wordpress DB User', parameterName: '/wordpress/db_user', stringValue: 'wp_admin', }); } }7. ECSの作成
ECSのリソースを作成します。
注意すべき点は、2020年6月現在Fargateのlatestバージョンは1.3.0ですが、1.3.0ではEFSをサポートしていないため、1.4.0を指定する必要があります。
また、CDK及びCloudformationではまだ、インフラコードからFargateとEFSの連携ができないため、手で作成する必要があります。
タスク定義をインフラコードで作成した後、コンソールから「新しいリビジョン」を選択し、EFSの追加、コンテナ上でEFSをマウントします。
コンテナパスは/var/www/htmlにします。export class EcsStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, stackUtil: StackUtil, props?: cdk.StackProps) { super(scope, id, props); // Load ECS Cluster const cluster = new ecs.CfnCluster(this, 'Cluster', { clusterName: 'wordpress-cluster', }); // Task Execution Role const executionRole = new iam.Role(this, 'TaskExecutionRole', { roleName: 'wordpress-taskexecution-role', assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy'), ], inlinePolicies: { 'INLINE': new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:GetParameter', 'ssm:GetParameters', 'ssm:GetParameterHistory', 'ssm:GetParametersByPath', ], resources: [ `arn:aws:ssm:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:parameter/*`, ], }), new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:DescribeParameters', ], resources: [ '*', ], }), ], }), }, }); // Task Role const taskRole = new iam.Role(this, 'TaskRole', { roleName: 'wordpress-task-role', assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), inlinePolicies: { 'INLINE': new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:GetParameter', 'ssm:GetParameters', 'ssm:GetParameterHistory', 'ssm:GetParametersByPath', ], resources: [ `arn:aws:ssm:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:parameter/*`, ], }), new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'ssm:DescribeParameters', ], resources: [ '*', ], }), ], }), }, }); // Task Definition let taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', { cpu: 256, executionRole, family: 'wordpress-taskdefinition', memoryLimitMiB: 512, taskRole, }); // Container let containerDefinition = new ecs.ContainerDefinition(this, 'wordpress', { image: ecs.ContainerImage.fromRegistry('wordpress:latest'), taskDefinition, cpu: 256, environment: { REGION: cdk.Aws.REGION, }, logging: ecs.LogDriver.awsLogs({ streamPrefix: 'wordpress', logGroup, }), memoryReservationMiB: 512, secrets: { WORDPRESS_DB_HOST: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbHostParameterName', `/wordpress/db_host`), ), WORDPRESS_DB_PORT: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbPortParameterName', `/wordpress/db_port`), ), WORDPRESS_DB_PASSWORD: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbPasswordParameterName', `/wordpress/db_password`), ), WORDPRESS_DB_NAME: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbNameParameterName', `/wordpress/db_name`), ), WORDPRESS_DB_USER: ecs.Secret.fromSsmParameter( ssm.StringParameter.fromStringParameterName(this, 'WpDbUserParameterName', `/wordpress/db_user`), ), } }); containerDefinition.addPortMappings({ containerPort: 80, hostPort: 80, protocol: ecs.Protocol.TCP, }); // Service const fargateService = new ecs.CfnService(this, 'EcsService', { serviceName: 'wordpress-service', cluster: cluster.clusterArn, desiredCount: 1, launchType: ecs.LaunchType.FARGATE, loadBalancers: [ { containerName: 'wordpress' containerPort: 80, targetGroupArn: cdk.Fn.importValue('LbTgArn'), }, ], deploymentConfiguration: { maximumPercent: 200, minimumHealthyPercent: 100, }, networkConfiguration: { awsvpcConfiguration: { securityGroups: [ systemSecurityGroup.securityGroupId, ], subnets: vpc.publicSubnets.map(c => c.subnetId), assignPublicIp: 'ENABLED', }, }, platformVersion: '1.4.0', // TODO: latest healthCheckGracePeriodSeconds: 30, taskDefinition: taskDefinition.taskDefinitionArn, }); } }まとめ
Fargateを利用することでログの可視化(Cloudwatch)や、セキュリティ強化のためにWAFを導入したり、死活監視でXrayを使ったりなど、アーキテクチャの幅が広がりそうです。
- 投稿日:2020-06-23T15:36:42+09:00
AWS LambdaのCORSでハマったからreturnを共通化した
はじめに
前回、AWS Lambdaを使用したサーバーレス開発について、私がハマった箇所をまとめました。
インフラエンジニアがやってみた AWSでサーバーレス Webアプリケーション開発そこでCORSについて毎回returnでハマるのでreturnを共通化しました。
文中のAWS LambdaのソースはPython 3.8で書かれています。言いたいこと
CORSでエラーが出たらLambdaのreturnを疑え。
Why?
JavascriptのコンソールにCORSのエラーが出るとき、十中八九Lambdaで正しくreturnしていないからです。
CORSの仕組みや考え方は以下の参考ページが大変詳しいです。
なんとなく CORS がわかる...はもう終わりにする。ある程度仕組みを理解して頂いたところで、CORSのエラーが出るパターンは以下になります。
- Lambda側でOPTIONSメソッドに応答していない
- Lambda側で応答していない or 応答している内容に不備がある
かぶっている部分もありますが、大枠でこの2つになると思います。
ポカレベルの内容ですが気づきにくく、結果ハマりました。returnを共通化する
まず、丁寧にreturnしないといけないので、それなりにreturn部の処理が長くなってしまいます。
なので共通化してreturnできるように2つの関数を作成しました。# API Gatewayのルールに則った成功の response を生成する def create_success_response(body, **kwargs): origin = '*' methods = 'GET' for k, v in kwargs.items(): if k == 'origin' : origin = v if k == 'methods' : methods = v headers = { 'Access-Control-Allow-Headers' : 'Content-Type', 'Access-Control-Allow-Origin' : origin, 'Access-Control-Allow-Methods' : methods } logger.info( 'return values headers = {}, body = {}, origin = {}, methods = {}' .format(headers, body, origin, methods) ) return { 'isBase64Encoded': False, 'statusCode' : 200, 'headers' : headers, 'body' : json.dumps(body) } # API Gatewayのルールに則った失敗の response を生成する def create_error_response(body, **kwargs): origin = '*' methods = 'GET' for k, v in kwargs.items(): if k == 'origin' : origin = v if k == 'methods' : methods = v headers = { 'Access-Control-Allow-Headers' : 'Content-Type', 'Access-Control-Allow-Origin' : origin, 'Access-Control-Allow-Methods' : methods } return { 'isBase64Encoded': False, 'statusCode': 599, 'headers': headers, 'body': json.dumps(body) }
create_error_response
のほうはstatusCode
を599
でハードコーディングしています。
要件がある場合は、methodsと同じように引数で外部から変更できるようにしてください。
originの内容もサイトのセキュリティポリシーに合わせて、URLを絞ってください。OPTIONSメソッドに応答していない
LambdaがOPTIONSに対してちゃんと応答しているか疑いましょう。
GET, POST, PUT, DELETE…などなどは応答していたけどOPTIONSを忘れていた、という事があると思います。
というか私がそうでした。はい、OPTIONSについての処理を追加しましょう。
OPTIONSメソッドをちゃんと処理しよう#======================================================= # OPTIONS : CORSに必要 #======================================================= elif event['httpMethod'] == 'OPTIONS': logger.info('handle the options method.') return create_success_response( { 'message': 'successfully: called options method.' }, methods='GET,PATCH,DELETE' )この時大事なのが、methodsにLambdaで受け付けるHTTP Methodをすべて書くことです。
PUT, PATCH, POSTなど細かな違いもちゃんと仕様に合わせて書きましょう。応答していない or 応答している内容に不備がある
returnを書いてるから応答してる!と思ったら大間違いです!
return時にちゃんと、CORSの仕様に則った応答を返す必要があります。
具体的に言うとcreate_success_response
、create_error_response
関数のheaders
の部分です。
returnを共通化したので、return時に共通化した関数を呼んであげれば大丈夫になりました。return時に共通化した関数を呼ぶreturn create_success_response( response, methods='GET' )どこの処理でもreturn時に関数を呼ぶようにしています。
共通化した関数を経由することで、期待されているレスポンスに適切にフォーマットした後にreturnすることが出来るようにしました。最後に
適切なフォーマットでreturn出来ていないことが毎回のハマりポイントでした。
returnの処理を共通化することでミスに気づきやすくなりました。javascript consoleに出力されるCORS errorにさよなら!
- 投稿日:2020-06-23T15:18:12+09:00
サーバレスなVOD配信環境を構築
AWS Media Blog の Creating a secure video-on-demand (VOD) platform using AWS の記事で紹介されていた download this detailed lab guideを参考にサーバレスなVOD配信環境を構築してみました。
サーバレスなVOD配信環境でできること
認証されたユーザーのみが動画をアップロード、処理、配信および閲覧可能なサーバレスのVODストリーミングプラットフォームです。
■動画アップロード画面(管理者権限付与ユーザのみログイン可能)
ログイン
動画アップロード
■動画配信画面(認証済ユーザのみ)
ログイン
動画一覧
動画配信
サーバレスなVOD配信環境のアーキテクチャ
■概要
■説明
DeepL翻訳このサーバーレスVODワークフローソリューションは、 Amazon Cognito、AWS AppSync、Amazon S3、AWS Lambda、Amazon DynamoDB、AWS Secrets Manager、 AWS Elemental MediaConvert、Amazon CloudFront、AWS Amplify、AWS CloudFormation を含む複数のAWSサービスを利用して構築されています。 このソリューションでは、CognitoはGraphQL APIへのアクセスを保護するCognito User Poolsを介してWebアプリケーションのユーザーを認証します。 APIはCognito User Pool内のグループに基づいたきめ細かなアクセスが可能です。 また、Cognitoは、コンテンツをS3にアップロードするためのアクセスのために、一時的に限定された特権を持つAWSのクレデンシャルを生成しています。 GraphQL APIを利用したAppSyncでは、クライアントアプリがサーバーからデータをフェッチ、変更、サブスクライブできるようにしています。 今回のソリューションでは、GraphQL APIを利用して動画に対してCRUD(Create/Read/Update/Delete)操作を行い、動画をS3バケットに格納しています。 このワークフローでは、2つのS3バケットを使用しています。 1つは生の動画を保存するため、もう1つは異なる出力フォーマットとビットレートの動画を保存するためです。 複数の Lambda 関数は、 MediaConvert ジョブのトリガー、 DynamoDB へのメタデータの保存、 署名付き URL トークンの作成、 MediaConvert ジョブの終了時の通知の送信 など、さまざまな目的に使用されます。 MediaConvert はアップロードされた動画を 2 Mbps 1 Mpbs 600 Kbps 400 Kbps の HLS 形式で自動的にトランスコードします。 ビデオコンテンツは、さまざまなネットワーク帯域幅接続を持つ複数のデバイスで再生できるように、適応ビットレートのストリームとしてエンコードされます。 Secrets Managerは、CloudFrontの秘密鍵を安全に保存し、CloudFrontのURLに署名するために使用します。 CloudFrontは、実行時にアプリケーションを介してCDN Edgeのロケーションを介して、許可されたユーザーにコンテンツを安全に配信します。 その他の設定情報 ・Signed Cookies/URLs CloudFrontが各URLの有効期限、許可されたIPアドレス、FileNameを設定できるようにします。 デフォルトでは、CDNで配布されたコンテンツにはNo Readアクセスが割り当てられています。 コンテンツは、アプリが生成した適切なSigned Cookieを使用してリクエストされた場合にのみダウンロードしてアクセスすることができます。 ・S3 CORSの設定 S3/CDN経由でコンテンツへのアクセスを許可するウェブサイトを設定します。S3 CORS設定の詳細については、こちらのブログ記事をご覧ください。 AmplifyとCloudFormationは、ソリューションのバックエンドに関わるリソースやサービスの迅速な展開を容易にします。サーバレスなVOD配信環境を構築する
■公式ドキュメント
VOD-Blog-LabGuide ※Wordファイル(docx)
■前提条件
AWSアカウント
- IAMユーザでAWSマネジメントコンソールにログイン(step4以外)
- IAMユーザ名:vodaws
- IAMポリシー:AdministratorAccess
- ルートアカウントでAWSマネジメントコンソールにログイン(step4のみ)
AWSマネジメントコンソール
- 言語
- 日本語
- リージョン
- ap-northeast-1 (Tokyo)
■Step1: Setting up Development Environme
1. AWS Cloud9コンソールに移動後、【 Create environment 】を選択
2. Name environment の設定後、【Next step 】を選択
Name: VodAws
Description: This environment is for the AWS Cloud9 tutorial.3. Environment setting にて t3.smallを選択後、【Next step 】を選択 ※インスタンスタイプ以外はデフォルト
4. 設定内容を確認後、【 Create environment 】を選択
5. Welcomeタブ横の(+) を選択し、別タブの新規ターミナルを表示
■Step2: Installing Packages and Configuring Environment
1. 以下のコマンドを実行してcredentialsファイルをコピー
コマンドcp ~/.aws/credentials ~/.aws/config2.以下のコマンドを実行してAmplify CLIをインストール
コマンドnpm install -g @aws-amplify/cliインストール時にWARNが表示されますが今回は無視します。
3. 以下のコマンドを実行してVodAws.zipをダウンロード
コマンドwget https://testorlando1.s3.amazonaws.com/VodAws.zip4. 以下のコマンドを実行してVodAws.zipを解凍
コマンドunzip VodAws.zip5. 以下のコマンドを実行してVodAwsディレクトへ移動
コマンドcd VodAws5. 以下のコマンドを実行してNPMをインストール
コマンドnpm installインストール時にWARNが表示されますが今回は無視します。
■Step3: Deploying Backend using Amplify Cli
1. 以下のコマンドを実行して~/environment/VodAwsにいることを確認
コマンドpwd
2. 以下のコマンドを実行してAWSバックエンドのセットアップ
コマンドamplify initプロンプトの選択については下記のとおり。
上記選択後、バックグラウンドで処理が走ります。
3. 以下のコマンドを実行してプロジェクトにAPIモジュールを追加
コマンドamplify add apiプロンプトの選択については下記のとおり。
上記選択後、APIモジュール追加処理。
4. 以下のコマンドを実行してschema.graphql を編集
コマンドcat << EOF > /home/ec2-user/environment/VodAws/amplify/backend/api/vodaws/schema.graphql type vodAsset @model (subscriptions: {level: public}) @auth( rules: [ {allow: groups, groups:["Admin"], operations: [create, update, delete, read]}, {allow: private, operations: [read]} ] ) { id:ID! title:String! description:String! #DO NOT EDIT video:videoObject @connection } #DO NOT EDIT type videoObject @model @auth( rules: [ {allow: groups, groups:["Admin"], operations: [create, update, delete, read]}, {allow: private, operations: [read]} ] ) { id:ID! token: String @function(name: "VodAws-prod-tokenGen") } EOF5. 以下のコマンドを実行してデプロイを実行
コマンドamplify push ※continue?についてはYを選択プロンプトの選択については下記のとおり。
Query/Mutationのコード生成有無
生成するコードの言語の選択
ファイル名のパターン(queries, mutations, subscriptions)の入力
全てのGraphQLの操作に対してのコード生成有無
タイプ同士で相互参照している場合のネストの最大値
上記選択後、デプロイ実行
6. ブラウザの別タブよりCloudFormationダッシュボードへ移動
CloudFormationダッシュボードへ移動
ネスト表示に切り替え
7. amplify-vodaws-prod-*のスタック名を選択後、出力に表示されている値(赤丸の個所)をメモ帳等に控える
8. amplify-vodaws-prod--authvodaws****のスタック名を選択後、出力に表示されている値(赤丸の個所)をメモ帳等に控える
■Step4: Creating CloudFront Key Pairs
DeepL翻訳重要 IAMユーザーはCloudFrontのキーペアを作成することができません。キーペアを作成するには、ルート資格情報を使用してログインする必要があります1. 別ブラウザを開き、ルートアカウントでAWSマネジメントコンソールにログイン
2. 画面右上のアカウント名をクリック後、【 マイセキュリティ資格情報 】を選択
3. セキュリティ認証画面の【 新しいキーペアの作成 】を選択
4. 【 プライベートキーファイルのダウンロード 】を選択してローカルにダウンロード
DeepL翻訳重要 CloudFrontのキーペアの秘密鍵を安全な場所に保存し、希望する管理者のみが読めるようにファイルのパーミッションを設定します。 誰かがあなたの秘密鍵を取得すると、有効な署名付きURLや署名付きクッキーを生成して、あなたのコンテンツをダウンロードすることができます。 秘密鍵は二度と取得できないので、紛失したり削除したりした場合は、新たにCloudFrontの鍵ペアを作成する必要があります5. 出力に表示されているアクセスキーID(赤丸の個所)をメモ帳等に控える(署名付きURLや署名付きCooki作成に利用)
以降はルートアカウントによる作業は発生しない為、 ルートアカウントでログインしているAWSマネジメントコンソールについてはログアウト
■Step5: Storing CloudFront Key Pairs
Step5以降はStep3にて使用したAWSマネジメントコンソール(IAMユーザログイン)を使用
1. Step3にて使用したCloud9のターミナルよりを以下のコマンドを実行してStep4の3のプライベートキーファイルをコピー
コマンドcat /home/ec2-user/environment/privateKey.pem ※ファイルが存在しないことを確認 cat << EOF > /home/ec2-user/environment/privateKey.pem (Step4の3のプライベートキーファイルの内容) EOF■Step6: Storing Private key using AWS SecretsManager
1. 以下のコマンドを実行して秘密鍵をSecretsManagerに保存後、出力に表示されている値(赤丸の個所)をメモ帳等に控える
コマンドaws secretsmanager create-secret --name VodAws --secret-binary file://privateKey.pem■Step 7: Verify the values of all the variables
1. 以下の変数の値を控えていることを確認
変数名 値 pAppClientID Step 3 の8のAppClientID pAppClientIDWeb Step 3 の8のAppClientIDWeb pAuthRoleArn Step 3 の7のAuthRoleArn pIdentityPoolID Step 3の8のIdentityPoolID pPemID Step 4 の5のアクセスID pS3 Step 3 の7のDeploymentBucketName pSecretPem Step 6 の1のName pSecretPemArn Step 6 の1のARN pSourceFolder vod-helpers (規定値) pUnAuthRoleArn Step 3 の7のUnAuthRoleArn pUserPoolID Step 3の8のUserPoolId pAuthRoleName Step 3 の7のAuthRoleName penv prod (規定値) pUnAuthRoleName Step 3 の7のUnAuthRoleName ■Step8: Deploying CloudFormation Template
1. vod-helpers.zipをローカルにダウンロードの上、解凍(vod-helpersフォルダ)
ダウンロード先URL:https://testorlando1.s3.amazonaws.com/vod-helpers.zip
2. 別タブにてS3ダッシュボードに移動
3. amplify-vodaws-prod-***-deploymentを選択
4. 1のvod-helpersフォルダをアップロード画面にドラックアンドドロップ後、【アップロード】を選択
5. vod-helpersを選択後、【アクション】より【公開する】を選択
6. 【公開する】を選択
7. Launch with CloudFormation Console のリンクを別タブで表示
Launch with CloudFormation Console
https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https:%2F%2Fs3.amazonaws.com%2Ftestorlando1%2FParentStack.json&stackName=VodAwsStack
※引数のregionをap-northeast-1に変更しています8. スタックのクイック作成が開いたことを確認
9. パラメータの空欄にStep 7の1で控えた値を入力
10. 機能のチェックボックスにチェック後、【 スタックの作成 】を選択
11. VodAwsStackのスタック名を選択後、出力に表示されている値(赤丸の個所)をメモ帳等に控える
12. step6の1のCloud9ターミナルに戻り、以下のコマンドを実行してsrcディレクトリに移動
コマンドcd /home/ec2-user/environment/VodAws/src/13. step6の1のCloud9ターミナルに戻り、以下のコマンドを実行してsrcディレクトリに移動
コマンドcat << EOF > aws-video-exports.js const awsvideoconfig = { "awsInputVideo": "Step8の11のoVODInputS3の値", "awsOutputVideo": "Step8の11のoVODOutputUrlの値" }; export default awsvideoconfig; EOF13. 以下のコマンドを実行してVodAwsディレクトリに移動
コマンドcd /home/ec2-user/environment/VodAws/■Step9: Hosting our app on Amplify
1. 以下のコマンドを実行してプロジェクトに静的ホスティングを追加
コマンドamplify hosting addプロンプトの選択については下記のとおり。
実行するプラグインモジュールを選択
環境の選択
ホスティングするバケット名の確認(デフォルト)
設定確認
1. 以下のコマンドを実行して静的リソースをAmazon S3およびAmazon CloudFrontに公開
コマンドamplify publish ※continue?についてはYを選択2. 公開が完了するとcloudFrontのURLが表示
3. 以下のコマンドを実行してnpm serverを起動
コマンドnmp start起動確認ができたらContrl+Cで停止(今回はlocalhostの閲覧確認を行わない)
4. ブラウザよりcloudFrontのURLの閲覧
■Step 10: Create Users in Cognito User Pool
1. 別タブにてCognitoダッシュボードに移動
2. 【 ユーザープールの管理 】を選択
3. vodawsse**userpool を選択
4. 【 ユーザーの作成 】を選択
5. 動画公開可能のユーザ作成
今回は【Vodaws 】というユーザー名で作成
電話番号は国番号から入力 例)日本の場合(81)6. 【 グループに追加 】を選択
7. Admin を入力後、【グループに追加】を選択
8. ブラウザより https:// cloudFrontのURL /Admin へアクセス後、ユーザー名(Vodaws)および仮パスワードを入力の上、パスワード変更を実施
9. ログイン後、画像アップロード確認(mp4)
画像アップロード確認後、ログアウト
10. Step10の4の画面に戻り、動画閲覧専用のユーザ作成
今回は【guest】というユーザー名で作成
電話番号は国番号から入力 例)日本の場合(81)11. ブラウザより https:// cloudFrontのURL / へアクセス後、ユーザー名(guest)および仮パスワードを入力の上、パスワード変更を実施
12. ログイン後、Vodawsユーザーがアップロードしたsampleが表示されていることを確認
13. sampleを選択して動画が閲覧できることを確認
- 投稿日:2020-06-23T14:29:07+09:00
AWSにおける最適なDB選択
DBの歴史
要件の変化(2000年~)
RDBMSだけでは様々な要件に対応できなくなり、KVSなど特性を持ったDBが誕生した。
項目 従来要件 新要件 ユーザ ~10万 100万+ データ量 ~TB PB-EB 範囲 社内 グローバル パフォーマンス 秒 マイクロ秒 AWSにおけるデータカテゴリと選択指針
グラフ化や台帳といったカテゴリもあるが、本整理の範囲外。
データカテゴリ Relational Key-value Document In-memory AWS サービス RDS DynamoDB DocumentDB ElastiCache 特徴 参照結合性、ACIDトランザクション 高スループット、低レイテンシー ドキュメント保存し、高速クエリ 超低レイテンシ 選択指針 汎用的なDB、特に要件がなければ… 高スケーラビリティ/数ミリ秒のレスポンスタイム/シンプルなクエリでよい スキーマを決められないデータの格納 ミリ秒未満のレスポンスタイム/キャッシュ利用したい
- 投稿日:2020-06-23T14:29:07+09:00
AWSにおける最適なDB選択指針
本整理の目的
特に頭を使わず、DBならRDSでしょと考えてきた基盤エンジニア(5年目)が適材適所なDB選択を体系的に学びなおしたのでまとめる。
参考は2019年のAWS Summitのセッションより。
https://www.youtube.com/watch?v=h1r8AzOdlqoDBの歴史[要件の変化(2000年~)]
RDBMSだけでは様々な要件に対応できなくなり、KVSなど特性を持ったDBが誕生した。
項目 従来要件 新要件 ユーザ ~10万 100万+ データ量 ~TB PB-EB 範囲 社内 グローバル パフォーマンス 秒 マイクロ秒 AWSにおけるデータカテゴリと選択指針
グラフ化や台帳といったカテゴリもあるが、本整理の範囲外。
データカテゴリ Relational Key-value Document In-memory AWS サービス RDS DynamoDB DocumentDB ElastiCache 特徴 参照結合性、ACIDトランザクション 高スループット、低レイテンシー ドキュメント保存し、高速クエリ 超低レイテンシ 選択指針 汎用的なDB、特に要件がなければ… 高スケーラビリティ/数ミリ秒のレスポンスタイム/シンプルなクエリでよい スキーマを決められないデータの格納 ミリ秒未満のレスポンスタイム/キャッシュ利用したい
- 投稿日:2020-06-23T14:00:09+09:00
ターミナルからAWS EC2へ〜シャットダウンまで
こんにちは
今回からマークダウンも併用していこうと思います。
スライドの利点とマークダウンの利点をうまく使い分けしていきたいです。今回も"触ってみた"系の記事なんですが、
macターミナルからAWS EC2へ入って、起動中のEC2をシャットダウンする
までの一連にトライしたので、そちらを記します。
今まで通り、自分がつまずいた箇所を明記しておきたいので、
そちらは斜体太字で記すようにしていきます。
また本記事は書籍AWSをはじめよう ~AWSによる環境構築を1から10まで~
を参考にしています。EC2サーバを立てる@AWSマネジメントコンソール
一連の作業は済んでますので、ざっくり手順ベースで振り返ります。
手順
- IAMユーザでAWSマネジメントコンソールにサインイン
- 「サービス」から「EC2」を選択
- 「インスタンスの作成」を押下
- 「Amazon Linux」を選択
- 「t2.micro」を選択(無料利用枠を活用するので)
- EBS/タグは活用しないのでスキップし、「SG」の設定
- 「起動」
- キーペアの作成(1度切り!)
- 「Name」からインスタンスに命名
- 「インスタンスの状態」が「runnning」であることを確認
上記の手順自体は恙無く進みましたが、気になっているのは6.「SG」関連です。
今回はすぐにシャットダウンするEC2インスタンスでしたので特に設定せず、
上記メッセージが出てくる状態。SLA次第だとは思いますが、
具体的に
・セキュリティの詳細設定の方法
・どんなセキュリティレベルをどういうサービスに設定するのか
を判断できるようになる必要があります。今後の課題です。あとインスタンタイプも同じく、とりあえずt系(無料枠ですし)選んでますが
なぜそのインスタンスタイプを選択するのかの判断ができるよう、別途深堀ります。macターミナルからEC2に入る〜サーバ停止
こちらも手順ベースで。
手順
- macにてターミナル起動
- chmodで、キーペアファイルに対する読み書き制限の厳格化
chmod 600 ~/(キーペアファイル格納場所)
- 対象EC2インスタンスをIPアドレスで指定しつつ「-iオプション」で利用する鍵を指定
ssh ec2-user@(IPアドレス) -i ~/(キーペアファイル格納場所)
- 初回サーバ接続時の信頼性確認
yes
を返す- シャットダウンコマンドの実行
sudo shutdown -h now
- AWSマネジメントコンソールから、状態の「stop」を確認
実際の画面がこちら。
ちょっと打鍵ミスしてやり直しましたけど手順自体は問題なく進みました。
課題になったのはコマンド慣れしていないのでsudoや-i、-hなどを調べながら実施したことです。
sudo : rootユーザに成らなくてもrootユーザの権限で処理を実行できるコマンド
オプションは調査中。その辺がわからないと自在にはできないかな。。。あとがき
シャットダウンまでの一連の流れ自体で(打鍵ミス以外は)詰まるところもなく、流れました。
しかし、大事なのは途中斜体太字で書いているような「なぜ」の部分だと思いますので、
その辺り、もう少し掘っていきたいと思います。
- 投稿日:2020-06-23T11:56:01+09:00
AWS☆☆☆☆ デプロイまでの道のり4-最終章(短いバージョン、全4回)
1)背景
第4回目の最終章です。
自身のポートフォリオをデプロイしました。最後の作業としてドメインの紐つけをします。
AWS関連手順記事はすごく多いので、ここでは備忘録も含めて、非常に端的に手順を記載します。2)環境
項目 内容 OS.Amazon Linux AMI release 2018.03 Ruby v2.5.1 Ruby On Rails v5.2.4.3 MySQL v5.6 Unicorn v5.4.1 3)内容
以下設定で65分程度かなと思います。(段取りが分かっていれば、30分)
※【ローカルマシン】指定以外は、全てAWSでの作業になります。(1)お名前ドットコムからドメインを取得(20分)
同サイトからドメインを契約します。ここについては割愛いたします。
(2)Nginxの導入と設定(20分)
- yumパッケージを活用してNginx(webサーバ)を導入する
- Nginxのconfigファイルを設定する
- Nginxのパッケージ権限の付与(/var/lib/nginx)
- Unicorn設定ファイルの変更(Nginxを経由して処理を行うために設定)
(3)AWS-Route53の設定(10分)
- ホストゾーンの新規作成
- 新規レコードセットに同ElaspicIPを登録する
(4)お名前ドットコムの設定(15分)
- AWSで新規に割り当てられたNSレコードをネームサーバ名として登録する
- DNS設定(ElaspicIPと、ドメインの紐付けを行う)
(2)Nginx設定2(10分)
- 登録したドメイン名を同設定ファイルに設定する。
これで完了です。
指定のドメインにアクセスすると、NGINXを介してUnicornが起動しているrailsアプリを参照することが出来ます。
正直簡単です。出来るだけ難しく書かないように端的に記載しました。
以上です。
- 投稿日:2020-06-23T11:39:45+09:00
AWS 基礎
前提
AWS(クラウドプラットフォーム)について学んだことを書いていきます。
本題
巨大クラウドプラットフォーム
では、クラウドサービスの次にAWSついて書いていきます。
世界15箇所で提供されるクラウドサービス
展開されている地域のことを
リージョン
と言います。
AWSの利用者は、これらの好きなリージョンに、仮想サーバーや仮想ネットワークなどを構築して運用できます。
居住国とリージョンとは関係ありません。
日本国内に住んでいても、バージニア北部などの米国のリージョンを使うこともできます。
とはいえ、地理的に近いリージョンほどネットワークのレスポンスが速いため、日本国内から利用する場合には、東京リージョン(ap-northeast-1)を使うことがほとんどです。東京リージョン以外を使う理由
・東京リージョンでは、まだ提供されていないサービスを使いたい
・東京リージョンよりも、安く運用したい
・東京リージョンが万が一異常を起こした時のバックアップとして、別のリージョンに設置したいAWSでは100以上のサービスが提供されている
AWSでは特にマネージドサービスが充実しています。
AWSでよく使われるサービス
基本的にこれだけ理解すれば、オンプレミスで実現していたのと同じ、ほとんどの業務システムを構築できるはずです。
データはリージョン間を勝手に移動しない
AWSで仮想サーバーなどを構築するときには、どのリージョンに作成するのかを初めに決めます。
リージョンを1度決めると、そのサーバーが他のリージョンに勝手に移動することはありません。
そのため、国外に持ち出してはいけないデータを運用する場合も、東京リージョン上のサーバーで運用すれば問題ありません。AWSのデメリット
主なデメリットは次の2つですが運用の工夫で解決できます。
1、定額での運用ができない
AWSは従量課金であるため、定額での運用ができない点が運用上のデメリットとしてよく挙げられます。
情報システムでは予算を確保して運用することも多いため、AWSを使いたいと思っても「いくらかかるかわからない」のでは、社内決裁が降りない、取引先の理解が得られないことも多いでしょう。
しかし、AWSにはAWS簡易見積もりツールが提供されており、高い精度で、どのぐらいの金額がかかるかを予測できます。
予測しにくいのが、「ネットワークトラフィック」ですが、「1ユーザー当たり、平均でどのくらいのデータを送受信するか」を実測し、それに想定されるユーザー数を掛け算すれば、想定から大きくかけ離れた値になることはありません。2、自分で全てをコントロールできなくなる
そして次によくある問題が、AWSに運用管理を任せるので、完全に自分でコントロールできなくなってしまうという点です。
これは、主に次の3つ問題(不安)に分けることができます。・データ流出の問題
まず、AWSにデータを預けることになるので、データの消失や流失が起きないかが心配になります。
しかし、AWSでは各種プライバシー認証・コンプライアンス認証をとった環境で運営されており、設定のミスや各種攻撃などに注意すればAWSを使っただけでデータが筒抜けということはまず起こりません。
もちろん、オンプレミス同様にアクセス情報を秘匿するといった対策は必須です。・AWSの大規模障害
次に危惧されるのがAWS自体の大規模障害です。
社内の基幹システムをAWSで運用する場合、万一、AWSが停止した時は、社内業務が停止する恐れがあります。
オンプレミスでの運用ならエンジニアを派遣して、ひとまず暫定復旧を始めることまでできますが、AWSの場合は、AWSに任せて復旧を待つよりほか方法がありません。
もし本当に停止すると業務を打撃するようなシステムの場合は、AWSを利用しない、もしくは、AWSとオンプレミスを併用して、AWSが止まったときにはオンプレミスに切り替えられるようにするなど対策が必要です。
可用性や今までの障害情報などを適切に収集し、AWSを通信しない体制を構築しておくことは必要です。・サービスがいつまで提供されるか
最後に、いつまで(個別の、あるいは全体の)サービスが提供されるのかという問題もあります。
もし、サービスが終わってしまうと、別のシステムに作り替えなければいけません。
こうした懸念を避けるには、多数のユーザーが使っているサービスだけで構成するあまりAWS独自のアンマネージドサービスに依存した作りにしないといった設計上の考慮が大事です。AWSを過信しない
AWSは管理運用コストを減らせる、サービスを迅速に増強できるなど、数多くのメリットがあります。
これらの面ではオンプレミスのサービスの利便性を完全に上回ります。
可用性やセキュリティについての懸念もありますが、AWSではこれはかなり高水準で保たれています。
利用企業、団体のリストを見れば信頼性の高さがうかがえます。
コスト面でも、いくつかのケースではオンプレミスよりも優れているでしょう。
初期費用をかけられないようなケースでは、設備投資不要で必要な時だけ費用が発生するAWSは強い見方となります。
しかし、過信は禁物です。
クラウドサービスだからサービスが安定する、安全になる、安価になる訳ではありません。IAMユーザー
サインインしているAWSアカウント(ルートユーザー)は、AWSに対する全ての操作のほか、支払い方法の変更や解約など、契約に関する操作もできる強力なアカウントです。
万が一、漏洩すると被害が大きくなります。
そこで、AWSアカウントは、そうした特殊な操作が必要な時にだけにしか使わないようにし、普段のAWS操作には、別アカウントを作成して、そのユーザーを使って操作するようにします。
AWSを操作できるユーザーのことをIAMユーザーと言います。アクションとポリシー
AWSにおける各種操作は、アクションと呼ばれる単位で構成されています。
例えば、仮想サーバーを作成できるアクション、仮想サーバーを実行できるアクション、ストレージを読み込みできるアクション、ストレージを読み書きできるアクションなどです。
アクションは、とても数が多く、一つ一つ設定すると煩雑なばかりか、設定漏れも生じやすくなります。
そこでAWSでは、一つ一つ権限を設定するのではなく、あらかじめ目的ごとにアクションをグループ化したポリシーと呼ばれるものをIAMユーザーに適用することで、ユーザーが操作可能な権限を付与します。
ポリシーは自分で作ることもできますが、既存のポリシーがたくさん用意されています。
例えば、仮想サーバーに関する全ての操作ができるポリシー、仮想サーバーの新規作成や削除、設定変更などはできないが、実行や停止はできるポリシー、ストレージに関する全ての操作ができるポリシー、ストレージに関する読み書きができるポリシーなどです。
IAMユーザーに対して、このしたポリシーを複数適用すると、それらのポリシーで許可されているアクションが操作できるようになります。・IAMグループ
IAMグループは、IAMユーザーをグループ化して権限設定する概念です。
複数のユーザーに対して、同じ権限設定をしたいときに使います。・IAMロール
IAMユーザーがユーザー(人間)に対するアカウントなのに対し、IAMロールはAWSのリソースに対するアカウントです。
例えば、仮想サーバー(EC2)から、ストレージやサービス(S3)にアクセスする場合、IAMユーザーで管理しようとすると、EC2のプログラムに、S3にアクセスするためのユーザー名やパスワード(より正確に言うとIAMの設定で作成できるアクセスキーやシークレットアクセスキー)を使って認証する必要があります。
しかし、AWSではそうする代わりにS3にアクセスできるIAMロールを作成しておき、そのIAMロールをEC2に適用すると、それだけでアクセスできるようになります。
このように、あるサービスから、別のサービスにアクセスしたい時、アクセス元のサービスに対して設定して使うのが、IAMロールです。
- 投稿日:2020-06-23T10:38:33+09:00
QRコード読み取り(ZBar)
ZBar bar code reader
を使う。まずはインストール
OS「Amazon Linux AMI」の場合
yum install -y zbar-toolsOS「Linux version XXX.amzn1.x86_64」の場合(2014年から使っているEC2)
yum install zbar-devel
pip install zbar
or
/usr/local/bin/pip2.7 install zbar
※Python3系だと動かないので2.6or2.7でインストール
Python3系の場合は↓これを入れると出来るらしい.
https://github.com/zplab/zbar-py実行
zbarimg qr.png
QR-Code:http://aaaaa/ddddd.htmlurlもいける便利
zbarimg https://wwww.sample.com/qr.png
QR-Code:http://aaaaa/ddddd.html時間がないので後日記事修正
- 投稿日:2020-06-23T08:32:15+09:00
【22時間で合格】 SAA-C02 AWS認定ソリューションアーキテクト-アソシエイト合格NRTA【多分これが一番早いと思います】
概要
SAA-C02受験、はーじまーるよー。
というわけで昨日2020/06/22、SAA-C02版のAWS認定ソリューションアーキテクト-アソシエイトに合格したので、私がどんな勉強をしたのか、どんな問題が出たのかなどをお伝えできればと思います。
前提として、私は2018年末にクラウドエンジニアとなってから、AWSのアーキテクチャなどについてはあまり触っていません。CLIでいくつかのサービスを自動的に設定するような実装を何度かしたことがある程度で、基本的には業務の自動化をメイン業務としていました。また、昨年3月にクラウドプラクティショナーを取得しています。
今回は有料アイテムを使ったコストパフォーマンスチャートを使用します。
途中ガバって時間を割いてしまったところがありますが、実際にはやらないほうがいいと思います。レギュレーション
・勉強した時間と試験時間のみ計測を行います。
・その他日常生活時間は含みません。(Not Real Time Attack)
・今回は縛りプレイではないので、有料アイテムを使用します。
・前作のクリア報酬を使用します。
・タイムセールを使用します。攻略チャート
勉強内容
1.黒本
リンク 3h 2618円
3時間くらいでとりあえず一通り読んで章末問題を回答しました。
古い本なので試験に直接役立つことはなかったですが、おおざっぱにベースとなる知識を仕入れられるという意味ではよかったかもしれません。
付属の模擬テストは面倒だったのでやりませんでした。2.ウェルアーキテクトフレームワーク
リンク 1h
本日のガバプレイ枠です。
しばらく読んで資格の役に立たなそうだったので読むのをやめました。
実際に実務で構築する際は何をしなければならないかのチェックリストになりそうな内容なのでよいと思いますが、この内容は踏み込みすぎという印象を受けました。3.模擬試験(udemy)
リンク 16h 1610円
1回分につき回答40min-1h、復讐1hくらいのペースで1回ずつ解きました。
また、そこで得た内容を整理するのに2hくらいかけました。
以下はその結果です。初回 ①(基礎知識)の正答率72% 初回 ⑥(高難易度)の正答率40% 初回 ②(高難易度)の正答率56% 初回 ③(高難易度)の正答率66% 初回 ④(高難易度)の正答率56% 初回 ⑤(高難易度)の正答率52%(当日の朝解いた)何週もするのは問題を暗記する効果しかないと思うので、1回ずつだけやりました。
普通に難しくて、試験前はめちゃくちゃ不安になりました。
とはいえこの模擬テストは新版対応をうたってるだけあって試験対策としてとても良いと思います。
ここに出てくる問題でわからなかったものを調べるのを繰り返していれば、本試験でも十分な知識が身についているはずです。
本試験はこの内容の半分かもうちょいくらいの難易度だと思っていいです。
めっちゃ簡単に感じました。4.AWS Solutions Architect - Associate Practice
40min 2000円→無料(クラウドプラクティショナー合格特典)
本日のガバプレイ枠その2です。
AWSが用意した公式模擬問題25問くらい
試験前日に解いたら結果が届いたのは本試験結果と同時だったので正直そんなに意味はなかったです。
Udemyの模擬問題のほうが安くて量が多くて解説もあって答え合わせもしやすくてよいので割と無駄です。
無料ならとりあえずやってみてもいいかな。試験
使用した時間 1h20min 15000円→7500円(クラウドプラクティショナー合格特典)
テストセンターで受験しました。
現在は自宅で受験も可能なようですが、英語でのやり取りが必要なのと壁にポスターはってあったりするだけでもダメなようなので、やめました。
実はコロナの影響で腰痛がやばくて毎週注射三本うってるんですが、テストセンターでは問題より痛みと戦うほうがつらかったです。
めちゃくちゃ慎重にといても試験時間の半分くらいで終わります。
Udemyの模擬試験やってると、サービス問題が多いなと感じるはずです。
また、出題傾向も近いですし、全く同じような内容が試験として何問かありました。内容としては「こういう構成と背景があるんだけど」という前提のもと、「こういう状況で何を使う?」「どういう組み合わせでこれを実現する?」「このポリシー読める?」「サービスの特徴は?」みたいなことを聞かれまくります。
Udemyとの難易度の差は、サービスの概要くらいを知っていれば消せる選択肢が多くあって消去法でも解ける問題が多いことと、必要とされる理解度がもう少し浅くなることでしょうか。クリアにかかったコスト
時間 : 22h
お金 :11728円(特典なしの場合:21228円)おわりに
総勉強時間、コスト共にかなり抑えることができました。
時間だけでもこれの4倍くらいかけるかたも多いのではないでしょうか。
実際にはほぼUdemyの模擬試験だけで受かるという方も多い気がします。
多分これが一番早いと思います。アソシエイト取ろうとするときに最初どんな勉強方法でやるかって皆さん悩まれると思うんですけど、や「ウェルアーキテクト」だの「黒本・青本・アクセンチュア本」だの「主要サービスのよくある質問」だの「ハンズオンコンテンツ」だの「ホワイトペーパー」だの「無料トレーニング」だの「有料トレーニング」だのといろいろ方法はあるし、特にサービスごとにブラックベルト読めみたいな話はよくあると思います。
私はブラックベルトちゃんと読んだことないのでいいのかわかりませんが、AWSよくわからんしサービス使ってみてるわけでもない人がただでさえ出題範囲が広いサービスのさらに個別の詳細資料読めっていわれるといろんな概念知らないと理解しにくく難しく、「めんどくさいなー」と思うんじゃないかと思います。というか僕はブラックベルト読んだほうがいいよと助言をいただいたのですが、面倒だなぁと思ってやりませんでした。
安心してください。ブラックベルト読まなくても受かります。
以下、完走した感想ですが、勉強してる間は「こんなにさぼっていいんだろうか」と思いながらやってました。実際最初は上にあげたようないろんな資料を参照してめっちゃ勉強しなきゃと思っていたのですが、業務以外にもAWSエンジェル道場に参加していることもあって時間があまりなく、途中で効率重視に切り替えました。正直やってよかったと思いますが、あくまでそれは実務でAWSを触る前提の話です。もし受験される方が実務経験がない方なら、単純な試験対策は仕事になった時に苦労すると思います。この場合、ハンズオンで触りながらゆっくりやるといいと思います。
以上、ありがとうございました。
- 投稿日:2020-06-23T08:19:48+09:00
[AWS]VPCの設計の考え方
VPCとは
・Virtual Private Cloudの略で、AWSアカウントを作成するとデフォルトで作成される。
・ネットワーク的に分離された領域。インターネットGWをアタッチしないと外と通信もできない。
・FWはセキュリティグループと呼ばれるもので制御する。
・VPCの中にサブネットを作成し、セグメント単位での管理が可能
・ルートテーブルでルーティング制御ができるシングル?マルチ?
一つのアカウントで2つ以上のVPCを作ったり、複数アカウントで複数のVPCを作るというケースもあります。
まず、シングルのVPCの場合、全ての環境が一つの空間に作られます。
マルチでVPCを作成する場合は、本番環境、ステージング環境でVPCを分けるパターンがあります。VPCの設計はアカウント設計に関連します。
例えば、アカウントをシステムごとに分ける、であれば
Aシステムのアカウントに、本番/ステージング/開発でVPCを分けるケースが考えられます。
他にも、アカウントを環境ごとに変える、であれば
本番環境のアカウントには、AシステムのVPC、BシステムのVPCという分け方も考えられます。VPCを分けることのメリデメ
一番大きいのは、リスクを分断できるという点です。
後述しますが、一つのVPCに本番や検証環境が混在していると、誤操作のリスクもありますし
何かしらの攻撃で侵入を許した場合、同一VPCは影響を受けてしまいます。
なので、セキュリティの面からも環境毎にネットワークを分離することをオススメします。逆にデメリットですが、VPCが増えすぎると管理がしづらいというのがあります。
VPCピアリングの設定が複雑になってきます。
ですが今はTransitGatewayというものがあるので、そちらを活用すればそのデメリットは軽減されます。VPCの設計注意点
IPアドレスの範囲に気をつける
VPCを作成する際に使用するIPの範囲は一般的には以下を指定します。
10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255気をつけないといけないのは、VPCピアリングなど別のVPCと繋ぐ場合にIPアドレスの範囲が重複していると対応できません。
よくある構成として、環境毎、あるいはシステム・環境毎にアカウント、VPCを分ける場合
以下が参考になりましたので、リンクを貼っておきます。
AWS導入前に知っておきたかった「VPC設計」VPCピアリングの特徴
異なるVCP同士を繋げるVPCピアリングという方法があります。
これは以下の注意点があります。
・IPアドレスの重複がないこと
・同じリージョンであること
・二つ先のVPCには直接通信ができない。
→VPCがA,B,Cとあった場合でVPCピアリングをAとB、BとCとしている場合、
AとCは直接通信ができない、という制約があります。
なので、社内でVPCが増えていくようなアカウント・VPC設計をしているのであれば
VPCピアリングを使用するよりも、TransitGatewayで集約した方がいいです。これだけは最低限考慮する
昔は1アカウント1VPCなんていう考えもあったのかもしれませんが、以下の観点では最低限分けた方がいいです。
・環境(本番、ステージング、開発)でVPCを分ける
→いったん攻撃を受けてしまったら、同一VPCは影響を受ける可能性が非常に高い
・レイヤー(WEB、DB、フロント(LB))はサブネットで分ける
→インターネットとの接続点は明確に最小限に分けておく最後に
AWS案件に携わってまだ1ヶ月のレベルなので、指摘や意見などあればどんどんコメントいただけるとありがたいです。
- 投稿日:2020-06-23T00:48:06+09:00
(Mac)AWS Cloud9テキストエディタのショートカットキー
controlキー(^)主体
ショートカットキー 意味 ^ + w テキスト内のコードを
折り返して表示する。^ + t カーソルの左の文字を
右へズラす。^ + @ インデントを左へ
(shift+tab)と同じ^ + g 単語を選択、
2回目以降は他の
同じ単語を選択する^ + a 行の先頭へカーソルを移動 ^ + u 単語を大文字に変換 ^ + o 行を挿入 ^ + ] インデントを右へ ^ + v 一番下の行へ
カーソルを移動^ + n 新規のテキストエディタを開く optionキー(⌥)主体
ショートカットキー 意味 ⌥ + t 新規ターミナルを開く ⌥ + s ターミナルから
テキストエディタに
カーソルをとばす他のキーは記号を打ち込める。
commandキー(⌘)主体
ショートカットキー 意味 ⌘ + _ エディタ画面全体を縮小 ⌘ + m ウィンドウを最小化する ⌘ + ] オープンファイルを
切り替える
(右のファイルへ)⌘ + ] オープンファイルを
切り替える
(左のファイルへ)⌘ + > ショートカットキー
コマンド一覧を表示⌘ + < setting画面を表示 ⌘ + o ファイル一覧を表示 ⌘ + i オープンファイル一覧を表示 ⌘ + u treeビューの表示・非表示 ⌘ + a テキストエディタ上で
全てを選択他にもわかったことがあれば追記します。
- 投稿日:2020-06-23T00:35:49+09:00
クラウド認定資格について整理する (AWS / Azure / GCP)
私の所属する会社の部門では、クラウド認定資格を取得しよう、というムードが高まっています。クラウド認定資格について調べる担当となったので、大手3クラウドについて認定資格を調べてみました。なお金額はざっくり円換算しています。2020年6月時点でのまとめとなります。
AWS
まずは王道のAWS認定資格となります。 12個の資格があります。AWS Certifications というようです。
まとめ
- 入門編 (約1.1万円/90分):
- Cloud Practitioner
- 一般編 (約1.5万円/130分):
- Solutions Architect Associate
- Developer Associate
- DevOps Administrator Associate
- 応用編 (約3万円/180分):
- Solutions Architect Professional
- DevOps Engineer Professional
- 専門編 (約3万円/180分):
- Advanced Networking Specialty
- Security Specialty
- Machine Learning Specialty
- Alexa Skill Builder Specialty
- Data Analytics Specialty
- Database Specialty
参考
AWS 認定
https://aws.amazon.com/jp/certification/Azure
次にAzure認定資格です。少しややこしいのですが試験に合格しないと認定資格を受験できないようです。MCP (Microsoft Certification Program) というようです。5つに整理されたようなのですが、ロールごとにもっと細かく試験は準備されているようです(パブリッククラウド認定資格まとめ に整理されています)。
まとめ
- 入門編 (約1.25万円/90分):
- Azure Fundamentals (AZ-900)
- 一般編 (約2.1万円/180分〜210分):
- Azure Administrator Associate (AZ-104)
- Azure Developer Associate (AZ-204)
- 応用編 (約2.1万円/210分):
- Azure DevOps Engineer Expert (AZ-400)
- Azure Solutions Architect Expert (AZ-300, AZ-301)
- 専門編 (約2.1万円/210分):
- -
参考
【Azureの資格2019年版】Azureの認定資格とクラウド初心者におすすめの資格をご紹介
https://www.fenet.jp/infla/column/technology/66/
Azure関連のMCP試験と認定資格 ~2019年版~
https://blog.nextscape.net/archives/Date/2018/12/mcp2019
パブリッククラウド認定資格まとめ AWS / Microsoft Azure / Google Cloud
https://qiita.com/nakazax/items/47a22b3ca3280a0f9891GCP
最後に、GCPです。だいたいAWS、Azureと同じような認定があるようです。7つありました。言語ごとに個別の Google Cloud Webassessor アカウントが必要とのことです。Google Cloud Certified と言うのが共通の呼び名?のようです。
まとめ
- 入門編:
- -
- 一般編 (約1.6万円/120分):
- Associate Cloud Engineer (JPN)
- 応用編 (約2.1万円/120分):
- Professional Cloud Architect (JPN)
- Professional Data Engineer (JPN)
- Professional Cloud DevOps Engineer
- Professional Cloud Network Engineer
- Professional Cloud Security Engineer
- Professional Collaboration Engineer (JPN)
- 専門編:
- -
参考
認定資格取得のための登録
https://cloud.google.com/certification/register?hl=jaそれでは全員全冠目指してがんばるぞ。
- 投稿日:2020-06-23T00:15:05+09:00
AWS CodeBuild で Jenkins では成功していたファイルディレクトリの権限系のテストをするとなんかうまくいかない
この記事を書くに至った経緯
私が開発しているチームでは、Jenkinsでビルド・テストを行っていました。
色々と環境をAWSに載せ替えていく中で、AWS CodeBuildを使用することになりました。
ところが、ReadOnlyに設定したファイルにWriteができてしまうではないですか!
これはどうして、ということで調べた結果、わかったことがあります。何が原因だった?どうやって解決した?
CodeBuild内ではデフォルトではroot権限で実行されます。公式のドキュメントにそう記載されています。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/troubleshooting.html#troubleshooting-root-build-commands今までビルド・テストを行っていたのはオンプレCIサーバ上のJenkinsです。
JenkinsではJenkinsユーザでビルドコマンド等が実行されていました。じゃあnon-rootなユーザをadduserしてそのユーザで実行してあげればいいかな、とも思ったのですが、
CodeBuildのDockerFileを読むとcodebuild-user
なるユーザがいることに気がつきました。https://github.com/aws/aws-codebuild-docker-images/blob/master/al2/x86_64/standard/2.0/Dockerfile
こちらの42行目にRUN useradd codebuild-user
と書かれています。じゃあ、それを利用してあげればいいんじゃない?ってことで、やってあげると無事に成功しました。
教訓
- ビルドやテストを行っているユーザがどういう権限を持っているのかを把握するのは大切
- 公式のDockerImage(というか公式の何かしら)に書かれていることを少しでも把握することは問題解決の一歩となる
- 今回は答えだったけど
- 投稿日:2020-06-23T00:15:05+09:00
AWS CodeBuild で オンプレのJenkins では成功していたファイルディレクトリの権限系のテストをするとなんかうまくいかない
この記事を書くに至った経緯
私が開発しているチームでは、Jenkinsでビルド・テストを行っていました。
色々と環境をAWSに載せ替えていく中で、AWS CodeBuildを使用することになりました。
ところが、ReadOnlyに設定したファイルにWriteできないことをテストすると失敗しているではないか!
これはどうして、ということで調べた結果、わかったことがあります。何が原因だった?どうやって解決した?
CodeBuild内ではデフォルトでroot権限で実行されます。公式のドキュメントにそう記載されています。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/troubleshooting.html#troubleshooting-root-build-commands今までビルド・テストを行っていたのはオンプレCIサーバ上のJenkinsです。
JenkinsではJenkinsユーザでビルドコマンド等が実行されていました。じゃあnon-rootなユーザをadduserしてそのユーザで実行してあげればいいかな、とも思ったのですが、
CodeBuildのDockerFileを読むとcodebuild-user
なるユーザがいることに気がつきました。https://github.com/aws/aws-codebuild-docker-images/blob/master/al2/x86_64/standard/2.0/Dockerfile
こちらの42行目にRUN useradd codebuild-user
と書かれています。じゃあ、それを利用してあげればいいんじゃない?ってことで、やってあげると無事に成功しました。
教訓
- ビルドやテストを行っているユーザがどういう権限を持っているのかを把握するのは大切
- 公式のDockerImage(というか公式の何かしら)に書かれていることを少しでも把握することは問題解決の一歩となる
- 今回は答えだったけど
- 投稿日:2020-06-23T00:15:05+09:00
AWS CodeBuild において オンプレのJenkins では成功していたファイル権限系のテストをするとうまくいかない
この記事を書くに至った経緯
私が開発しているチームでは、Jenkinsでビルド・テストを行っていました。
色々と環境をAWSに載せ替えていく中で、AWS CodeBuildを使用することになりました。
ところが、ReadOnlyに設定したファイルにWriteできないことをテストすると失敗しているではないか!
これはどうして、ということで調べた結果、わかったことがあります。何が原因だった?どうやって解決した?
CodeBuild内ではデフォルトでroot権限で実行されます。公式のドキュメントにそう記載されています。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/troubleshooting.html#troubleshooting-root-build-commands今までビルド・テストを行っていたのはオンプレCIサーバ上のJenkinsです。
JenkinsではJenkinsユーザでビルドコマンド等が実行されていました。じゃあnon-rootなユーザをadduserしてそのユーザで実行してあげればいいかな、とも思ったのですが、
CodeBuildのDockerFileを読むとcodebuild-user
なるユーザがいることに気がつきました。https://github.com/aws/aws-codebuild-docker-images/blob/master/al2/x86_64/standard/2.0/Dockerfile
こちらの42行目にRUN useradd codebuild-user
と書かれています。じゃあ、それを利用してあげればいいんじゃない?ってことで、やってあげると無事に成功しました。
教訓
- ビルドやテストを行っているユーザがどういう権限を持っているのかを把握するのは大切
- 公式のDockerImage(というか公式の何かしら)に書かれていることを少しでも把握することは問題解決の一歩となる
- 今回は答えだったけど