- 投稿日:2020-07-21T23:21:39+09:00
AWS Cloud9 でダークフラットテーマを使用する方法
サンプルコード
- user.settings のサンプルをGitHub で晒しているのでタイトルでピンとくる方は適当にコピーして利用してください
- https://github.com/k-yone/aws-cloud9-dark-flat-theme
- 以下詳細
Cloud9 のフラットテーマはlight しかない?
- Cloud9 のsetting GUI 上からはフラットテーマの選択肢が一つしか表示されていません
![]()
- 旧UI ではダークフラットテーマが選択できたため,そちらに慣れているユーザや,
VS Code を代表としたモダンなエディタに目が慣れているユーザにとってはちょっと気分が悪いですuser.settings で直接指定するとdark flat テーマが指定できる
- USER SETTINGS タブから,設定ファイルを直接編集するモードに移ります
![]()
- 以下のようにgeneral.@skin フィールドに
"flat-dark"
を指定すると隠れたダークフラットテーマが指定できます- 隠しコマンドみたいでちょっとわくわくしますね
user.settings{ "general": { "@skin": "flat-dark" } }console もダークテーマに
- 再掲ですが私が設定しているuser.settings をGitHub にさらしているので真似たい部分だけコピーして活用してください
- https://github.com/k-yone/aws-cloud9-dark-flat-theme
- 投稿日:2020-07-21T20:00:38+09:00
Equinix Network Edge で Oracle Cloud とAWSを接続してみてみた
Equinix Network Edgeは、相互接続できる仮想ネットワークサービスです。
ハードウェアを追加購入することなくメトロを選び、エッジデバイスの選択と展開、Equinix Cloud Exchange Fabric™(ECX Fabric™)への接続を数分で行うことができます。
ネットワークエッジでは、Cisco、Juniper Networks、Fortinet、Palo Alto Networksなどのプロバイダーのネットワークおよびセキュリティデバイスを選択、設定し他の市場のネットワークプロバイダーやクラウドに接続できます。
ということで、Oracle Cloud Infrastructure(OCI) と AWSを接続してみてみます。
そしてついでに、OCIの Public Service である、Object StorageなどはTransit Routing設定すれば、Private PeeringでAWSとFastConnect経由で疎通できるのでやってみてみます。■ 構成イメージ
Equinix Network Edge のCisco CSR1000V を使用してOCI とAWS を接続します
OCIとAWSの設定は事前に行っておき、ここでは、Equinix EdgeとOCI FastConnect、AWS Direct Connectの設定を行います。
OCIのTransit Routing設定は次を参考として事前にVCN,DRG,ルート・テーブル,セキュリティリストなど作成しておきます
・参考: Transit Routing + IPSec VPN / FastConnectで Object Storage, Autonomous Databaseへ接続してみてみた■ Equinix Cloud ExchangeコンソールLOGIN
Equinix Cloud ExchangeポータルへLoginします
① Equinixホームページ
https://www.equinix.co.jp/services/edge-services/network-edge/ ページから、右上にある[ログイン]から[Equinix Cloud Exchangeポータル]をクリック② Equinix Cloud Exchangeポータル 選択
■ Equinix Network Edge Virtual Device作成
Equinix Network EdgeのVirtual Deviceを作成します。
ここでのVirtual Deviceは、Cisco CSR100Vを選択します。(1) Create Virtual Device
[Network Edge] > [Create Virtual Device]をクリック(2) Select Vendor Packages
ここで、CISCO, Juniper vSRX , Fortinat Fotigateを選択できます
ここでは、'Cisco CSR 1000V'を選択し,[See Description]をクリック(3) Cisco CSR 1000V
[Select and Continue]をクリック
(4) Select Edge Location
Edge Deviceの Metoro(ロケーション)を選択
ここでは、'Ashburn'を選択
(5) Device Deetails
以下内容を入力し、[Next Additional Services]をクリック・Edge Device - Device Name: Webコンソールに出力する名前 - Host Name Prifix: Deviceホスト名 ・Device Status Notifications - email address(es): Notification Mailを受信するアドレス ・Software Pakage A version - Software Pakage: Pakageタイプ - Version: Version ・Select License Throughput: 帯域を選択(6) Additional Services
Virtual Deviceの SSHユーザー、IPアドレスを必要に応じて追加設定し、[Next Review]をクリック
(7) Create a Cisco CSR 1000V(3)
Terms & COndition項目にある [Order Trems]をクリック
(8) Review and Submit
内容を確認し、Terms & Conditionsにある [order Terms]をクリック
(9) Terms & Conditions
記載されている契約事項を確認し、問題なければ、[I Have read and understand these terms]チェックし、[Accept]をクリック
(10) Terms & Conditions Accepted
[Create Edge Device]をクリック
(11) Your Edge Devices(s) were created and are being provisoned
View your device in your dashboardにある[Go to the Edge Device]をクリック■ Equinix Network Edge と OCI FastConnect接続
● OCI FastConnect 作成
OCIコンソールへログインし、Equinix Cloud Exchangeへ接続するFastConnectを作成します
(1) FastConnect画面
OCIへログインし、リージョンを選択、ここでは[US East(Ashburn)]を選択
[ネットワーキング] > [FastConnect]画面へ遷移し、
[FastConnectの作成]をクリック(2) 接続の作成:接続タイプ
以下設定を行い、[次]をクリック・接続タイプ:[Oracleプロバイダの使用]を選択 ・プロバイダ: [Equinix:CloudExchange] を選択(3) 接続の作成:構成
以下設定をおこない[作成]をクリック・名前: 抵当な名前を設定 ・コンパートメント: 作成するコンパートメントを選択 ・仮想回線タイプ: [プライベート仮想回線]を選択 ・動的ルーティング・ゲートウェイ: DRGを選択 ・プロビジョニングされた帯域幅: 帯域を選択 ・顧客GBP IPアドレス: Equinix側 BGPアドレスを設定 ・ORACLE BGP IPアドレス: OCI側 BGPアドレスを設定 ・顧客GBP ASN: Equinix側 BGPアドレスを設定(4) FastoConnect作成完了
OCIDを[コピー]しておき、Equinix Edge画面で接続設定するときに使用して接続します
● Equinix Edge Create Connection to OCI
作成したOCI FastConnectと Equinix Edgeの接続設定をします
(1) Virtual Device画面
作成したEdge Device画面にある[Connections]をクリック
(2) I want to connect to:
Frequent Connectionsより、[Oracle Cloud]をSelectし、[Oracle CLoud Infrastructure-OCI-FastConnect]の[Create COnnection]をクリック
(3) Select Locations
以下設定を行い、[Next]をクリック・Select Location: [Ashburn]を選択 ・Virtual Device in Ashburn: [CSR1000v]を選択 ・Destination: Ashburn]を選択(4) Connection Details
以下入力し、[Next]をクリック・Connection information: コンソール表示する名前を設定 ・VIrtual Circuit OCID: 作成したFastConnectのOCIDを設定 ・Connection Speed: 帯域幅を設定(5) Review
設定内容を確認し、[Submit your Order]を設定
(6) Your order was submitted
[Go to My Inventory]をクリック
(7) Connect-OCI-Ashburn
以下、Primary BGP Information項目を入力し、[Accept]をクリック・Local ASN: Equinix EdgeのASNを設定 ・Local IP Address: Equinix EdgeのBGP IPを設定 ・Remote ASN: OCIのASN 31898 を設定 ・Remote IP address OCIのBGP IPを設定Equinix Edge と OCI FastConnect接続確認
Equinix EdgeとOCI FastConnect が接続できたことを確認します
OCI FastConnect画面にある以下項目がグリーン色であることを確認
・ライフサイクル状態: プロビジョニング済 ・BGP状態: 稼働中■ Equinix Network Edge と AWS Direct Connect接続
● 1. AWSアカウントID確認
ECX Fabric portal画面で、AWSアカウントIDを用いてAWS接続用Connectionを作成すると、自動で AWS側に Direct Connectが作成されます。
ということでまず、AWSアカウントIDを確認します。① AWSログイン
AWSコンソール上部にある[ユーザー名]から、[マイアカウント]をクリック
② アカウント設定画面
アカウントID を確認し、コピーしておきます
● 2. Equinix Cloud Exchange Connection作成
(1) ECX Fabric portalログイン
ECX Fabric portalログインし、「Network Edge]画面から、[Connections]をクリック
(2) Frequent Connections画面
[AWS]を選択し、"AWS Direct Connect" の[Create Connection]をクリック
(3) Steps: Connecting to AWS画面
3つの接続手順を確認して、[Create a Connection to Amazon Web Services]をクリック
(4) Select Locations画面
以下設定をして、[Next]をクリック・Origin欄 - Select Location : Equinix Edgeルーターのlocationを選択 - Cirtual Devices in Ashburn: AWSと接続するEquinix Edgeルーターを選択 ・Destination欄 - Suggested: Equinix Edgeルーターと最も近い AWSのLocaitonを選択(5) Connection Details画面
以下設定をして、[Next]をクリック- Connection Information: 任意の名前を設定 - AWS ACCOUNT ID: 事前に調べておいた AWS ACCOUNT IDを設定 - Connection Speed: 作成するAWS Direcconnectの帯域を設定(6) Review画面
設定内容を確認して、[Submit your Order]をクリック
(7) Your order was submitted画面
[Go to My Inbentory] をクリック
もしくは、[Accept hosted Connection on AWS]をクリックしてもOK
(8)Important Information画面
[Accept hosted Connection]をクリック
すると、設定したAWS User IDに 設定した接続名で Direct Connect が作成されます。
● 3. AWS 仮想プライベートゲートウェイ作成
AWS VPCのゲートウェイとなる、仮想プライベートゲートウェイを作成
そして、これをDirect Connect接続するための Direct Connectゲートウェイへ関連付けます(1) 仮想プライベートゲートウェイ画面
[AWS Direct Connect] > [仮想プライベートゲートウェイ]画面から、[仮想プライベートゲートウェイ]をクリック
(2) 仮想プライベートゲートウェイを作成する画面
以下内容を設定し、[仮想プライベートゲートウェイを作成する]をクリック- 名前タグ:必要に応じて任意の名前を設定 - ASN: [AmazonのデフォルトASN]を選択(3) 仮想プライベートゲートウェイを作成画面
[閉じる]をクリック
(4) 仮想プライベートゲートウェイをVPCにアタッチ
仮想プライベートゲートウェイ画面から、作成した仮想プライベートゲートウェイを選択し、[アクション]リストから、[VPCにアタッチ]をクリック(5) VPCにアタッチ画面
以下内容を設定し、[はい、アタッチします]クリック- VPC: 仮想プライベートゲートウェイをアタッチするVPCを選択
(6) 仮想プライベートゲートウェイ画面
状態が ’atattching’ になればOK
● 4. AWS Direct Connect ゲートウェイ作成
(1) Direct Connect ゲートウェイ画面
[AWS Direct Connect] > [Direct Connect ゲートウェイ]画面から、[Direct Connect ゲートウェイを作成する]をクリック
(2) Direct Connect ゲートウェイを作成する画面
以下内容を設定し、[Direct Connect ゲートウェイを作成する]をクリック- 名前:任意の名前を設定 - Amazon側のASN: デフォルトの'64512'を設定(3) ゲートウェイの関連付け
[Direct Connect ゲートウェイ]画面から,[ゲートウェイの関連付け]タブを選択し、[ゲートウェイを関連づける]をクリック
(4) ゲートウェイを関連付ける画面
以下内容を設定し、[ゲートウェイを関連付ける]をクリック- ゲートウェイ: 事前に作成した仮想プライベートゲートウェイを選択● 5. AWS Direct Connect接続設定
(1) AWS Direct Connect接続画面
AWS Webコンソールにログインし、[AWS Direct Connect] > [接続]をクリック
Equinix Network Edgeの手順で[Accept hosted Connection]クリックでDirect Connectが作成されていて「状態」は'ordering'であるとを確認
作成された Direct Connect IDをクリック
(2) AWS Direct Connect画面
[承認する]をクリックして、Direct Connect接続を承諾
(3) ホスト接続を承諾する画面
[確認する]をクリックし、承諾
(4) 仮想インターフェイス画面
[仮想インターフェイスを作成する]をクリック
(5) 仮想インターフェイスを作成する画面
以下設定を行い、[仮想インターフェイスを作成する]をクリック- 仮想インターフェイスのタイプ: Private Peerinしたいので[プライベート]を選択 - 仮想インターフェイス名: 任意の名前を設定 - 接続: Direct Connectの接続名を選択 - 仮想インターフェイスの所有者: 自分のAWSアカウントを設定 - ゲートウェイタイプ: ここでは、[Direct Connect ゲートウェイ]を選択 - Direct Connect ゲートウェイ: 事前に作成した「Direct Connect ゲートウェイ」を選択 - VLAN: 自動で裁判されたデフォルト値を使用 - BGP ASN: Equinix Network Edgeに設定した65201を使用(6) 仮想インターフェイス画面
仮想インターフェイスが作成され、以下ステータスを確認[状態]: 'Avalable' [BGP ステータス] : 'down'そして、以下自動生成されたピアリング情報をメモし、Equinix Connections設定で使用します
- BGP 認証キー - ルーターのピアIP - AmazonルーターのピアIP● 6. Equinix Connections AWS接続設定
(1) Connections画面
Equinix Webコンソールにログインし、作成したAWSの Connection をクリック
(2) ConnectionーAWS画面
右下の欄にある Primary 'BGP Information' 欄にある[Edit]をクリック(3) BGP Information欄
以下内容を設定し、[Accept]をクリック- Local ASN: 任意のPrivate ASN(64512~65534)を設定 - Local IP Address: AWS仮想インターフェース作成で自動採番された、'ルーターのピアIP'を設定 - Remote ASN: '64512'を設定 - Remote IP address: AWS仮想インターフェース作成で自動採番された、'AmazonルーターのピアIP'を設定 - BGP Authentication key: AWS仮想インターフェース作成で自動作成された'BGP 認証キー'を設定(4) BGP Information欄
Provisionig Statusが’PROVISIONING’から、'Active' になれば、BGP通信確立完了
● 7. AWS Direct Connect通信確立確認
(1) 仮想インターフェイス BGPステータス確認
AWSv Webコンソールにログインし、[AWS Direct Connect] > [仮想インターフェイス] > [作成した仮想インターフェイス名]をクリック
BGPステータスが 'UP' であることを確認■ AWS VPC設定
● VPC ルートテーブル設定
(1) VPC ルート伝搬設定
VPC の[ルート伝搬]タブをクリックし、以下内容を設定- 仮想プライベートゲートウェイ: Direct Connect利用している[仮想プライベートゲートウェイ]を選択 - 伝搬: [はい]を選択(2) VPC ルート伝搬確認
VPC の[ルート]タブをクリックし、以下のように対抗のルートが伝搬されていることを確認
ここでは、OCI Ashburnリージョンと接続しているので、以下2種類のルートがOCIからAWSへ伝搬されていることを確認できる
OCI VCNルート: 10.10.10.0/24 OCI OSNルート: Public IP Address Rangesを参照● ネットワークACL設定
[VRTUAL PRIVATE CLOUD] > [ネットワークACL]を選択し、インバウンドルールを以下のように設定
ここでは、テスト用途でOCIのVCN 10.10.0.0/16 のプロトコルをすべて通すように設定しています
● セキュリティグループ設定
[VRTUAL PRIVATE CLOUD] > [セキュリティーグループ]を選択し、インバウンドルールを以下のように設定
ここでは、テスト用途でOCIのVCN 10.10.0.0/16 のプロトコルをすべて通すように設定しています
■ 疎通確認
● OCI --> AWS 疎通確認
OCI Compute Instanceから、AWS EC2インスタンスへ通信できることを確認
・ssh接続確認
[opc@ashburn-inst01 ~]$ ssh -i AWS_EC2.pem ec2-user@172.31.0.10 hostname ip-172-31-0−10.ec2.internal・ping疎通確認
[opc@ashburn-inst01 ~]$ ping 172.31.0.10 -c 3 PING 172.31.0.10 (172.31.0.10) 56(84) bytes of data. 64 bytes from 172.31.0.10: icmp_seq=1 ttl=60 time=1.88 ms 64 bytes from 172.31.0.10: icmp_seq=2 ttl=60 time=1.90 ms 64 bytes from 172.31.0.10: icmp_seq=3 ttl=60 time=1.85 ms --- 172.31.0.10 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2004ms rtt min/avg/max/mdev = 1.855/1.882/1.903/0.040 ms・tracerouteルート確認
OCI->EquinixのBGPピアIP 192.168.254.~ を通ること確認[opc@ashburn-inst01 ~]$ traceroute 172.31.0.10 traceroute to 172.31.0.10 (172.31.0.10), 30 hops max, 60 byte packets 1 140.91.196.18 (140.91.196.18) 0.090 ms 140.91.196.82 (140.91.196.82) 0.073 ms 140.91.196.119 (140.91.196.119) 0.087 ms 2 192.168.254.22 (192.168.254.22) 0.784 ms 0.777 ms 0.748 ms 3 169.254.255.25 (169.254.255.25) 1.061 ms 1.365 ms 1.020 ms 4 172.31.0.10 (172.31.0.10) 3.469 ms 3.375 ms 3.366 ms・iperf3帯域確認
AWSのDirect Connect 50Mで設定してるので、50M程度出力されることを確認[root@ashburn-inst01 opc]# iperf3 -c 172.31.0.10 Connecting to host 172.31.0.10, port 5201 [ 4] local 10.10.0.2 port 58216 connected to 172.31.0.10 port 5201 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-1.00 sec 7.86 MBytes 65.9 Mbits/sec 206 11.3 KBytes [ 4] 1.00-2.00 sec 5.59 MBytes 46.9 Mbits/sec 87 15.6 KBytes [ 4] 2.00-3.00 sec 5.90 MBytes 49.5 Mbits/sec 106 4.24 KBytes [ 4] 3.00-4.00 sec 5.59 MBytes 46.9 Mbits/sec 117 9.90 KBytes [ 4] 4.00-5.00 sec 5.90 MBytes 49.5 Mbits/sec 108 25.5 KBytes [ 4] 5.00-6.00 sec 5.59 MBytes 46.9 Mbits/sec 106 15.6 KBytes [ 4] 6.00-7.00 sec 5.90 MBytes 49.5 Mbits/sec 70 7.07 KBytes [ 4] 7.00-8.00 sec 5.59 MBytes 46.9 Mbits/sec 76 8.48 KBytes [ 4] 8.00-9.00 sec 5.90 MBytes 49.5 Mbits/sec 95 11.3 KBytes [ 4] 9.00-10.00 sec 5.59 MBytes 46.9 Mbits/sec 99 14.1 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 59.4 MBytes 49.9 Mbits/sec 1070 sender [ 4] 0.00-10.00 sec 58.9 MBytes 49.4 Mbits/sec receiver iperf Done.● AWS --> OCI 疎通確認
AWS EC2インスタンスから、OCI Compute Instanceへ通信できることを確認
・ssh接続確認
[ec2-user@ip-172-31-0-2 ~]$ ssh -i ~/id_rsa opc@10.10.0.2 ashburn-inst01・ping疎通確認
[ec2-user@ip-172-31-0-2 ~]$ ping 10.10.0.2 -c 3 PING 10.10.0.2 (10.10.0.2) 56(84) bytes of data. 64 bytes from 10.10.0.2: icmp_seq=1 ttl=61 time=1.90 ms 64 bytes from 10.10.0.2: icmp_seq=2 ttl=61 time=2.05 ms 64 bytes from 10.10.0.2: icmp_seq=3 ttl=61 time=2.07 ms --- 10.10.0.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 5ms rtt min/avg/max/mdev = 1.895/2.005/2.066/0.077 ms・tracerouteルート確認
AWSのBGPピアIP 169.254.~ を通ること確認[ec2-user@ip-172-31-0-2 ~]$ traceroute 10.10.0.2 traceroute to 10.10.0.2 (10.10.0.2), 30 hops max, 60 byte packets 1 169.254.255.1 (169.254.255.1) 1.096 ms 1.088 ms 169.254.255.5 (169.254.255.5) 0.374 ms 2 169.254.255.25 (169.254.255.25) 1.157 ms 1.082 ms 1.080 ms 3 169.254.255.26 (169.254.255.26) 1.487 ms 1.734 ms 1.715 ms 4 140.91.196.50 (140.91.196.50) 1.672 ms 140.91.196.55 (140.91.196.55) 1.649 ms 140.91.196.123 (140.91.196.123) 1.624 ms 5 ip-10-10-0-2.ec2.internal (10.10.0.2) 1.892 ms !X 1.835 ms !X 1.927 ms !X・iperf3帯域確認
AWSのDirect Connect 50Mで設定してるので、50M程度出力されることを確認[root@ip-172-31-0-2 ec2-user]# iperf3 -c 10.10.0.2 Connecting to host 10.10.0.2, port 5201 [ 5] local 172.31.0.10 port 58610 connected to 10.10.0.2 port 5201 [ ID] Interval Transfer Bitrate Retr Cwnd [ 5] 0.00-1.00 sec 7.42 MBytes 62.2 Mbits/sec 129 15.6 KBytes [ 5] 1.00-2.00 sec 5.84 MBytes 49.0 Mbits/sec 89 19.8 KBytes [ 5] 2.00-3.00 sec 5.59 MBytes 46.9 Mbits/sec 69 12.7 KBytes [ 5] 3.00-4.00 sec 5.72 MBytes 48.0 Mbits/sec 63 19.8 KBytes [ 5] 4.00-5.00 sec 5.47 MBytes 45.9 Mbits/sec 88 25.5 KBytes [ 5] 5.00-6.00 sec 6.15 MBytes 51.6 Mbits/sec 70 11.3 KBytes [ 5] 6.00-7.00 sec 5.90 MBytes 49.5 Mbits/sec 103 9.90 KBytes [ 5] 7.00-8.00 sec 5.41 MBytes 45.4 Mbits/sec 60 18.4 KBytes [ 5] 8.00-9.00 sec 6.09 MBytes 51.1 Mbits/sec 112 11.3 KBytes [ 5] 9.00-10.00 sec 5.47 MBytes 45.9 Mbits/sec 53 15.6 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 59.1 MBytes 49.5 Mbits/sec 836 sender [ 5] 0.00-10.00 sec 58.7 MBytes 49.2 Mbits/sec receiver iperf Done.● AWS --> OCI Object Storage疏通確認
AWS EC2インスタンスから、OCI OSNにあるObject Storageへ疏通できることを確認
・ping疏通確認
[ec2-user@ip-172-31-0-2 ~]$ ping objectstorage.us-ashburn-1.oraclecloud.com -c 3 PING objectstorage.us-ashburn-1.oraclecloud.com (134.70.31.247) 56(84) bytes of data. 64 bytes from 134.70.31.247 (134.70.31.247): icmp_seq=1 ttl=61 time=2.48 ms 64 bytes from 134.70.31.247 (134.70.31.247): icmp_seq=2 ttl=61 time=2.46 ms 64 bytes from 134.70.31.247 (134.70.31.247): icmp_seq=3 ttl=61 time=2.41 ms --- objectstorage.us-ashburn-1.oraclecloud.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 6ms rtt min/avg/max/mdev = 2.414/2.450/2.487/0.071 ms・tracerouteルート確認
AWSのBGPピアIP 169.254.~ を通ること確認[root@ip-172-31-0-2 ec2-user]# traceroute -I objectstorage.us-ashburn-1.oraclecloud.com traceroute to objectstorage.us-ashburn-1.oraclecloud.com (134.70.35.189), 30 hops max, 60 byte packets 1 169.254.255.1 (169.254.255.1) 0.672 ms 0.665 ms 0.663 ms 2 169.254.255.25 (169.254.255.25) 1.326 ms 1.345 ms 1.369 ms 3 169.254.255.26 (169.254.255.26) 1.836 ms 1.837 ms 1.836 ms 4 140.91.196.123 (140.91.196.123) 1.830 ms 1.992 ms 2.004 ms 5 134.70.35.189 (134.70.35.189) 28.091 ms 27.916 ms 27.931 ms■ 参考
●Network Edge
• Network Edge
• Platform Equinix上でNetwork Edgeを活用したCisco vManage●Network Edge 技術リソース
• Interconnection - Network Edge
• User Guide
• Deploy & Config
- 投稿日:2020-07-21T18:55:53+09:00
SSMで特定のInstanceへのRDPだけを許可する
SSMネタの第3弾です
ことの発端
社長:「〇〇のAWSアカウントの請求額、高いねんけど」
社長:「ClientVPNが一番しめてるわ」
社長:「なんとかならん?」
このClientVPNはプライベートにあるWindowsサーバへ接続するためで、利用するのはWindows上で動いてるソフトのメンテ用になってます
何かあるとき(トラブル時)しか使わないので常時ClientVPNを置いておくのはもったいないってことで、ClientVPNをやめてSSMに置き換えてみます(インフラ民はSSMでつないでるのでClientVPNは使ってません)
やりたいこと
- RDPだけに制限したい
- 接続先を特定のWindowsサーバだけにしたい
RDPだけに制限する
RDPのポートだけに接続するSSMドキュメントを作成する
AWS-StartPortForwardingSession
はどのポートでも接続することができるため、このドキュメントをコピーして新たにRDPのポートだけのドキュメントを作成します以下はドキュメントのコンテンツ内容です
rdp_forward_document.json{ "schemaVersion": "1.0", "description": "Document to start port forwarding session over Session Manager", "sessionType": "Port", "parameters": { "localPortNumber": { "type": "String", "description": "(Optional) Port number on local machine to forward traffic to. An open port is chosen at run-time if not provided", "allowedPattern": "^([0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$", "default": "0" } }, "properties": { "portNumber": "3389", "type": "LocalPortForwarding", "localPortNumber": "{{ localPortNumber }}" } }変更箇所は
parameters
からportNumber
を削除して、properties
のportNumber
を 3389 の固定にするだけです上記のファイルで新たにドキュメントを作成
aws ssm create-document --content file://rdp_forward_document.json --name RdpForwardingSession --document-type Session --document-format JSONIAMユーザを作成
IAMユーザはSSMだけ使えるようにしたいので「プログラムによるアクセス」で作成します
IAMユーザに作成したドキュメントを許可するポリシーを設定します
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ssm:StartSession", "Resource": [ "arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:document/RdpForwardingSession" ] }, { "Effect": "Allow", "Action": "ssm:TerminateSession", "Resource": "arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:session/${aws:username}-*" } ] }
ssm:TerminateSession
では自分自身のsessionだけを対象とするため、${aws:username}-*
とします試しにテストしてみます
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX --document-name RdpForwardingSession Starting session with SessionId: hoge-xxxxxxxxxxxxxxxxx Port 13389 opened for sessionId hoge-xxxxxxxxxxxxxxxxx.$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX --document-name AWS-StartPortForwardingSession --parameters 'portNumber=3389' An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxxx:user/hoge is not authorized to perform: ssm:StartSession on resource: arn:aws:ssm:ap-northeast-1::document/AWS-StartPortForwardingSession
AWS-StartPortForwardingSession
は AccessDenied となったので意図通りのようですDocument指定なしでも試してみます
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX Starting session with SessionId: hoge-xxxxxxxxxxxxxxxxx Windows PowerShell Copyright (C) 2016 Microsoft Corporation. All rights reserved. PS C:\Windows\system32>あれ・・・? 入れる・・・
AWSのドキュメントを確認してみます
AWS CLI でセッションドキュメントのアクセス許可チェックを適用するデフォルトでは、IAM ユーザーポリシーでセッションを開始するアクセス許可がアカウントのユーザーに付与されている場合、そのユーザーはこの
SSM-SessionManagerRunShell
SSM ドキュメントにアクセスできます。つまり、AWS CLI を使用してstart-session
コマンドを実行し、--document-name
オプションでドキュメントを指定しない場合、システムはSSM-SessionManagerRunShell
を使用してセッションを開始します。セッションは、ユーザーの IAM ポリシーでSSM-SessionManagerRunShell
ドキュメントへのアクセスが明示的に許可されていない場合でも開始されます。なるほど・・・
デフォルトまたは任意のセッションドキュメントへのアクセスを制限するには、ユーザーにセッションドキュメントへのアクセスが明示的に許可されているかどうかを検証する条件要素を、ユーザーの IAM ポリシーに追加できます。この条件が適用されると、ユーザーは
start-session
AWS CLI コマンドの--document-name
オプションの値を指定する必要があります。ってことなのでポリシーに明示的に許可されているかどうの条件を追加します
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ssm:StartSession", "Resource": [ "arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:document/RdpForwardingSession" ], "Condition": { "BoolIfExists": { "ssm:SessionDocumentAccessCheck": "true" } } }, { "Effect": "Allow", "Action": "ssm:TerminateSession", "Resource": "arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:session/${aws:username}-*" } ] }もう再度テスト
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxxx:user/hoge is not authorized to perform: ssm:StartSession on resource: arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-XXXXXXXXXXXXXXXXXAccessDenied となりました
これで1つ目の課題はOKになりました
接続先を特定のInstanceだけにする
2つ目の課題、接続先も制限したいのでResourceにInstanceのARNを追加します
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ssm:StartSession", "Resource": [ "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-XXXXXXXXXXXXXXXXX", "arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:document/RdpForwardingSession" ], "Condition": { "BoolIfExists": { "ssm:SessionDocumentAccessCheck": "true" } } }, { "Effect": "Allow", "Action": "ssm:TerminateSession", "Resource": "arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:session/${aws:username}-*" } ] }試しに別のInstanceへ接続
$ aws ssm start-session --target i-YYYYYYYYYYYYYYYYY An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxxx:user/hoge is not authorized to perform: ssm:StartSession on resource: arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-YYYYYYYYYYYYYYYYYあとは、AccessKey/SecretAccessKey と aws cliコマンドをべた書きしたバッチファイルをメンテする人に渡せばOK
これでなんとかClientVPNを撤廃できそう
SSMネタが続いたので次回は違うものにしよう・・・
- 投稿日:2020-07-21T18:48:54+09:00
Greengrassでエッジ推論 - ビデオからの物体検知〜MQTT通知
AWS Greengrass でエッジ推論をやってみたかったので、TensorflowのObject Detection APIで、カメラに人が写ったらMQTTトピックで通知し、映像はKinesis Video Streamsに配信するという習作と実験を行いました。
作業はほぼ環境構築に終始してしまいましたが、Greengrassを使ってクラウド側からの設定によって、エッジ側にMLモデルと処理を同期して実行する一連の流れを理解することができました。
また、Greengrassの設定の要所も確認することができました。全体のイメージ
- AWS側は、Greengrassグループを作成し、エッジでTensorflow Object Detectionを行うLambda関数と、使用するモデルデータを関連付けします。また、ビデオをリモートで確認できるようにKinesis Video Streamsを準備します。
- エッジ側は、Greengrassコアを動作させますが、今回は練習なので、GreengrassCoreはDockerで作成します。Dockerfileがここからダウンロード出来ます。
- Lambdaの実行環境はPython3.7で、Gstreamerを使ってカメラの映像から、Tensorflowでの物体検知、Kinesis Video Streamsへの配信をパイプライン処理します。Gstreamerを使うのはビデオの処理をプラガブルに変更できるからで、ここで詳しい使い方は説明しませんが、情報は検索すればたくさん出てきます。
- カメラは、Gstreamerで処理するので何でも良いです。私は Tapo C200というAmazonで投げ売りされていたのを使っています。このカメラだとRTSPで覗けます。ラズパイやPCのカメラならV4L2を使うと良いです。
- 物体検知は、SSD Mobilenet ver.2のcocoデータセットのモデルをダウンロードして使用しました。検知するのは "person" だけとします。 検知できたらMQTTトピックで通知します。
- 図にはトピックをサブスクライブしてアラームする側のデバイスを描いていますが、これは次回にします。Echoに喋らせるか、AWS Chatbotでslackに通知したりする方が良いかもしれません。
作成したものは https://github.com/sabmeua/gg_gst このリポジトリにあります。以降の設定などは、このリポジトリを使って説明します。
ちなみに、私は普段Pythonを書きません。またTensorflowも今回初めて使用しました。その点ご容赦いただき、変な用法や実装がありましたらご指摘いただけるとありがたいです。
設定手順
Greengrassコアの準備
今回はDockerなのでイメージをビルドするだけです。Gstreamerと必要なプラグイン、Tensorflowなどをインストールしています。
docker-compose でビルドします。環境によってはけっこう時間がかかるかもしれません。Dockerボリュームとして証明書や設定ファイルをマウントするようになっていますが、これはGreengrassグループ作成時に準備します。$ docker-compose build
物体検知処理
Gstreamerのプラグインとして、イメージ中の/myplugins/python/ に実装しています。
- /myplugins/python/object_detection.py : Tensorflowで映像からpersonを検知して、Gstreamerメタデータに入れるプラグイン
- /myplugins/python/awsiot_notify.py : Gstreamerメタデータから検知した情報をMQTTトピック
object/detection
にパブリッシュするプラグインGreengrass環境で特別なことと言うと、モデルのファイルは別段ダウンロードの処理などを書かなくても、設定したファイルをGreengrassコアがデプロイ時に配置してくれるので、
AWS_GG_RESOURCE_PREFIX
という環境変数のパスでアクセスできることです。他には特別なことはしていません。PythonでのTensorflowの扱い方などは、こちらに詳しく解説されているので参考にしました。
Lambda関数の作成
LambdaでPython3.7の関数を作成します。アクセス権限など、その他の設定はGreengrass側の設定が採用されるので、ここでは名前以外は気にする必要はありません。
作成したら、以下のようにmakeでソースをfunction.zipにまとめてアップロードして関数を更新します。この src/lambda_function.pyが関数の本体です。
$ make lambda-archive cd src;\ zip -r ../function.zip greengrasssdk lambda_function.py adding: greengrasssdk/ (stored 0%) adding: greengrasssdk/__init__.py (deflated 32%) adding: greengrasssdk/utils/ (stored 0%) adding: greengrasssdk/utils/__init__.py (stored 0%) adding: greengrasssdk/utils/testing.py (deflated 62%) adding: greengrasssdk/client.py (deflated 53%) adding: greengrasssdk/Lambda.py (deflated 65%) adding: greengrasssdk/SecretsManager.py (deflated 67%) adding: greengrasssdk/IoTDataPlane.py (deflated 74%) adding: greengrasssdk/stream_manager/ (stored 0%) adding: greengrasssdk/stream_manager/__init__.py (deflated 40%) adding: greengrasssdk/stream_manager/util.py (deflated 81%) adding: greengrasssdk/stream_manager/data/ (stored 0%) adding: greengrasssdk/stream_manager/data/__init__.py (deflated 90%) adding: greengrasssdk/stream_manager/streammanagerclient.py (deflated 79%) adding: greengrasssdk/stream_manager/exceptions.py (deflated 72%) adding: lambda_function.py (deflated 56%)実装について簡単に説明します。
通常、Lambdaをデマンドで実行する場合は、イベント発生時に、設定したハンドラが呼び出されるわけですが、今回はGreengrassコアが起動したタイミングで実行し、制限時間でタイムアウトすることなく実行し続ける 長い存続期間の Lambda 関数というライフサイクルの設定で実行します。この場合、ハンドラとして設定されているlambda_handler(event, context)
に処理を記述せず、ソースがロードされた時点で処理が開始されるように無限ループなり、スレッドを起動するように実装します。
今回はmain()
に処理を記述しており、ここでGstreamerのイベントループを開始しています。
lambda_function.py
で行っているのはGstreamerパイプラインの起動のみです。物体検知やKVSへの送信といった処理のパイプラインは環境変数で設定できるようにしていて、Greengrass側のLambdaの実行設定の際に設定します。src/lambda_function.py#!/usr/bin/env python3 import os import sys import traceback import gi gi.require_version('Gst', '1.0') gi.require_version('GLib', '2.0') gi.require_version('GObject', '2.0') from gi.repository import GLib, GObject, Gst import logging logger = logging.getLogger(__name__) logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) STREAM_NAME = os.environ.get('STREAM_NAME') IOT_CREDENTIAL_ENDPOINT = os.environ.get('IOT_CREDENTIAL_ENDPOINT') CERT_ID = os.environ.get('CERT_ID') KVS_CMD = f'kvssink stream-name={STREAM_NAME} framerate=15'\ ' aws-region=ap-northeast-1'\ ' log-config=/kvs_log_configuration'\ ' iot-certificate="iot-certificate,'\ f'endpoint={IOT_CREDENTIAL_ENDPOINT},'\ f'cert-path=/greengrass/certs/{CERT_ID}.cert.pem,'\ f'key-path=/greengrass/certs/{CERT_ID}.private.key,'\ 'ca-path=/greengrass/certs/root.ca.pem,'\ 'role-aliases=KvsCameraIoTRoleAlias"' DEFAULT_PIPELINE = 'videotestsrc ! clockoverlay auto-resize=false'\ ' ! videorate ! video/x-raw,format=I420,framerate=15/1'\ ' ! x264enc tune=zerolatency ! h264parse' def on_message(bus: Gst.Bus, message: Gst.Message, loop: GLib.MainLoop): mtype = message.type if mtype == Gst.MessageType.EOS: logger.info("End of stream") loop.quit() elif mtype == Gst.MessageType.ERROR: err, debug = message.parse_error() logger.error(err, debug) loop.quit() elif mtype == Gst.MessageType.WARNING: err, debug = message.parse_warning() logger.warning(err, debug) return True def main(): logger.info('Start gstream pipeline') Gst.init(sys.argv) cmd = os.environ.get('PIPELINE', DEFAULT_PIPELINE) if os.environ.get('USE_KVS', True): cmd += f' ! {KVS_CMD}' logger.info('Pipeline : %s', cmd) pipeline = Gst.parse_launch(cmd) bus = pipeline.get_bus() bus.add_signal_watch() pipeline.set_state(Gst.State.PLAYING) loop = GLib.MainLoop() bus.connect("message", on_message, loop) try: loop.run() except Exception: traceback.print_exc() loop.quit() pipeline.set_state(Gst.State.NULL) main() # This is a dummy handler and will not be invoked # Instead the code above will be executed in an infinite loop for our example def lambda_handler(event, context): returnGreengrassにLambda関数を設定する際、バージョンまたはエイリアスで指定する必要があるため、作成した関数のバージョンを発行して、これにエイリアス
dev
を設定します(キャプチャでは ver.2 になっています)。Greengrassグループの設定
Greengrassグループの作成はAWSコンソールでAWS IoTのウィザードに沿って設定するだけですが、設定にはいくつかポイントがあります。
Greengrassグループ作成で
デフォルト作成を使用
を選択します。グループ名は
test
としました。Greengrassコアの名前はtest_Core
となりますが、これもそのままOKしました。もう少し気の利いた名前にした方が良かったです。証明書の配置
作成を実行すると、コア用の証明書、プライベートキー、パブリックキー、設定ファイルのtarballがダウンロードできます。これをdocker-composeのディレクトリの
certs
とconfig
に展開します。またCA 証明書も必要なので、ダウンロードして certs/root.ca.pem に保存します。
プライベートキーはLambdaを実行する ggc_user/ggc_group から参照されるので644
にしておきます。$ ls -l certs/ config/ certs/: 合計 16 -rw-r--r-- 1 sabmeua sabmeua 1220 7月 13 11:35 0f0c0953bd.cert.pem -rw-r--r-- 1 sabmeua sabmeua 1679 7月 13 11:35 0f0c0953bd.private.key -rw-r--r-- 1 sabmeua sabmeua 451 7月 13 11:35 0f0c0953bd.public.key -rw-r--r-- 1 sabmeua sabmeua 1188 6月 22 14:03 root.ca.pem config/: 合計 4 -rw-r--r-- 1 sabmeua sabmeua 875 7月 13 11:35 config.jsonエッジ環境のローカルファイルシステムへのロギングの設定
コンソールで作成したGreengrassグループの
設定
画面からローカルログ設定
をinfoレベルで行うようにします。これによりLambdaの出力をファイルにロギングできます。Lambda実行環境の設定
今回Lambda環境をDockerで実行するので、同じく
設定
画面にて、デフォルトの Lambda 関数コンテナ化の設定をコンテナなし
に変更します。実行ユーザはデフォルトのままggc_user/ggc_groupにしておきます。Lambdaの設定
Greengrassグループの
Lambda
の画面で、Lambdaの追加
->既存のLambdaの使用
を選択して、先ほど作成した関数gg-gst-test
を、バージョンにエイリアスdev
を選択して追加します。追加した関数の設定を編集します。
ここで、設定するのは2箇所です。まず、Lambdaのライフサイクルを存続期間が長く無制限に稼働する関数にする
に変更します。もう一つは、タイムアウトを25
に変更します。無制限と言いながらタイムアウトを設定するのは変な気がしますが、ここにかかれている通り、Lambda関数の呼び出し前に20秒のスリープがあるので、その間に終了しないようにするためです。また、このLambdaの設定画面で、実行時の環境変数を設定します。
キー 説明 値 GST_PLUGIN_PATH Gstreamerのプラグインの所在を指定する /usr/local/lib/gstreamer-1.0:/myplugins STREAM_NAME KVSのストリーム名 test_Core IOT_CREDENTIAL_ENDPOINT kVSにiot-credentialsでアクセスするための認証エンドポイント ※自身の環境を参照 CERT_ID 証明書、キーのファイルのbasename ※自身の環境を参照 PIPELINE Gstreamerの処理パイプライン ※後述 IOT_CREDENTIAL_ENDPOINT はaws cliでこのように確認できます。
$ aws iot describe-endpoint --endpoint-type iot:CredentialProvider { "endpointAddress": "XXXXXXXXXXXXXX.credentials.iot.ap-northeast-1.amazonaws.com" }PIPELINE にはビデオソースにあわせたパイプラインを記述します。RTSPのカメラからの場合、私の環境では前処理など含めて以下のようになります。KVSに配信する kvssink のパイプラインは、Lambda関数内に記述しています。
rtspsrc location=rtsp://192.168.10.115:554/stream2 user-id=hogehoge user-pw=fugafuga ! rtph264_depay ! videorate ! video/x-h264,framerate=15/1 ! videoconvert ! object_detection model=models/ssd_mobilenet_v2_coco_2018_03_29/frozen_inference_graph.pb ! awsiot_notify ! videoconvert ! x264enc tune=zerolatency bframes=0 key-int-max=45 bitrate=512 ! video/x-h264,profile=baseline,stream-format=avc,alignment=au,framerate=15/1
object_detection
が物体検知のプラグインで、オプションでモデルファイルを指定します。ここで指定したモデルファイルは、デプロイ時に展開されるよう後ほど設定します。
続くawsiot_notify
が検知した情報を MQTT パブリッシュするプラグインです、それ以降はKVSに配信するkvssink
の入力に合わせるため、h.264エンコードしています。MLモデルリソースの設定
TensorflowのObject Detectionで使用するモデルをGreengrassに設定して、Lambda関数と関連付けます。
SageMakerのモデルを使用できるようですが、今回はこちらからダウンロードして使用します。http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz
ダウンロードしたファイルをS3にアップロードして、Greengrassグループの
リソース
の画面から選択します。Lambdaの実行をコンテナなしで行うため、パーミッションを以下のように設定する必要があります。OSグループIDの
997
は ggc_group の番号です。Lambda関数gg-gst-testと関連付けて、実行時に参照できるようにします。以上の設定で、Greengrassコアのデプロイ時にエッジ側にリソースが同期されます。
MQTTトピックの設定
サブスクリプション
の画面で、物体検知を通知するためのMQTTトピックの設定を行います。
ソースをLambda関数 gg-gst-test に、ターゲットを Iot Cloud にします。トピックフィルタは指定しないと、ワイルドカード指定されすべてキャプチャされるようになります。この設定により、ローカルMQTTブローカーではなく、AWS IoT側に通知できます。
Kinesis Video Streamsの設定
ストリームの作成
最後に、Kinesis Video Streams(以下 KVS)のストリームを作成します。ストリーム名は、Greengrassコアの名前と同じにする必要があります。その他はデフォルトのままで問題ありません。
ストリーミング用ポリシー、ロールの作成
KVSへのストリーミングはGstreamerのkvssinkで行いますが、kvssinkはオプションで、AWSIoTの証明書を利用してKVSにアクセスすることができます。
そのために必要となるロールとポリシーの設定をこの説明に従って、以下のように実行します。$ cat <<JSON > iam-policy-document.json { "Version":"2012-10-17", "Statement":[ { "Effect":"Allow", "Principal":{ "Service":"credentials.iot.amazonaws.com" }, "Action":"sts:AssumeRole" } ] } JSON $ aws iam create-role --role-name KVSCameraCertificateBasedIAMRole --assume-role-policy-document 'file://iam-policy-document.json' | tee iam-role.json { "Role": { "Path": "/", "RoleName": "KVSCameraCertificateBasedIAMRole", "RoleId": "AROAXGR6GGYYWJPW32Z5L", "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/KVSCameraCertificateBasedIAMRole", "CreateDate": "2020-07-13T04:50:07Z", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "credentials.iot.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } } } $ cat <<'JSON' > iam-permission-document.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "kinesisvideo:DescribeStream", "kinesisvideo:PutMedia", "kinesisvideo:TagStream", "kinesisvideo:GetDataEndpoint" ], "Resource": "arn:aws:kinesisvideo:*:*:stream/${credentials-iot:ThingName}/*" } ] } JSON $ aws iam put-role-policy --role-name KVSCameraCertificateBasedIAMRole --policy-name KVSCameraIAMPolicy --policy-document 'file://iam-permission-document.json' $ aws iot create-role-alias --role-alias KvsCameraIoTRoleAlias --role-arn $(jq --raw-output '.Role.Arn' iam-role.json) --credential-duration-seconds 3600 | tee iot-role-alias.json { "roleAlias": "KvsCameraIoTRoleAlias", "roleAliasArn": "arn:aws:iot:ap-northeast-1:XXXXXXXXXXXX:rolealias/KvsCameraIoTRoleAlias" } $ cat <<JSON > iot-policy-document.json { "Version":"2012-10-17", "Statement":[ { "Effect":"Allow", "Action":[ "iot:Connect" ], "Resource":"$(jq --raw-output '.roleAliasArn' iot-role-alias.json)" }, { "Effect":"Allow", "Action":[ "iot:AssumeRoleWithCertificate" ], "Resource":"$(jq --raw-output '.roleAliasArn' iot-role-alias.json)" } ] } JSON $ aws iot create-policy --policy-name KvsCameraIoTPolicy --policy-document 'file://iot-policy-document.json' $ aws iot attach-policy --policy-name KvsCameraIoTPolicy --target 'arn:aws:iot:ap-northeast-1:XXXXXXXXXXXX:cert/0f0c0953bd4a248aa210a2411328e9659c9dc0bc90e64c9625c08e807c0819c0'正しく作成出来ているかどうかは、以下のように確認できます。describe-streamが成功すれば問題ないです。
$ export IOT_GET_CREDENTIAL_ENDPOINT=$(aws iot describe-endpoint --endpoint-type iot:CredentialProvider --output text) $ curl -v -H "x-amzn-iot-thingname:test_Core" --cert certs/0f0c0953bd.cert.pem --key certs/0f0c0953bd.private.key https://${IOT_GET_CREDENTIAL_ENDPOINT}/role-aliases/KvsCameraIoTRoleAlias/credentials --cacert certs/0f0c0953bd.cert.pem > token.json $ AWS_ACCESS_KEY_ID=$(jq --raw-output '.credentials.accessKeyId' token.json) AWS_SECRET_ACCESS_KEY=$(jq --raw-output '.credentials.secretAccessKey' token.json) AWS_SESSION_TOKEN=$(jq --raw-output '.credentials.sessionToken' token.json) aws kinesisvideo describe-stream --stream-name test_Core以上で準備が整いました。
動作確認
結果がわかりやすいように、カメラ画像ではなく、MP4のファイルからの物体検知で試します。
ビデオはこれを使いました。
https://www2.nhk.or.jp/archives/creative/material/view.cgi?m=D0002161315_00000
CPUだけだとけっこう処理が厳しいので、予め640x360、15fpsに落としています。Lambdaの環境変数をこのように変更しました。ビデオをdemux, decodeして、確認ようの時刻を入れています。検出、通知処理を行い、再度h.264エンコードしています。
filesrc location=/data/D0002161315_00000_V_000_640x360_15fps.mp4 ! decodebin ! clockoverlay ! videoconvert ! object_detection model=models/ssd_mobilenet_v2_coco_2018_03_29/frozen_inference_graph.pb ! awsiot_notify ! videoconvert ! x264enc tune=zerolatency bframes=0 key-int-max=45 bitrate=512 ! video/x-h264,profile=baseline,stream-format=avc,alignment=au,framerate=15/1
まず、Greengrassコアのコンテナを
docker-compose up
して起動します。$ docker-compose up Starting aws-iot-greengrass ... done Attaching to aws-iot-greengrass aws-iot-greengrass | Process with pid 13 does not exist already aws-iot-greengrass | Setting up greengrass daemon aws-iot-greengrass | Validating hardlink/softlink protection aws-iot-greengrass | Waiting for up to 1m10s for Daemon to start aws-iot-greengrass | aws-iot-greengrass | Greengrass successfully started with PID: 13このようにコアのプロセスが起動したら、AWS IoTのコンソールのデプロイの画面から
デプロイ
を選択します。上手くいけば正常に完了しました
となり、Lambda関数や、リソースがAWS側と同期され、関数が起動します。関数の出力は
log/user/ap-northeast-1/XXXXXXXXXXXX/gg-gst-test.log
というログファイルに出力されるので、これを tail すると、このような感じでログが流れました。[2020-07-21T07:18:57.327Z][INFO]-lambda_function.py:53,Start gstream pipeline [2020-07-21T07:18:58.455Z][INFO]-lambda_function.py:60,Pipeline : filesrc location=/data/D0002161315_00000_V_000_640x360_15fps.mp4 ! decodebin ! clockoverlay ! videoconvert ! object_detection model=models/ssd_mobilenet_v2_coco_2018_03_29/frozen_inference_graph.pb ! awsiot_notify ! videoconvert ! x264enc tune=zerolatency bframes=0 key-int-max=45 bitrate=512 ! video/x-h264,profile=baseline,stream-format=avc,alignment=au,framerate=15/1 ! kvssink stream-name=test_Core framerate=15 aws-region=ap-northeast-1 log-config=/kvs_log_configuration iot-certificate="iot-certificate,endpoint=c1m4lov0fgg33l.credentials.iot.ap-northeast-1.amazonaws.com,cert-path=/greengrass/certs/0f0c0953bd.cert.pem,key-path=/greengrass/certs/0f0c0953bd.private.key,ca-path=/greengrass/certs/root.ca.pem,role-aliases=KvsCameraIoTRoleAlias" (略) [2020-07-21T07:19:45.151Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.150 | Dummy-1 | Detect score=0.9208017587661743 [2020-07-21T07:19:45.155Z][ERROR]-__init__.py:1028,DEBUG | greengrasssdk.IoTDataPlane | 21.07 07:19:45.151 | Dummy-1 | Publishing message on topic "object/detection" with Payload "{"bounding_box": [0, 0, 0, 0], "confidence": 0.9208017587661743, "class_name": "", "track_id": 0, "pts": "0:00:53.866666666"}" [2020-07-21T07:19:45.208Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.207 | Dummy-1 | Detect score=0.9566311836242676 [2020-07-21T07:19:45.257Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.256 | Dummy-1 | Detect score=0.9690361022949219 [2020-07-21T07:19:45.305Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.305 | Dummy-1 | Detect score=0.952594518661499 [2020-07-21T07:19:45.353Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.353 | Dummy-1 | Detect score=0.9480921030044556 [2020-07-21T07:19:45.402Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.401 | Dummy-1 | Detect score=0.9473453164100647 [2020-07-21T07:19:45.452Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.451 | Dummy-1 | Detect score=0.9678215384483337 [2020-07-21T07:19:45.504Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:45.503 | Dummy-1 | Detect score=0.9282958507537842 [2020-07-21T07:19:46.195Z][ERROR]-__init__.py:1028,DEBUG | root | 21.07 07:19:46.195 | Dummy-1 | Detect score=0.9128057956695557 [2020-07-21T07:19:46.196Z][ERROR]-__init__.py:1028,DEBUG | greengrasssdk.IoTDataPlane | 21.07 07:19:46.195 | Dummy-1 | Publishing message on topic "object/detection" with Payload "{"bounding_box": [0, 0, 0, 0], "confidence": 0.9128057956695557, "class_name": "", "track_id": 0, "pts": "0:00:55.266666666"}" (略)
07:19:45
に人を検知して、トピックobject/detection
にパブリッシュされています。MQTTテストクライアントでサブスクライブすると、このように確認できました。また、Kinesis Video Streamsで該当時刻の映像をみると、
07:19:45
に人が映っていました。実験は成功です。
まとめ
- Greengrassでエッジ推論での物体検知の実装方法を知ることができました。
- Lambdaの実装や設定はかなり自由度が高いことがわかりました。
- CPUだけでは処理が厳しいことがわかったので、ラズパイでH/Wでenc/decするとか、JetsonNanoやEdgeTPUなどを導入したほうが良いと思いました。
- Greengrassのドキュメントはけっこう充実していることがわかりました。ドキュメントを読んでいて、今回は使用しなかった
コネクタ
を使うと、色々できそうなことがわかりました。- Dockerで動かす(Lambdaをコンテナなしで実行する)ために必要な設定が多いです。コンテナで実行したほうが良いと思いました。
- 投稿日:2020-07-21T18:17:06+09:00
Kubernetes CLIオンリーのデプロイ環境構築
わざわざJenkinsを立てるのはかったるい、でもデプロイユーザーは欲しい。
そんなわがままな構成です。
Github, aws ECR, k8s(not EKS)という構成。deployサーバはk8sとは別だがEC2。
②~⑥までをSkaffoldが行います。tl;dr
deployユーザーを作成し、skaffold runできるところまでの要点をまとめています。
Deployサーバのユーザー調整
Dockerはインストールしてdeployサーバ上で動かしておいてください。
k8sは、deployサーバから管理者ユーザーからkubectlが一通り動くようにしておいてください。(deployユーザーは別途作ります)POSIXユーザー作成
Deployサーバに普通にadduserしてください。sudo権限はいりません。今回はdeployユーザーとします。
Github DeployKey登録
レポジトリのSettingsからDeploy Keysってのを登録できます。
sshkeygen -t ed25519
とかで作ってください。ssh 秘密鍵作成
Githubへのアクセス権限とサーバへのアクセス権限は変わってくるので別で作っておくことをお勧めします。
きょうびed25519でよいでしょう。
~/.ssh/authorized_keysに追加するのをお忘れなく。sudoなしでdockerコマンドを実行できるように。
こちらを参考に。
https://qiita.com/DQNEO/items/da5df074c48b012152ee
deployユーザにsudo権限はつけないほうがいいので別ユーザーでdeployユーザーをdocker groupに入れてあげておくれまし。
dockerdの再起動とdockerユーザーの再ログインが必要です。k8s ServiceAccount作成
deployユーザーでk8sのクラスタにアクセスできるようにします。
awsのセキュリティグループで、deployサーバからk8sのapiにアクセスできるようにするのを忘れないようにしましょう。デフォルトだと6443番とか?https://qiita.com/murata-tomohide/items/a8a6d66534f55491bd01 を参考にdeployユーザーのサービスアカウントを作成します。clusterrolebindingするところでnamespaceを指定してアクセスを限定します。
aws ECR
Elastic Container Registryの略、Dockerのレジストリですね。
deployサーバからはpushが行える必要があり、k8sのクラスタからはpullができる必要があります。
EC2ロールを使うか、IAMでユーザー作るかはあなた次第。
- ECRリポジトリ作成
- ポリシー調整
- 今回はRoleを付けました。ポリシーはecr:なんちゃら、既存のならばAmazonEC2ContainerRegistryなんちゃらです。
VPCエンドポイントを作成するのを忘れないようにしてください。https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/vpc-endpoints.html#ecr-vpc-endpoint-considerations
ようするに、VPCエンドポイントでECRへのアクセスは内側を通るように設定しましょう。ということです。今回はs3に加えてecrを設定しました。k8s ECR設定
今回はEC2内のノードなので、AmazonEC2ContainerRegistryReadOnlyポリシーEC2のIAMロールに当てました。
ロール使っているのでsecretなどの設定は不要です。github からソースを持ってくる。
githubのDeploykeysを使ってソースを落とします。
環境変数GIT_SSH_COMMANDを入れれば指定した鍵を使ってくれます。(必ずしも~/.gitconfigに書く必要はありません)
$ GIT_SSH_COMMAND='ssh -i ~/.ssh/hogehoge' git clone
Skaffoldでpushする
最初にECRのログインパスワードを取得してログインしておくのを忘れないようにしてください。ECRのpushコマンドの1個目です。(セッション切れ次第再度実行する必要があり〼。)
aws ecr get-login-password --region [region] | docker login --username AWS --password-stdin [repoURL]
マニフェストは
build.artifacts[].imageにECRのリポジトリのURLを入れます。tagはなくてもOKです。同じようにk8sのyamlも変えます。
build.local.pushをtrueにします。https://qiita.com/murata-tomohide/items/5f40a8e6528ecf2e3794
できた
これでdeployサーバからdockerユーザーで一連のデプロイが行えるようになっているはずです。
shell等にしておけば一発ですね。(じゃあJenkinsでええやr、k8sならJenkinsXつかえy)
今回は要点だけにして、コマンド等は端折りました。(手抜きみなさんデプロイオペレーションは自分のPCで行わないようにしましょう。お兄さんとの約束だ。
- 投稿日:2020-07-21T18:09:06+09:00
AWS Elastic File Systemのアップデートについて
EFSの自動バックアップがデフォルト設定に
Announcing automatic backups for Amazon Elastic File System
今までEFSをバックアップする場合は、AWS BackupでVaultを手動で作成する必要がありましたが、上記アップデートによりバックアップ設定を自動で作成してくれるとのこと。
EFSの作成が簡単にできる新しいコンソール
New Amazon Elastic File System console simplifies file system creation and management
今まで諸々と設定を入れなければならなかったEFSが2クリックで作成できるようになっております。
勿論、前述のバックアップもデフォルトで設定。逆に細かい設定をする場合は、カスタマイズという項目を選べばOK。
バックアップの可否も決めることが可能。簡単作成について
まずは新しいコンソール画面。
[ファイルシステムの作成から]…
[作成]。
もうできた!!自動バックアップについて
ちなみに自動バックアップの設定は以下。
増分バックアップですが、毎日取得のライフサイクル5週間なので、
費用を抑えるなら1週間とかに変えた方が良さそう。
- 投稿日:2020-07-21T16:57:53+09:00
AWSハンズオン実践メモ 〜AWS 環境のコード管理 AWS CloudFormationで Web システムを構築する〜
はじめに
AWS公式のハンズオンシリーズの中から、CloudFormationで Web システムを構築するハンズオンを実施しました。
本記事は自身のハンズオン学習メモとして投稿します。
目次
ハンズオンの目的
- AWS環境をコードを使用して管理する方法を学習する
クラウドにおける構成管理の考え方をご理解頂くとともに、AWS CloudFormationを使用したWebシステムの環境構築について、実際に手を動かして理解を深めることができます。
(https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/ より引用)
本編
開発環境の構築
- 開発環境としてAWS Cloud9の環境を構築
- マネジメントコンソールからインスタンスを作成
- Cloud9の環境確認と設定
- バージョン情報の確認
- AWS CLIの補完設定
- エディタ設定
テンプレートの実行方法+VPCの作成
- マネジメントコンソールからVPC用スタックを作る
01_vpc.ymlAWSTemplateFormatVersion: 2010-09-09 Description: Hands-on template for VPC Resources: CFnVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 InstanceTenancy: default EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: handson-cfn PublicSubnet1: Type: AWS::EC2::Subnet Properties: CidrBlock: 10.0.0.0/24 VpcId: !Ref CFnVPC AvailabilityZone: !Select [ 0, !GetAZs ] MapPublicIpOnLaunch: true Tags: - Key: Name Value: PublicSubnet1 PublicSubnet2: Type: AWS::EC2::Subnet Properties: CidrBlock: 10.0.1.0/24 VpcId: !Ref CFnVPC AvailabilityZone: !Select [ 1, !GetAZs ] MapPublicIpOnLaunch: true Tags: - Key: Name Value: PublicSubnet2 PrivateSubnet1: Type: AWS::EC2::Subnet Properties: CidrBlock: 10.0.2.0/24 VpcId: !Ref CFnVPC AvailabilityZone: !Select [ 0, !GetAZs ] Tags: - Key: Name Value: PrivateSubnet1 PrivateSubnet2: Type: AWS::EC2::Subnet Properties: CidrBlock: 10.0.3.0/24 VpcId: !Ref CFnVPC AvailabilityZone: !Select [ 1, !GetAZs ] Tags: - Key: Name Value: PrivateSubnet2 CFnVPCIGW: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: handson-cfn CFnVPCIGWAttach: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref CFnVPCIGW VpcId: !Ref CFnVPC PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref CFnVPC Tags: - Key: Name Value: Public Route PublicRoute: Type: AWS::EC2::Route DependsOn: CFnVPCIGW Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref CFnVPCIGW PublicSubnet1Association: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicRouteTable PublicSubnet2Association: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet2 RouteTableId: !Ref PublicRouteTable Outputs: VPCID: Description: VPC ID Value: !Ref CFnVPC Export: Name: !Sub ${AWS::StackName}-VPCID PublicSubnet1: Description: PublicSubnet1 Value: !Ref PublicSubnet1 Export: Name: !Sub ${AWS::StackName}-PublicSubnet1 PublicSubnet2: Description: PublicSubnet2 Value: !Ref PublicSubnet2 Export: Name: !Sub ${AWS::StackName}-PublicSubnet2 PrivateSubnet1: Description: PrivateSubnet1 Value: !Ref PrivateSubnet1 Export: Name: !Sub ${AWS::StackName}-PrivateSubnet1 PrivateSubnet2: Description: PrivateSubnet2 Value: !Ref PrivateSubnet2 Export: Name: !Sub ${AWS::StackName}-PrivateSubnet2
- Cloud9でのテンプレートの編集
パラメータについては、適宜テンプレートリファレンスを参照して作成していく。
- AWS CLIを利用してスタックの更新
validateして
aws cloudformation validate-template --template-body file://01_vpc.ymlupdateする
aws cloudformation update-stack --stack-name handson-cfn --template-body file://01_vpc.ymlEC2の作成
- 配布したテンプレートでEC2を起動
createする
aws cloudformation create-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
- 不足設定を書き加えて、テンプレートを完成させる
02_ec2.ymlAWSTemplateFormatVersion: 2010-09-09 Description: Hands-on template for EC2 Parameters: VPCStack: Type: String Default: handson-cfn EC2AMI: Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 Resources: EC2WebServer01: Type: AWS::EC2::Instance Properties: ImageId: !Ref EC2AMI InstanceType: t2.micro SubnetId: subnet-04c1d329aec13802b UserData: !Base64 | #! /bin/bash yum update -y amazon-linux-extras install php7.2 -y yum -y install mysql httpd php-mbstring php-xml wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/ tar zxvf /tmp/latest-ja.tar.gz -C /tmp cp -r /tmp/wordpress/* /var/www/html/ touch /var/www/html/.check_alive chown apache:apache -R /var/www/html systemctl enable httpd.service systemctl start httpd.service SecurityGroupIds: - !Ref EC2SG EC2SG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: sg for web server VpcId: vpc-0dca3e5092f72557c SecurityGroupIngress: - IpProtocol: tcp CidrIp: 10.0.0.0/16 FromPort: 80 ToPort: 80 Outputs: EC2WebServer01: Value: !Ref EC2WebServer01 Export: Name: !Sub ${AWS::StackName}-EC2WebServer01validateして
aws cloudformation validate-template --template-body file://02_ec2.ymlupdateする
aws cloudformation update-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.ymlRDS, ELBの作成、スタックのライフサイクル・分割
- RDS・ELB用スタックの作成
以下のテンプレートを作成し、上記と同様にCreate&validate&update。
03_rds.ymlAWSTemplateFormatVersion: 2010-09-09 Description: Hands-on template for RDS Parameters: VPCStack: Type: String Default: handson-cfn DBUser: Type: String Default: dbmaster DBPassword: Type: String Default: H&ppyHands0n NoEcho: true Resources: DBInstance: Type: AWS::RDS::DBInstance DeletionPolicy: Delete Properties: DBInstanceClass: db.t2.micro AllocatedStorage: "10" StorageType: gp2 Engine: MySQL MasterUsername: !Ref DBUser MasterUserPassword: !Ref DBPassword DBName: wordpress BackupRetentionPeriod: 0 DBSubnetGroupName: !Ref DBSubnetGroup VPCSecurityGroups: - !Ref DBSecurityGroup DBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: DB Subnet Group for Private Subnet SubnetIds: - Fn::ImportValue: !Sub ${VPCStack}-PrivateSubnet1 - Fn::ImportValue: !Sub ${VPCStack}-PrivateSubnet2 DBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Sub ${AWS::StackName}-MySQL VpcId: Fn::ImportValue: !Sub ${VPCStack}-VPCID SecurityGroupIngress: - IpProtocol: tcp FromPort: 3306 ToPort: 3306 CidrIp: 10.0.0.0/16 Outputs: DBEndpoint: Value: !GetAtt DBInstance.Endpoint.Address Export: Name: !Sub ${AWS::StackName}-DBEndpoint04_elb.ymlAWSTemplateFormatVersion: 2010-09-09 Description: Hands-on template for ALB Parameters: VPCStack: Type: String Default: handson-cfn EC2Stack: Type: String Default: handson-cfn-ec2 Resources: FrontLB: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Ref AWS::StackName Subnets: - Fn::ImportValue: !Sub ${VPCStack}-PublicSubnet1 - Fn::ImportValue: !Sub ${VPCStack}-PublicSubnet2 SecurityGroups: - !Ref SecurityGroupLB FrontLBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: LoadBalancerArn: !Ref FrontLB Port: 80 Protocol: HTTP DefaultActions: - Type: forward TargetGroupArn: !Ref FrontLBTargetGroup FrontLBTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Name: !Sub ${AWS::StackName}-tg VpcId: Fn::ImportValue: !Sub ${VPCStack}-VPCID Port: 80 Protocol: HTTP HealthCheckPath: /.check_alive Targets: - Id: Fn::ImportValue: !Sub ${EC2Stack}-EC2WebServer01 SecurityGroupLB: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Ref AWS::StackName VpcId: Fn::ImportValue: !Sub ${VPCStack}-VPCID SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 Outputs: FrontLBEndpoint: Value: !GetAtt FrontLB.DNSName Export: Name: !Sub ${AWS::StackName}-Endpoint
- 完成した構成の動作を確認
無事にWordPressに接続成功。
スタックのライフサイクル・分割について
- 個々のスタックは、ライフサイクルと所有者を基準に分割
- VPC用スタックをベースとして、他スタックからクロススタック参照によって連携
作成した AWS リソースの削除
スタックを削除すると紐づくリソースが全て削除される。
おわりに
異なるスタックのリソースを参照できるクロススタック参照と、ネストの方法について調べてみた。
クロススタック参照
- 参照される側のテンプレート
"Outputs"の項目でExportプロパティを記述し、値をエクスポート- 参照する側のテンプレート
組み込み関数Fn::ImportValueを使って、値をインポート詳しくは以下を参照。
CloudFormationのスタック間でリソースを参照するネスト
以下により、上位テンプレートで下位テンプレートからの出力を受ける事が出来る。また、上位テンプレートで受けた出力は別の下位テンプレートへの入力として指定することもできる。
- ネストするテンプレートをAmazonS3上にアップロード
- 下位のテンプレートで渡したいパラメータをOutputsに記述
- 上位のテンプレートでは"組み込み関数Fn::GetAttを利用する
詳しくは以下を参照。
CloudFormationでスタックをネストする所感
スタックの作成時、テンプレートから依存関係を自動で判別し構築してくれるのは便利だと感じた。
比較対象としては他プラットフォームも含めて管理できるTerraformが挙がってくると思うので、そちらも触ってみたい。
- 投稿日:2020-07-21T16:54:16+09:00
[C#]AWSの使用料金をAPIで取得する
AWSの使用料金がえらいことに・・・
思いのほかAWSの使用料金が上がっていて、青ざめた経験が誰しもあるはず。
定期的に請求ページを確認すればいいのですが、休日は見てなかったりして
気づいたときは多額の請求がきていた…なんてことも。そこで、CostExplorer APIを使っていつどのくらい使用したのかわかるようにしてみました。
※CostExplorer APIはリクエストごとに費用が発生するのでやりすぎに注意しましょう!
(記載時点で1回のリクエストにつき0.01ドル)必要なもの
AWSのAccessKeyとSecretKey
AWSSDK.CostExplorerをインストールコード(Console)
string awsAccessKey = "xxxxxxxxxxx"; string awsSecretKey = "xxxxxxxxxxxxxxxxxxxxx"; AmazonCostExplorerClient client = new AmazonCostExplorerClient(awsAccessKey, awsSecretKey, RegionEndpoint.USEast1); GetCostAndUsageRequest req = new GetCostAndUsageRequest(); req.TimePeriod = new DateInterval(); req.TimePeriod.Start = "2020-07-01"; req.TimePeriod.End = "2020-07-20"; req.Granularity = Granularity.DAILY; req.Metrics = new List<string>() { "AMORTIZED_COST" }; GetCostAndUsageResponse cost = client.GetCostAndUsage(req); for (int i = 0; i < cost.ResultsByTime.Count; i++) { string start = cost.ResultsByTime[i].TimePeriod.Start; string end = cost.ResultsByTime[i].TimePeriod.End; foreach (string key in cost.ResultsByTime[i].Total.Keys) { decimal amount = decimal.Parse(cost.ResultsByTime[i].Total[key].Amount); string unit = cost.ResultsByTime[i].Total[key].Unit; Console.WriteLine(start + "~" + end + " Amount=" + amount + " Unit=" + unit); } }結果
2020-07-01~2020-07-02 Amount=47.6436917916 Unit=USD 2020-07-02~2020-07-03 Amount=47.2799385496 Unit=USD 2020-07-03~2020-07-04 Amount=0.0012009547 Unit=USD 2020-07-04~2020-07-05 Amount=0.001352335 Unit=USD 2020-07-05~2020-07-06 Amount=0.0013171085 Unit=USD 2020-07-06~2020-07-07 Amount=0.0013171085 Unit=USD 2020-07-07~2020-07-08 Amount=0.0013171085 Unit=USD 2020-07-08~2020-07-09 Amount=0.0013171085 Unit=USD 2020-07-09~2020-07-10 Amount=0.2201781931 Unit=USD 2020-07-10~2020-07-11 Amount=48.1395790234 Unit=USD 2020-07-11~2020-07-12 Amount=48.1393261349 Unit=USD 2020-07-12~2020-07-13 Amount=48.1394533349 Unit=USD 2020-07-13~2020-07-14 Amount=6.6676519934 Unit=USD 2020-07-14~2020-07-15 Amount=0.0009903077 Unit=USD 2020-07-15~2020-07-16 Amount=0.0009903077 Unit=USD 2020-07-16~2020-07-17 Amount=0.0009903077 Unit=USD 2020-07-17~2020-07-18 Amount=0.0009903077 Unit=USD 2020-07-18~2020-07-19 Amount=0.0009903077 Unit=USD 2020-07-19~2020-07-20 Amount=0.0009903077 Unit=USD10日~13日にやらかしてますね…
この時、DocumentDBの検証をやっていてインスタンス落とすの忘れてて
土日放置してたようです。あとは、このレポートを定期的/閾値を超えたらメールで送ったり
メッセンジャーに送ったりすれば被害を低減できるでしょうか。そもそも自分でちゃんと管理しろと言われそうですがね。
自分用の雑なコンソールアプリです。
閾値を超えたらメール送信するアプリ
- 投稿日:2020-07-21T16:23:50+09:00
【初心者】AWS Hands-on for Beginnersをやってみた感想
はじめに
AWS(Amazon Web Services)には、初めてAWSを触る人向けに、ハンズオン形式学ぶことができる「AWS Hands-on for Beginners」というコンテンツが提供されています。
オンプレの現場経験のない自分が、こちらを一通り学んでみた所感を書き連ねようと思います。
「AWSを触ってみたいけど、よくわからないからハンズオンで学んでみようかな...」
と考えている方の参考になれば幸いです。行ったコンテンツ
ハンズオンはじめの一歩: AWS アカウントの作り方 & IAM 基本のキ
Security #1 アカウント作成後すぐやるセキュリティ対策
Network 編#1 AWS 上にセキュアなプライベートネットワーク空間を作成する
注意事項
基本的には受講する前提条件はありません。
アカウント作成もコンテンツ内で丁寧に解説されています。
しかし、すでに所持しているAWSアカウントを使用する方は注意が必要です。
ハンズオン内で様々なリソースを作成するため、今あるリソースに影響が及ぶ可能性がありますので注意して進めてください。
また、一部料金が発生するコンテンツもあります。
詳しくはコンテンツ内で解説されているのでご参照下さい。自分が進めていく中ではそんなにかかっていないので($1にも満たない)あまり気にしすぎないでもいいと思われます。
事前知識(あればいいかな程度)
AWSの基礎知識(簡単な単語を見てわかる程度)
- 「リージョン」,「アベイラビリティーゾーン」,「EC2」といった基本的な用語がすごく出てきます。
途中で少し解説があり、知らなくても問題はないですが、知っていたほうがよりわかりやすいです。ネットワークやミドルウェアの知識(概要)
- AWS上でネットワークを構築してちょっとしたシステムを動かす、みたいなことも行うので、サーバの役割やデータベースがどういうものか、IPアドレスはなんなのか等はわかっておいたほうがいいのかなと思います。
「冗長性」や「ロードバランサ」などの単語に聞き覚えがあれば問題ないかと思います。それぞれのコンテンツについて
ハンズオンはじめの一歩: AWS アカウントの作り方 & IAM 基本のキ
まず、AWSアカウントの作り方を学びます。
その後、AWSアカウントを何も見ずに作ると真っ先につまずくであろう「ルートユーザ」と「IAMユーザ」の違いを、実際にユーザを作成しながら理解します。
IAMユーザにはポリシーと呼ばれるアクセス権限の設定を振りあてるのですが、デフォルトで用意されているポリシーだけではなく、自分でポリシーを作ってみるということも行います。
そしてグループとロールの概念を理解し、終了となります。
こちらのコンテンツでは、AWSで作業を行うにあたって基本であるアカウント周りについてわかりやすくカバーされていたかなと感じます。
IAMという概念を理解していなければ、「リソースにアクセスできない」などでつまずいてしまうこともあるのかな?と思ったので、普段IAMユーザの方も知識として持っておいて損はないと思います。
Security #1 アカウント作成後すぐやるセキュリティ対策
こちらのコンテンツでは、上記で作成したアカウントのIAMページにある「セキュリティステータス」をオールグリーンにすることを目標に進めます。
その後、請求金額の確認方法やレポートの取り方などAWSを利用していく上での基本的な管理方法、セキュリティ上やるべきことを学びます。そして「ベストプラクティス」と呼ばれるシステムの最も良い状態を目指すためにやるべきことを確認します。
ハンズオンなので実際に手を動かしてレポートをためてみたり、予算を決定してみたりするのは非常にわかりやすく、よりセキュアに今後AWSを利用できるようになると思います。
しかし、レポートをためる演習の際は、一定期間リソースを動かしておかないとレポートがたまらないので、講師が行っているのをみて納得するしかないのかなと思います。
Network 編#1 AWS 上にセキュアなプライベートネットワーク空間を作成する
このコンテンツでは実際にVPC(Virtual Private Cloud)を作成し、AWS内にネットワーク空間を作成します。
VPC内の「PrivateSubnet」と「PublicSubnet」について理解をし、実際にルーティングを定義します。そしてVPCにインターネットゲートウェイを置き、通信を行います。
また、PrivateSubnetから「NAT ゲートウェイ」を用いたインターネットへの接続方法とその用法も学びます。
構成図を見ただけでは理解しにくい「VPC」、「サブネット」などを実際にアドレスを定義してルートテーブルを明示的に関連付けすることで、AWSのネットワークについて理解できる非常にいい内容だったなと思います。
汎用的な構成図をもとに作成していたので、自分で応用もできるような内容でした。スケーラブルウェブサイト構築編
本コンテンツでは、最終目標をスケーラブルなWebサイトが構築できるまでとし、進めていきます。
なのでかなり具体的にAWSの使い方がとらえられるコンテンツかなと思います。まず、VPCを作成し、EC2(Elastic Compute Cloud:仮想サーバを構築できるサービス)でWebサーバを作成し、WordPressをインストールします。
次に、そのWordPress用のDBをRDS(Relational Database Service:分散リレーショナルデータベースサービス)で作成します。
そして、ロードバランサを作成し、AMI(Amazon マシンイメージ)により2つ目のEC2インスタンスを起動し、先ほど作成したRDS DBインスタンスのマルチAZ化を行います。
その後、システム全体の可用性の確認と称して片方のEC2インスタンスを停止しても問題がないこと、RDSのフェイルオーバーを行っても問題がないことを確認し、終了となります。
全体を通してAWSでよく言われているマルチAZ配置がよくわかりました。片方のEC2を実際に落としてみて可用性を確認するのは楽しかったです。
どういう構成にするのかというのは大事なことなので、私のような初心者にはお勧めの内容となっていると思います。AWS 上で静的な Web サイトを公開しよう!
本コンテンツではHTMLとCSSで構成された静的なWebサイトをS3(Simple Storage Service:オンラインストレージのWebサービス)のホスティング機能を用いて公開します。
Cloud9(オンラインのIDE)を用いて静的コンテンツを開発し、AWS CLI(Command Line Interface:コマンドラインからサービスを制御できるサービス)でコンテンツの最初に作るS3のバケットにファイルをアップします。
そしてS3のホスティング機能を用い、外からWebページがしっかりと表示されていることを確認します。
また、CloudFrontを用いてキャッシュさせてCDNを体験します。
その後はオプションとなるのですが、Route 53を用いて独自のドメインを取得し、S3にHTTPアクセスをしてみたり、ACMで証明書を発行し、HTTPS通信を実現します。
実務では静的なWebサイトを用いた構成はそんなにないとは思うのですが、こういった学習で抽象的になってしまうCDNを体験できるのはいいかなと思います。
ですが、CloudFrontが一つの変更を行うのに数分から数十分かかってしまい、さくさく進められないハンズオンだなという印象を受けました。
まとめ
今回、AWS Hands-on for Beginners をやってみて、非常にわかりやすいハンズオンであると感じました。
一つ一つの画面に対して丁寧に解説を行っていたり、それぞれのリソースがどういった動きをするのかを構成図からわかりやすく解説をされていて、非常に為になると思いました。自分のようにオンプレの経験がなくともAWSやクラウドに興味があるという方にはいい内容かなと思うのでぜひご参考ください。
- 投稿日:2020-07-21T15:23:02+09:00
オンプレからAWSに移行した話
もう一年以上前の話ですが、エキサイトのWisteriaをAWSに移行した話を書こうと思います。
Wisteriaとは
機械学習を使ったコンテンツレコメンドのシステムです、紹介ページ
システム構成
移行前のシステム構成はこんな感じ、MLの部分が重いのでキューの仕組みを入れて処理をしていました。
移行前の課題
- openstackが暴走する
- cassandraが安定しない
- zookeeperのファイルがよく壊れる
- stormがうまく立ち上がらない
- 色んなミドルウエアのバージョンが古い
- 障害時にサーバーが多すぎて、原因の特定が難しい(ログが色んな場所に点在)、zabbixも入れているがそれだけでは追いきれない
会社ではDevOpsが推奨されていたので、サーバー周りもアプリケションエンジニアが見ないといけない、3ヶ月に一度は障害が起きていたのでしんどい
移行の計画
オンプレでは運用上の色んな問題があり、せっかく移行するので問題を解決しつつ、クラウドに最適化した形で運用のコストを下げたいと言う思いがありました、そこで考えたプランは3つ
プランA (色々最適化)
- Front / Api / Tool / Batch はコンテナ(ECS)
- MySQLはAurora
- CassandraはDynamoDB
- Kafka、StormはKinesis、Lambda
- AutoScale、自動Deployなど
プランB (問題になっている部分をなるべくマネージド)
- Front / Api / Tool / Batch はEC2
- MySQLはAurora
- CassandraはDynamoDB
- Kafka、StormはMSK、EC2
- AutoScale、自動Deployなど
プランC (ほぼ何もせずそのまま移行)
- Front / Api / Tool / Batch / Cassandra / Kafka、Storm はEC2
- MySQLはAurora
- AutoScale、自動Deployなど
移行期間が2ヶ月と言うこともありプランAは現実的に無理、頑張ればプランBで行けるかもしれないということでプランBで行くことにしました。
メンバー構成
初期メンバーは3名+途中から1名追加になり計4名で行いました、分担は以下の通り
- EC2を構築してアプリケーションを移行するメンバー
- CassandraをDynamoDBに移行するメンバー
- Kafka、Stormを移行するメンバー
- その他は手が開いた人がやる
みんなクラウド移行はほぼ初めてだったので、実際に移行を始めるといろんな問題が発生することになった
移行
EC2編
オンプレ時代からansibleで構成管理していたので、スムーズにくと思っていたが…
- OS古い問題
- Ubuntu16を使っていたがサポートが2021年で切れるため、やもなくUbuntu18へアップデート
→ これにより諸々のパッケージのバージョンが上がる、フロント、APIをphpで書いていたので、アプリケーションのテスト工数が膨らむ、やもなくphpだけダウングレード
Kafka/Storm編
- バージョンがあまりにも古い問題
- Stormのバージョンがv0.9.xだったので、ec2でもこのバージョンをインストール、Amazon MSKと連携してみたが全くうまくいかない
→ チーム内で協議
①stomのバージョンをあげてMLのソースを書き直す
②MSKを使わず、kafkaをec2で構築する
③kafka/stormをやめる
→ ③を選択し、kinesis/Lambdaにすることにしました。理由は、運用で悩まされていたkafka/stormをやめたかった、将来的にStormをやめるのにソースを書き直すモチベーションがわかないなどCassandra編
- Cassandraのデータ移行に悪戦苦闘
- マイグレーションツールを使って移行をする予定で進めていたが、Macだとツールが不安定で落ちたり、ツールの使い方も分からなかった部分もあり悪戦苦闘、ようやく進んだと思ったらcassandraとツールのバージョンが合わず、そもそも使えなかったりで1ヶ月溶かす
→ 結局マイグレーションツールを使わず、cassandraのデータをダンプして、データパイプラインで入れることにしました。
移行後の構成
そんなこんなで移行後の構成はこうなりました。
当初想定していた構成とは若干異なりますが、ec2以外はマネージドにすることが出来ました。感想
大変な部分もありましたが比較的順調に移行が行えました。
クラウドに移行したことにより、運用で問題になっていた部分もほぼ解消し、安定した運用が行えるようになりました。
費用も半分以下に抑えることができてよかったです。サーバー周りのインフラ的なことから解放され、アプリケーションに専念できることが一番よかったとつくづく思います。
- 投稿日:2020-07-21T13:49:25+09:00
【AWS SQS】SQSを構築し、EC2からメッセージをポーリングする
目標
AWS SQSを構築しメッセージをキューに投入(AWSコンソール上から投入する)、その後投入したメッセージをAWS SDKを利用してEC2から取得(ポーリング)する。
SQSとは
アプリケーション間でやりとりされるメッセージを送受信するためのAWSが提供するキューサービスのこと。
受信側がメッセージをSQSに問い合わせてメッセージを取得するPull型のサービスです。SQSに関する基本情報は以下記事がわかりやすくまとめられていると思いました。
Amazon SQS前提
・AWS SDK(AWS SDK for Rubyを本記事では利用)を使用可能なEC2インスタンスが構築済みであること(※)。
※AWS SDK for Rubyを構築した際の参考手順
【AWS SDK】EC2自動構築用スクリプト(1.AWS SDK for Rubyのセットアップ)作業の流れ
項番 タイトル 1 SQSの構築 2 SQSにメッセージを送信 3 EC2からメッセージをポーリングする 手順
1.SQSの構築
①SQSコンソールを開く
②
キューを作成
をクリック③作成するキューの設定
今回はスタンダードキューを利用します(※1)
キューの名前は任意のものを記載します。※1 SQSには以下2つのタイプのキューが存在します。特徴を簡単にまとめます。
・スタンダードキュー
⇒最低1回のメッセージ配信を保証するが、リクエストのタイミングによっては同一メッセージが複数回配信される可能性がある。
⇒メッセージ配信の順序はベストエフォート型(メッセージ送信と配信の順序が異なる可能性がある。)・FIFOキュー
⇒同一メッセージが複数回配信されることはない。
⇒メッセージ配信の順序は先入れ先出し型(メッセージ送信と配信の順序が同一となる。)
⇒高性能なため、スタンダードキューよりも少し料金が高い。キューの詳細設定(※2)をします。
今回はメッセージ受信待機時間
のみ20秒に設定し、それ以外はデフォルトのままとしています。※2 以下簡単にキューの詳細設定の内容を記載致します。
・可視性タイムアウト
メッセージを受信した後に一定時間、該当のメッセージを他システムから見えなくさせる機能のこと。
可視性タイムアウトとして指定した時間内にメッセージ処理を完了させ、メッセージ削除することで、
同一メッセージに対する複数回処理を防ぐことが可能となります。・配信遅延(遅延キュー)
キューにメッセージを送信した後、指定した時間が経過した後にメッセージを表示させるようにする機能・メッセージ受信待機時間
ロングポーリングorショートポーリングの設定を行うことが出来ます。
デフォルトはショートポーリング(メッセージ受信待機時間が0秒)となっており、キューが空の場合でもすぐ再リクエストを行います。
SQSはメッセージのリクエスト回数によって料金が判断されるため、空メッセージのリクエストを繰り返すと料金がかさんでしまいます。
その対策として有効なのが、ロングポーリング(メッセージ受信待機時間が0秒より上)となります。
ロングポーリングを設定すると空メッセージを受け取った場合、指定した秒数分待機する(キュー接続を持続する)ため、
SQSのリクエスト回数を減らし料金を節約することが可能となります。
要件にもよりますが、基本的にはロングポーリングを使用するのがAWSの推奨となっているようです。キューへのアクセス設定はデフォルトのままとします。
最後に暗号化、デッドレターキュー(※3)、タグの設定もありますが今回は設定なしとします。
キューの作成
をクリック※3 デッドレターキュー
処理結果がエラーとなったメッセージを何回かリトライ後、自動的に別のキューに移動する機能
問題のあるメッセージが別キューに集中するため識別しやすくなり、当該メッセージが正規のキューに残存することを防ぎます。2.SQSにメッセージを送信
作成したSQSキューにAWSコンソール上からメッセージを送信してみます。
①作成したSQSキューの詳細画面から
メッセージの送受信
をクリック
②
メッセージ本文
を記載後メッセージ送信
をクリック
この手順を何回か繰り返します。
③送信したメッセージの内容確認
メッセージ送信欄の下段にあるメッセージ受信欄からメッセージをポーリング
をクリック
メッセージが表示されればOKです
3.EC2からメッセージをポーリングする
①AWS SDK for Rubyが利用可能なEC2インスタンスにポーリング実行用スクリプトを配備
# ********************************************************************************** # <機能概要> # 指定したSQSキューのメッセージをポーリングする # # <機能詳細> # 常駐プロセスとして稼働し、指定したSQSキューのメッセージをポーリングし取得時刻及びメッセージ本文を標準出力する。 # 取得したメッセージは出力後削除する。 # メッセージが空の場合は指定した時間(wait_time_seconds)分待機した後、キューが空であることを伝えるメッセージを出力する。 # # <スクリプト用法> # ruby <スクリプトパス> # ********************************************************************************** require 'aws-sdk' # キュー名 queue_name = "MyTestQueue" # SQS操作用インスタンス作成 sqs = Aws::SQS::Client.new # キューURLの取得 begin queue_url = sqs.get_queue_url(queue_name: queue_name).queue_url rescue Aws::SQS::Errors::NonExistentQueue puts "A queue named '#{queue_name}' does not exist." exit(false) end loop do # キューからメッセージを取得 receive_message_result = sqs.receive_message({ queue_url: queue_url, message_attribute_names: ["All"], # 全属性のメッセージを取得 max_number_of_messages: 5, # 最大でも5メッセージの取得 wait_time_seconds: 20 # メッセージが空の場合は20秒待機 }) # メッセージを取得した時刻を取得 timestamp = Time.new # メッセージが空のときはemptyメッセージ出力 if receive_message_result.messages.nil? puts "#{timestamp.strftime("%Y-%m-%d %H:%M:%S")}: Message is empty." end receive_message_result.messages.each do |message| # 取得したメッセージ本文を表示 puts "#{timestamp.strftime("%Y-%m-%d %H:%M:%S")}: #{message.body}" # メッセージをキューから削除 sqs.delete_message({ queue_url: queue_url, receipt_handle: message.receipt_handle }) end end②スクリプト実行し、メッセージをポーリングする。
AWSコンソールから事前投入した3つメッセージは即座に処理され、メッセージが空の場合は指定した時間分待機することを確認できました。
またメッセージ待機中に新規メッセージをキューにプットした場合、そのメッセージは即座に処理されることも確認できました。[ec2-user@basehost ~]$ ruby queue.rb 2020-07-21 04:13:32: test2 # AWSコンソールから事前投入したメッセージその1 2020-07-21 04:13:33: test3 # AWSコンソールから事前投入したメッセージその2 2020-07-21 04:13:33: test1 # AWSコンソールから事前投入したメッセージその3 2020-07-21 04:13:53: Message is empty. # wait_time_secondsで指定した時間分(20秒)待機後、emptyメッセージ出力 2020-07-21 04:14:01: This message is the message sent during the waiting time. # メッセージ待機時間中にキューにプットしたメッセージ、プット後即座に処理された。 2020-07-21 04:14:21: Message is empty. 2020-07-21 04:14:41: Message is empty. 2020-07-21 04:15:01: Message is empty.
- 投稿日:2020-07-21T11:54:23+09:00
PythonではじめるAWS CDK
Pythonで始めるAWS CDK
最近までいろいろと触る機会があったのと、AWS CDK+Pythonの記事が少なかったので書いてみた。
内容はAWS CDKのインストール〜デプロイまで。ついでにLambda関係でよく使いそうなところをいくつか。実行環境
- Python 3.7.4
- OSX Catalina 10.15.5
Python、Pipが実行可能な環境であることが前提で書いています。
はじめに
AWS CDKってなに?
AWS クラウド開発キット (AWS CDK) は、使い慣れたプログラミング言語を使用してクラウドアプリケーションリソースをモデル化およびプロビジョニングするためのオープンソースのソフトウェア開発フレームワークです。
かなり大雑把にまとめると、使い慣れたプログラミング言語でAWSのリソースを定義、作成できるIaC(Infrastructure as Code)ツールですよっと。
なんでAWS CDKなの?
環境設定をコードで管理したい。けどterraformとかに手を出すほどでもないし、template.ymlは書きたくない…。何よりAWSの公式!
なんでPythonなの?
(TypeScriptやったことないから…)
LambdaをPythonで書いていたからその延長線上でPythonでやってみた使ってみた感想
- 後述するが間接的にCloudFormationを使用しているので、実務で使用する場合はAWS CloudFormation の制限は一読しておくことをお勧めする。
- リリースは頻繁にされているので日々改善されているようだが、使い込んでいくと正直、現状では痒いところに手が届かない感が否めない。少なくともクロススタック参照はなんとかして欲しい。
- 調べて出てくるのはTypeScriptがほとんどなので、わざわざPythonを使うメリットはそこまでない
AWS CDKのインストール
- Getting started with the AWS CDKを参考に進めていく。
Node.jsのインストール
前提として、Node.jsが必要なのでインストールされていない場合はまずこちらをインストールする
なぜNode.jsが必要かというと、AWS CDK自体はTypeScriptで書かれており、Pythonなど他の言語はjsiiというライブラリで自動的にTypeScriptに変換してくれているらしい。すごい。Q: AWS CDK を使用するために JavaScript ランタイムをインストールする必要があるのはなぜですか?
AWS は、AWS Construct ライブラリパッケージのビジネスロジックを TypeScript で構築し、サポートされている各プログラミング言語へのマッピングを提供します。これにより、AWS CDK コンストラクトの動作が異なる言語間で一貫していることを確認でき、すべての言語で利用できる包括的なコンストラクトパッケージのセットを提供できます。AWS CDK プロジェクトで作成したコードはすべてお客様ご希望のプログラミング言語でネイティブになっています。JavaScript ランタイムはお客様のプログラミング経験の実施詳細です。jsii プロジェクトは https://github.com/aws/jsii で参照できます。Node.jsのインストール自体は簡単で、Node.jsの公式からインストーラをダウンロード。あとはインストーラに従ってポチポチしていけば勝手にインストールしてくれる。
インストールが完了したらバージョンを確認
$ node -v v12.18.2 $ npm -v 6.14.5AWS認証情報の設定
AWS CLIがインストールされている場合は
aws configure
コマンドを実行すればプロンプトで設定可能だが、わざわざAWS CLIインストールしたくない場合は手動で設定する。以下はmac or linuxの設定手順。Windowsの場合は
%USERPROFILE%\.aws\config
と%USERPROFILE%\.aws\credentials
を作成し、認証情報、リージョンを設定する$ mkdir ~/.aws $ touch ~/.aws/config $ touch ~/.aws/credentialsエディタで
~/.aws/config
を開き、以下の通りリージョンを設定し、保存する[default] region=ap-northeast-1エディタで
~/.aws/credentials
を開き、以下の通り認証情報を設定し、保存する。[default] aws_access_key_id={アクセスキーID} aws_secret_access_key={シークレットアクセスキー}AWS CDKのインストール
npmを使用してインストールする
$ sudo npm install -g aws-cdkバージョンを表示し、インストールされていることを確認。
$ cdk --version 1.52.0 (build 5263664)デプロイ用S3バケットの作成
cdk bootstrap
コマンドでCloudFormationで使用するS3バケットを作成する
これはリージョンごとに実施する必要があるので注意。$ cdk bootstrap ⏳ Bootstrapping environment aws://323617333195/ap-northeast-1... CDKToolkit: creating CloudFormation changeset... ✅ Environment aws://323617333195/ap-northeast-1 bootstrapped.CDK appを作る
- Your first AWS CDK appを参考に進めていく。
- 参考までに、今回作成したコードはここに置いてあります。
プロジェクトディレクトリを作成
mkdir hello-cdk cd hello-cdk
cdk init
コマンドを実行cdk init app --language python
実行が終わったらvirtualenvを起動する
(pip3を使用している場合はpip3に読み替えて実行すること)source .env/bin/activate pip install -r requirements.txtpipenvを使用したい場合は、virtualenvを起動せずに
.env
ディレクトリを削除して代わりにpipenvを起動するS3バケットを作成してみる
pip install aws-cdk.aws-s3
hello_cdk_stack.pyにs3バケットを作成するコードを追加する
(bucket_nameは既存のバケット名と重複するとデプロイ時にエラーになるため、重複しないものへ書き換えること)hello_cdk_stack.pyfrom aws_cdk import core from aws_cdk import aws_s3 as _s3 class HelloCdkStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here bucket = _s3.Bucket(self, "MyFirstBucket", bucket_name="kimi-first-cdk-bucket")デプロイコマンドを実行
$ cdk deploy hello-cdk: deploying... hello-cdk: creating CloudFormation changeset... ✅ hello-cdk Stack ARN: arn:aws:cloudformation:ap-northeast-1:323617333195:stack/hello-cdk/3497b790-ca3f-11ea-9236-0eb7b90bbf8eデプロイ完了後にAWSマネジメントコンソールでS3バケットが作成されていることを確認できた
AWSマネジメントコンソールでCloudFormationを開くと
hello-cdk
というスタックができている。これはAWS CDKがリソースを作成するのにCloudFormationを使用しているため。
cdk synth
コマンドを実行すればCloudFormationテンプレートを出力することもできる。$ cdk synth
また、作成したリソースを全て削除したい場合は
cdk destroy
コマンドでスタック単位でリソースを削除することが可能。
ただし、S3バケットなど削除されないリソースが一部あるので注意が必要。$ cdk destroy
Lambdaをデプロイしてみる
- 参考までに、今回作成したコードはここに置いてあります。
シンプルなLambda関数をデプロイする
新しいプロジェクトを作成。
$ mkdir cdk-lambda $ cd cdk-lambda/ $ cdk init app --language pythonせっかくなのでPipenvを使ってみる。
$ rm -rf .env $ rm -rf source.bat $ rm -rf requirements.txt $ pipenv shell必要なパッケージをインストール
$ pipenv install aws_cdk.core $ pipenv install aws_cdk.aws_lambdaLambda関数を置くディレクトリを作成し、Lambda関数のPythonファイルを作成
$ mkdir function $ touch function/index.py今回はあくまでもサンプルなので、Lambdaのコードは適当
index.pyimport json print('Loading function') def lambda_handler(event, context): print("value1 = " + event['key1']) print("value2 = " + event['key2']) print("value3 = " + event['key3']) return event['key1'] # Echo back the first key value
cdk_lambda_stack.py
にLambda関数を作成するコードを追記cdk_lambda_stack.pyfrom aws_cdk import core from aws_cdk import aws_lambda as _lambda class CdkLambdaStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here lambdaFn = _lambda.Function(self, "SampleLambdaFunction", code=_lambda.Code.from_asset('function/'), runtime=_lambda.Runtime.PYTHON_3_7, handler="index.lambda_handler", function_name="sample_lambda_function" )いざ、デプロイ!
$ cdk deploy
AWSマネジメントコンソールでデプロイされていることを確認。
Lambda関数に環境変数を設定する
Functionを作成する際に
environment
パラメータを指定するか、add_environment
メソッドで設定するcdk_lambda_stack.py# 環境変数を追加 lambdaFn.add_environment(key="STAGE", value="DEV")s3トリガーを設定する
必要なライブラリをインストール
$ pipenv install aws_cdk.aws_s3 $ pipenv install aws_cdk.aws_s3_notificationsライブラリをインポート
cdk_lambda_stack.pyfrom aws_cdk import ( core, aws_lambda as _lambda, aws_s3 as _s3, aws_s3_notifications, )s3バケットを作成し、通知イベントを設定。
今のところ、この方法では既存のS3バケットには設定できない。既存のS3バケットにイベントを設定したい場合はカスタムリソースを使用する。cdk_lambda_stack.pybucket = _s3.Bucket(self, "SampleBucket", bucket_name="kimi-first-cdk-bucket") notification = aws_s3_notifications.LambdaDestination(lambdaFn) bucket.add_event_notification(_s3.EventType.OBJECT_CREATED, notification, _s3.NotificationKeyFilter(prefix="hoge", suffix=".csv"))Cloudwatch Eventsから定期的に起動する
必要なライブラリをインストール
$ pipenv install aws_cdk.aws_events $ pipenv install aws_cdk.aws_events_targetsインストールしたライブラリをインポート
cdk_lambda_stack.pyfrom aws_cdk import ( core, aws_lambda as _lambda, aws_s3 as _s3, aws_s3_notifications, aws_events as _events, aws_events_targets as _targets )イベントルールを作成するコードを追加。
今回スケジュール文字列を使用して設定しているが、Schedule.cron
やSchedule.rate
など別の方法でも指定可能。cdk_lambda_stack.pyrule = _events.Rule(self, "SampleEventRule", rule_name="schedule_trigger_event", schedule=_events.Schedule.expression("cron(10 * * * ? *)") ) rule.add_target(_targets.LambdaFunction(lambdaFn))参考
AWS CDK Examples サンプルコード集。言語によって差はあるが、いろいろ揃っているのでかなりありがたい
- 投稿日:2020-07-21T09:55:18+09:00
【ネットワークインターフェースのでタッチで】You do not have permission to access the specified resource.が出る
- 投稿日:2020-07-21T09:55:18+09:00
【ネットワークインターフェースのデタッチで】You do not have permission to access the specified resource.が出る
- 投稿日:2020-07-21T09:39:46+09:00
Elastic BeanstalkのドメインをRoute53の独自ドメインに紐付ける方法
はじめに
Elastic Beanstalkで構築したWebアプリケーションを独自ドメインに紐付ける方法をまとめました
方法
Route 53にて、独自ドメイン(Aレコード)を選択して、エイリアスに「はい」を選択する
その後、エイリアス先にElastic Beanstalkのドメインを記入する参考
- 投稿日:2020-07-21T07:26:44+09:00
IAMユーザーを作成する
AWSでのユーザー
AWSではユーザーは2種類あります。
・ルートユーザー
・IAMユーザー一番最初に作ったAWSアカウントは「ルートユーザー」になります。
普段の作業はIAM(アイアム)ユーザーでログインしてから作業します。
これはセキュリティを強固にするためです。
詳しくは「IAM ベストプラクティス」で検索してください。IAMユーザーの作成手順
今回は一番最初のIAMユーザーの作成をメモしていますので、ルートユーザーでログインしています。
山田さん用のIAMを作る場合は、
・システムA用の山田さん
・システムA用の鈴木さん
・システムB用の山田さん
というイメージで作成するといいようです。IAMのダッシュボードへ移動
ユーザー>ユーザーを追加
詳細設定を入力
プログラムによるアクセス
プログラムからアクセスするのに使ったりする場合にチェック入れる
AWS マネジメントコンソールへのアクセス
AWS マネジメントコンソール へのログイン、つまり人間が操作する場合にチェックを入れる
カスタムパスワード
好きなパスワードを設定できる
パスワードのリセットが必要
チェックを入れると最初にサインインした人がパスワードを再設定するようにできる。
管理者とユーザーが違う場合に使うと便利。アクセス許可の設定
ここでは簡単に設定するため
AWSが用意している管理者権限(基本機能が全て使える)ポリシーを選択しました。タグの追加
タグをつけることで絞り込みができたりします。
システム名や状態(status : terminated)、権限とかロールとか?良い方法がわかったら追記します…
一応以下の記事が参考になるかも…
- Tagging Best Practices(pdf)
- IAM リソースタグを使用した IAM ユーザーおよびロールへのアクセスとそのユーザーおよびロールのアクセスの制御 - AWS Identity and Access Management
確認画面
閉じると、
IAMユーザーが追加されたのを確認できます。
IAMユーザーでサインインしなおす
ルートからサインアウトして、
IAMユーザーとしてサインインしなおします。
これでIAMユーザーでサインインしました。
参考
- 投稿日:2020-07-21T06:58:25+09:00
EC2上のnginxとPHP7.4を連携
EC2にインストールされたnginx上で、PHP7.4を動かす方法のメモです。
Appacheと違って、少し設定が必要だったので、手順をまとめておこうと思います。
(Amazon Linux 2
での設定方法です。)
- php7.4のインストールは、こちらを参考にしてください。
nginxの設定
/etc/nginx/nginx.conf
にphpの設定を行います。$sudo vi /etc/nginx/nginx.conf server { listen 80; listen [::]:80; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }php-fpmの設定
/etc/opt/remi/php74/php-fpm.d/www.conf
にnginxと連携するための設定を行います(5箇所、設定を行います)。$sudo vi /etc/opt/remi/php74/php-fpm.d/www.conf user = nginx group = nginx listen = /var/run/php-fpm/php-fpm.sock listen.owner = nginx listen.group = nginxsockファイル用の設定
php-fpmでは、上記の
/var/run/php-fpm/php-fpm.sock
ファイルを起動時に作成します。
Amazon Linux 2
では、再起動すると/var/run
ディレクトリがリセットされてしますので、起動時に/var/run/php-fpm
を自動生成するスクリプトを設定します。$sudo vi /etc/tmpfiles.d/php-fpm-run.conf d /var/run/php-fpm 0755 root rootphp-fpmの起動
以下のコマンドで、php-fpmを起動します。
$sudo systemctl start php74-php-fpm.servicephp-fpmの確認
以下のコマンドで、php-fpmの状態を確認します。
active(running)
となっていれば、正常に起動しています。$sudo systemctl status php74-php-fpm.service ● php74-php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/php74-php-fpm.service; disabled; vendor preset: disabled) Active: active (running) since Mo 2020-07-20 21:13:23 UTC; 36min ago Main PID: 24651 (php-fpm) Status: "Processes active: 0, idle: 5, Requests: 1, slow: 0, Traffic: 0req/sec" CGroup: /system.slice/php74-php-fpm.service ├─24651 php-fpm: master process (/etc/opt/remi/php74/php-fpm.conf) ├─24652 php-fpm: pool www ├─24653 php-fpm: pool www ├─24654 php-fpm: pool www ├─24655 php-fpm: pool www └─24656 php-fpm: pool wwwphpinfo()で、phpが動いているかを確認
phpinfoを呼び出すファイルを作成し、nginxのホームディレクトリ(
/usr/share/nginx/html
)に配置します。$sudo vi info.php <? php phpinfo(); ?>ブラウザからアクセスし、以下の画面が表示されれば、nginx上で、phpが正常に稼働しています。
以上で、nginxとPHP7.4の連携設定は完了です。
- 投稿日:2020-07-21T06:18:16+09:00
EC2にPHP7.4をセットアップする
EC2にPHP7.4をインストールする方法のメモです。
EC2のインスタンスを立ち上げてからの手順をまとめておこうと思います。
(Amazon Linux 2
へのインストール方法です。)インスタンスのアップデート
yum update
を実行し、インスタンスをアップデートします。$ sudo yum updateリポジトリのアップデート
Amazon Linux 2は、デフォルトで
PHP5.4
がインストールされてしまうため、
PHP7.4
がインストールされるように、リポジトリをアップデートします。$sudo amazon-linux-extras install epel $sudo yum install epel-release $sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpmPHP7.4のインストール
yum
コマンドでPHP7.4をインストールします。$ sudo yum install -y php74 php74-php php74-php-fpmPHP7.4のリンク設定
PHP7.4が動作するように、シンボリックリンクを設定します。
$ sudo ln -s /usr/bin/php74 /usr/bin/phpインストールの確認
以下のコマンドで、インストールされたバージョンを確認します。
$ php -v PHP 7.4.8 (cli) (built: Jul 9 2020 08:57:23) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies以上で、PHP7.4のセットアップは完了です。
- 投稿日:2020-07-21T02:39:06+09:00
EC2にMySQL8.Xをセットアップする
EC2にMySQL 8.X をインストールする方法のメモです。
EC2のインスタンスを立ち上げてからの手順をまとめておこうと思います。
(Amazon Linux 2
へのインストール方法です。)インスタンスのアップデート
yum update
を実行し、インスタンスをアップデートします。$ sudo yum updateインスタンスからMariaDB用パッケージを削除
yum
コマンドで、MariaDBのパッケージを削除します。$ sudo yum remove mariadb-libsMySQLのリポジトリを追加し、有効化
yum
コマンドで、MySQLのリポジトリを追加し、有効化します。$ sudo yum -y install https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm $ sudo yum-config-manager –enable mysql80-communityyumリポジトリの確認
MySQL8.Xのリポジトリが、”enabled=1”になっているかを確認します。
sudo cat /etc/yum.repos.d/mysql-community.repo [mysql55-community] name=MySQL 5.5 Community Server baseurl=http://repo.mysql.com/yum/mysql-5.5-community/el/7/$basearch/ enabled=0 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql [mysql56-community] name=MySQL 5.6 Community Server baseurl=http://repo.mysql.com/yum/mysql-5.6-community/el/7/$basearch/ enabled=0 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql [mysql57-community] name=MySQL 5.7 Community Server baseurl=http://repo.mysql.com/yum/mysql-5.7-community/el/7/$basearch/ enabled=0 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql [mysql80-community] name=MySQL 8.0 Community Server baseurl=http://repo.mysql.com/yum/mysql-8.0-community/el/7/$basearch/ enabled=1 gpgcheck=1MySQLのインストール
yum
コマンドで、MySQLをインストールします。$ sudo yum install mysql-community-serverインストールされたMySQLのバージョン確認
MySQLバージョンを確認します。
$ mysqld --version /usr/sbin/mysqld Ver 8.0.21 for Linux on x86_64 (MySQL Community Server - GPL)MySQLの起動と自動起動の設定
MySQLを起動し、インスタンス起動時に自動で起動するように設定します。
$ sudo systemctl start mysqld.service $ sudo systemctl enable mysqld.serviceMySQLの状態確認
MySQLの状態を確認する。
$ sudo systemctl start mysqld.service ● mysqld.service - MySQL Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: active (running) since Mo 2020-07-20 13:32:14 UTC; 3h 47min ago Docs: man:mysqld(8) http://dev.mysql.com/doc/refman/en/using-systemd.html Main PID: 21998 (mysqld) Status: "Server is operational" CGroup: /system.slice/mysqld.service └─21998 /usr/sbin/mysqld以上で、MySQL8.Xのセットアップは完了です。
- 投稿日:2020-07-21T00:58:21+09:00
【Java】Amazon SESを利用してメールを送信する
はじめに
AWSのSES(Simple Email Service)を使用する機会があったため、復習も兼ねて、Javaプログラムでメール送信する方法をまとめたいと思います。
SMTPを使用する方法とAWS SDKを使用する方法がありますが、ひとまず、SMTPの方法を記載します。
後日、AWS SDKについても追記します。Amazon SESについて
- Amazon SES(Simple Email Service)はAmazonが提供するメール配信サービス
- 導入コストが低く、小規模で安価な運用が可能
- 毎月最初の 62,000 通のメールについては無料で送信できる(SES料金)
- AWSの他のサービスを使用することでメールログの保存や分析が可能
事前準備(SESコンソール)
プログラムを作成する前に下記をする必要があります。
送信元(From)アドレスの認証、送信先(To)アドレスの認証
アカウントはサンドボックスと呼ばれるテスト環境に新規ユーザーとして作成されるため、確認した E メールアドレスでの E メール送受信のみができます。
未確認の E メールアドレスに E メールを送信する、1 日あたりに送信できる E メールの数を増やす、高速で E メールを送信するためには、アカウントをサンドボックスの外に移動する必要があります。手順
- AWSにログインし、SESコンソールを開く
- 「Email Addresses」をクリック
- 「Verify a New Email Address」ボタンをクリック
- 認証するメールアドレスを入力して、「Verify This Email Address」ボタンをクリック
- 受信したメール内のリンクをクリック
- 手順2.の画面を開くと指定したメールアドレスのVerification Statusがverified(認証済み)になっている
これでメールアドレスの認証は完了です。
「Send a Test Email」ボタンをクリックでメールが送受信できるか確認できます。SMTPユーザーを作成して認証情報(ユーザー名とパスワード)を取得する
手順
- AWSにログインし、SESコンソールを開く
- 「SMTP Settings」をクリック
- 「Create My SMTP Credentials」ボタンをクリック
- SMTPユーザーの名前を入力して「作成」ボタンをクリック(名前はデフォルト値でも可)
- 「ユーザーの SMTP セキュリティ認証情報を表示」をクリック
- 表示された認証情報をコピーして安全な場所に保存しておく or 「認証情報のダウンロード」でcsvをダウンロード
IAMコンソール > アクセス管理 > ユーザー で作成したSMTPユーザーを確認できます。
動作環境
- eclipse Version: 2020-06 (4.16.0)
- javaバージョン
$ java -version java version "1.8.0_231" Java(TM) SE Runtime Environment (build 1.8.0_231-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)Javaプログラム
- eclipseでMavenプロジェクトを作成
- pom.xmlにJavaMailの依存関係を追加(MvnRepositoryでJavaMailを検索して最新バージョンのjarを追加)
- メール送信プログラム作成
pom.xml<!-- 依存関係 --> <dependencies> <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency> </dependencies>SesSmtpSample.javapublic class SesSmtpSample { // 送信者アドレスと送信者名(SESコンソールで認証したメールアドレス) static final String FROM = "sender@example.com"; static final String FROMNAME = "Sender Name"; // 宛先アドレス(SESコンソールで認証したメールアドレス) static final String TO = "recipient@example.com"; // SESコンソールで作成したSMTPユーザー名とパスワード static final String SMTP_USERNAME = "smtp_username"; static final String SMTP_PASSWORD = "smtp_password"; // SESコンソールで作成したConfig Setを指定。メールログの保存をするときなどに使用する。今回は不要なのでコメントアウト // static final String CONFIGSET = "ConfigSet"; // Amazon SES SMTPのエンドポイント(リージョンがオレゴンの場合はus-west-2) static final String HOST = "email-smtp.us-west-2.amazonaws.com"; // Amazon SES SMTPのエンドポイントのポート番号. static final int PORT = 587; // メール件名 static final String SUBJECT = "Amazon SES test (SMTP interface accessed using Java)"; // 本文 static final String BODY = String.join( System.getProperty("line.separator"), "<h1>Amazon SES SMTP Email Test</h1>", "<p>This email was sent with Amazon SES using the ", "<a href='https://github.com/javaee/javamail'>Javamail Package</a>", " for <a href='https://www.java.com'>Java</a>." ); public static void main(String[] args) throws Exception { // SMTPサーバーを定義 Properties props = System.getProperties(); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.port", PORT); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.auth", "true"); // メールセッションの確立 Session session = Session.getDefaultInstance(props); // メール作成 MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(FROM,FROMNAME)); msg.setRecipient(Message.RecipientType.TO, new InternetAddress(TO)); msg.setSubject(SUBJECT); msg.setContent(BODY,"text/html"); // Configuration Setを設定。今回は使用しないのでコメントアウト //msg.setHeader("X-SES-CONFIGURATION-SET", CONFIGSET); Transport transport = session.getTransport(); // メール送信 try { System.out.println("Sending..."); // SMTPサーバに接続 transport.connect(HOST, SMTP_USERNAME, SMTP_PASSWORD); // メール送信 transport.sendMessage(msg, msg.getAllRecipients()); System.out.println("Email sent!"); } catch (Exception ex) { System.out.println("The email was not sent."); System.out.println("Error message: " + ex.getMessage()); } finally { // 接続終了 transport.close(); } } }SMTPのエンドポイントはリージョンによって変わります。
AWSのリファレンスで確認できます。おわりに
Amazon SESの日本語ドキュメントがあるため、基本的にはドキュメント通りにやっていけば問題なくメール送信できると思います。