- 投稿日:2021-04-28T23:29:53+09:00
異なるアカウントのあるプロファイルで作業するためのaws-cli設定(備忘録)
はじめに Qiitaでは主にネタ記事を投稿する主義だったのですが、最後に投稿してから一年近く...笑 流石にまずいと思ったので、本来は自分のhatenaブログで投稿する内容ですが、aws-cliの設定方法の備忘録を載せたいと思います。 対象の読者 ・既に自分のAWSアカウントでaws-cliの初期設定をしたことがある方 ・働いてる企業のAWSアカウントでaws-cliをローカルで操作する必要が出てきた方 ・複数のロール&異なるAWSアカウントで行う必要がある方 手順 ・アクセストークンとシークレットトークンを取得する 取得方法についてですが、AWSのコンソールの右上のアカウント部分を選択して、マイセキュリティ視覚情報をクリックすると確認することができます。ロール権限などの問題がある場合は取得できないと思いますので、そのときはインフラを管理してる方に事情を話して取得しましょう。 取得方法に関する説明はこちら) https://www.multcloud.com/jp/tutorials/s3-key.html ・自分のパソコンのターミナルでaws configure —profile <好きな名前>を実行 例: $ aws configure --profile company AWS Access Key ID [None]: {アクセスキー(各自)} AWS Secret Access Key [None]: {シークレットアクセスキー(各自)} Default region name [None]: ap-northeast-1 Default output format [None]: json この処理が終わると、~/.aws/configファイルと~/.aws/credentialファイルの内容はそれぞれ以下のようになると思います。 [default] region = ap-northeast-1 output = json [profile company] region = ap-northeast-1 [default] aws_access_key_id = ********************* aws_secret_access_key = ********************* [company] aws_access_key_id = ********************* aws_secret_access_key = ********************* ・プロファイルの追加 例えばcompanyで設定されているアカウントからスイッチロールしたい場合、configファイルを以下のように編集します(今回はロールの名前をsandboxとします) [profile sandbox] region = ap-northeast-1 role_arn = ロールの情報 source_profile = company(例えば、会社のアカウントならsource_profileを先ほど設定したcompanyにする) 確認用: aws s3 ls --profile sandbox ここまでできると、複数のAWSアカウントやロールを使ってaws-cliを使えるようになると思います。ただし、色んなプロファイルを扱うときは--profile指定をしないといけないので、忘れないように注意してください。
- 投稿日:2021-04-28T21:24:01+09:00
CloudWatchのエラーログをSlackに通知する
いちいちLaravelのログを見るのがめんどくさいと思いCloudWatch Logsに転送しました。しかし、Slackに通知させた方がより便利だと思ったので今回は下記のような構成で行きます。 通知したいロググループに対してメトリクスフィルターを作成する CloudWatchにて通知したいEC2ののロググループを選択し、「 アクション 」「 メトリクスフィルターを作成する 」をクリック フィルターパターンはERRORログを出力したいのでERRORとします。そして、メトリクスフィルターを作成しましょう。 SNSのトピックを作成しましょう 任意の名前でさくっと作りましょう。 Lambdaの処理 Lambdaの構成はこんな感じになります。 SNSには作成したトピックを割り当てます。 lambda_function.py import json import urllib.request import logging from collections import OrderedDict import os import datetime import calendar import boto3 logger = logging.getLogger() logger.setLevel(logging.INFO) #抽出するログデータの最大件数 OUTPUT_LIMIT=5 #何分前までを抽出対象期間とするか TIME_FROM_MIN=5 def lambda_handler(event, context): logger.info("Event: " + str(event)) message = json.loads(event['Records'][0]['Sns']['Message']) logs = boto3.client('logs') # MetricNameとNamespaceをキーにメトリクスフィルタの情報を取得する。 metricfilters = logs.describe_metric_filters( metricName = message['Trigger']['MetricName'] , metricNamespace = message['Trigger']['Namespace'] ) logger.info("Metricfilters: " + str(metricfilters)) #ログストリームの抽出対象時刻をUNIXタイムに変換(取得期間は TIME_FROM_MIN 分前以降) #終了時刻はアラーム発生時刻の1分後 timeto = datetime.datetime.strptime(message['StateChangeTime'][:19] ,'%Y-%m-%dT%H:%M:%S') + datetime.timedelta(minutes=1) u_to = calendar.timegm(timeto.utctimetuple()) * 1000 #開始時刻は終了時刻のTIME_FROM_MIN分前 timefrom = timeto - datetime.timedelta(minutes=TIME_FROM_MIN) u_from = calendar.timegm(timefrom.utctimetuple()) * 1000 # ログストリームからログデータを取得 response = logs.filter_log_events( logGroupName = metricfilters['metricFilters'][0]['logGroupName'] , filterPattern = metricfilters['metricFilters'][0]['filterPattern'], startTime = u_from, endTime = u_to, limit = OUTPUT_LIMIT ) # メッセージを整形しつつslackに通知 for event in response['events']: postText = ''' {logStreamName} {message} '''.format( logStreamName=str(event['logStreamName']), message=str(event['message'])).strip() logger.info("Response: " + str(response)) send_data = { "text": postText, } send_text = json.dumps(send_data) request = urllib.request.Request( "https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxxx/xxxxxxx", data=send_text.encode('utf-8'), method="POST" ) with urllib.request.urlopen(request) as response: response_body = response.read().decode('utf-8') IAMロールの設定 IAMロールにて先ほど作成したLambda関数にポリシーをアタッチします。 そして、AWSLambdaBasicExecutionRoleをクリックしてにポリシーの編集を行います。 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:ap-northeast-1:009554248005:*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents", "logs:DescribeMetricFilters" ], "Resource": [ "arn:aws:logs:ap-northeast-1:009554248005:log-group:/aws/lambda/cloudwatch:*" ] } ] } CloudWatch Alarmを設定します CloudWatch Alarmにてアラームを作成します。設定は以下の通りです。しきい値が1以上を超えたらSNSトピックに送信するように設定します。 送信するSNSトピックは先ほど作成したものを選択 Slackの設定 https://w1618578007-hxz964946.slack.com/intl/ja-jp/apps を開き、「 マストアプリ 」をクリックし、検索窓で「 Incoming Webhook 」と検索 そしてSlackに追加して通知させたいチャンネルを選択します。その後、生成されたWebhook URLをコピーしましょう。のちに使います。 最後に確認します 意図的にログを吐くようにして、このような通知が来れば完了です。アイコンやアプリ名はカスタマイズすることも可能ですよ。 参考文献 ・ https://qiita.com/yahagin/items/2248287c5285cd1e9201 ・ https://blog.chakimar.net/aws-chatbot-cloudwatch-logs/
- 投稿日:2021-04-28T21:18:05+09:00
5G MEC (KDDI / AWS Wavelength) を試す(実測編)
起こした MEC にアクセスしましょう さて、先行記事 では KDDI 5G MEC (その実体は AWS Wavelength インスタンス)を構築するところまでを説明しました。うまくできたでしょうか。 今回は作成した Wavelength instance に KDDI 5G 端末から、ping による往復遅延の計測を行いましたので、まずその結果報告を行います。分析・考察は後で情報を集めながらやろうと思います。 測ってみた 機器構成 今回計測する KDDI MEC と端末側の機器構成を示します。 つまり、先行記事 で作成した KDDI 5G MEC に、5G 携帯およびモバイルルータでアクセスしよう、というものです。機材はそれぞれ以下の通りです。 Smartphone (Android) - Google Pixel 5 Mobile Router - Spped Wi-Fi 5G X01 手法 愚直に ping (ICMP Echo 往復) と traceroute (ICMP Time Exceeded) を行いました。ルータには Windows PC が繋がれており、WSL Ubuntu 18.04 環境の ping / traceroute コマンドを実行しています。Android Smartphone では traceroute コマンドではなく android-netdiag を使った自作アプリ(つまりアプリ自身が TTL をセットしたパケットを送出する)で計測しています。 計測対象は 設定編 で作成した EC2 Instance と Wavelength Instance です。但し今回はkix-Osaka, nrt-Tokyo Zone の両方に対してワンセットずつ作成しましたから、計測ごとに計 4 つのインスタンスに対して ping / traceroute を行ったことになります。 およそ 5G 接続されているときばかり計測しました。一部 4G になったときに同じ経路を通ることを確認するようなことはしましたが、全計測地点で 5G / 4G の変化を追うようなことはしていません。 計測地点 今回計測したのは "四条河原町交差点から少し東に入った" ところ。Apple Store 京都近辺です。 上のリンクがうまくたどれなくても、au の "エリアマップ" で「キーワード検索」に「京都府京都市下京区立売中之町」を指定すればこのあたりが表示されるでしょう。(上の表示は 2021/4/23 時点のものです。かなりこまめに変わります。) Pixel 5 は Sub6 帯(3.6GHz〜)のみ対応。5G X01 は Sub6 とミリ波(30GHz〜)に対応しているのですが、今回は見ての通り Sub6 帯しかサービスされていないようなので、そこは違いとしては出ないと思われます。 結果 計測は Apple Store 前あたりを数カ所、数メートル程度移動しては計測しました。10箇所以上で計測したのですが、ここでは Wavelength instance で最も良い数字を出すことにします。逆に言えば、驚くほど良い数字が出たわけでは無い、ということです。とにかく見て下さい。 Best case (with 5G Mobile Router) 以下、5G Mobile Router による結果を示します。Wavelength instance への遅延計測では、Apple Store が入居している ゼロゲートというビルの出入り口前あたりが、最も良い数字がでました。 PING 106.161.xxx.xxx (106.161.xxx.xxx) 56(84) bytes of data. 64 bytes from 106.161.xxx.xxx: icmp_seq=1 ttl=244 time=23.9 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=2 ttl=244 time=45.4 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=3 ttl=244 time=32.5 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=4 ttl=244 time=33.3 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=5 ttl=244 time=39.9 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=6 ttl=244 time=45.1 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=7 ttl=244 time=44.5 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=8 ttl=244 time=31.6 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=9 ttl=244 time=31.7 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=10 ttl=244 time=41.0 ms --- 106.161.xxx.xxx ping statistics --- 10 packets transmitted, 10 received, 0% packet loss, time 1809ms rtt min/avg/max/mdev = 23.989/36.949/45.482/6.914 ms 最短 23.9ms、平均で 36.9ms です。ただ、かなり振れ幅( jitter )が大きいと思えます。 全試行を通じて最も短い遅延数字が 17.8ms で、Apple Store の四条通をはさんだ向かい側あたりでした。但しその時の平均は 40ms で、このゼロゲート入り口前よりも若干悪くなっています。本当に偶発的に短い時間で返ってきた、と思える状況です。 そしてこのときの経路は、こんな感じでした。しばらく private IP address だなと思ったら、KDDI のネットワークに入り、そのまま KDDI の網のなかです。ping が返すホップ数( 255-244 = 11 )から、このすぐ後に Wavelength instance に到達しているものと思います。(通常の traceroute が出す時間情報は余り意味が無いので消して、代わりに whois で確認した所有者情報を手で付けています。) traceroute to 106.161.xxx.xxx (106.161.xxx.xxx), 25 hops max, 60 byte packets 1 172.24.240.1 # private 2 192.168.128.1 # private 3 172.25.197.122 # private 4 172.25.195.1 # private 5 172.25.195.90 # private 6 27.86.109.101 # KDDI 7 27.86.109.97 # KDDI 8 175.135.250.213 # KDDI 9 175.135.250.169 # KDDI 10 * * * 11 * * * 12 * * * ...以下25hopまで返事なし... Best case (with Smartphone) ところが面白いことに、5G Mobile Router + PC より、Smartphone (Pixel5) の方が早い数字を出します。場所は同じくゼロゲート入り口前です。 PING 106.161.xxx.xxx (106.161.xxx.xxx) 56(84) bytes of data. 64 bytes from 106.161.xxx.xxx: icmp_seq=1 ttl=245 time=21.1 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=2 ttl=245 time=21.1 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=3 ttl=245 time=19.4 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=4 ttl=245 time=17.9 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=5 ttl=245 time=15.1 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=6 ttl=245 time=13.2 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=7 ttl=245 time=22.7 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=8 ttl=245 time=18.5 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=9 ttl=245 time=17.1 ms 64 bytes from 106.161.xxx.xxx: icmp_seq=10 ttl=245 time=14.9 ms --- 106.161.xxx.xxx ping statistics --- 10 packets transmitted, 10 received, 0% packet loss, time 1816ms rtt min|avg|max|mdev = 13.242|18.147|22.768|2.916 ms なんと最短 13.2ms、平均でも 18.1 ms。そして最大でも 22.7ms と、かなり安定しています。 なんだこれは、と思ってあと二回、この場所で続けて計測したのですが、結果は安定して、以下の通りでした。 rtt min|avg|max|mdev = 12.875|19.938|40.978|7.455 ms rtt min|avg|max|mdev = 13.503|18.540|25.296|3.296 ms 他の地点、たとえば道路向かいでは平均で 30ms 程度になるなど、違いが出るところなどは Mobile Router のケースと同じなのですが、それでも全体に低遅延でした。 このときの経路は以下の通りです。 Traceroute : 1. * 2. 10.60.164.249 # private 3. 172.25.160.193 # private 4. 172.25.161.203 # private 5. 27.86.109.173 # KDDI 6. 27.86.109.169 # KDDI 7. 175.135.250.221 # KDDI 8. 175.135.250.173 # KDDI 9. * 10. * 11. 106.161.xxx.xxx # KDDI (target host) private 領域を超えた先は Mobile Router のときと若干違いがありますが、まあ同じ経路をたどっているのでしょう。 分布 ちょっと分かりにくいグラフになってしまうのですが、何度も行った計測のうち、それぞれの地点での計測の結果がどのような分布になっているのか、またそれが Mobile Router と Smartphone でどのくらいの違いが出ているのか、ざっくり示します。 左半分の青い×印が Mobile Router での計測値。右半分のオレンジの×印が Smartphone での計測値です。 それぞれの地点で10回 ping で計測して、その結果を縦に並べて示しています。計測の時系列に右に並んでいますが、Mobile Router の左から何番目の地点が、Smartphone での左から何番目に対応する、といったことはありません。恐らく、ですが、少し時間を離して計測すればそれなりに違う結果が出ることが予想されるので、厳密な比較はちょっと意味が無いように思います。(それでも、5m 移動して計測するとかなり悪化し、5m 戻ってきたら比較的近い値が出る、という印象を持つ程度には安定しており、「完全な偶発」でも無いようです。) それにしても Mobile Router より Smartphone の方が低遅延な数字が出るのはどういうことでしょう。計測環境(使っているツール)が異なるとは言え、しかし Mobile Router に繋がれている Windows PC + WSL でこんな何十ミリ秒もの遅れが出ないことは確認していますし、Smartphone の App が、何十ミリも短めの時間を報告することも無いでしょう。(see; android-netdiag ) 少しこの辺りのノウハウを、多くの環境、多くの端末で、事例として集めるのが良いように思えます。計測した人はぜひ結果をお知らせください。集積しましょう! その他わかったこと 計測は Apple Store 前あたりで行いましたが、ほんの数メートル移動するだけで状況がかなり変わります。この地域が良いと思って試したのですが、実は余り良い環境では無かったのかも知れません。 計測は平日の深夜、1am 頃に行いました。昼間に一度試したのですが、夜間にやったときの方が 20-40% 程度低遅延で、振れ幅も低め、という印象です。 当然といえば当然ですが、kix-Osaka の Wavelength Zone のインスタンスの方が、nrt-Tokyo のそれよりレスポンスは早いです。 ToDo 5G Mobile Router と Smartphone の違いについて情報を集めなければ。 一箇所で継続的に測定して変化(安定度?)を見たい。 もう少し組織的に何度も繰り返し計測できる仕組みを作ってローラー作戦的にデータを集めたい。5G/4G比較も。 mineo の 5G オプションをつけたものを契約して試したが、これがどうやら閉域網を通らない。その結果をまとめなければ。 気になるお値段は 私にとってこれが(ほぼ)初めての AWS 利用で、現在はこの実験のためにしか AWS を利用していません。それでちょこちょこ遅延計測したところ、こんな感じになりました。 つまり私がちょこちょこ遅延計測した程度では \$2.21 ⁄ day から上がりませんでした。三日ほど前からインスタンスを停止したところ、\$0.44 程度に下がっています。インスタンスを削除してしまえばゼロになるわけなので、実験する前に作って、実験が終わったら停止するようにしてしまえば、まあお小遣い程度で気楽に試せるのではないかと思います。 au 5G smartphone をお持ちの方はぜひお試し下さい。 おわりに 今回最も気になったのは遅延の大きさそのものではなく、その揺れ( jitter )でした。パケットごとに随分違います。 現時点では KDDI の 5G 網は、4G 網の上に構築された NSA タイプです。つまり 5G 接続したとしても、アンテナからワンホップあたりでもう 4G 網に流合する形でパケットが MEC に届けられます。それでもインターネットに一度出たりすることはない、とのことですからまだマシなのでしょうが、大きめの遅延数字と、ちょっと見過ごせない大きな jitter が出ています。 今回の数字や傾向を、他の KDDI 5G MEC 経験のある方などに確認してみたのですが、おおよそ同様の数値とのことでした。私達のテストが何か大きく間違えているわけではない、ということでしょう。むしろ、東京などではこれほど短い数字を見ることがなかった、という話もあったので、やはり利用者が少ないときに試すのが良いようです。(私は現在のところ「悪くてもこのくらい」という数字が欲しいわけではなく、「最良でこのくらいになる」可能性を調べたいので。) とりあえず現時点では「家庭の固定回線(ファイバ)からインターネット経由でアクセスした方が遙かに低遅延」な状況であることには間違い無いようです。「なんだ 5G MEC ってそんなもんなの? 5ms くらいで考えてるんじゃ無いの」と思う人もいるでしょうが、私が興味があるのは、これが「交差点の信号機上にアンテナ、その脇の箱に MEC」という状況になったとき、走る車の端末との往復遅延がどのくらいまでその 5ms に近づくか、です。KDDI の Wavelength が SA 方式の経路上に置かれ、京都の最寄りの au 携帯基地局の中に設置されたとき、そのアンテナの近くでどんな数字が得られるか、です。 今回はまず、とりあえず測っただけ、という段階です。この数字が何を意味しているか、どう読み取れば良いか、といった分析・考察は後でもう少し情報を集めながらやろうと思います。
- 投稿日:2021-04-28T20:58:12+09:00
ローカルのコンテナの出力をFluentdでS3に保存する
やりたいこと ローカルでFluentdコンテナを動かして、他のコンテナの標準出力を集めてS3にログを保存したい。 構成 Fluentdコンテナと、サンプルとしてそこに出力を送り込むNginxコンテナを作ります。 ├─fluentd │ docker-compose.yml │ Dockerfile │ fluent.conf │ └─nginx docker-compose.yml Fluentdコンテナ Dockerfile FROM fluent/fluentd:v1.12.2-1.0 # Timezone ARG TZ RUN echo ${TZ} USER root RUN apk add --update --no-cache tzdata && \ cp /usr/share/zoneinfo/${TZ} /etc/localtime && \ echo ${TZ} > /etc/timezone && \ apk del tzdata # AWS ARG AWS_KEY_ID ARG AWS_SEC_KEY ARG S3_BUCKET ARG AWS_REGION ENV AWS_KEY_ID=${AWS_KEY_ID} ENV AWS_SEC_KEY=${AWS_SEC_KEY} ENV S3_BUCKET=${S3_BUCKET} ENV AWS_REGION=${AWS_REGION} # for fluentd v1.0 or later RUN gem install fluent-plugin-s3 --no-document # Config USER fluent COPY fluent.conf /fluentd/etc/ デフォルトだとログのタイムスタンプがUTCになってしまうのでタイムゾーンの設定と、S3出力のためのプラグインをインストールします。 docker-compose.yml version: '3.7' services: fluentd: build: context: ./ args: TZ: Asia/Tokyo AWS_KEY_ID: XXXXXXXXXXXXXXXX AWS_SEC_KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX S3_BUCKET: mybucket AWS_REGION: ap-northeast-1 restart: always ports: - 24224:24224 - 24224:24224/udp タイムゾーンとAWSのアクセスキーと出力先のバケットを渡します。 fluent.conf <source> @type forward port 24224 bind 0.0.0.0 </source> <match debug.**> @type copy <store> @type file path /fluentd/log/debug time_slice_format %Y%m%dT%H%M time_slice_wait 5m </store> <store> @type stdout </store> </match> <match s3.**> @type s3 aws_key_id "#{ENV['AWS_KEY_ID']}" aws_sec_key "#{ENV['AWS_SEC_KEY']}" s3_bucket "#{ENV['S3_BUCKET']}" s3_region "#{ENV['AWS_REGION']}" check_object false time_slice_format %Y%m%dT%H%M time_slice_wait 5m path fluentd_logs/ s3_object_key_format %{path}%{time_slice}/%{hms_slice}.%{file_extension} </match> <match **> @type stdout </match> s3.**タグにマッチした入力がS3に保存されるように設定します。 確認用に保存のタイミングを短くしています。 コンテナの起動・確認 Fluentdコンテナを起動して、直接データを入力してみます。 >docker-compose up -d >docker-compose exec fluentd sh $ echo '{"hello":"fluentd"}' | fluent-cat debug.test $ ls -l /fluentd/log/debug/ -rw-r--r-- 1 fluent nogroup 57 Apr 28 14:00 buffer.b5c1014353321a2e64426684b2464c202.log -rw-r--r-- 1 fluent nogroup 79 Apr 28 14:00 buffer.b5c1014353321a2e64426684b2464c202.log.meta $ ls -l /fluentd/log/ drwxr-xr-x 2 fluent nogroup 4096 Apr 28 14:07 debug -rw-r--r-- 1 fluent nogroup 57 Apr 28 14:04 debug.20210428T1400.log $ cat /fluentd/log/debug.20210428T1400.log 2021-04-28T14:00:52+09:00 debug.test {"hello":"fluentd"} $ echo '{"hello":"fluentd"}' | fluent-cat s3.test >aws s3 ls s3://mybucket/fluentd_logs/ PRE 20210428T1400/ コンテナ内部とS3にログが保存されることが確認できました。 S3にはgzip形式でログが保存されます。 Nginxコンテナ docker-compose.yml version: '3.7' services: web: image: nginx:latest ports: - "80:80" logging: driver: "fluentd" options: fluentd-address: "localhost:24224" tag: "s3.docker.{{.Name}}" fluentd-async-connect: "true" Nginxの公式イメージはデフォルトでアクセスログを標準出力にエラーログを標準エラー出力に吐くのでロギング・ドライバにFluentdを指定すればそのままログが流れます。 コンテナを起動して、NginxデフォルトページにアクセスするとS3にアクセスログが保存されているのが確認できます。 2021-04-28T14:55:31+09:00 s3.docker.nginx_web_1 {"source":"stdout","log":"172.23.0.1 - - [28/Apr/2021:05:55:31 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36\" \"-\"","container_id":"410c2125509ef500c8a22a3093c95ac1b9ee51d9ff893a4d062f7bb7fb56a8c9","container_name":"/nginx_web_1"}
- 投稿日:2021-04-28T20:26:57+09:00
【AWS】VPCの概要
プログラミング勉強日記 2021年4月28日 前の記事でもVPCについて触れているが今回はよりVPCの理解が深まったので、まとめる。 VPCとは 一言でいうと、AWSクラウドのネットワークからユーザ専用の領域を切り出して作る仮想ネットワーク。 AWSクラウドのネットワーク空間に様々なネットワーク機器やネットワークが使われている。その中に自分専用のAWSクラウドを利用する領域としてVPCを設定する。まず、AWSのアカウントを作ったらVPCがデフォルトで設定される。 VPCの特徴 任意のIPアドレス範囲を選択して仮想ネットワークを構築する サブネットの作成・ルートテーブルやネットワークゲートウェイの設定など、仮想ネットワーキング環境を完全に制御できる 必要に応じてクラウド内外のネットワーク同士を接続できる 複数の接続オプション(インターネット経由・VPN/専用線(Direct Connect)が利用できる 単一のVPCを構築すると単一のAZの範囲に設定される 同じリージョン内ではVPCは複数のAZにリソースを含められる サブネットとVPC VPCとサブネットの組み合わせでネットワーク空間を構築する。VPCはVPCをさらに小さい単位に区切る仕組みであるサブネットとのセットが必須になる。サブネット側がAZとマッピングされて1つのAZと1つのサブネットが紐づいて構成される。デフォルトでVPCを作っても1つサブネットがデフォルトで構成される。
- 投稿日:2021-04-28T20:20:18+09:00
AWS Organizationsで組織にアカウントを追加しスイッチロールする
AWS Organizationsから「AWSアカウントを追加」をクリック アカウント名、メールアドレスを入力する IAMロール名はデフォルトのままで問題はない 「AWSアカウントを作成」をクリックしてしばらく待つとアカウントが作成される IAMから以下のようなポリシーを作成してスイッチロールを許可したユーザーにアタッチする { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::{アカウントID}:role/{IAMロール名(デフォルトであればOrganizationAccountAccessRole)}" } ] } コンソールの右上あたりにあるメニューの「ロールの切り替え」をクリック アカウント追加時の「アカウント名」「IAMロール名(デフォルトであればOrganizationAccountAccessRole)」、表示名は適当に入れて「ロール切り替え」をクリックする 追加したアカウントに切り替わっているはず
- 投稿日:2021-04-28T18:44:32+09:00
AWS Aurora ServerlessをCloudFormationで構築する際の注意点
TL;DR Port PreferredBackupWindow PreferredMaintenanceWindow をコメントアウトすればスタック更新できるよ! 序文 CloudFormationで構築したAurora Serverlessには独特の癖というかハマりポイントがあるのでメモ。 設定しなくても良い項目 Port そもそもがServerlessの場合はポート番号の変更自体が不可で、MySQL互換なら 3306 、PostgreSQL互換なら 5432 でしか作成できないので設定しないくても良いです。 扱いが面倒な項目 PreferredBackupWindow PreferredMaintenanceWindow 作成時に値を設定しておかないとデフォルト値(東京リージョンで作成する場合、BackupWindowは 13:00–21:00 UTC = 22:00-06:00 JST のどこか30分間、MaintenanceWindowはランダムな曜日の 13:00–21:00 UTC = 22:00-06:00 JST のどこか30分間)で作成されてしまいます。 さらにこの項目は作成後に更新する手段がありません。 そのため、作成時には設定しておきたくなる項目です。 それだけなら最初にしっかり考えて設定しておいて、値を更新しなければ済む・・・と思わせておいて、この先に罠が待っています。 実例 例えばこんな感じのテンプレートでAurora Serverlessを構築したとしましょう。 DBCluster: Type: AWS::RDS::DBCluster Properties: Engine: aurora EngineMode: serverless Port: 3306 PreferredBackupWindow: 17:00-18:00 PreferredMaintenanceWindow: sun:19:00-sun:20:00 MasterUsername: hoge MasterUserPassword: hogehoge その後、スケールサイズを指定したくなって、以下のようにテンプレートを編集します。 ポートやバックアップウィンドウ、メンテナンスウィンドウは変更していません。 DBCluster: Type: AWS::RDS::DBCluster Properties: Engine: aurora EngineMode: serverless Port: 3306 PreferredBackupWindow: 17:00-18:00 PreferredMaintenanceWindow: sun:19:00-sun:20:00 MasterUsername: hoge MasterUserPassword: hogehoge ScalingConfiguration: MinCapacity: 1 MaxCapacity: 2 ところがこのテンプレートでスタック更新をすると以下のどれかのエラーでスタックの更新に失敗します。 You currently can't modify EndpointPort with Aurora Serverless. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterCombination; Request ID: 12345678-9abc-def0-1234-56789abcdef01) You currently can't modify BackupWindow with Aurora Serverless. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterCombination; Request ID: 12345678-9abc-def0-1234-56789abcdef01) You currently can't modify MaintenanceWindow with Aurora Serverless. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterCombination; Request ID: 12345678-9abc-def0-1234-56789abcdef01) このような状態から更新したい場合には値を変更していなくても、更新不能な項目を外しておく必要があります。 DBCluster: Type: AWS::RDS::DBCluster Properties: Engine: aurora EngineMode: serverless # Port: 3306 # PreferredBackupWindow: 17:00-18:00 # PreferredMaintenanceWindow: sun:19:00-sun:20:00 MasterUsername: hoge MasterUserPassword: hogehoge ScalingConfiguration: MinCapacity: 1 MaxCapacity: 2 AWSに対応してもらいたい! 結構昔からある問題(→AWSフォーラム)で、AWSのCloudFormationの公開カバレッジロードマップ内にIssueも立って(→#396)います。 が、残念ながら検討段階にも入っていません(→roadmap)。 この問題に限らず、Issueについた「いいね」数は開発陣がチェックしているそうで、内部的にそこそこの影響力があるそうです。 ※ サポート窓口や、(現在閉館中ですが)AWS Startup Loft Tokyoのスタッフに言うよりも効果的だと言われました せっかくインフラ構成をコード化できても、更新の度にコメントアウトしたり、コメントアウトしたものをコミットしていると管理しにくいことこの上ないので是非とも対応して頂きたいなーと思っております。
- 投稿日:2021-04-28T18:13:35+09:00
pythonで Azure Blob、AWS S3からMD5ハッシュ値を取得する
はじめに 本年度から業務内容がWindowsアプリ開発からAWS関連の業務に代わり、 最初のタスクが「Azure Blob Storageから AWS S3に移行されたデータが正しく移行されているかの検証」でした。 aws s3にはアップロード時に、アップロード前と後のオブジェクトの整合性を検証する手段があるのですが、今回は既に全データ移行済みだったため、BlobとS3のメタデータを取得して格納されているMD5ハッシュ値で検証を実施しました。 ちなみに言語はpythonを使っています。 結論 オブジェクトのメタデータ取得(S3編) オブジェクトのメタデータ取得(Blob編) 終わり オブジェクトのメタデータ取得(S3編) pythonかつaws s3のメタデータを取得する方法は探せば多くの情報が見つかると思います。 下記のコードもその一例になります。 from azure.storage.blob import BlobServiceClient # AWS CLIの aws configure コマンドで .aws/credentialsファイルに書き込むこと aws_access_key_id = '' aws_secret_access_key = '' bucket_name = '' key_name = '' s3_cli = boto3.client('s3',aws_access_key_id, aws_secret_access_key) # オブジェクトのメタデータを取得 s3_resp = s3_cli.head_object(bucket_name, key_name) # レスポンスからMD5ハッシュが格納されているEtagを取得 s3obj_etag = s3_resp['ETag'].strip('"') return s3obj_etag key_idやbucket_nameは自分の環境にあわせて値を代入してください。 boto3.client()でs3へアクセスするオブジェクトをまず取得します。 その後、head_object()でオブジェクトのメタデータを取得します。 # オブジェクトのメタデータを取得 s3_resp = s3_cli.head_object(bucket_name, key_name) s3_respはjsonが返ってきます。返り値の中身は下記のようなデータが入っています。 "s_respの中身の例" {'ResponseMetadata': {'RequestId': '9dad3fc3-0e30-1dbc-a754-06bdfcde1d5e', 'HostId': '', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Sun, 13 Dec 2020 22:43:10 GMT', 'x-amz-request-id': '9dad3fc3-0e30-1dbc-a754-06bdfcde1d5e', 'last-modified': 'Sun, 13 Dec 2020 22:40:57 GMT', 'etag': '"669fdad9e309b552f1e9cf7b489c1f73-2"', 'content-type': 'binary/octet-stream', 'x-amz-server-side-encryption': 'AES256', 'x-amz-version-id': 'fe14c26b-bba0-6edf-a754-06bdfcde1d5e', 'accept-ranges': 'bytes', 'content-length': '10485760', 'server': 'CloudianS3'}, 'RetryAttempts': 0}, 'AcceptRanges': 'bytes', 'LastModified': datetime.datetime(2020, 12, 13, 22, 40, 57, tzinfo=tzutc()), 'ContentLength': 10485760, 'ETag': '"669fdad9e309b552f1e9cf7b489c1f73-2"', 'VersionId': 'fe14c26b-bba0-6edf-a754-06bdfcde1d5e', 'ContentType': 'binary/octet-stream', 'ServerSideEncryption': 'AES256', 'Metadata': {}} 返り値の参考例 https://zenn.dev/nowko/books/550bcd398f3122/viewer/ce44b4 head_objectの返り値にETagというキーがあります。この値がMD5ハッシュ値になります。 'ETag': '"669fdad9e309b552f1e9cf7b489c1f73-2"' 数字型として使う場合は、下記のようにstrip()で "" を削除して使いましょう。 # レスポンスからMD5ハッシュが格納されているEtagを取得 # ""を除去 s3obj_etag = s3_resp['ETag'].strip('"') 以上でaws s3のMD5ハッシュ取得については終了です。 オブジェクトのメタデータ取得(Blob編) s3と違ってazure blobのメタデータ取得については、探すのに時間がかかりました。 なので、ここからは皆さんのお役になる情報だと思います。 from azure.storage.blob import BlobServiceClient # BLOB接続文字列 connectionString = '' container_name = '' blob_name = '' blob_service_client = BlobServiceClient.from_connection_string(connectionString) blob_client = blob_service_client.get_blob_client(container_name, blob_name) # BLOBのすべてのユーザー定義メタデータ、標準HTTPプロパティ、およびシステムプロパティを受け取る prop = blob_client.get_blob_properties() bytearray = prop['content_settings']['content_md5'] return bytearray.hex() 以下、解説になります。 from_connection_string()、get_blob_client()を使ってBlobClientを取得します。 blob_service_client = BlobServiceClient.from_connection_string(connectionString) blob_client = blob_service_client.get_blob_client(container_name, blob_name) BlobClientクラスにはget_blob_properties()というAPIがあり、このAPIがBLOBのメタデータ(BlobProperties)を返してくれます。 ここで注意点なのですが、BlobPropertiesにはetagというキーがありますが、今回欲しいハッシュ値は、content_settingsキーの値ContentSettingsにcontent_md5というキーがありこちらになります。 prop = blob_client.get_blob_properties() bytearray = prop['content_settings']['content_md5'] return bytearray.hex() content_md5はbytearray型なので、hex()で変換することでs3で取得した値と同じものになるかと思います。 終わり 以上になります。 先にs3のハッシュを取得できていたため、BlobPropertiesにはetagを見つけて返り値を確認した時は、なぜs3の返り値と値が異なるのかと頭を抱えていました。 Microsoftのドキュメントをきちんと確認することはやはり大事ですね。 皆さんはデータ移行時は必ずアップロード時に整合性を確認して、失敗した場合はリトライなどの処理をしましょう。データ数が多いので、移行後の整合性確認はお金の無駄でしかありません。
- 投稿日:2021-04-28T17:44:16+09:00
AWS DevOps Monitoring Dashboardを試してみた
はじめに 「AWS DevOps Monitoring Dashboard」という、CI/CDのアクティビティが可視化されるいい感じのソリューションがあったので、試してみました! CloudFormationテンプレートが配布されているのでリソースの立ち上げは簡単なのですが、ちょっとしたハマりどころがあったので共有します。 ちなみに、料金が発生します。 Q: このソリューションの費用はいくらですか? A: 2021 年 3 月の時点で、米国東部 (バージニア北部) の AWS リージョンでこのソリューションをデフォルト設定で実行するためのコストは、開発チームによるコードの変更やコードのデプロイなどの CI/CD アクティビティから 1 か月あたり 100GB のデータが生成され、QuickSight の作成者が 1 人、閲覧者が 10 人いて、それぞれが月に 2 回ダッシュボードにアクセスすると仮定すると、約 34.20 USD/月です。 各 AWS のサービスのコスト内訳などの詳細なコスト見積もりについては、ソリューション実装ガイドをご参照ください。 よくある質問 前準備 QuickSight立ち上げ CI/CDのアクティビティを可視化するツールとして、QuickSightを利用します。 QuickSightは、ほかのAWSサービスとは少し違い、AWSアカウント以外に専用のアカウントを作成する必要があります。 そのため、まずQuickSightのアカウントを作成します。 マネコンの検索窓からQuickSightと入力し、アクセスします。 「Sign up for QuickSight」を押下するとエディション選択画面になるのですが、ここでエンタープライズエディションを選択します。(ガイド参照) Amazon QuickSight deployment This solution requires Amazon QuickSight resources to be deployed in an Amazon QuickSight Enterprise edition account in the same Region. If you plan to use the Amazon QuickSight dashboard feature, you must subscribe to Amazon QuickSight Enterprise edition in the account where you deploy the solution. Refer to Signing Up for An Amazon QuickSight Subscription if you do not have an Amazon QuickSight Enterprise account set up. Ensure that you have the QuickSight Principal ARN, as you will need it later when you deploy the solution. For information, refer to Retrieve the Amazon QuickSight Principal ARN. エディションを選択するとアカウント作成画面になるので、案内に沿って作成します。 (リージョンは普段使っているものを選択することをお勧めします。) 以下のコマンドをCLIで打ち、作製したアカウントのARNを入手します。 $ aws quicksight list-users --region <REGION> --aws-account-id <ACCOUNT ID> --namespace default > ... "Arn": "arn:aws:quicksight:<REGION>:<ACCOUNT ID>:user/default/<USER NAME>" ... リソースの立ち上げ スタックの作成 ソリューションのページからCloudFormationテンプレートをダウンロードします。 ダウンロードしたテンプレートをもとに、スタックを作成します。 「スタックの詳細を指定」のページにQuickSightのARNを入力する箇所があるので、先ほど入手したARNを入力します。 少しするとスタックが作成されるので、作成されたらQuickSightにアクセスし、ダッシュボードから確認します。 ハマりどころ アクセス権限がないと怒られました。 なのでアクセス権限を付与します。 QuickSightの右上、「QuickSightの管理」→「セキュリティのアクセス権限」から付与を行います。 S3とAthenaのアクセス権限があればよいと思います。 スタック作成時に自動生成されたバケットとCloudTrailの証跡ログを保管しているバケットのアクセス許可を行うとうまくいきました。 S3バケットを選択、更新してもアクセス権限が反映されない場合は以下を試してみてください。 実際に動かしてみる 適当に作ったCodePipelineを動かしてみます。 CodeCommitのPushをトリガーにCodeBuildでビルドを行い、デプロイフェイズでデプロイを行うPipelineを作成しました。 Pipelineを動かして数分後QuickSightを見ると、Pushがカウントされていることがわかります。 まとめ 誰がコミットしたか等が見える化され、CI/CDのマネジメントがより容易にできるようになるソリューションだと思います。 管理に大変さを感じている方は一度試してみてください。
- 投稿日:2021-04-28T17:25:36+09:00
【AWS】IAMユーザーのセキュリティを設定 no.3
こんにちは。まゆみです。 AWSについての記事をシリーズで書いています。 今回は第3回目になります。 前回の記事では、IAMを使って、ユーザーを追加する方法を書きました。 今回は、ルートユーザーやIAMユーザーのセキュリティを強化する方法について書いていきます。 ではさっそく始めていきますね。 ルートユーザーとIAMユーザーは二重に守られる AWSのユーザーは、二重のレイア―を作ることで守られます。 ①強固なパスワード ②Multi Factor Authentification(MFAと略される) 多要素認証 では実際にAWSのコンソールから試してみましょう パスワードポリシー パスワードをどの程度、強力な物にするかはコンソールの中の IMA > アカウント設定 で設定する事ができます。 『Change』をクリックすると下のような画面になります。 MFA パスワードを強固な物にしただけでは、まだハッカーにパスワードを盗まれたりする可能性も否定できません。 そこで、MFAも合わせて使います。 あなたの持っているスマホなどのデバイスにQRLコードで読み込んだカウントダウンタイマーのようなものを利用して、そこに表示される6桁の数字を入力します。(この記事では、Google Autheiticatorによる 多要素認証を説明します。) Google Autheiticatorの入手は、携帯のAPP StoreにGoogle Autheiticatorと検索して探してみてください。 MFAでもセキュリティを強化する事によって ①パスワードが盗まれる ②携帯デバイスが盗まれる と2つのことが起こらないと、他人がAWSにログインできないようにすることができます 上記のスクショで示しているように、『マイセキュリティ資格情報』をクリックします 少しスクロールすると、下のような画面になりますので、そこにある『MFAデバイスの割り当て』をクリックします 割り当てられるMFAデバイスのタイプは、Google Autheiticatorのみではありませんが、この記事では、Google Autheiticatorを使うと仮定して解説しますね。 『仮想MFAデバイス』をチェックして続行をクリック ①あらかじめ入手したGoogle AutheiticatorのQRコードリーダーでQRコードを読み込み ②10秒ごとに新しい6桁の数字が表示されるので ③1回目の6桁と、その次に表示される6桁の数字をそれぞれ、MFAコードと書かれたボックスに入力します。 以上の設定をすると、再度ログインする際に、MFAコードも入力するように求められます。 その時はあなたのデバイスに表示されている6桁の数字を入力してくださいね。 まとめ 今回の記事は以上で終わりにします。 次回も、また引き継きAWSについての記事を書いていきますね。
- 投稿日:2021-04-28T17:25:30+09:00
CloudFrontでタイムアウトによる504エラーを回避する方法
まえおき 皆さん、こんにちは! ハンズラボのサムです! 今回は私がCloudFrontを検証中に知った知ってたらちょっと役に立つかも?な小技を紹介させていただきます! 504 Error Origin Response Timeout CloudFrontのOriginの設定項目に、【Origin Response Timeout】というOriginとの通信でタイムアウトになる時間を設定する項目があります。 こちらの項目なのですが、上限値はMax 60sとなっており、ちょっと長めの処理や負荷がかかっている際に60sだと504 Errorで下記のような画面になることがあります。 これは実はAWSサポートの【サービス制限の緩和】から【Origin Response Timeout】のMax時間を伸ばすことが出来きます! ただ、これにも上限があって【60s -> 180s】が限界みたいです(ハードリミットらしい) なので、万が一CloudFrontの【Origin Response Timeout】で引っかかるようなことがあれば是非この方法を試してみてください! もっとも、そんなにレスポンスがかからないように構築しないといけないという考え方が普通なので、この方法はあくまでもどうしても困ったら試す程度だと思います。 以上、CloudFrontの小技?でした!
- 投稿日:2021-04-28T15:55:06+09:00
LaravelのログをCloudWatch Logsに投げる
CloudWatchFullAccess権限を持っているIAMユーザを作成 こちらの記事を参考にしてください。作成した時に生成されたアクセスキーとシークレットアクセスキーをenvファイルに記述しましょう。あと、LOG_CHANNEL=cloudwatchとしておきましょう。 .env LOG_CHANNEL=cloudwatch AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx AWS_DEFAULT_REGION=ap-northeast-1 ライブラリインストール 下記のコマンドを打ちましょう。composer経由でインストールします。これをインストールすると、依存関係で aws/aws-sdk-php、monolog/monologもインストールされます composer require maxbanton/cwh コード まずはこのクラスを作ります。 App\Logger\CloudWatchLogger.php <?php namespace App\Logger; use Aws\CloudWatchLogs\CloudWatchLogsClient; use Maxbanton\Cwh\Handler\CloudWatch; use Monolog\Logger; class CloudWatchLogger { /** * Create a custom Monolog instance. * * @param array $config * @return \Monolog\Logger */ public function __invoke(array $config) { $sdkParams = $config["sdk"]; $tags = $config["tags"] ?? [ ]; $name = $config["name"] ?? 'cloudwatch'; // Instantiate AWS SDK CloudWatch Logs Client $client = new CloudWatchLogsClient($sdkParams); // Log group name, will be created if none $groupName = config('app.name') . '-' . config('app.env'); // Log stream name, will be created if none try { $instance_id = file_get_contents("http://169.254.169.254/latest/meta-data/instance-id"); // <- ※1 } catch (\Exception $e) { $instance_id = null; } $streamName = $instance_id ?? config('app.hostname', 'localhost'); // <- ※2 // Days to keep logs, 14 by default. Set to `null` to allow indefinite retention. $retentionDays = $config["retention"]; // Instantiate handler (tags are optional) $handler = new CloudWatch($client, $groupName, $streamName, $retentionDays, 10000, $tags); // Create a log channel $logger = new Logger($name); // Set handler $logger->pushHandler($handler); return $logger; } } config/logging.php の 'channels' => [ ] に、以下を追加します。 config/logging.php 'cloudwatch' => [ 'driver' => 'custom', 'via' => App\Logger\CloudWatchLogger::class, // <- 上で作成したロガークラス 'sdk' => [ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'version' => 'latest', 'credentials' => [ 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY') ] ], 'retention' => env('CLOUDWATCH_LOG_RETENTION', 7), // <- ログ保存期間(null の場合は無制限) ], 実際にログを吐き出すようにしましょう。CloudWatch Logsより確認できたら完了です。 public function index() { Log::error('エラーが発生しました'); } 参考文献 ・https://idealive.jp/blog/2019/07/22/laravel-amazon-cloud-watch-logs/
- 投稿日:2021-04-28T15:54:17+09:00
AWS×オンプレ1
0.はじめに AWSが毎月のようにサービスを増やしていく中、 オンプレとAWS間での接続であったり、移管であったり、諸々サービスが増えてきました。 ただ、必ずしもAWSへの移管が正義で、オンプレが不都合というわけでもなく、 そこは運用するサービスのドメインの性質であったり、コスト面で考えていく必要があるのではないでしょうか。 前置きはそんな感じで、本日はAWSとオンプレ間で利用可能なサービスだったり、 接続、移管系のサービスを紹介していこうと思います! 1.AWS Snowファミリー まずはデータ転送サービスで、AWS Snowファミリーを紹介します。 こちらは、現在のところ「Snowcone」「Snowball」「Snowmobile」の3つのサービスで形成されてるAWS随一のオンプレ→AWSのデータ転送サービスです。 まずはSnowconeから紹介します AWS Snowcone 以前からあったAWS Snowballを更に小型化したデバイスで、 エッジコンピューティング、エッジストレージやデータ転送デバイスとして使用することができます。 また、デバイスを直接AWSに送付することで、 ストレージに記録されたデータをS3などAWSのストレージサービスに転送して頂くこともできるため、 AWSへのデータ移管としても利用することができます。 snowballと比べると、重量は2.1kgと持ち運びも可能な重さで、 1デバイスあたり最大8TBのストレージ容量が設計されています。 AWS Snowball snowファミリーの最古参で、40〜52vCPUを提供し、 単体で一時的な大規模コンピューティングが可能なデバイスです。 またLambda関数や、もちろんEC2インスタンスを稼働させることも可能で、 断続された環境下での開発後、AWSグローバル上にデプロイすることでサービスを展開することも可能です。 AWS Snowmobile もはやネタなのかなと最初は思っていましたが、実際に運用された例もあるということで驚き、 AWS Snowシリーズ最大にして最強のデバイス?snowmobileです。 どこがmobileなのかよくわかりませんが、トラックに積載されたコンテナ自体が本体で、 最大100ペタバイトのストレージを提供し、オンプレデータセンターからAWSへのデータ移管を正に物理的に行います。 オンプレデータセンターへ配送され、ローカルネットワークで接続し、データ転送をしたのちAWSに帰って行き、 最終的にデータはS3に展開されます。 データの暗号化はもちろん、コンテナ自体も、不正開封防止、防水、および温度制御を備えています。 また消防、専門のセキュリティ担当者、GPS 追跡、アラームモニタリング、 24時間年中無休の監視カメラ、輸送中に警護するセキュリティ車両などオプションも豊富に用意されています。 ただ日本国内だと、道路交通法でこのサイズのコンテナの積載は認められていないようですが、 いつか国内で走るsnowmobileを写真に収められる日が来ることを楽しみにしています。 2.AWS outposts 次にオンプレとAWS共存の道を選ぶためのサービス「AWS outposts」です。 こちらは、先程のオンプレtoAWSとは全く違って、AWS in オンプレという構図のサービスになります。 どういうことかというと、写真のようなラックをオンプレデータセンターに設置し、 内部で1つのアベイラリティゾーンとして、AWSサービスを展開するものです。 対応しているサービスは、「Amazon EC2」「Amazon EBS」「Amazon ECS」「Amazon EKS」「Amazon EMR」「Amazon VPC」「Amazon RDS」「Amazon S3」等の主要サービス。 コンプライスアンス的に、クラウドへのデータ移管ができないようなシステムに対しての、ソリューションの1つとなります。 今ではVMware Cloud on AWSなどもありますが、 物理的にデータをオンプレから出すことが許されない状況などでは、 AWS outpostsが活躍するのではないでしょうか。 3.VMware Cloud on AWS 先ほどoutpotsの説明でも出しましたが、今度は逆にオンプレ in AWSという構築で、 AWSデータセンター内の物理サーバー内で、VMwareを動かすことができます。 (構成図はサーバーワークス社様の記事より引用) https://blog.serverworks.co.jp/tech/2020/05/28/vmconaws/ オンプレで運用されているVMware環境をAWS上に移管するハードルを極端に下げることに成功しました。 ただ、あくまで管理はVMwareにより行われていたり、通常のVPCではなく、 AWSデータセンター内にあるVMwareの物理サーバーで構成される、 VMWareのNSXによって構築される仮装ネットワーク上に存在するため、 通常のAWSクラウドサービスのような使い勝手ではありませんが、 VMware環境下のシステムであれば大きなネットワークの設定変更が必要なく、 サーバーをAWS内に移管することを可能とします。 4.いったんまとめ 近年AWSは、オンプレ顧客の獲得に力を入れており、独自サービスの展開とともに、移管のハードルを下げています。 まだまだAWS×オンプレ的には5分の1程度の紹介しかできていないと思うので、引き続き第2弾を書いていきます。 他の記事もよかったらどうぞ。
- 投稿日:2021-04-28T15:39:33+09:00
画像認識で音楽ゲームのスコアを記録するシステムをつくる(AWS・Cloud Vsion API)
はじめに クラウドサービス(AWSとGCP)の学習をかねて、プロジェクトセカイカラフルステージの音楽ゲームの結果画面の画像から、画像認識を行なって結果を保存するシステムを作りました。また、以下の記事やサイトを参考にしました。 参考 https://dev.classmethod.jp/articles/ocr-with-lambda-using-cloud-vision-api/ https://docs.aws.amazon.com/cdk/latest/guide/hello_world.html https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-tutorial.html#with-s3-tutorial-create-function-createfunction https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-layer-simulated-docker/ システムの構成 このシステムは以下のような構成で作られています。 おそらく基本的なAWSのサーバレスの構成に近いのかなと思っています。S3に画像が上げられるとそれをフックにLambda起動し、CloudVisionAPIを通して画像認識を行い、それから得られた結果をS3とDynamoDBに保存するといった流れになっています。 また、AWSのリソースをいい感じに作ってくれるものはいくつかありますが、今回はAWSCDKを利用してみました。CDK自体は様々な言語で利用ができますが、今回はPythonでつくりました。 CloudFormationを直に書いて作るより、これぐらいシンプルな構成だとわかりやすく作れるのでいいのかなと思いました。できないこともあるのかもしれないですが、コードを書くようにリソースを定義できるので見やすかったり、エラーが事前に出てくれるのでわかりやすいのかなとも思います。 事前準備 AWSを使うためにIAMユーザーやCredentialなどの準備が必要です。また、画像認識のためにGCPも利用しているのでそこらへんの準備もします。お金は多分かからないですが、従量課金のサービスなので使いすぎるとかかります。 また、PythonのライブラリをLambdaでも使えるようにするためにDockerを利用しました。 CloudVisionAPIを使えるようにする CloudVisionAPIを有効化する。 サービスアカウントを作成する。 サービスアカウントのキーから鍵を追加、新しい鍵を作成でJSONのファイルをダウンロードする。 権限周りでも少し設定がいるのかもしれませんが、自分はこれで利用することができました。 AWSCDKのインストールと初期化 $ npm install -g aws-cdk # cdkインストール $ cdk bootstrap # デプロイ用のS3バケット作成 CDKでつくる 以下のようにするとCDKので作成するためのテンプレートが生成されます。また、このCDKで作られたアプリケーション専用のPython環境を使えるようにVirtualenvが用意されていますが、ここらへんは自分が使いやすい方法で大丈夫です。今回は、用意されたものを利用します。 $ mkdir score-record $ cd score-record $ cdk init app --language python # pythonでcdkを作る $ source .venv/bin/activate # このアプリケーション専用のPython環境を使う(好きな環境で) requirement.txtの変更とインストール requirement.txtを修正します。これらは、AWSのリソースを作成するのに必要なものです。また、一応Lambdaで利用するライブラリもインストールします。 requirements.txt aws-cdk.core aws-cdk.aws-s3 aws-cdk.aws-lambda aws-cdk.aws-dynamodb aws-cdk.aws-s3-notifications google-cloud-vision boto3 pillow pandas $ python -m pip install -r requirements.txt つくっていくよ フォルダ構成 score-record ├── function │ │── gcp.json │ └── index.py ├── layers │ └── requirements.txt ├── score_record │ └── score_record_stack.py ├── .venv │ └── .... │ ├── app.py ├── cdk.json └── requirements.txt AWSのリソース作成 score_record_stack.py from aws_cdk import ( core, aws_s3, aws_s3_notifications, aws_lambda, aws_dynamodb) class ScoreRecordStack(core.Stack): def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # The code that defines your stack goes here # 画像を入れるところのバケット score_image_bucket = aws_s3.Bucket( self, "ScoreImageBucket", bucket_name="score-image-bucket", #ここの名前は他の人が使うと使えない removal_policy=core.RemovalPolicy.DESTROY) #アプリケーションを消すとバケットが消える # 記録を保存するためのバケット score_data_bucket = aws_s3.Bucket( self, "ScoreDataBucket", bucket_name="score-data-bucket", #ここの名前は他の人が使うと使えない removal_policy=core.RemovalPolicy.DESTROY) #アプリケーションを消すとバケットが消える # 記録を保存するためのDynamoDBテーブル score_data_table = aws_dynamodb.Table( self, "score_table", # テーブル名 partition_key=aws_dynamodb.Attribute( # Dynamodbテーブルpartition_keyの設定 name="id", type=aws_dynamodb.AttributeType.STRING ), removal_policy=core.RemovalPolicy.DESTROY) #アプリケーションを消すとテーブルが消える # Lambdaからライブラリを使うためのLayer score_lambda_layer = aws_lambda.LayerVersion( self, "ScoreLambdaLayer", code=aws_lambda.AssetCode("layers/"), compatible_runtimes=[aws_lambda.Runtime.PYTHON_3_8]) # Lambda関数 lambdaFn = aws_lambda.Function( self, "ScoreVisionFunction", code=aws_lambda.Code.from_asset("function/"), runtime=aws_lambda.Runtime.PYTHON_3_8, # python3.8で行う handler="index.handler", # 起動場所 function_name="score_vision_function", layers=[score_lambda_layer], # score_lambda_layerを利用する timeout=core.Duration.seconds(30)) # タイムアウト30秒に # 環境変数設定 lambdaFn.add_environment("GOOGLE_APPLICATION_CREDENTIALS", "gcp.json") lambdaFn.add_environment("SCORE_BUCKET_NAME", score_data_bucket.bucket_name) lambdaFn.add_environment("SCORE_TABLE_NAME", score_data_table.table_name) # 画像が入ったのをフックにLambdaを起動 notification = aws_s3_notifications.LambdaDestination(lambdaFn) score_image_bucket.add_event_notification(aws_s3.EventType.OBJECT_CREATED, notification) # 各S3とDynamoDBにアクセス権限をLambdaに与える score_image_bucket.grant_read_write(lambdaFn) score_data_bucket.grant_read_write(lambdaFn) score_data_table.grant_read_write_data(lambdaFn) LambdaLayerの作成 layers/requirements.txt google-cloud-vision Pillow pandas $ cd layers $ docker run --rm -v "$PWD":/var/task "public.ecr.aws/sam/build-python3.8" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.8/site-packages/; exit" このようにするとlayersのフォルダにLambdaで実行するようのライブラリをインストールすることができます。 score-record ├── function │ │── gcp.json │ └── index.py ├── layers │ │── requirements.txt │ └── python # ここから下が追加される │ └── lib │ └── python3.8 │ └── site-packages │ │── ライブラリ │ └── ライブラリ ├── score_record │ └── score_record_stack.py ├── .venv │ └── .... │ ├── app.py ├── cdk.json └── requirements.txt LambdaFunctionの作成 function/index.py import boto3 import uuid import os import pandas as pd import datetime import re from urllib.parse import unquote_plus from PIL import Image, ImageDraw from google.cloud import vision s3 = boto3.client('s3') dynamodb = boto3.resource('dynamodb') # 画像編集関連 def edit_image(image_path, edited_path): with Image.open(image_path) as image: img_width, img_height = image.size img = image.crop((0, 0, 1300, img_height)) draw = ImageDraw.Draw(img) draw.rectangle((0, 0, 170, 170), fill=(0, 0, 0)) draw.rectangle((0, 170, 1300, 550), fill=(0, 0, 0)) draw.rectangle((0, 820, 1300, 940), fill=(0, 0, 0)) draw.rectangle((0, 700, 500, 850), fill=(0, 0, 0)) draw.rectangle((0, 400, 80, 850), fill=(0, 0, 0)) draw.rectangle((880, 0, 1300, 850), fill=(0, 0, 0)) draw.rectangle((0, 820, 250, img_height), fill=(0, 0, 0)) draw.rectangle((0, 1260, img_width, img_height), fill=(0, 0, 0)) filter_img = img.convert('L') filter_img.save(edited_path) def handler(event, context): # 保存するデータのカラム columns = ["name", "difficulty","score", "combo", "perfect", "great", "good", "bad", "miss"] allSekaiScore_df = pd.DataFrame(columns=columns) for record in event['Records']: bucket = record['s3']['bucket']['name'] key = unquote_plus(record['s3']['object']['key']) print("start recognize" + key) tmpkey = key.replace('/', '') download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey) edited_path = '/tmp/edited-{}'.format(tmpkey) s3.download_file(bucket, key, download_path) # バケットから画像をダウンロード edit_image(download_path, edited_path) # 画像編集 with open(edited_path, "rb") as f: content = f.read() client = vision.ImageAnnotatorClient() image = vision.Image(content=content) print("start recognize" + key) # CloudVisionAPIで文字認識 response = client.document_text_detection( image=image, image_context={'language_hints': ['ja']} ) # 認識結果を表示 print(response.full_text_annotation.text) words = response.full_text_annotation.text.replace(" ", "").split("\n") print(len(words)) print(words) # ここらへんは画像処理によって変わる if len(words) == 16: name, difficulty, score, _, combo = words[:5] score = re.sub("\\D", "", score[:8]) # 数字以外を取り除く combo = re.sub("\\D", "", combo) # 数字以外を取り除く perfect, great, good, bad, miss = words[10:15] print("name: " + name) print("difficulty: " + difficulty) print("score: " + score) print("combo: " + combo) print("perfect: " + perfect) print("great: " + great) print("good: " + good) print("bad: " + bad) print("miss: " + miss) perfect, great, good, bad, miss = int(perfect), int(great), int(good), int(bad), int(miss) score, combo = int(score), int(combo) sekaiscore_df = pd.DataFrame([[name, difficulty, score, combo, perfect, great, good, bad, miss]], columns=columns) allSekaiScore_df = allSekaiScore_df.append(sekaiscore_df) # DynamoDBにデータを保存 TABLE_NAME = os.environ["SCORE_TABLE_NAME"] score_data_table = dynamodb.Table(TABLE_NAME) score_data_table.put_item( Item={ 'id': str(uuid.uuid4()), 'name': name, 'difficulty': difficulty, 'score': score, 'combo': combo, 'perfect': perfect, 'great': great, 'good': good, 'bad': bad, 'miss': miss } ) print("dynamodb put") # 画像を削除 s3.delete_object( Bucket=bucket, Key=key ) if response.error.message: raise Exception( '{}\nFor more info on error messages, check: ' 'https://cloud.google.com/apis/design/errors'.format( response.error.message)) allSekaiScore_df = allSekaiScore_df.reset_index() allSekaiScore_df = allSekaiScore_df[columns] dt = datetime.datetime.now() csv_key = "csv/{0:%Y-%m-%d-%H-%M-%S}.csv".format(dt) score_data_bucket = os.environ["SCORE_BUCKET_NAME"] # csvデータの保存 s3.put_object( Bucket=score_data_bucket, Body=allSekaiScore_df.to_csv(index=False).encode(), Key=csv_key, ) print("save csv") return allSekaiScore_df.to_csv(index=False).encode("utf-8") 画像編集関連 このまま画像認識を行うと曲や背景などによって結果が変わってしまうので、なるべく同じような形の結果になるように画像を編集します。 この編集ではiPadPro10.5インチで撮影したものを利用しています。他の端末や画像サイズが違う場合は変わるので気をつけてください。 元画像 編集後の画像 認識の結果 デプロイするよ $ cdk deploy 動作確認 S3バケットに画像をアップロードします。 無事に動作していればS3にはcsvファイルが、DynamoDBテーブルを見ると記録が保存されています。また、画像をアップロードしたバケットは空になっています。 おわりに 必要がなければ、以下のコマンドで今回作成した環境を消しましょう。 cdk destroy
- 投稿日:2021-04-28T13:40:55+09:00
AWSを理解する[ネットワーク構築編]
ネットワークを構築する 要点 リージョンを指定(東京) VPCの作成 サブネットの作成 インターネットゲートウェイを作成し、VPCにアタッチ 新たにルートテーブルを作成し、パブリックサブネットのデフォルトルートテーブルに設定する デフォルトゲートウェイをインターネットゲートウェイに設定する サブネットを分割する主な2点の理由 物理的な隔離: 1階と2階とで別のサブネットに分けたいという、物理的に分けたい時に有効。 セキュリティ上の理由: 経理部のネットワークだけを分離して、他の部署からはアクセスできないようにするなど。 ネットワーク構築に関する用語集 EC2: 仮想的なサーバー インスタンス: 起動された各サーバー(EC2)の個体 Wireshark: ネットワークを流れる生のデータや、流れるデータを覗き見れる。 NAT: Network Address Translationの略で、内部で通用するアドレスを外部とも通信できるアドレスに変換する技術(これを利用すると片方向だけの接続を許すことができ、インターネットからDBサーバーに接続出来ないが、DBサーバーからインターネットには接続することができる。) Region: 世界22箇所に分散された各地域のデータセンター群のこと アベイラビリティゾーン: リージョンをさらに分割し、物理的に距離が相当離れたネットーワークや電源網などの設備で、あるアベイラビリティゾーンが地震や洪水が起こっても、他のアベイラビリティゾーンには影響を受けない耐障害性を高める概念がある。 Amazon VPC: 銅のようなIPアドレス範囲を使うか指定できる サブネット: VPCを更に分割して利用でき、サブネットの中にサーバー(EC2)を配置できる。 グローバルIP(パブリックIP): インターネットに接続する際に用いるIPアドレス プライベートIP: インターネットで使用されないIPアドレス CIDR表記: 「192.168.1.0~192.168.1.255」の場合、プレフィックスは24ビットです。IPアドレス範囲をCIDR表記する場合、その範囲は「CIDRブロック」と呼ばれます。 サブネットマスク表記: プレフィックスのビット数だけ2進数の1を並べ、残りは0で表す表記。「192.168.1.0~192.168.1.255」の場合、サブネットマスクは「255.255.255.0」なので、「192.168.1.0/255.255.255.0」と表記します。 パブリックサブネット: インターネットからアクセスすることを目的としたサブネット(webサーバーなどを配置する) プライベートサブネット: インターネットから隔離したサブネット(データベースサーバーなどを配置する) プロトコル: パケット: データを送受信する際の単位でヘッダー情報やデータの実態が含まれている ルートテーブル: 宛先IPアドレスの値が、いくつの時には、どのネットワークに流すべきか設定できる ディスティネーション: 宛先アドレスのこと ネクストポップ(ターゲット): ディスティネーションから流すネットワーク先のこと デフォルトゲートウェイ: 転送先が何も設定されていない時のデフォルトの転送先 ネットワーク構築に関する補足 まずネットワークを構築する際はIPアドレスの範囲を定める IPアドレスは前半の部分をネットワーク部、後半の部分をホスト部を言う。 IPアドレスを2進数で表記したとき、「ネットワーク部のビット長」を「/ビット長」で示す方法です。このビット長のことを「プレフィックス(prefix)」と言います。 CIDR表記やサブネットマスク表記は単純に、先頭から、いくつ分のIPアドレス範囲を示しているかを示す表記方法に過ぎない。 実際のネットワークでは、割り当てられたCIDRブロックを、そのまま使わずに、小さなブロックに分割して利用することがほとんど。 サブネットをインターネットに接続するにはインターネットゲートウェイを用いる(自分のネットワークにインターネット回線を引き込むというイメージ) ネットワークにデータを流すためにはルーティングテーブル(ルートテーブル)が必要 インターネットで使われている「TCP/IP」というプロトコルではデータを細切れにしたパケットという単位でデータが送受信されている。 あるサブネットに対してだけ、ルートテーブルを変更したい時は、必ず、新しいルートテーブルを作成して、ルートテーブルに割り当てます。 tips ネットワーク関連コマンド ping traceroute telnet nslookup dig 補足 ICANN(Internet Corporation for Assigned Names and Numbers): IPアドレスを一括管理している団体 APNIC(Asia Pacific Network Information Center): アジア圏のIPアドレスを管理している団体 JPNIC(Japan Network Information Center): 日本のIPアドレスを管理している団体 2011年2月3日にICANNが持つIPアドレス(IPv4)の在庫がなくなり、JPNICでも約2ヶ月後の2011年4月15日に在庫がなくなった。そのため、IPv4からIPv6への移行が進められたが互換性がないため以降はスムーズではなく、移行が完了するまでは1つIPアドレスを複数のエンドユーザーで共有するNATという仕組みでIPアドレス問題を解決した。
- 投稿日:2021-04-28T10:59:31+09:00
【AWS】IAMとは?概要と使い方を詳しく説明 no.2
こんにちは、まゆみです。 AWSに関する記事をシリーズで書いています。 今回は第2回目になります。 前回の記事では、 そもそもクラウドとはどんなサービスのことなのか? AWSの概要 について書かせていただきました。 今回の記事から、もう少し具体的な内容に踏み込んでいこうと思います。 今回の記事では、AWSの『IAM(アイ・エー・エム)』とは何なのかについて書いていきますね。 ではさっそく始めていきます。 IAMとは? IAMとは『Identity Access Management』の略になります。 IAMとはその名の通り、AWSを使う個人やグループの特定のリソースに対するアクセス権をコントロールするサービスになります。 全てのAWSユーザーに全てのリソースへのアクセス権を与えるのではなく、個人やグループに必要なアクセス権を必要に応じて与えることができるのが、IAMです。 ユーザーやグループに、それぞれに相応しい権限を与えるために ①ユーザー追加をする ②そのユーザーに必要なアクセス権を与える の2段階が必要です。 特定のアクセス権を個々人にそれぞれ付与することもできますが、あるグループに所属する人、全員に同じ権限を与えることもできます。 グループの中に入れることができるのは、『ユーザー個人』であり、『グループ』はグループのなかに入れることはできません。 また、グループに属さないユーザーを作るのはベストプラクティスではありませんが、認められています。(上記のイラストの例で言えば、一番右の女性はどのグループにも所属していません) 他のグループにまたがって新しいグループを作ることも可能です。(上の例ではGroupCのようなグループを作ることも可能) ポリシーとは? 引用元:AWSコンソール ユーザー、またはグループを作ったあとは、それぞれのユーザー・グループにふさわしいポリシーを紐づけることです。 ポリシーとは、ある特定のユーザー・グループができるアクセス権の書かれたドキュメントです。 上記のスクショに書かれているように、通常JSONフォーマットで保存されています。 引用元:AWSコンソール ポリシーは、個々のユーザーに対しても、グループ分けされたそのメンバー全員にも付与する事ができます。 では、ここで一つの疑問。。。 例えば EC2(サーバーコンピュータのようなもの)にあるアプリケーションがあり、そこを経由してS3(ストレージのようなもの)内にあるファイルにアクセスしなければいけないなどの時はどうしたら良いのでしょうか? それが『Roll(ロール)』と言われるものになります。 ポリシーは、特定のユーザーやグループに付与されるものですが、ロールは主にインスタンスに対して与えられるものになります。 実際にIAMを使ってみる では、IAMの概要が理解できたところで、実際にIAMを使ってみましょう AWSのサービスの、『セキュリティ、ID、およびコンプライアンス』に『IAM』はあります。 また、新規登録の際に自動的にユーザーが作られたと思いますが、それはルートユーザーと言われるもので全ての権利が与えられている者なので、パワーを持ちすぎているという理由から、日々のタスクをこなす際に使うことは推奨されていません。 なので、新しいユーザーを追加しましょう 『ユーザーを追加』をクリック 必要事項を入力します。 今回は、私しかユーザーがいないので、『カスタムパスワード』で自分の作ったパスワードを使用しますが、例えば他の誰かのためのユーザー追加をする時は、自動生成パスワードを選択してもよいでしょう。 パスワードのリセットが必要かどうかも、その時々で臨機応変に選択してくださいね。 『グループの作成』をクリック グループ名を入力して、ポリシーを選択してチェックします。 これで、このグループに属するメンバーは全員チェックしたポリシーを引き継ぐことになります その後、『グループの作成』をクリック タグ名を追加できますが、オプションなので、入れても入れなくても構いません 確認画面になります そのまま先に進むと、ユーザー登録を無事に終えることができます もし、このユーザー登録情報のバックアップを取っておきたかったり、他の人のためにユーザーの追加をした場合などには、 .csvのダウンロード Eメールの送信 をすることもできます まとめ 今回の記事は、ここで締めくくらせていただきます。 次回も引き続きAWSについての記事を投稿しますので、よろしくお願いします
- 投稿日:2021-04-28T02:47:11+09:00
[AWS]VPCの設定
以下の記事を参考にさせていただきました。 はじめに AWSのEC2でRailsアプリをデプロイしたのでメモとして残しておきます。 今回はVPCの設定をしていきます 自分の手順書としてのメモですので画像はありません。あしからず。 VPCを作成 AWSページの上部にあるサービス検索欄で「VPC」と入力し「VPC」をクリックします。 ※ここでリージョンを「東京」にしていない方は右上のリージョンを選択して「アジアパシフィック(東京)」に変更しましょう 以下の通りに入力します。 1. 名前タグ: VPC_for_アプリ名 2. IPv4 CIDR ブロック: 10.0.0.0/16 3. IPv6 CIDR ブロック: IPv6 CIDR ブロックなし 4. テナンシー:「デフォルト」 5. タグ: キー: Name 値: VPC_for_アプリ名 「VPCを作成」を選択 サブネットを作成 画面の左から「サブネット」を選択して遷移したページから「サブネットを作成」をクリックします。 以下の通りに入力します。 1.VPC ID: 「先ほど作成したVPC」 2.サブネット名: 「アプリ名-Subnet-1a」 3.アベイラビリティーゾーン: 「ap-northeast-1a」 4.IPv4 CIDR ブロック: 「10.0.0.0/24」 5.タグ: キー:「Name」, 値:「アプリ名-Subnet-1a」 インターネットゲートウェイを作成 画面左「インターネットゲートウェイ」をクリックして、「インターネットゲートウェイの作成」を選択します。 以下の通りに入力します。 1.名前タグ:「Gateway_for_アプリ名」 2.タグ: キー:「Name」, 値:「Gateway_for_アプリ名」 「インターネットゲートウェイの作成」を選択します。 ゲートウェイをVPCと紐付ける 先ほど作成したゲートウェイとVPCを紐付けます。 ゲートウェイを選択した状態で「アクション」をクリックして、「VPCにアタッチ」を選択します。 そして「VPCを選択」から作成した「VPC_for_アプリ名」を選択して 「インターネットゲートウェイをアタッチ」を選択します。 ルートテーブルの作成 次にルートテーブルを作成します。 画面左の「ルートテーブル」を選択して、「ルートテーブルの作成」を選択します。 1.名前タグ:「Table_for_アプリ名」 2.VPC:「VPC_for_アプリ名」 3.キー: キー:「Name」、値:「Table_for_アプリ名」 作成をクリック 作成したルートテーブルの「ルートの編集」を行います。 作成したテーブルを選択した状態で、下のタブの「ルート」を選択し、「ルートの編集」を選択します。 以下の通りに記述 1.送信先:「0.0.0.0/0」 2.ターゲットの項目を選択し、「Internet Gateway」を選択、先ほど作成したゲートウェイを選択 3.「ルートの保存」をクリックします。 次にサブネットとの紐付けをします。 画面左から「サブネット」を選択し、先ほど作成したサブネットを選択して画面下の「ルートテーブル」から「ルートテーブルの関連付けを編集」を選択します。 「ルートテーブル ID」から作成したテーブル「Table_for_アプリ名」を選択します。 「保存」をクリックします。 セキュリティグループを作成 セキュリティグループを作成します。 画面左から「セキュリティグループ」を選択して「セキュリティグループの作成」をクリックします。 以下の通りに記述します。 1.セキュリティグループ名:「アプリ名-SecurityGroup」 2.説明:「Security for アプリ名」 3.VPC:「VPC_for_アプリ名」(作成したVPC) 下のインバウンドルールで「ルールの追加」をクリック 以下の通りに記述 1.タイプ:「SSH」 2.プロトコル:「TCP」※自動選択 3.ポート範囲:「22」※自動選択 4.ソース:「マイIP」(自分のグローバルIPが表示) さらにルールを追加します。再度「ルールの追加」ボタンを選択 以下の通りに記述 1.タイプ:「HTTP」 2.プロトコル:「TCP」※自動選択 3.ポート範囲:「80」※自動選択 4.ソース:「任意の場所」(0.0.0.0/0, ::/0) 「セキュリティグループを作成」をクリック ※ここでインバウンドルールを設定しなかった場合はセキュリティグループの画面からインバウンドルールを変更できます。 以上でVPCの作成は終わりです。
- 投稿日:2021-04-28T00:24:50+09:00
linuxのiptablesでproxyサーバーを簡単に実現する方法
概要 linuxのiptablesでproxyサーバーを簡単に実現します。ローカルネットワーク内のpc1は、proxyサーバーを経由して、外部インターネットにアクセスします。 pc1(public ipなし) ----> proxy server(public ipあり) ---> インターネット ##pc1## private ip: 172.31.8.4 ##proxy server## private ip: 172.31.11.10 auto public ip: 13.231.116.234 環境 AWS VPC AWS EC2 (proxyサーバ:1台、pc1:1台) Debian 10 (HVM), SSD Volume Type - ami-0ac97798ccf296e02 (64-bit x86) t2.micro 手順 1. AWS EC2インスタンスの作成(proxyサーバ) ・ Auto-assign Public IP:Enable ・ 送信元/送信先チェックを無効にする 作成したEC2インスタンスを選択して --> Actions --> Networking --> Change source/destination check --> Stopにチェックを入れて、Saveボタンを押下します。 ・IP forwardを有効にする admin@ip-172-31-11-10:~$ cat <<EOF | sudo tee /etc/sysctl.d/ipforward.conf > net.ipv4.ip_forward=1 > EOF net.ipv4.ip_forward=1 admin@ip-172-31-11-10:~$ admin@ip-172-31-11-10:~$ sudo sysctl --system * Applying /etc/sysctl.d/99-sysctl.conf ... * Applying /etc/sysctl.d/ipforward.conf ... net.ipv4.ip_forward = 1 * Applying /etc/sysctl.d/protect-links.conf ... fs.protected_hardlinks = 1 fs.protected_symlinks = 1 * Applying /etc/sysctl.conf ... admin@ip-172-31-11-10:~$ ・iptablesにルールを追加する(source ip: 172.31.8.4 --> 172.31.11.10) 〜〜外部に送信する前に、source ip(pc1のip)を自動的にproxyサーバのeth0のipに設定する〜〜 admin@ip-172-31-11-10:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE admin@ip-172-31-11-10:~$ admin@ip-172-31-11-10:~$ sudo iptables -t nat -S -P PREROUTING ACCEPT -P INPUT ACCEPT -P POSTROUTING ACCEPT -P OUTPUT ACCEPT -A POSTROUTING -o eth0 -j MASQUERADE admin@ip-172-31-11-10:~$ 2. AWS EC2インスタンスの作成(pc1) ・ Auto-assign Public IP:Disable ・ Kernel IP routing tableを変更する 〜〜default Gatewayを削除する〜〜 admin@ip-172-31-8-4:~$ sudo ip route del default 〜〜新しいdefault Gateway(proxyサーバー)を追加する〜〜 admin@ip-172-31-8-4:~$ sudo ip route add default via 172.31.11.10 dev eth0 変更前: admin@ip-172-31-8-4:~$ sudo route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.31.0.1 0.0.0.0 UG 0 0 0 eth0 172.31.0.0 0.0.0.0 255.255.240.0 U 0 0 0 eth0 admin@ip-172-31-8-4:~$ 変更後: admin@ip-172-31-8-4:~$ sudo route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.31.11.10 0.0.0.0 UG 0 0 0 eth0 172.31.0.0 0.0.0.0 255.255.240.0 U 0 0 0 eth0 admin@ip-172-31-8-4:~$ 3.結果を検証する admin@ip-172-31-8-4:~$ curl yahoo.co.jp <HTML> <HEAD> <TITLE>Document Has Moved</TITLE> </HEAD> <BODY BGCOLOR="white" FGCOLOR="black"> <H1>Document Has Moved</H1> <HR> <FONT FACE="Helvetica,Arial"><B> Description: The document you requested has moved to a new location. The new location is "https://www.yahoo.co.jp/". </B></FONT> <HR> </BODY> admin@ip-172-31-8-4:~$ admin@ip-172-31-8-4:~$