- 投稿日:2019-11-24T22:51:45+09:00
AWSにdjango開発環境構築メモ(VSCode Remote SSH用)
前提
この構築のゴールは、AWS環境ではsshのみ開けて、サーバサイドの開発、デバックをClientPCのVSCodeでできるようにすることです。
Client
Windows10
サーバ
CentOS7(AWSで動作)※手順全部書いたつもりです。参考になるところあったら使ってください。
※毎回これするのも大変なのでansible化するかdokerイメージにしたい。
※VSCodeでのdjangoデバック環境は次の機会に。ssh 設定
.ssh/sshconfigにAWSで起動したCentOSののログイン情報を記載してSSHでパス無しでログインできるようにする。
LocalForwardの行は、Djangoのポートへの。PCでlocalhost:8000を開くとサーバ側に転送されて便利。# Read more about SSH config files: https://linux.die.net/man/5/ssh_config Host myserver HostName xxx.xxx.xxx.xxx User centos IdentityFile ~user/.ssh/xxxx.pem LocalForward 8000 localhost:8000VSCodeのRemote SSHで接続できる事を確認しておく
VSCodeにpythonのプラグインをインストールするサーバ側の変更
CentOS7のGitをVersion2に変更する
$ sudo yum -y remove git $ sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm $ sudo yum -y install git2uvenv環境を作ってdjangoをインストール。後で使う、mysqlclientもインストール
$ sudo pip3.6 install --upgrade pip $ cd ~/envs/activate $ python3 -m venv django $ source ~/envs/django/bin/a $ pip install django $ sudo yum install python-devel mysql-community-devel $ pip install mysqlclientdjangoのサンプルアプリ作成
$ cd ~/web/ $ django-admin startproject mysiteCent7のSQliteのバージョンだとdjangoが動かない。
SQLiteは諦めMysqlをインストール$ sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm $ yum info mysql-community-server $ yum -y install mysql-community-server $ sudo yum -y install mysql-community-server $ sudo systemctl enable mysqld.service $ sudo systemctl start mysqld.service $ sudo systemctl status mysqld.service $ sudo cat /var/log/mysqld.log|grep passwordMysqlのセキュリティ設定
[root@ip-172-31-33-248 ~]# mysql_secure_installation Securing the MySQL server deployment. Enter password for user root: The existing password for the user account root has expired. Please set a new password. New password: Re-enter new password: The 'validate_password' component is installed on the server. The subsequent steps will run with the existing configuration of the component. Using existing password for root. Estimated strength of the password: 100 Change the password for root ? ((Press y|Y for Yes, any other key for No) : No ... skipping. By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? (Press y|Y for Yes, any other key for No) : y Success. Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y Success. By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y - Dropping test database... Success. - Removing privileges on test database... Success. Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y Success. All done! [root@ip-172-31-33-248 centos]#MysqlのユーザとDB作成
mysql> create database django01; mysql> create user django@localhost identified by '************'; mysql> grant all on django01.* to django@localhost;venvの適用方法(メモ)
[centos@ip-172-31-33-248 web]$ source venv/bin/activate (venv) [centos@ip-172-31-33-248 web]$ python -V Python 3.6.2 (venv) [centos@ip-172-31-33-248 web]$ pip list Package Version ---------- ------- Django 2.2.7 pip 19.3.1 pytz 2019.3 setuptools 28.8.0 sqlparse 0.3.0djangoのDBをMysqlに変更
$ git diff diff --git a/mysite/settings.py b/mysite/settings.py index 94fdb96..cf0a816 100644 --- a/mysite/settings.py +++ b/mysite/settings.py @@ -75,8 +75,15 @@ WSGI_APPLICATION = 'mysite.wsgi.application' DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'django01', + 'USER': 'django', + 'PASSWORD': '********', + 'HOST': 'localhost', + 'PORT': '3306', + 'OPTIONS': { + 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", + }, } }python manage.py migrate python manage.py runserverクライアントPCで
http://localhost:8000
を開くとdjangoサーバにつながります。
- 投稿日:2019-11-24T21:14:55+09:00
AWS EC2でWindows2008から2012にインプレースアップグレードを試してみた
Windows Server 2008 R2 の期限が 2020年1月に切れます(現在2019年11月)。新規にEC2を構築して移行すればよいのですが、Windowsに インプレースアップグレード っていうのがあるらしいので試してみました。
概要
インプレースアップグレードというのは、Windows Server 2008R2 から 2012に変更できるみたいです。Microsoft公式では2世代までOKと書いているのですが、Win2008R2からWin2012R2はダメでした(Win2008R2からWin2012はOKでした)注意点
ドキュメントにネットワークドライバを更新せよと書いてあったので更新すると、リモートデスクトップで接続できなくなり、実験サーバーなので破棄しました。みなさんも注意してください。AWS 資料
インプレースアップグレードを実行する事前準備
今回は Windows Server 2008 R2 から Windows Server 2012 にアップグレードします。まずは現状のインスタンスにおまじない的な作業を3つ行います。
1 EC2Config サービスをアンインストール
[コントロールパネル][プログラムと機能] から EC2ConfigService をアンインストールします。
2 EC2Launch サービスのインストール
以下の2つをダウンロードします。
https://s3.amazonaws.com/ec2-downloads-windows/EC2Launch/latest/EC2-Windows-Launch.zip
https://s3.amazonaws.com/ec2-downloads-windows/EC2Launch/latest/install.ps1
zipは解凍せずにそのままです。同じ位置にps1を置きます(両方デスクトップに置きました)install.ps1 を右クリック「PowerShellで実行」してください。その後 C:\ProgramData\Amazon で確認してください(隠しフォルダなのでパスを直接入力)
3 AWS Systems Manager SSM エージェントのインストール
以下のダウンロードして実行してください。
https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/windows_amd64/AmazonSSMAgentSetup.exe
インストールメディアの作成
Windows のインストールメディアを用意するのですが、AWS の場合はメディア4GBのボリュームを作り、Dドライブにマウントさせます(おークラウドっぽい)
4 アベイラビリティーゾーン(AZ)とインスタンスIDを控えます。
5 メディアのボリュームの作成
[EC2][スナップショット] で「パブリックスナップショット」を選択します。説明に Windows 2012 と入れて検索します。Windows 2012 Japaneseで「ボリュームの作成」を実行します。先ほどのAZを指定します。
6 ボリュームをアタッチ
作成した4GBのボリュームを選択し「ボリュームのアタッチ」を実行します。インスタンスIDを指定します。
Windows アップグレード
インストールメディアを使ってアップグレードを行います。
7 EC2にリモートデスクトップでログインします。
Dドライブにインストールメディアが表示されています。Setup.exe を実行します。
<起動してすぐ終了する場合>
私の場合 Win2012R2 のインストールメディアが起動できず、Win2012 にするとできました。
8 実行中
9 確認
まとめ
Win2008から2012なら新規に2019を作った方がいいかもしれません。当然ながら無理やり2012になるので、細かいところでトラブルが発生するかもしれません。昔Win7からWin10のアップグレードのトラブルで苦労しました。1点モノのどうしようもないサーバーで、お客から催促されているならこの方法はアリかもしれません。
- 投稿日:2019-11-24T21:04:12+09:00
Go使ってAWS Lambdaでラムダ計算した
tl; dr
ソースコードはこちら
エンドポイントは
https://nd88j25ztg.execute-api.ap-northeast-1.amazonaws.com/dev/lambda
でヘッダにContent-type: application/json
とX-API-KEY: uwuZMJIWbqpmTpfzdEci2YaMGWFSvWz9ZfWFIjVf
を仕込んで{"step":1,"src":"(λx.x)a"}
みたいにPostしてください。curlでやると$ curl -X POST -H "Content-type: application/json" -d '{"step":1, "src": "(λx.x)a"}' -H 'X-API-KEY: uwuZMJIWbqpmTpfzdEci2YaMGWFSvWz9ZfWFIjVf' https://nd88j25ztg.execute-api.ap-northeast-1.amazonaws.com/dev/lambdaみたいな感じ。なお予告なく削除することもあるのでご了承を。
前置き
AWS Lambdaでラムダ計算をするというしょうもないネタ、絶対誰かやってると思ったんですが案外誰もやってない。そんじゃいっちょやってみっかてな感じで、じゃあ言語どうするかって考えたらやっぱ静的型付けがいいよねということでGoに決定。Goやるやる詐欺やめて触ってみるいい機会なのでやってみました。パッケージわけが面倒だったので全部
main
です。そもそもラムダ計算とは
正しく説明できそうにないので参考文献を挙げるにとどめておきます……。ここでは形無しラムダ計算のみ考えます。
ラムダ計算入門 https://www.slideshare.net/_yingtai/lambda-guide
ラムダ計算ABC - Sendai Logic Homepage https://sites.google.com/site/sendailogichomepage/files/ref/ref_03ラムダ計算のモデルを使ってもチューリングマシンと同じ表現力がありますよというお話。
Goで実装する
ラムダ計算
型システム入門を読みながらポチポチやってたらめっちゃ簡単でした
lambda.gopackage main import ( "sort" "strconv" ) type Name string type Names []Name func (xs Names) Len() int{ return len(xs) } func (xs Names) Less(i, j int) bool { return xs[i] < xs[j] } func (xs Names) Swap(i, j int) { xs[i], xs[j] = xs[j], xs[i] } type Var struct { name Name } type Lam struct { name Name expr Expr } type App struct { f Expr arg Expr } type Sym struct{ symbol rune } type Expr interface { reduce() Expr } func (x Var) reduce() Expr { return x } func (x Lam) reduce() Expr { return x } func (x App) reduce() Expr { switch g := x.f.(type) { case Var: return App{g, x.arg.reduce()} case Lam: return subst(g.name, x.arg.reduce(), g.expr.reduce()) case App: return App{x.f.reduce(), x.arg.reduce()}.reduce() default: panic("") } } func (x Sym) reduce() Expr { return x } var cnt = 0 func subst(x Name, s Expr, y Expr) Expr { switch z := y.(type) { case Var: if x == z.name { return s } else { return y } case Lam: if x == z.name { return z } else { if !elem(z.name, free(s)) { return Lam{z.name, subst(x, s, z.expr)} } else { n := Name((string)(z.name) + strconv.Itoa(cnt)) cnt++ return Lam{n, subst(x, s, subst(z.name, Var{n}, z.expr))} } } case App: return App{subst(x, s, z.f), subst(x, s, z.arg)} default: panic("") } } func free(x Expr) Names { switch y := x.(type) { case Var: return Names{y.name} case Lam: return remove(y.name, free(y.expr)) case App: return union(free(y.f), free(y.arg)) default: return Names{} } }Go言語で union とか直和型のようなデータを表現したいときは interface を使う - 嵐の小舟より https://tmrtmhr.info/tech/sum-type-in-golang/
こちらを参考にADTっぽいものをやってみました。中々それっぽく出来ていい感じ。パーサー
こっちのほうが難航したという。まず以下の部分で逆ポーランド記法に直してます。
parser.gofunc toRpn(str string) ([]rune, error) { stack := []rune{} rpn := []rune{} isParam := false lamCnt := 0 for _, c := range str { switch c { case '\\', 'λ': if isParam { return nil, errors.New("lmbda in parameters") } stack = push('\\', stack) isParam = true case '.': for { xs, x, err := pop(stack) if err != nil { return nil, errors.New("mismatched lambda") } stack = xs if x == '\\' { break } rpn = append(rpn, x) } isParam = false case '(': if isParam { return nil, errors.New("parens in parameters") } stack = push('(', stack) case ')': if isParam { return nil, errors.New("parens in parameters") } for { xs, x, err := pop(stack) if err != nil { return nil, errors.New("mismatched parens") } stack = xs if x == '(' { break } rpn = append(rpn, x) } for i := 0; i < lamCnt; i++ { rpn = append(rpn, '\\') } lamCnt = 0 case ' ', ' ': default: rpn = append(rpn, c) if isParam { lamCnt++ rpn = append(rpn, '.') } } } if isParam { return nil, errors.New("lacking expression") } for { xs, x, err := pop(stack) if err != nil{ break } if x == '(' || x == ')' || x == '\\' || x == '.' { return nil, errors.New("invalid tokens remain") } stack = xs rpn = append(rpn, x) } for i := 0; i < lamCnt; i++ { rpn = append(rpn, '\\') } return rpn, nil }逆ポーランド記法にすることにより括弧を除去できます。これをパーサに読み込ませてASTを得ます。
parser.gofunc parse(str string) (Expr, error) { rpn, err := toRpn(str) if err != nil { return nil, err } stack := []Expr{} for _, t := range rpn { switch t { case '\\': lam := true for lam { xs, x, _ := popExpr(stack) ys, y, err := popExpr(xs) if err != nil { return nil, errors.New("token exhausted") } stack = ys if w, ok := x.(Sym); ok { x = Var{Name(string([]rune{w.symbol}))} } if z, ok := y.(Sym); ok { if z.symbol == '.' { vs, v, err := popExpr(stack) if err != nil { return nil, errors.New("argument notfound") } stack = vs if u, ok := v.(Sym); ok { stack = pushExpr(Lam{Name(string([]rune{u.symbol})), x}, stack) lam = false } else { return nil, errors.New("argument must be symbol") } } else { y = Var{Name(string([]rune{z.symbol}))} stack = pushExpr(App{y, x}, stack) } } } default: stack = pushExpr(Sym{t}, stack) } } for { xs, x, err1 := popExpr(stack) if err1 != nil { return nil, errors.New("no result") } if x0, ok := x.(Sym); ok { x = Var{Name(string([]rune{x0.symbol}))} } ys, y, err2 := popExpr(xs) if err2 != nil { return x, nil } else { if y0, ok := y.(Sym); ok { y = Var{Name(string([]rune{y0.symbol}))} } stack = pushExpr(App{y, x}, ys) } } }
λ
でExpr
を消費しつつApp
にまとめていってます。prettify
てけとーにASTを文字列に直してるだけなので特に語ることなし。
main
Serverless Framework(Go) でHello worldしてみる - Qiita https://qiita.com/seike460/items/b54a61ec8d07b2be8c87
こちらを参考に、リクエストに対してレスポンスを返す関数を書くだけでした。簡単!
感想
AWS LambdaでWebAPIをさらっと作りたいときはserverless本当に便利ですね。Terraformの特化版のよう。Goは初めて書きましたが思いの外サクサク書けて良い感じ。C言語のような原初の風景も感じますが、エディタの補完が強力なので気持ちよく書けます。今度は非同期処理とかもやってみたいですね。
- 投稿日:2019-11-24T19:52:51+09:00
Amazon Transcribeを試してみた
twitterで「Amazon Transcribeがリリースされた」との情報をゲットしたため使ってみた。
Amazon Transcribeとは?
AWSの音声認識のサービス。音声ファイルをS3にアップロードすると、数分で自動で文字起こししてくれるサービス。
検証環境など
- iphoneのボイスメモを利用。
- 静かな部屋(周りに人がいないかつテレビ等も消した状態)でボイスメモの録音を実施。
- iphoneと発言者の距離は十数cm。
- つまり録音時の環境は良好。
結論
- 上記環境で利用する分には文字起こしの精度は非常に高い。(認識率100%)
検証方法
音声を録音する。
- iphoneの「ボイスメモ」機能を利用し音声を録音する。
- 音声ファイルをiphoneからPCに転送する。
PCでAWSマネジメントコンソールにログインする。
- 省略。
録音した音声ファイルをS3にアップロードする。
- バケットを作成する。(もちろん既存の物があればそれでOK。)
- 音声ファイルをバケットにアップロードする。
- アップロード完了したらバケットのバスをコピーしておく。
Amazon Transcribeのジョブを新規作成する。
- 「Output Data」は今回すべてデフォルトのままにする。(よくわかんない)
- 「Create」を押下。
今後の課題ややってみたいこと
- 議事録作成に応用できないか実験する。
- 職場のがやがやした環境の中で、どのくらいの精度を発揮できるか実験する。
- もちろん、文字起こしされたテキストを構造化し直すタスクは自身でやらないといけないが…)
- コールセンター業務に活用できないか考える。
- コールセンター業務で音声データの録音をやってるはず。これを「Amazon Transcribe」で文字起こししして、テキストマイニングかけて、チャットボットの精度向上に役立てるとか
- Amazon Connectと連携できないか。
つぶやき
音楽ファイルでやってみたけど、だめだった笑(あわよくば歌詞をすべて文字起こしして欲しかった)
- 投稿日:2019-11-24T18:17:49+09:00
8万語の辞書を持ったインテリBotを常時利用できるようにした話
やったこと
fugaしか答えない残念なBotに8万語の辞書を持たせてインテリBotにした話の続き、常時起動できないLINE Botだったので、Heroku化して常時利用できるようにしました。あと、AWSのAPI GatewayにAPIキーを設定してアクセス制御しました。
構成変更
- 変更前
- Nodejsが個人パソコン上にあるためLINE Botを常時起動するにはよくない構成でした
- 変更後
- 個人パソコン上の環境をHeroku化することで常時起動に適した環境にしました。
- 辞書APIのアクセス制御(APIキー)を設定しました。
参考サイト
- [API Gateway] APIキーと使用量プランを使用してアクセス制限を掛ける
- APIキーの設定方法を参考にさせて頂きました
では設定方法を紹介します。
1.[AWS] API GatewayにAPIキーを設定しよう
- API Gatewayで作成した辞書BotにAPIキーを設定します。
1-1.使用量プラインを作成しよう
AWSコンソールで、APIキーを設定するAPIを開き、
使用量プラン
をクリックします。
名前、レートなどの項目を設定し次へ
ボタンをクリックします。APIステージの追加で、APIキーを設定するAPIを設定し
次へ
ボタンをクリックします。(※辞書Botは、AWS上ではdemo-api
ステージdemo
で登録しています)これで使用量プランの作成が完了しました。
1-2.APIキーを作成しよう
AWSコンソールで、APIキーを設定するAPIを開き、
アクション
->APIキーの作成
をクリックします。名前を設定し保存ボタンをクリックします。
手順1-1で作成した使用量プランを設定します。
これで、APIキーの作成が完了しました。APIキーはここに表示されます。あとで使うのでどこかにコピーしておきます。
2.API GatewayでAPIキーを有効化しよう
作成したAPIキーを辞書Bot(API Gateway)のAPIで有効にします。
メソッドのリクエスト
をクリックします。APIキーの必要性をTrueにします。
これでAPIキーの有効化が完了しました。API Gatewayをデプロイすれば完了です。
3.動作確認しよう
APIキーによる制御ができるか動作確認します。
3-1.検証① APIキー無しで辞書APIにアクセスする
APIキー無しで辞書APIにアクセスすると、
{"message":"Forbidden"}
となり、辞書の情報が返ってきません、これは想定した動作になります。$ curl https://xxx.execute-api.ap-northeast-1.amazonaws.com/demo?test_id=book % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 23 100 23 0 0 306 0 --:--:-- --:--:-- --:--:-- 315{"message":"Forbidden"}3-2.検証② APIキー有りで辞書APIにアクセスする
APIキー有りで辞書APIにアクセスすると、辞書の情報が返ってきました。これは想定した動作になります。
$ curl https://xxx.execute-api.ap-northeast-1.amazonaws.com/demo?test_id=book --header "x-api-key:xxxxxx" % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 107 100 107 0 0 104 0 0:00:01 0:00:01 --:--:-- 104{"name": "(1) \u30db\u30c6\u30eb\u306e\u4e88\u7d04\u4fc2\u306b\u767b\u9332\u3059\u308b", "test_id": "book"}4.Nodejsで作ったLINE Botを更新しよう
Nodejsで作成したLINE Botを更新し以下の対応をします。
- APIキー対応
- Heroku化対応
server.js'use strict'; const express = require('express'); const line = require('@line/bot-sdk'); const axios = require('axios'); const PORT = process.env.PORT || 3000; const config = { channelSecret: 'xxxx', channelAccessToken: 'xxxx' }; const app = express(); app.post('/webhook', line.middleware(config), (req, res) => { console.log(req.body.events); Promise .all(req.body.events.map(handleEvent)) .then((result) => res.json(result)); }); const client = new line.Client(config); function handleEvent(event) { if (event.type !== 'message' || event.message.type !== 'text') { return Promise.resolve(null); } let mes = '' mes = '『' + event.message.text + '』の意味は…' getNodeVer(event.source.userId , event.message.text); return client.replyMessage(event.replyToken, { type: 'text', text: mes }); } const getNodeVer = async (userId, argKey) => { // 辞書API(API Gateway)のエンドポイント let apiUrl = 'https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/demo?test_id='+ argKey; apiUrl = encodeURI(apiUrl); // URLエンコード // ↓ヘッダーにAPIキーの設定なし //const res = await axios.get( apiUrl ); // ↓ヘッダーにAPIキーを設定 const res = await axios.get( apiUrl , { headers: { "x-api-key": "ここに、手順1.2で作成したAPIキーを設定する" } }); console.log(res.data.name); await client.pushMessage(userId, { type: 'text', text: res.data.name, }); } //Heroku非対応↓ //app.listen(PORT); //Heroku対応↓ app.listen(process.env.PORT || 8080); console.log(`Server running at ${PORT}`);5.Nodejsで作ったLINE BotをHeroku化しよう
ローカルのNodejs環境をHerokuにアップロードします。
Procfile
、.gitignore
ファイルを作成し、いくつかコマンドを実行するとHeroku化が完了します。※ Herokuにログインした状態で実行します
Procfile
ファイルを作り、Herokuにアップロードした後に実行するコマンドを指定します。procfileweb: node server.js
.gitignore
ファイルを作り、Herokuにアップロード不要なファイルを指定します。# Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # TypeScript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env # next.js build output .next以下コマンドを実行しHeroku化します。
# 初期化 git init # ファイル追加 git add --a # コミット git commit -m "commit" # アプリ名を設定 heroku create アプリ名 # Herokuにプッシュ git push heroku master
git push …
まで実行完了するとHeroku化成功です(2回目以降は、アプリ名の設定heroku create …
は不要です)6.LINE Botの設定を変更しよう
LINE DevelopersでBotのWebhookをHeroku化したサイトに設定します。
トラブルシュート
git push heroku master
でエラーになりました。heroku create アプリ名
で失敗していたのが原因でした。PS C:\Users\fuga> git push heroku master remote: ! Your account hoge@gmail.com does not have access to fugabot. fatal: unable to access 'https://git.heroku.com/fugabot.git/': The requested URL returned error: 403このエラーが出たとき、configに
[remote "heroku"]
の情報がありませんでした。PS C:\Users\fuga> cat .git\config [core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true symlinks = false ignorecase = true上記のようになったときの
heroku create
コマンドの実行結果がこれ↓PS C:\Users\fuga> heroku create fugabot Creating ⬢ fugabot... ! ! Name fugabot is already taken
heroku create
コマンドがエラー無く実行できたときはこんな感じになります。PS C:\Users\fuga> heroku create fugabot2 Creating ⬢ fugabot2... done https://fugabot2.herokuapp.com/ | https://git.heroku.com/fugabot2.git
heroku create
コマンド実行後のconfigはこんな感じでした。PS C:\Users\fuga> cat .\.git\config [core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true symlinks = false ignorecase = true [remote "heroku"] url = https://git.heroku.com/fugabot2.git fetch = +refs/heads/*:refs/remotes/heroku/*
- 投稿日:2019-11-24T15:52:41+09:00
[AWS SDK for PHP]署名付きPOSTを使い、直接クライアント側からAWS S3にファイルアップロード(PostObjectV4インスタンスを使用)
以下の流れで実装しました。
- PostObjectV4 のインスタンスを使い、署名付きPOSTに必要な情報を発行
- Vue.jsで、アプリケーションサーバを介さず、クライアント側から直接S3にファイルをアップロード
準備
AWS
S3でバケットを作成してください。
※IAMの設定は省略しますS3 CORSの設定
CORSを設定しておかなければなりません。
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>AWS-SDK-PHPのインストール
$ composer require aws/aws-sdk-php実装
署名付きPOSTに必要なデータを発行するPHPの処理と、ファイルアップロードするVue.jsの処理を記載します。
実装した処理は以下の通りです。
- 署名付きPOSTに必要なデータ形式のjsonを返すAPI
- Vue.jsから↑のAPIを叩き、レスポンスを取得
- レスポンスを利用し、ファイルアップロード
API(PHP)
<?php // laravel apiのcontrollerの処理を一部抜粋 public function getPresignedUrl(Request $request) { $s3Client = new \Aws\S3\S3Client([ 'credentials' => [ 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), ], 'region' => env('AWS_DEFAULT_REGION'), 'version' => 'latest' ]); $bucket = env('AWS_BUCKET'); $requestData = $request->all(); $formInputs = [ 'acl' => 'public-read', 'key' => 'hoge/' . $requestData['filename'] . '.' . $requestData['fileext'], ]; $options = [ ['acl' => 'public-read'], ['bucket' => $bucket], ['starts-with', '$key', 'hoge/'], ]; $expires = '+20 minutes'; $postObject = new \Aws\S3\PostObjectV4( $s3Client, $bucket, $formInputs, $options, $expires ); $formAttributes = $postObject->getFormAttributes(); $formInputs = $postObject->getFormInputs(); return response() ->json([ 'url' => $formAttributes['action'], 'fields' => $formInputs ]); }Client側(Vue.js)
<script> export default { name: 'AwsS3Upload', methods: { async upload() { const upload_files = document.getElementById('upload-file'); const upload_file = upload_files.files[0]; // 署名付きPOSTのAPI叩く let preSignedUrl = await this.getPresignedUrl(); // S3へアップロード let uploadS3Path = await this.uploadS3(preSignedUrl, upload_file); }, async getPresignedUrl() { // ↓ここのファイル名は仮置きで適当になってますw let filename = 'fuga'; let filetype = 'image/jpeg' let fileext = 'jpg' try { const url = '/api/get-presigned-url?filename=' + filename + '&filetype=' + filetype + '&fileext=' + fileext; let response = await axios.get(url); console.log('S3署名付きURL取得 成功'); return response; } catch (error) { console.log('S3 署名付きURL取得 失敗'); } }, async uploadS3(presignedUrl, up_file) { let data = presignedUrl.data; try { var formdata = new FormData(); for (let key in data.fields) { formdata.append(key, data.fields[key]); } formdata.append("file", up_file); const headers = { "content-type": "multipart/form-data", } console.log('S3 アップロード 開始'); let response = await axios.post( data.url, formdata, { headers: headers, } ); console.log('S3 アップロード 成功'); return data.url + '/' + data.fields.key; } catch (error) { console.log('S3 アップロード エラー'); } }, } } </script>結論
署名付きPOSTで、S3へ直接クライアントサイドからファイルアップロードができました。
参考
【AWS S3】S3 Presigned URLの仕組みを調べてみた
CORS(Cross-Origin Resource Sharing)について整理してみた
PresignedPost.php
ブラウザからS3へのダイレクトアップロード
- 投稿日:2019-11-24T15:03:28+09:00
【AWS/GCP】データベース、クラウドストレージ、CDN、DNSの簡単な比較
データベース、クラウドストレージ、CDN、DNS
AWSとGCPのサービスのどちらを使おうとなったときに、調べたメモです。
データベース
比較対象
下記3つです。
AWS Aurora
Spanner
Cloud SQL
SpannerとCloud SQLの比較
オンライントランザクション処理などが想定されない限り、
Spanner
は too muchな気がしました。
なので、Cloud SQL
で良さそうと感じています。
Cloud Spannerの概要と設計上の要点など
[ GCP ] メガネと学ぶ GCP (12) Cloud SQL と Spanner の比較 ~ 共通点、差異、料金 ~AWS AuroraとCloudSQLの比較
レプリケーションに関しては、Replica Lag(マスターとスレーブの間で起きる書き込みの遅延のこと)が短くなるので、Auroraではないかと思っています。
ここら辺は運用しながら、知識をつけていこうと思っています。
Amazon RDS for MySQLとAmazon AuroraとGoogle Cloud SQL(2nd Generation)のレプリケーションの違いその他
GKEからAWS Auroraにアクセスした時の注意事項
GCP を利用したセキュリティ要件対応 : VPC Service Controls を試してみた (その 1 : 概念の確認)クラウドストレージ
パフォーマンス
読み取り
- AWS S3:5,500 回以上の GET/HEAD リクエスト
- Google Cloud Storage:5,000 件の読み取りリクエスト
書き取り
- AWS S3:3,500 回以上の PUT/COPY/POST/DELETE リクエスト
- Google Cloud Storage:毎秒 1,000 件の書き込みリクエスト
料金
リクエスト数に対する料金 GET 料金
- Amazon S3:$0.037/10,000リクエスト
- Google Cloud Storage:$0.05/10,000リクエスト
AWS S3料金公式
Google Cloud Storageストレージ料金
- Amazon S3:$0.025/GB
- Google Cloud Storage:$0.023/GB
クラウドストレージ比較解説まとめ
S3の料金体系が分かりにくいと聞かれたので纏めた転送料金
ここもっと考慮すべき.......
現状の結論
現状だと、S3を使う方が良いのではと考えています。
パフォーマンスでは、S3の性能がよく、料金に関しては、ほとんど差分はないのが理由です。CDN
料金
AWS CloudFront
よりもGoogle Cloud CDN
の方が安い。
https://blog.haramishio.xyz/entry/compare-cf-cloudcdn?referrer=https%3A%2F%2Fwww.google.com%2Fパフォーマンス
レイテンシ
下記の比較ツールを確認すると、グローバルでは
Google Cloud CDN
の方がレイテンシは速いです。
Asiaだと、どちらも譲っていません。CDNPerf
Performance Report(グローバル)
Performance Report(Asia)可用性
CloudFrontは平均値としては、Google Cloud CDNよりも高いが、一時的に可用性が大幅に落ちている期間があるのが懸念です。
一方、Google Cloud CDNは安定的にサービスを提供できているのがうかがえる
CDNPerf
Performance Report(Global)
Performance Report(Asia)補足
さらに大事なこととして、*障害をどのように検知するか、そしてどのように対応するかが重要になると思います。
障害の発生確率は、下記よりGoogle Cloud CDNは、可用性の数値から年に4日落ちると想定されてます。
なのでこの4日間を検知する仕組みが必要となることを頭にいおれておく。可用性:98.782%
[可用性の参考数値] 99%(ツーナイン) 年:3.65日 月:7.2時間 週:1.68時間 日:14.4分 99.9%(スリーナイン) 年:8.76時間 月:43.2分 週:10.1分 日:1.44分 99.99%(フォーナイン) 年:52.56分 月:4.32分 週:6.05分 日:8.64秒 99.999%(ファイブナイン) 年:5.26分 月:25.9秒 週:6.05秒 日:0.86秒現状の結論
CloudFrontの可用性は気になりつつも、Cloud Frontのように細かいキャッシュの設定ができないのは難点かもしれません。
一方で、簡単に設定することができることは、Google Cloud CDNの大きなメリットと言えると思います。DNS
料金
料金がかかるところは2つ
①ホストゾーン→0.30ドルの違い
②トラフィック→料金同じ→Consになるほどデメリットではない機能面
DNSSECが差分になりうる?
AWS Route53
AWS Route53の特徴[Pros]
- 検索結果記事がよく出てくる
- 様々な企業が導入しているため、信頼性はこちらの方が高い
- RecLocで使用実績がある
- DNSをAWSRoute53で運用する2つのメリット
[Cons]
DNSSECがサポートされていないGoogle Cloud DNS
[Pros]
・DNSSECがサポートされている[Cons]
参考記事
クラウドDNSサービス比較解説まとめDNSSECが本当に必要?
メリット
- DNS のリクエスト・レスポンスを改ざん、偽造を防止できる
DNSのセキュリティ拡張"DNSSEC"入門デメリット
- DNSSECは、公開鍵認証を使うので、処理が遅くなる可能性がある
- 導入事例があまりない
あまりDNSSEC使ってるよという記事が見つからなかった....なぜだろうDNSSEC設定する場合は、
Google Cloud DNS
は容易に設定が可能そうですね。
めちゃ殴り書きになってしまいましたが、終わりでうす。
- 投稿日:2019-11-24T15:03:28+09:00
【AWS/GCP】データベース、クラウドストレージ、CDN、DNSの簡単な比較メモ
データベース、クラウドストレージ、CDN、DNS
AWSとGCPのサービスのどちらを使おうとなったときの自分用のメモです。
今後もうちょっとボリューミーにしていきたい。データベース
比較対象
下記3つです。
AWS Aurora
Spanner
Cloud SQL
SpannerとCloud SQLの比較
オンライントランザクション処理などが想定されない限り、
Spanner
は too muchな気がしました。
なので、Cloud SQL
で良さそうと感じています。
Cloud Spannerの概要と設計上の要点など
[ GCP ] メガネと学ぶ GCP (12) Cloud SQL と Spanner の比較 ~ 共通点、差異、料金 ~AWS AuroraとCloudSQLの比較
レプリケーションに関しては、Replica Lag(マスターとスレーブの間で起きる書き込みの遅延のこと)が短くなるので、Auroraではないかと思っています。
ここら辺は運用しながら、知識をつけていこうと思っています。
Amazon RDS for MySQLとAmazon AuroraとGoogle Cloud SQL(2nd Generation)のレプリケーションの違いその他
GKEからAWS Auroraにアクセスした時の注意事項
GCP を利用したセキュリティ要件対応 : VPC Service Controls を試してみた (その 1 : 概念の確認)クラウドストレージ
比較対象
AWS S3
Google Cloud Storage
パフォーマンス
読み取り
- AWS S3:5,500 回以上の GET/HEAD リクエスト
- Google Cloud Storage:5,000 件の読み取りリクエスト
書き取り
- AWS S3:3,500 回以上の PUT/COPY/POST/DELETE リクエスト
- Google Cloud Storage:毎秒 1,000 件の書き込みリクエスト
料金
リクエスト数に対する料金 GET 料金
- Amazon S3:$0.037/10,000リクエスト
- Google Cloud Storage:$0.05/10,000リクエスト
AWS S3料金公式
Google Cloud Storageストレージ料金
- Amazon S3:$0.025/GB
- Google Cloud Storage:$0.023/GB
クラウドストレージ比較解説まとめ
S3の料金体系が分かりにくいと聞かれたので纏めた転送料金
ここもっと考慮すべき.......
現状の結論
現状だと、S3を使う方が良いのではと考えています。
パフォーマンスでは、S3の性能がよく、料金に関しては、ほとんど差分はないのが理由です。CDN
比較対象
AWS CloudFront
Google Cloud CDN
料金
AWS CloudFront
よりもGoogle Cloud CDN
の方が安い。
https://blog.haramishio.xyz/entry/compare-cf-cloudcdn?referrer=https%3A%2F%2Fwww.google.com%2Fパフォーマンス
レイテンシ
下記の比較ツールを確認すると、グローバルでは
Google Cloud CDN
の方がレイテンシは速いです。
Asiaだと、どちらも譲っていません。CDNPerf
Performance Report(グローバル)
Performance Report(Asia)可用性
CloudFrontは平均値としては、Google Cloud CDNよりも高いが、一時的に可用性が大幅に落ちている期間があるのが懸念です。
一方、Google Cloud CDNは安定的にサービスを提供できているのがうかがえる
CDNPerf
Performance Report(Global)
Performance Report(Asia)補足
さらに大事なこととして、*障害をどのように検知するか、そしてどのように対応するかが重要になると思います。
障害の発生確率は、下記よりGoogle Cloud CDNは、可用性の数値から年に4日落ちると想定されてます。
なのでこの4日間を検知する仕組みが必要となることを頭にいおれておく。可用性:98.782%
[可用性の参考数値] 99%(ツーナイン) 年:3.65日 月:7.2時間 週:1.68時間 日:14.4分 99.9%(スリーナイン) 年:8.76時間 月:43.2分 週:10.1分 日:1.44分 99.99%(フォーナイン) 年:52.56分 月:4.32分 週:6.05分 日:8.64秒 99.999%(ファイブナイン) 年:5.26分 月:25.9秒 週:6.05秒 日:0.86秒現状の結論
CloudFrontの可用性は気になりつつも、Cloud Frontのように細かいキャッシュの設定ができないのは難点かもしれません。
一方で、簡単に設定することができることは、Google Cloud CDNの大きなメリットと言えると思います。DNS
比較対象
AWS Route53
Google Cloud DNS
料金
料金がかかるところは2つ
①ホストゾーン→0.30ドルの違い
②トラフィック→料金同じくらいGCP DNS
Route53
クラウドDNSサービス比較解説まとめパフォーマンスに関しては、また調べないとなー。
- 投稿日:2019-11-24T08:34:40+09:00
例の経営統合のニュースをAmazon Transcribeに文字起こしさせてみた
はじめに
AWSの自動音声認識サービスAmazon Transcribeが日本語に対応したとのことで、日本語音声を入力して文字起こしを試してみました。
題材
以下のニュース動画を利用しました。
1人のアナウンサーが1分間ほどニュースを読み上げる内容となっていて、複数人による会話などはありません。
文字起こし方法
Transcribeは、
- マネジメントコンソール
- AWS CLI
- AWS SDK for Python (Boto)
にて利用できますが、今回はAWS CLIを使ってみます。
1. 変換をリクエストする
あらかじめ以下のJSONを用意しておいた上で、
aws transcribe start-transcription-job
を実行します。request.json{ "TranscriptionJobName": "yl", "LanguageCode": "ja-JP", "MediaFormat": "mp3", "Media": { "MediaFileUri": "https://foobar.s3-ap-northeast-1.amazonaws.com/yl.mp3" } }$ aws transcribe start-transcription-job --cli-input-json file://request.jsonリクエストが受け付けられると、以下のようなレスポンスが返ってきます。
{ "TranscriptionJob": { "TranscriptionJobName": "yl", "TranscriptionJobStatus": "IN_PROGRESS", "LanguageCode": "ja-JP", "MediaSampleRateHertz": 48000, "MediaFormat": "mp3", "Media": { "MediaFileUri": "https://foobar.s3-ap-northeast-1.amazonaws.com/yl.mp3" }, "CreationTime": 1574510851.993 } }2. 変換ジョブのステータスを確認する
以下コマンドで変換ジョブのステータスを確認します。
$ aws transcribe list-transcription-jobs --job-name-contains "yl"もし変換が完了していればステータスは
COMPLETED
で返ってきます。{ "TranscriptionJobSummaries": [ { "TranscriptionJobName": "yl", "CreationTime": 1574510995.946, "CompletionTime": 1574511071.683, "LanguageCode": "ja-JP", "TranscriptionJobStatus": "COMPLETED", "OutputLocationType": "SERVICE_BUCKET" } ] }なお、今回の1分間の音声の変換ジョブの完了には、約1分15秒の処理時間がかかっていました。
3. 変換結果を取得する
以下コマンドで変換結果ファイルのURIを取得します。
$ aws transcribe get-transcription-job --transcription-job-name "yl"{ "TranscriptionJob": { "TranscriptionJobName": "yl", "TranscriptionJobStatus": "COMPLETED", "LanguageCode": "ja-JP", "MediaSampleRateHertz": 44100, "MediaFormat": "mp3", "Media": { "MediaFileUri": "https://foobar.s3-ap-northeast-1.amazonaws.com/yl.mp3" }, "Transcript": { "TranscriptFileUri": "https://s3.ap-northeast-1.amazonaws.com/aws-transcribe-ap-northeast-1-prod/(略)/asrOutput.json?X-Amz-Security-Token=xxxxxxxx&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20191123T122051Z&X-Amz-SignedHeaders=host&X-Amz-Expires=900&X-Amz-Credential=xxxxxxxx&X-Amz-Signature=xxxxxxxx" }, "CreationTime": 1574510995.946, "CompletionTime": 1574511071.683, "Settings": { "ChannelIdentification": false } } }
TranscriptFileUri
が変換結果ファイルのURIなので、ここからファイルを取得します。取得したファイルは以下のようになっていました(一部を抜粋)。
結果は
transcripts
とitems
に分かれています。{ "jobName": "yl", "accountId": "xxxxxxxxxxxx", "results": { "transcripts": [ { "transcript": "検索 サービス ヤフー ジャパン の (略) 発表 し 、 ます" } ], "items": [ { "start_time": "0.04", "end_time": "0.54", "alternatives": [ { "confidence": "1.0", "content": "検索" } ], "type": "pronunciation" }, { "start_time": "0.54", "end_time": "1.18", "alternatives": [ { "confidence": "1.0", "content": "サービス" } ], "type": "pronunciation" }, { "start_time": "1.25", "end_time": "1.73", "alternatives": [ { "confidence": "0.5202", "content": "ヤフー" } ], "type": "pronunciation" }, { "start_time": "1.73", "end_time": "2.1", "alternatives": [ { "confidence": "0.5202", "content": "ジャパン" } ], "type": "pronunciation" }, { "start_time": "2.1", "end_time": "2.23", "alternatives": [ { "confidence": "1.0", "content": "の" } ], }, // 略 { "start_time": "59.13", "end_time": "59.48", "alternatives": [ { "confidence": "1.0", "content": "発表" } ], "type": "pronunciation" }, { "start_time": "59.48", "end_time": "59.63", "alternatives": [ { "confidence": "1.0", "content": "し" } ], "type": "pronunciation" }, { "start_time": "59.63", "end_time": "60.05", "alternatives": [ { "confidence": "1.0", "content": "ます" } ], "type": "pronunciation" } ] }, "status": "COMPLETED" }文字起こし結果
前述のJSONの
transcript
の値が文字起こし結果全体となります。検索 サービス ヤフー ジャパン の 親会社 セット ホールディングス と 通信 アプリ 大手 の ライン は 今日 経営 統合 する こと で 合意 し た と 発表 し、 まし た 利用 者 数 億 人 規模 の 巨大 相手 企業 が 誕生 し ます 両社 が 発表 し た。 合意 案 で は 最終 的 に セット ホールディングス の 親会社 の ソフトバンク と ライン の 親会社 の 韓国 ネバー が 磯 パーセント ずつ 出資 する、 新 会社 を 作り ます その 傘下 に ホールディングス を 置い て ヤフー や ライン を 子会社 に し、 ます ライン と ヤフー の 親会社 と なる セット ホールディングス の 代表 に は 今 の セット ホールディングス の 川辺 健太郎 社長 が 代表 取締役 社長 県 娘 を ライン の 入れ ザワ 剛 社長 が 代表 取締役 権 更新 よう と し て 共同 で、 着き ます 両社 は 今日 の 午後 五 時 から 改憲 を 開い て 統合 の 狙い など を 発表 し、 ます
固有名詞や同音異義語などを除くと、目立った誤変換として挙げられるのは以下でしょうか。
- 数億人規模 : 1億人規模 (注:ニュースでは1億人と言っています)
- 巨大相手企業 : 巨大IT企業
- 磯パーセント : 50パーセント
- 代表取締役社長県娘を : 代表取締役社長兼Co-CEO
- 代表取締役兼更新よう : 代表取締役兼Co-CEO
Co-CEO(こ・しーいーおー)は難しかったようです。
磯パーセントは、よくわかりません
解説
items
さきほどの
transcript
には、ところどころに半角スペースが見受けられますが、Amazon Transcribeでは
全体的な文字起こし結果を
transcript
に品詞単位の文字起こし結果を
items
に返すようになっていて、
transcript
には、これら品詞単位の区切りに半角スペースが入っています。{ "jobName": "yl", "accountId": "xxxxxxxxxxxx", "results": { "transcripts": [ { "transcript": "検索 サービス ヤフー ジャパン の (略) 発表 し 、 ます" } ], "items": [ { "start_time": "0.04", "end_time": "0.54", "alternatives": [ { "confidence": "1.0", "content": "検索" } ],confidence
また、品詞ごとの変換結果の信頼性が
confidence
に格納されています。試しに
confidence
が
- 1.0(最高値)であれば黒
- 0.9以上1.0未満であれば濃い灰色
- 0.9未満であれば薄い灰色
で表示するよう、取得したJSONファイルを加工してみました。
import json def conv_color(confidence: float) -> str: if confidence == 1: return "black" elif confidence >= 0.9: return "gray" else: return "silver" with open('./transcript.json') as f: d = json.load(f) for item in d['results']['items']: color = conv_color(float(item['alternatives'][0]['confidence'])) print(f'<font color="{color}">', end='') print(item['alternatives'][0]['content'], end='') print('</font>', end='')すると、以下のような結果になりました。薄い部分はAmazon Transcribeも変換結果に自信が無い箇所・・・ということになります。
検索サービスヤフージャパンの親会社セットホールディングスと通信アプリ大手のラインは今日経営統合することで合意したと発表し、ました利用者数億人規模の巨大相手企業が誕生します両社が発表した。合意案では最終的にセットホールディングスの親会社のソフトバンクとラインの親会社の韓国ネバーが磯パーセントずつ出資する、新会社を作りますその傘下にホールディングスを置いてヤフーやラインを子会社にし、ますラインとヤフーの親会社となるセットホールディングスの代表には今のセットホールディングスの川辺健太郎社長が代表取締役社長県娘をラインの入れザワ剛社長が代表取締役権更新ようとして共同で、着きます両社は今日の午後五時から改憲を開いて統合の狙いなどを発表し、ます
費用
1秒の音声変換に、0.0004USDがかかります。ただし、15秒未満の場合は15秒分の料金がかかるとのこと。
今回の音声は約1分なので、おおよそ2〜3円ということになります。
なお、使い始めから1年間は、毎月60分の無料利用枠があります。
最後に
アナウンサーによるはっきりとした音声でも、いくつかの誤変換は発生していました。Amazon Transcribeでは変換結果の信頼度合い(confidence)を品詞ごとに持っているので、これをどう活用するかがポイントなのかもしれません。
また、今回は試せていませんが、音声内の話者数を2人から10人まで指定することが可能で、それら話者ごとの変換ができるようです。テレビ番組や会議の音声を文字起こしさせてみたら面白そうです。
参考
- 投稿日:2019-11-24T02:26:36+09:00
Saving Plansによるコスト試算
Saving Plansによるコスト試算
はじめに
AWSで運用しているシステムでコスト効率を上げるため、Saving Plansのコスト試算に関して調べました。
基本料金とSaving Plansのコスト試算についてまとめています。EC2の料金
Amazon EC2 料金表を確認しましょう。
基本的に常時稼働のEC2インスタンスではリザーブドインスタンス(RI)を購入して運用している方が多いと思います。
Saving Plansでは、常時稼働ではないが定期的・不定期に停止・起動を行っているようなサーバに適用することでコスト削減が望めそうです。Fargateの料金
AWS Fargateの料金を確認しましょう。
2019/11/23現在、東京リージョン(ap-northeast-1)では以下の料金となっていました。リソースタイプ 料金(per hour)
1 vCPU $0.05056
1 GB MEM $0.00553
Saving Plansでのコスト試算
AWSマネジメントコンソールのうち、EC2サービスにSaving Plansのメニューがあるので選択します。
※こちらに記載されている説明文(英語)はPurchase Saving Plansのリンク先に日本語訳があるので無視して大丈夫です
※請求ダッシュボード→Cost Explorer→コストエクスプローラ→Saving Plansからもいけます
- 投稿日:2019-11-24T02:26:34+09:00
AWS で MFA 必須の IAM アカウントを作成し、ユーザに受け渡す手順について
多段階認証 (MFA) が必須の IAM アカウントを作成して、ユーザに受け渡す手順について。
MFA 必須でパスワードリセット可のポリシーについて
公式のドキュメントは以下の2つです。
- https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/tutorial_users-self-manage-mfa-and-creds.html
- https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_aws_my-sec-creds-self-manage.html
基本的にはドキュメントの通りにやればいいのですが、このままだと、初回のパスワードリセットが許可されません。
この点についての説明が、英語版と日本語版で異なっていました。
注記
このポリシー例では、サインイン時のパスワードのリセットをユーザーに許可していません。新しいユーザーおよびパスワードの期限が切れているユーザーは、これを行う場合があります。これを許可するには、iam:ChangePassword
をステートメントDenyAllExceptListedIfNoMFA
に追加します。英語版だと、
Note
This example policy does not allow users to reset a password while signing in. New users and users with an expired password might try to do so. You can allow this by addingiam:ChangePassword
andiam:GetAccountPasswordPolicy
to the statementDenyAllExceptListedIfNoMFA
.英語版に従っておくのが無難そうなので、以下の2つを
DenyAllExceptListedIfNoMFA
に追加します。
iam:ChangePassword
iam:GetAccountPasswordPolicy
追加した JSON は以下です。(実際に設定するときは、公式のドキュメントからコピペしてください)
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowViewAccountInfo", "Effect": "Allow", "Action": [ "iam:GetAccountPasswordPolicy", "iam:GetAccountSummary", "iam:ListVirtualMFADevices" ], "Resource": "*" }, { "Sid": "AllowManageOwnPasswords", "Effect": "Allow", "Action": [ "iam:ChangePassword", "iam:GetUser" ], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "AllowManageOwnAccessKeys", "Effect": "Allow", "Action": [ "iam:CreateAccessKey", "iam:DeleteAccessKey", "iam:ListAccessKeys", "iam:UpdateAccessKey" ], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "AllowManageOwnSigningCertificates", "Effect": "Allow", "Action": [ "iam:DeleteSigningCertificate", "iam:ListSigningCertificates", "iam:UpdateSigningCertificate", "iam:UploadSigningCertificate" ], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "AllowManageOwnSSHPublicKeys", "Effect": "Allow", "Action": [ "iam:DeleteSSHPublicKey", "iam:GetSSHPublicKey", "iam:ListSSHPublicKeys", "iam:UpdateSSHPublicKey", "iam:UploadSSHPublicKey" ], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "AllowManageOwnGitCredentials", "Effect": "Allow", "Action": [ "iam:CreateServiceSpecificCredential", "iam:DeleteServiceSpecificCredential", "iam:ListServiceSpecificCredentials", "iam:ResetServiceSpecificCredential", "iam:UpdateServiceSpecificCredential" ], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "AllowManageOwnVirtualMFADevice", "Effect": "Allow", "Action": [ "iam:CreateVirtualMFADevice", "iam:DeleteVirtualMFADevice" ], "Resource": "arn:aws:iam::*:mfa/${aws:username}" }, { "Sid": "AllowManageOwnUserMFA", "Effect": "Allow", "Action": [ "iam:DeactivateMFADevice", "iam:EnableMFADevice", "iam:ListMFADevices", "iam:ResyncMFADevice" ], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "DenyAllExceptListedIfNoMFA", "Effect": "Deny", "NotAction": [ "iam:CreateVirtualMFADevice", "iam:EnableMFADevice", "iam:GetUser", "iam:ListMFADevices", "iam:ListVirtualMFADevices", "iam:ResyncMFADevice", "sts:GetSessionToken", "iam:ChangePassword", "iam:GetAccountPasswordPolicy" ], "Resource": "*", "Condition": { "BoolIfExists": { "aws:MultiFactorAuthPresent": "false" } } } ] }初期ユーザ用・MFA 設定済みユーザ用ポリシー
ポリシーを2つ作ります。
- パスワードリセットを許可したポリシー (初期ユーザ用)
- パスワードリセットにMFA が必要なポリシー (既存ユーザ用)
前者のポリシー名と説明を、以下のように設定します。
説明文に URL が書けないので、後から参照できるように公式ドキュメントのタイトルを書くことにしました。MFARequiredOnlyForTheFirstLogin Created YYYY-MM-DD - Copied and edited the official sample JSON to enable password reset - AWS Allows MFA-Authenticated IAM Users to Manage Their Own Credentials on the My Security Credentials Pageポリシーの JSON は、上で説明した通り、公式ドキュメントからコピペして、Action を2つ追加したものを設定します。
そして、このポリシーだけを設定したグループ
NotYetLoginUsers
を作成します。後者のポリシー名と説明は、以下のように設定します。
MFARequiredForCurrentUsers Created YYYY-MM-DD - Copied from the official document - AWS Allows MFA-Authenticated IAM Users to Manage Their Own Credentials on the My Security Credentials Pageポリシーの JSON は、公式ドキュメントのものをそのまま使います。
IAM アカウントの受け渡し
以下の手順で受け渡します。
- アカウントを作成し、
NotYetLoginUsers
グループにだけ所属させる- メール等で仮のパスワードを伝えて、パスワードリセットと MFA 登録を依頼する
- 本人の MFA 登録が確認できたら、
NotYetLoginUsers
グループから外し、MFARequiredForCurrentUsers
と必要な権限を設定する2 の時点では何も権限がないので、パスワードはメールで送ってもよいことにしています。
パスワードポリシーの影響について
パスワードポリシーに、ユーザにパスワードの変更を許可する
Allow users to change their own password
というオプションがあります。このオプションは、オンにしておく方が良さそうでした。
オフの場合、
- ポリシーで明示的に指定しない限り、パスワードを変更できなくなる
- ユーザ作成時にパスワードリセットを求めると、自動的に
IAMUserChangePassword
が追加されるという挙動になるようです。
逆に、ポリシーを設定さえすれば、そちらが優先されるようです。全ユーザに、上記 MFA 必須のポリシーを設定するのであれば、どちらでも基本的には同じ動作になります。
ただし、オフにすると、新規ユーザ作成時に勝手に
IAMUserChangePassword
ポリシーが設定されてしまうので、オンにしておくのが無難だと思います。
- 投稿日:2019-11-24T02:18:04+09:00
Saving Plansによるコスト試算
Saving Plansによるコスト試算
はじめに
AWSで運用しているシステムでコスト効率を上げるため、Saving Plansのコスト試算に関して調べました。
基本料金とSaving Plansのコスト試算についてまとめています。EC2の料金
Amazon EC2 料金表を確認しましょう。
基本的に常時稼働のEC2インスタンスではリザーブドインスタンス(RI)を購入して運用している方が多いと思います。
Saving Plansでは、常時稼働ではないが定期的・不定期に停止・起動を行っているようなサーバに適用することでコスト削減が望めそうです。Fargateの料金
AWS Fargateの料金を確認しましょう。
2019/11/23現在、東京リージョン(ap-northeast-1)では以下の料金となっていました。
リソースタイプ 料金(per hour) 1 vCPU $0.05056 1 GB MEM $0.00553 Saving Plansでのコスト試算
AWSマネジメントコンソールのうち、EC2サービスにSaving Plansのメニューがあるので選択します。
※こちらに記載されている説明文(英語)はPurchase Saving Plansのリンク先に日本語訳があるので無視して大丈夫です
※請求ダッシュボード→Cost Explorer→コストエクスプローラ→Saving PlansからもいけますSaving Plansについて
上記の画面でPurchase Saving Plansのリンクをクリックすると以下の画面が表示されます。
以下の説明文にある通り、2種類のSaving Plansを提供しているようです。
- Compute Saving Plans
- EC2 Saving Plans
主に
Amazon ECS on AWS EC2
かAmazon ECS on AWS Fargate
で使い分ける感じでしょうかSaving Plansでのコスト試算について
推奨する Compute Saving Plans、推奨する EC2 Instance Saving Plansにある通り、コストエクスプローラにより自動で算出された推奨プランを提示してくれる様です。
頭捻って色々試算しないといけないなと思ってましたが、トグルスイッチをポチポチ切り替えるだけでSaving Plansの種類や期間に応じた推奨プランを提示してくれるのでコスト試算するのはそんなに難しくないですね。Saving Plansの注意点について
- Compute Saving Plans
- どのECS Clusterに適用されるのか意識して購入しましょう
- EC2 Instance Saving Plans
- どのEC2インスタンスに対して何が適用されるか意識して購入しましょう
- Saving Plans上はインスタンスファミリまでしか表示されません
- 脳死で推奨プラン通りに購入してしまって、
実は不要な前払い料金を払ってしまった・・・
なんてことも発生しうると思います。- (Saving Plansで使用傾向は加味して推奨プランを提示してくれますが)定常的に起動/停止していない変則的に利用するサーバなどが含まれている可能性があります
- 1年以内に廃止する予定のサーバなど含まれていないか考慮しましょう
- 損益分岐点がいつなのかも考慮できると良さそうです
参考リンク