AWS独学メモ

頑張って学んでいきます。

サービス俯瞰

コンピューティング関連

サービス名 概要
EC2 仮想サーバー
EC2 Container Service Doker(アプリ実行環境構築ツール)運用サービス
EC2 Container Regstry Dokerイメージ保存・共有サービス。
Elastic Beanstalk .NET/PHP/Python/Ruby/Node.jsアプリを自動でAWSにデプロイ。
Lambda クライアントからのリクエスト発生時に任意プログラミング起動。イベント駆動型サービス。
Auto Scaling CPU使用率等、事前決定条件に応じ、EC2インスタンス増減
Elastic Load Balancing トラフィックに応じ、複数EC2インスタンスに負荷分散

ストレージ・コンテンツ配信

サービス名 概要
S3 ファイルサーバ。画像格納したり。
CloudFront コンテンツ配信ネットワーク。利用者から近い場所から効率よく配信
EBS EC2データを保持するストレージ。EC2のHDD,SSDのような役割。
Elastic File System EC2共有ファイルストレージ
Glacier 低価格ストレージ。仕様頻度低いけど長期保存のバックアップ用。
Import / Export Snowball ペタバイト級の大容量転送サービス。
Storage Gateway オンプレミスとAWSを接続

DB関連

サービス名 概要
RDS DB(MySQL/Oracle/SQL Server/PostgreSQL/Aurora)が利用できる
Database Migration Service 最小限停止時間でDBを移行。オンプレミスのDBサーバからの移行等に用いる
DynamoDB NoSQLデータベスサービス構築/運用。
ElastiCache クラウドでのメモり内キャッシュの管理サービス
Redshift ビッグデータを分析

ネットワーク

サービス名 概要
VPC プライベートネットワーク構築サービス。
Direct Connect オンプレミスのネットワークとAWSのVPCネットワークを直接接続。
Route 53 DNS(ドメイン名とIPアドレスを対応)

開発者用ツール

サービス名 概要
CodeCommit プライベートGit
CodeDeploy 開発アプリを実行環境に自動配置
CodePipeline 継続的デリバリ使用したアプリのリリース

開発ツール

サービス名 概要
CloudWatch AWSリソース監視サービス
CloudFormation テンプレート利用したリソースの作成と管理
CloudTrail ユーザアクティビティとAPI使用状況確認
Config リソースのイベントリ変更の追跡
OpsWorks Chef利用し操作の自動化
Service Catalog 標準化製品の作成と使用
Trusted Advisor パフォーマンスとせきゅりてぃの最適化

セキュリティ

サービス名 概要
IAM AWS認証
Directory Service Active Directoryのホスティングと管理
Inspector アプリのセキュリティ分析
CloudHSM 暗号鍵管理の専用ハードウェア
Key Management Service 暗号鍵作成と管理
WAF 攻撃から保護するファイアウォール

分析

サービス名 概要
EMR Hadoopフレームワーク
Data Pipeline オーケストレーションサービス
Kinesis リアルタイムストリーミングデータとの連携
Machine Learning 機械学習
QuickSight 高速ビジネスインテリジェンスサービス

モバイルサービス

サービス名 概要
Mobile Hub モバイルアプリの構築/テスト/監視
API Gateway RESTful APIの構築/管理
Cofnito ユーザID及びアプリデータの同期
Device Farm iOS/Android/FireOSアプリのテスト
Mobile Analytics アプリ分析の収集/表示/エクスポート
Mobile SDK モバイルソフトウェアの開発キット

アプリケーションサービス

サービス名 概要
AppStream ストリーミングサービス
CloudSearch マネージド型検索サービス
Elastic Transcorder メディアと動画変換
SES Eメール送受信
SNS プッシュ通知サービス
SQS メッセージキューサービス
SWF アプリ同士を連携ワークフローサービス

大企業向け

サービス名 概要
WorkSpaces クラウド上仮想デスクトップパソコンサービス
WorkMail セキュリティ保護、企業向けEメール及びカレンダー
WorkDocs ファイル共有サービス

S3について

用語

用語 意味
バケット データの入れ物
オブジェクト 格納ファイル

ステップ

  1. バケット作成
  2. オブジェクト格納

EC2について

用語

用語 意味
EC2 仮想サーバ。オンプレミスのWindowsサーバやUNIXサーバに相当。
インスタンス 1台の仮想サーバ
EBS(Elastic Block Store) サーバのHDDに相当する仮想ディスク
AMI(Amazon Machine Image) サーバにインストールするOSやミドルウェアやアプリのイメージ。新インスタンスを複数生成時、AMIを利用。
yum パッケージ管理システム
scp(secure copy) SSH機能を用いて、安全にファイル転送する

EC2にSSH接続した

参考ページ1
参考ページ2

ミドルウェアをインストール

yum更新
$ sudo yum -y update
httpdインストール
$ sudo yum  install -y httpd
httpd起動
$ sudo service httpd start
httpd自動起動を確認
$ sudo chkconfig --list httpd
httpd自動起動を設定
$ sudo chkconfig  httpd on
$ sudo chkconfig  httpd off

scp(コンテンツをアップロードする)

【現在ここで躓き中!】
→ 突破!!

参考ページ1

HTTPコンテンツをコピー

HTTPコンテンツのコピー

$ sudo cp /home/ec2-user/index.html /var/www/html/

【現在ここで躓き中!】index.htmlへアクセスできない

続きを読む

terraformでS3バケットのACLに権限を付与する

CloudFrontのアクセスログをS3に保存させる事はごくごく普通にあると思いますが、terraformで環境を構築しているとS3作成時に特殊なACLは設定できず、CloudFront作成時にログ出力指定をしていると権限不足で落ちてしまいます。

参考: アクセスログ – Amazon CloudFront

terraformだけで解決できれば一番良いのですが、2017年6月現在ではissueが出ているものの反映されるのはまだ先になりそうな感じです。

GUIからぽちぽちしてると勝手にACLを作ってくれるので、手で作った後にterraformに記載するとかいう意味のない作業をしていたのですが、そんな作業やりたくなかったので無理やり気味ではありますがterraform applyを実行するだけでS3にACLを付与し、CloudFrontの構築まで一気通貫で行えるようにちょっとした工夫を加えてみました。

準備するもの

linux/mac前提です。windowsの場合はbash on windowsであれば動作可能です。

必須

  • terraform
  • AWS CLI

推奨

  • direnv

準備するスクリプト

bin/AssignAwsdatafeedsAcl
#!/bin/sh

# 自身のディレクトリパスを取得
CURRENT_DIR=$(cd $(dirname $0);pwd)/

# 引数のチェックを行う
if [ $# -ne 1 ]; then
    exit 1
fi

# バケット名を引数から取得
BUCKET_NAME=$1

TEMP_FILE=$(mktemp)

# S3待ち(waitが無い場合にエラーが発生)
sleep 2

# 現在のバケットACL情報を取得する
aws s3api get-bucket-acl --bucket ${BUCKET_NAME} > ${TEMP_FILE}
if [ $? -ne 0 ]; then
    # テンポラリファイルを削除する
    rm -f ${TEMP_FILE}
    exit 1
fi

# ACLにawsdatafeeds権限が含まれていない場合は追加する
grep awsdatafeeds ${TEMP_FILE}
if [ $? -eq 1 ]; then
    # 追記する文字列を取得
    INPUT_LINES=$(perl -p -e 's/n/\n/' ${CURRENT_DIR}acl.txt)
    if [ $? -ne 0 ]; then
        # テンポラリファイルを削除する
        rm -f ${TEMP_FILE}
        exit 1
    fi

    # 権限情報を追記
    sed -i -e "s/("Grants": *[)/1n${INPUT_LINES}/" ${TEMP_FILE}
    if [ $? -ne 0 ]; then
        # テンポラリファイルを削除する
        rm -f ${TEMP_FILE}
        exit 1
    fi

    # 権限情報をS3バケットに反映
    aws s3api put-bucket-acl --bucket ${BUCKET_NAME} --access-control-policy "$(cat ${TEMP_FILE})"
    if [ $? -ne 0 ]; then
        # テンポラリファイルを削除する
        rm -f ${TEMP_FILE}
        exit 1
    fi
fi

# テンポラリファイルを削除する
rm -f ${TEMP_FILE}

exit 0
bin/acl.txt
        {
            "Permission": "FULL_CONTROL",
            "Grantee": {
                "DisplayName": "awsdatafeeds",
                "ID": "c4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0",
                "Type": "CanonicalUser"
            }
        },

上記2ファイルをパスが通ったところに配置しておきます。
シェルスクリプトの方にはちゃんと実行権限を付与しましょう。

ちなみにdirenvを使って、terraform実行パスなどでPATHを追加するのが推奨です。

.envrc
export AWS_DEFAULT_PROFILE=[AWSプロファイル名]
export AWS_DEFAULT_REGION=[デフォルトとするリージョン]

export AWS_PROFILE=$AWS_DEFAULT_PROFILE
export AWS_REGION=$AWS_DEFAULT_REGION

PATH_add `pwd`/bin

terraformの記述

s3.tf
resource "aws_s3_bucket" "sample" {
    bucket = "sample-cfn-logs"
    acl    = "private"
    tags {
         Name = "sample-cfn-logs"
    }

    provisioner "local-exec" {
         command = "AssignAwsdatafeedsAcl ${aws_s3_bucket.test.bucket}"
    }
}

概要

terraformのprovisionerにlocal-execという、実行マシンでのコマンド実行機能があります。

これはリソースが作成されたのちに実行されるので、S3リソースが作成された後にシェルスクリプトを実行し、AWS CLIを利用してS3バケットにACLを付与しています。

上記スクリプトでは下記の様な処理を行っています。

  1. aws cli: S3バケットの設定済みACLを取得
  2. shell: 取得したACLにawsdatafeedsの権限が付与されているかチェックする
  3. shell: 権限がない場合、権限の内容を取得したACLに追記する
  4. aws cli: 改変したACL情報をS3バケットに反映する

S3バケットが構築されてからAPIで叩けるまでに微妙なタイムラグがあるらしく、sleepが入っていないとAPIを叩いた時にバケットが存在しないと怒られてしまいます。

ちゃんとするならば、APIのレスポンスを見て待つ処理を入れるのが良いのですが、terraformがMulti ACLに対応するまでの暫定的な対応なのでsleepで濁しています。

配置したスクリプトにパスが通っていないとlocal-execの指定時にわざわざパスを書いてあげる必要があるので、direnv使ってパス通しちゃいましょう。

相対パスがどこからになるのか知らない。

ちなみにacl.txtの内容を変えると好きな権限を入れれます。でもあまり使わないですし変更検知もされないので推奨はしません。

どうしてもという場合はaws_s3_bucketリソースの代わりにnull_resourceリソースを使って毎回スクリプトをキックするようにした上で、前回実行のACLと反映するACLに差分がある時に実行するなど工夫をしてみてください。

結論

はよterraform自体で対応して。

続きを読む

AWS LambdaにMecabを乗せてPythonで動かす

実装するにあたりこちらのサイトを参考にさせて頂きました!
ありがとうございます!

pythonのバージョンは2.7
localの環境はWindows bashです。

はじめに

Mecabはコードにネイティブバイナリを使用しているため、Lambdaの実行環境と同じ環境でデプロイパッケージを作成する必要があります。
(ソースはここです。Lambdaの実行環境ドキュメント
なので、EC2でAmazon Linuxインスタンスを立て、その中でデプロイパッケージを作成していきます。

必要なファイル及び作成環境の準備

まず必要なファイルをローカル上にDLします。
① mecab-0.996.tar.gz
② mecab-ipadic-2.7.0-20070801.tar.gz
上記2つはここからDLできます
③ mecab-python-0.996.tar.gz
ここからDLできます。

次にlinuxインスタンスにsshでログインします。
やり方分からないよって方は、AWSのドキュメントの「Linuxインスタンスへの接続」の項を参照していただけると分かると思います!

Linuxインスタンスは、立てたばかりの状態ではコンパイラなどが入っていないのでインストールします。

Linuxインスタンス上
[ec2-user ~]$ sudo yum groupinstall "Development Tools"

そしてLinuxインスタンスのホームディレクトリにmecab-functionディレクトリを作成します。

Linuxインスタンス上
$mkdir mecab-function

先ほどDLした①〜③のファイルを全てLinuxインスタンスのホームディレクトリに送信します。
(こちらも詳細はドキュメントの「scpを利用してファイルを転送するには」の項を参照していただけると分かると思います。)

ローカル上
scp -i /path/秘密キーファイルの名前 /path/mecab-0.996.tar.gz ec2-user@インスタンスのパブリックDNS名:~

scp -i /path/秘密キーファイルの名前 /path/mecab-ipadic-2.7.0-20070801.tar.gz ec2-user@インスタンスのパブリックDNS名:~

scp -i /path/秘密キーファイルの名前 /path/mecab-python-0.996.tar.gz ec2-user@インスタンスのパブリックDNS名:~

ここまで出来たら、Linuxインスタンスのホームディレクトリには以下のファイルやディレクトリが存在してると思います。

mecab-function/
mecab-0.996.tar.gz
mecab-ipadic-2.7.0-20070801.tar.gz
mecab-python-0.996.tar.gz

次は、今落としたmecabなどをディレクトリにインストールしていきます。

ディレクトリへのインストール

ここからは、Linuxインスタンス上での操作となります。
まず、mecabとmecab-ipadicを解凍してインストールしていきます。

① mecabのインストール

$tar zvxf mecab-0.996.tar.gz
$cd mecab-0.996
$./configure --prefix=$DIR_HOME/local --with-charset=utf8
$make
$make install

“$DIR_HOME”は、mecab-functionディレクトリのパスです。
mecab-functionディレクトリ内で以下のコマンドを実行すると、パスを取得できます。

$pwd

“–prefix=ディレクトリのパス”で、mecabをインストールするディレクトリを指定しています。

“–with-charset=utf8″は、mecabをutf8で使用するという宣言をしています。
この宣言をしないと、mecabが上手くparseできなかったり、エラーが出たりするので注意してください。
ちなみに、”–enable-utf8-only”とは違うのでこちらも注意してください。

“make install”が完了したら、mecab-0.996ディレクトリから、ホームディレクトリに戻ります。

② mecab-ipadicのインストール

$tar zvxf mecab-ipadic-2.7.0-20070801.tar.gz
$cd mecab-ipadic-2.7.0-20070801

# mecabの場所をPATHに追加
$export PATH=$DIR_HOME/local/bin:$PATH

$./configure --prefix=$DIR_HOME/local --with-charset=utf8
$make
$make install

“$DIR_HOME”など、①と同じです。
“make install”が終了したら、ホームディレクトリに戻ります。
ここで、”mecab”コマンドを実行した時に動作すればmecabとmecab-ipadicのインストールは正しくできています。

③mecab-pythonのインストール

$pip install mecab-python-0.996.tar.gz -t $DIR_HOME/lib

pipは、-tでライブラリのインストール先を指定できます。

ここまで出来ると、mecab-function内は以下の構造になっていると思います。

mecab-function
|- lib/
|- local/
|- exclude.lst
|- function.py

function.pyとexclude.lstって何?ってなりますよね?
次でその2つのファイルについて説明します。

function.pyの説明

Lambdaのハンドラー関数を含むpythonのコードを説明します。
今回は、入力された日本語を単に分かち書きして出力するハンドラー関数を作成しました。

function.py
#coding: utf-8

import json
import os
import ctypes

#ライブライのパスを取得
libdir = os.path.join(os.getcwd(), "local", "lib")
libmecab = ctypes.cdll.LoadLibrary(os.path.join(libdir, "libmecab.so.2"))

import MeCab

#mecabの辞書(ipadic)へのパスを取得
dicdir = os.path.join(os.getcwd(), "local", "lib", "mecab", "dic", "ipadic")
#mecabのrcファイルへのパスを取得
rcfile = os.path.join(os.getcwd(), "local", "etc", "mecabrc")
tagger = MeCab.Tagger("-d{} -r{}".format(dicdir, rcfile))


def handler(event, context):
    """
    event = {
        "sentence": 分かち書きしたい文章
    }
    """
    sentence = event.get("sentence")
    encode_sentence = sentence.encode("utf_8")
    node = tagger.parseToNode(encode_sentence)
    result = []
    while node:
        surface = node.surface
        if surface != "":
            test_list = [surface]
            print surface
            print test_list
            decode_surface = surface.decode("utf_8")
            result.append(decode_surface)
        node = node.next
    return result

“ctypes.cdll.LoadLibrary()”で、動的リンクライブラリをロードしています。
また、MeCab.Taggerクラスのオブジェクトを作成する際に、辞書とmecabrcファイルへのパスを指定してあげる必要があります。

exclude.lstの説明

zipファイル作成時に除外するファイルの一覧です。

exclude.txt
*.dist-info/*
*.egg-info
*.pyc
exclude.lst
local/bin/*
local/include/*
local/libexec/*
local/share/*

デプロイパッケージの作成

いよいよデプロイパッケージの作成です。
mecab-function/libにある

_MeCab.so
MeCab.py
MeCab.pyc

の3つのファイルをmecab-fucntionに移します。
ここまで行えば、以下のような感じになってると思います。

mecab-function
|- lib/
|- local/
|- _MeCab.so
|- exclude.lst
|- function.py
|- MeCab.py
|- MeCab.pyc

そして、mecab-functionディレクトリで以下のコマンドを実行すると、mecab-function.zipが作成されます。

$zip -r9 mecab-function.zip * -x@exclude.lst

mecab-function.zipが以下のような構造になっていたら完成です。

mecab-function
|- lib/
|- local/
|- _MeCab.so
|- function.py
|- MeCab.py
|- MeCab.pyc

あとは、mecab-function.zipをLambdaにあげれば完了です!
Linuxインスタンス上にあるmecab-function.zipをscpコマンドを使ってローカルに転送してAWS Lambdaのコンソール画面から直接あげてもいいですし、S3に飛ばしてからあげてもいいと思います。
自分は、ローカルに一旦転送しました。

ローカルに転送するには、ローカルで以下のコマンドを実行します。

ローカル上
scp -i /path/秘密キーファイルの名前 ec2-user@インスタンスのパブリックDNS名:~/mecab-function/mecab-function.zip /転送したい場所のpath(ローカル上)/mecab-function.zip

このコマンドの詳しい内容は、おなじみAWSのドキュメントの「scpを利用してファイルを転送するには」を参照していただければと思います。

まとめ

最後に重要なポイントをまとめたいと思います。

① デプロイパッケージは、Linuxインスタンス上で作成する!
② mecabをimportする時に、動的リンクライブラリをロードする。
③ MeCab.Taggerでオブジェクト作成時に、辞書とmecabrcファイルへのパスを渡してあげる。
④デプロイパッケージの構造は、この記事で示したようにする。

ここまで読んで頂きありがとうございました。

続きを読む

AWS 認定ソリューションアーキテクト – アソシエイト 合格までに勉強したこと

概要

AWS 認定試験には「これを勉強すればいいよ!」という教科書があるわけではないので、何を勉強したらいいか分からず困っている人も多いと思います。
なので、私の勉強記録を共有します。

勉強前のスペック

AWSの初級者です。
EC2インスタンス起動やEBSのスナップショット取得の経験があるくらいでした。

勉強方法概要

AWS活用本を一冊読んで、
あとはAWS クラウドサービス活用資料集にある BlackBelt のスライド(PDF)を淡々と読みました。

その後、模擬試験を受けて本試験を受験しました。

勉強方法詳細

少し前に買っていた以下の本を読みました。分かりやすいです。

Amazon Web Services 定番業務システム12パターン設計ガイド

BlackBelt

自分が読んだ資料に○を付けました。
また、模擬試験と本試験を受けた経験から、各資料の重要度を評価しました。
※当たり前ですが、読んでいない資料の重要度は評価していません。また、重要度の正確性も保証しません。

コンピューティング

資料 読んだ  重要度 
[Amazon EC2] 
[Amazon EC2] Windows
[Amazon EC2] HPC
[Amazon EC2] リザーブドインスタンス
[Amazon EC2] スポットインスタンス
[Amazon EC2] Instance Store & Elastic Block Store
[Amazon EC2] VMImport/Export
[Elastic Load Balancing]
[Elastic Load Balancing] ロードバランサと Socket 接続を使用したイベント通知サーバの負荷分散
[Elastic Load Balancing] ELBを評価するためのベストプラクティス
[Auto Scaling]
[Amazon EC2 Container Service]
[AWS Elastic Beanstalk]
[AWS Lambda]
[AWS Lambda] update
[Amazon Lightsail]
[AWS Batch]

ストレージ & コンテンツ配信

資料 読んだ  重要度 
[Amazon EBS]
[Amazon S3] 
[Amazon CloudFront]
[Amazon CloudFront] Flash Media Server on AWS
[Amazon CloudFront] CloudFront 上限緩和申請 計算方法&申請手順
[Amazon CloudFront] まだ間に合う! Amazon CloudFront で ATS 対応
[Amazon Glacier]
[Amazon Glacier] 機能編
[AWS Storage Gateway]
[Amazon Elastic File System]

データベース

資料 読んだ  重要度 
[Amazon RDS]
[Amazon RDS] Aurora
[Amazon DynamoDB]
[Amazon ElastiCache]
[Amazon ElastiCache] Redis QA資料
[Amazon Redshift] 
[Amazon Database Migration Service]

ネットワーキング

資料 読んだ  重要度 
[Amazon VPC]
[Amazon VPC] VPN接続設定 参考資料
[AWS Direct Connect] 
[Amazon Route53]

開発者用ツール

資料 読んだ  重要度 
[AWS CodeCommit]
[AWS CodeBuild]
[AWS CodeDeploy]
[AWS CodePipeline]
[AWS SDK]
[AWS SDK] Java & .NET
[AWS SDK] PHP & Ruby & Boto(Python) & Javascript in Node.js
[AWS SDK] AWS Client side SDK Android & iOS & Javascript
[AWS CLI]
[AWS AWS Tools for Windows Powershell]

管理ツール

資料 読んだ  重要度 
[Amazon CloudWatch]
[AWS CloudFormation]
[AWS CloudTrail]
[AWS Config]
[AWS OpsWorks] AWS OpsWorksのご紹介
[AWS OpsWorks]
[AWS OpsWorks] ハンズオン
[AWS Service Catalog]
[Trusted Advisor] AWS サポート & Trusted Advisor
[Amazon EC2 Systems Manager]

セキュリティ & アイデンティ

資料 読んだ  重要度 
[Identity and Access Management (IAM)] 
[AWS CloudHSM] CloudHSM & Key Management Service
[AWS Key Management Service]
[AWS Directory Service]
[Amazon Inspector]
[AWS WAF]
[AWS Certificate Manager]

分析

資料 読んだ  重要度 
[Amazon EMR(Elastic MapReduce)]
[AWS Data Pipeline]
[Amazon Elasticsearch Service] Amazon CloudSearch & Amazon Elasticsearch Service
[Amazon Kinesis]
[Amazon QuickSight]
[Amazon Athena]

AI

資料 読んだ  重要度 
[Amazon AI]]

IoT

資料 読んだ  重要度 
[AWS IoT]

ゲーム開発

資料 読んだ  重要度 
[Amazon Lumberyard]

モバイルサービス

資料 読んだ  重要度 
[Amazon Cognito]
[Amazon Cognito] Amazon Cognito update
[Amazon Cognito] Amazon Cognito / Amazon Mobile Analytics
[AWS Device Farm]
[Amazon Mobile Analytics] Amazon Cognito / Amazon Mobile Analytics
[Amazon SNS] Amazon SNS/SQS
[Amazon SNS] モバイルプッシュ通知
[Amazon Pinpoint]  

アプリケーションサービス

資料 読んだ  重要度 
[Amazon API Gateway] 
[Amazon AppStream]
[Amazon CloudSearch] Amazon CloudSearch & Amazon Elasticsearch Service
[Amazon Elastic Transcoder]
[Amazon SES]
[Amazon SES] Amazon SES-Easy DKIM 設定サポート資料
[Amazon SQS] Amazon SNS/SQS
[Amazon Simple Workflow Service (SWF)]

エンタープライズアプリケーション

資料 読んだ  重要度 
[Amazon WorkSpaces]
[Amazon WorkDocs]
[Amazon WorkMail]
[Amazon Chime]

その他

資料 読んだ  重要度 
[Cost Explorer]
[AWS Management Console]

補足

重要度の低い資料も読んだ方がいいです。
なぜなら、マネージドサービス自体がAWSの活用事例であり、それらを知ることでシステム設計の勘所が分かるようになるからです。
また、重要度の高い機能との連携についての記載があることもあり、理解が深まります。

続きを読む

Visual Studio Codeでリモートマシン上のNode.jsファイルを直接操作(編集、デバッグ実行)する

実現すること

Visual Studio Codeでリモートマシン上のNode.jsファイルを直接操作(編集、デバッグ実行)します

    debug.png
    ローカルマシン(Windows)でリモートマシン(Linux)のNode.jsファイルを直接操作

対象者

  • Visual Studio Codeを使ってNode.jsの開発をしている人
  • LinuxマシンのファイルをViとかEmacsで編集するが煩わしいと思っている人
  • ローカルで開発したコードをいちいちリモートのLinuxサーバに転送するのが面倒な人
  • リモートのLinuxサーバのソースを直接デバッグ実行したい人

検証環境

  • ローカルマシン

    • Windows 10
    • Visual Studio Code 1.13.0
  • リモートマシン

    • AWS EC2 (Amazon Linux AMI 2017.03.0.20170417 x86_64 HVM)

リモートマシン側の準備

Node.js

インストール

$ sudo su
# curl -sL https://rpm.nodesource.com/setup_8.x | bash -
# yum install -y gcc-c++ make
# yum install -y nodejs

動作確認

# curl -sL https://deb.nodesource.com/test | bash -
# npm --v
# node -v

参考URL

リンク:https://github.com/nodesource/distributions#enterprise-linux-based-distributions

jmate

インストール

# npm -g install jmate

参考URL

リンク:https://github.com/jrnewell/jmate

SSH

セキュリティグループの設定でインバウンド、アウトバウンドともに52698ポートを許可します。

  • タイプ:カスタムTCPルール
  • プロトコル:TCP
  • ポート範囲:52698
  • ソース:許可したいIPアドレス

クライアントマシン側の準備

Visual Studio Code, Node.js

Visual Studio Code, Node.jsをインストールしておきます。

Windows用のSSHクライアントのインストール

Windowsで実行可能はSSHクライアント(ssh.exe)をインストールしPATHを通します。
SSHクライアントは、 git for windows などに含まれています。

SSH

キーペア

インスタンス生成時に作成したキーペア(*.pemファイル)を ~.ssh に保存します。
ここでは、my-ec2.pem というファイル名で保存したものとして以降説明します。

configファイル

毎回長いsshコマンドをうたなくても大丈夫なようにconfigファイルに設定を書いておきます。

~.sshconfig
ServerAliveInterval 60

Host my-ec2
    HostName ※EC2のIPアドレス
    User ec2-user
    IdentityFile ~/.ssh/my-ec2.pem
    RemoteForward 52698 127.0.0.1:52698

テスト

sshコマンドでサーバにアクセスできることを確認します。

> ssh my-ec2

自動的にログインできればSSHの設定完了です。

Remote VSCode

インストール

Visual Studio Code > EXTENSIONS (Ctrl+Shift+X) > Remote VSCode > Install

settings.jsonの設定

Visual Studio Code > File > Preferences > Settings (Ctrl+Comma)

User Settingsに以下を追記

  //-------- Remote VSCode configuration --------

    // Port number to use for connection.
    "remote.port": 52698,

    // Launch the server on start up.
    "remote.onstartup": true

"remote.onstartup": false の設定にした場合は、F1でcommand palleteを表示し、Remote: Start server でRemote VSCodeのサーバーを起動します。

ローカルのVisual Studio Codeでリモートのファイルを操作

  1. Visual Studio Codeを起動します。
  2. Visual Studio CodeのTerminalでサーバにSSH接続します。

    > ssh my-ec2
    
  3. ファイルオープン
    Visual Studio Codeでリモートのファイルを開きます。

    $ jmate -p 52698 ファイル名.js
    
  4. 編集とデバッグ実行
    4.1. ファイルを編集します。
    4.2. ソースコードにブレークポイントをはります。
    4.3. デバッグウィンドウを開きます。(Ctrl+Shift+D)
    4.4. デバッグ実行します。(F5)

 これで、ファイルの編集、ステップ実行、変数の参照、ウォッチ式の設定、コールスタックの参照、ブレークポイントの設定がローカルファイルと同様に動作するようになりました。

続きを読む

AWSのec2にnginx+php7+mysqlを導入してwordpressを構築する準備をする

日本時間に設定

sudo cp /usr/share/zoneinfo/Japan /etc/localtime

ルートへ

sudo su -

nginxインストール

yum install -y nginx

php7インストール準備

rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm

php7インストール

yum install -y --enablerepo=webtatic-testing php70w php70w-devel php70w-fpm php70w-mysql php70w-mbstring php70w-pdo

nginx起動テスト

/etc/rc.d/init.d/nginx start

起動確認できたらnginx設定周り調整

nginx.conf

vi /etc/nginx/nginx.conf
nginx.conf
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}



http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   60;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.

    gzip_static       on;
    gzip              on;
    gzip_http_version 1.0;
    gzip_vary         on;
    gzip_comp_level   6;
    gzip_min_length 1024;
    gzip_types        text/plain text/xml text/css text/javascript
                      application/xhtml+xml application/xml
                      application/rss+xml application/atom_xml
                      application/javascript application/x-javascript
                      application/x-httpd-php application/json;
    gzip_disable      "MSIE [1-6].";

    proxy_cache_path  /var/cache/nginx levels=1:2
                      keys_zone=one:4m max_size=50m inactive=120m;
    proxy_temp_path   /var/tmp/nginx;
    proxy_cache_key   "$scheme://$host$request_uri";
    proxy_set_header  Host               $host;
    proxy_set_header  X-Real-IP          $remote_addr;
    proxy_set_header  X-Forwarded-Host   $host;
    proxy_set_header  X-Forwarded-Server $host;
    proxy_set_header  X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header  Accept-Encoding    "";
    proxy_connect_timeout 5;
    proxy_send_timeout 10;
    proxy_read_timeout 120;
    proxy_hide_header X-Pingback;
    proxy_hide_header X-Powered-By;
    proxy_hide_header Etag;
    proxy_hide_header Vary;
    proxy_cache_use_stale timeout invalid_header http_500 http_502 http_503 http_504;
    proxy_cache_lock on;
    proxy_cache_lock_timeout 5s;
    index  index.html index.php index.htm;

    upstream backend {
        server unix:/var/run/nginx-backend.sock;
    }

    upstream phpfpm {
        server unix:/var/run/php-fpm.sock;
    }


    include /etc/nginx/conf.d/*.conf;


}        

リバースプロキシ用にバックエンド系

vi /etc/nginx/conf.d/backend.conf
backend.conf
server {
    listen unix:/var/run/nginx-backend.sock;
    server_name we-shirts.jp;
    root   /var/www/html;
    access_log  /var/log/nginx/backend.access.log;
    client_max_body_size 24M;
    fastcgi_connect_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_send_timeout 180;
    gzip              off;
    gzip_vary         off;

    location / {
#        ssi on;
#         index  index.html index.php index.htm;
        try_files /index.php?$args /index.php?q=$uri&$args;
#        try_files $uri $uri/ /index.php?$args /index.php?q=$uri&$args;
        index  index.php index.html index.htm;
#        try_files $uri $uri/ /index.php?$args /index.php?q=$uri&$args;
    }

    location ~ .(php|html)$ {
        try_files $uri =404;
        expires        off;
        fastcgi_pass   phpfpm;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_param  REMOTE_ADDR      $http_x_real_ip;
        fastcgi_pass_header "X-Accel-Redirect";
        fastcgi_pass_header "X-Accel-Buffering";
        fastcgi_pass_header "X-Accel-Charset";
        fastcgi_pass_header "X-Accel-Expires";
        fastcgi_pass_header "X-Accel-Limit-Rate";
    }

}

サーバ共通設定系

vi /etc/nginx/conf.d/hogehoge.conf
hogehoge.conf
server {
     listen       80;
     server_name  we-shirts.jp;
     root         /var/www/html;
     index        index.php index.html index.htm;
     charset      utf-8;

     client_max_body_size 100M;

     location = /favicon.ico { access_log off; log_not_found off; }
     location = /robots.txt { access_log off; log_not_found off; }
     location = /apple-touch-icon.png { access_log off; log_not_found off; }
     location ~ /. { deny all; access_log off; log_not_found off; }

     location ^~ /license.txt          { deny all; access_log off; log_not_found off; }
     location ^~ /readme.html          { deny all; access_log off; log_not_found off; }
     location ^~ /readme-ja.html       { deny all; access_log off; log_not_found off; }
     location ^~ /wp-activate.php      { deny all; access_log off; log_not_found off; }
     location ^~ /wp-blog-header.php   { deny all; access_log off; log_not_found off; }
     location ^~ /wp-cron.php          { deny all; access_log off; log_not_found off; }
     location ^~ /wp-load.php          { deny all; access_log off; log_not_found off; }
     location ^~ /wp-mail.php          { deny all; access_log off; log_not_found off; }
     location ^~ /wp-settings.php      { deny all; access_log off; log_not_found off; }
     location ^~ /wp-signup.php        { deny all; access_log off; log_not_found off; }
     location ^~ /wp-trackback.php     { deny all; access_log off; log_not_found off; }
     location ^~ /xmlrpc.php           { deny all; access_log off; log_not_found off; }

     set $mobile '';
     if ($http_user_agent ~* '(DoCoMo|J-PHONE|Vodafone|MOT-|UP.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|Windows CE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)') {
       set $mobile '@ktai';
     }
     if ($http_user_agent ~* '(iPhone|iPod|incognito|webmate|Android|dream|CUPCAKE|froyo|BlackBerry|webOS|s8000|bada|IEMobile|Googlebot-Mobile|AdsBot-Google)') {
       set $mobile '@smartphone';
     }
     if ($http_cookie ~* "wptouch(_switch_cookie=normal|-pro-view=desktop)") {
         set $mobile "@smartphone.desktop";
     }

     location ^~ /wp-content/uploads/ {
         expires 30d;
#         rewrite ^ http://static.tbsradio.jp$request_uri? permanent;
     }

     location ~* /wp-(content|admin|includes) {
         index   index.php index.html index.htm;
         if ($request_filename ~* .*.(xml|gz)) {
             break;
             expires 1d;
         }
         if ($request_filename ~* .*.(txt|html|js|css|swf)) {
             break;
             expires 30d;
         }
         if ($request_filename ~* .*.(ico|jpeg|gif|png|wmv|flv|mpg|gz)) {
             break;
             expires 365d;
         }
         if ($request_filename ~ .*.php) {
             break;
             proxy_pass http://backend;
         }
     }

     location ~* (.*).(gif|jpe?g|JPG|png|ico) {
#        rewrite ^ http://static.tbsradio.jp$request_uri? permanent;
     }

     location ~* (.*).(css|less|js) {
         break;
     }

     location /feed {
         proxy_pass http://backend;
     }
     location ~ .*.php {
         proxy_pass http://backend;
     }

#     error_log /var/log/nginx/elb_error.log;
#     empty_gif;
#     break;



     location @wordpress {
#        ssi on;
         set $do_not_cache 0;
         if ($http_cookie ~* "comment_author_|wordpress_( !test_cookie)|wp-postpass_" ) {
             set $do_not_cache 1;
         }
         if ($request_method = POST) {
             set $do_not_cache 1;
         }

         proxy_no_cache     $do_not_cache;
         proxy_cache_bypass $do_not_cache;
         proxy_read_timeout 300;
         proxy_redirect     off;
         proxy_cache        one;
         proxy_cache_key    "$scheme://$host$request_uri$mobile";
         proxy_cache_valid  200 10m;
         proxy_cache_valid  404 1m;
#         proxy_set_header Try-Redirect-To-File $redirect_to;
         proxy_pass         http://backend;
     }

     location / {
         root /var/www/html;
         auth_basic “REstricted”;
         auth_basic_user_file /var/www/html/.htpasswd;

         try_files $uri @wordpress;
     }

     location ~ .xml {
         rewrite ^/sitemap.xml$ /index.php?sitemap=1 last;
         rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last;
         rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
         try_files $uri @wordpress;
     }


     location /healthcheck.html {
         satisfy   any;
         allow     all;
     }

     #error_page 404 /404.html;
     #    location = /40x.html {
     #}

        # redirect server error pages to the static page /50x.html
        #
     #error_page 500 502 503 504 /50x.html;
     #    location = /50x.html {
     #}


     #location /s3/ {
     #     proxy_set_header Authorization "";
     #     proxy_pass https://s3-ap-northeast-1.amazonaws.com/hogehoge-static-data/s3/;
     #}

}

ドキュメントルートディレクトリ作成

mkdir /var/www/html/hogehoge
chown nginx:nginx /var/www/html/hogehoge

php-fpm系設定

vi /etc/php-fpm.d/www.conf
www.conf
user = nginx
group = nginx
listen = /var/run/php-fpm.sock;
listen.owner = nginx

listen.group = nginx

listen.mode = 0660

security.limit_extensions = .php .html

php-fpmとnginx起動

/etc/rc.d/init.d/php-fpm start
/etc/rc.d/init.d/php-fpm restart

php-fpm.sockのパーミッション調整

chmod 666 /var/run/php-fpm.sock

動作確認

cd /var/www/html/hogehoge/
vi test.php 
test.php
<?php phpinfo();?>

ブラウザでアクセス

http://xxxxxxxxxxxxxxxx.amazonaws.com/hogehoge/test.php

basic認証準備

yum install -y httpd-tools
cd /var/www/html
htpasswd -c .htpasswd loginid
password

hogehoge.confのlocation / に下記追加

hogehoge.conf
location / {
      auth_basic “REstricted”;
      auth_basic_user_file /var/www/html/.htpasswd;  
}

mysqlインストール

yum install -y mysql-server
chkconfig mysqld on
service mysqld start

続きを読む

[IPSec-VPN] クラウド間(GCP⇔AWS)通信

プロローグ

GCP(Google Cloud Platform)とAWS(Amazon Web Service)の間のSite-to-Site VPN通信(クラウド間VPN通信)は、超簡単にできる

  • GCPの「VPN接続」機能とAWSの「VGW(Virtual Private GW)」は、直結可能!
  • Azureの「仮想ネットワークゲートウェイ」とAWSのVGWは、(数年前は)繋げなかった…
    • 確か「どちらが先にグローバルIPアドレスを払い出す?」問題。
    • ARM版では未検証。
  • AWSのようにWindows-VPNを試してみたが、不発…
    • 詳細は(エピローグ中の)「gcpとAWSのNW観点の差異」をご参照。

手順

  1. [gcp] 外部IPアドレス(以下、この値をGIPと呼ぶ)を取得する。

    • AWSのVGWはグローバルIPアドレスが自動的に割り振られる(=Uncontrollable)なので、gcp側でControlする。
  2. [AWS] GIPに相当するCGW(Customer Gateway)を作成する。
  3. [AWS] VGWを作成し、VPCに紐づける。
    • このとき、VPCに紐づいているRouteTableにおいて、VGWの「Route Propagation」を「Yes」にしておくと、「AWS→gcp」のルートがAWS側に自動設定される。
  4. [AWS] SecurityGroupを調整する。
    • gcp側のプライベートNWからの通信を受け付けるべく開ける(テスト用ICMPとか)。
  5. [AWS] 上記のCGWとVGWをツナぐVPN Connection(VPNC)を作成する。
    • 「Routing Options」:まずは敷居の低い「static」で…
    • 「Static IP Prefixes」:gcp側のNWアドレス(CIDR)を指定。
  6. [AWS] VPNCのConfigurationをDownloadする。
    • AWS側グローバルIPアドレス/Pre-Shared-Key(2つずつ)は、AWSが自動割り当てする(=Uncontrollable)。
  7. [gcp] VPN接続を作成する。

    • gcp側のIPアドレスとして「GIP」を設定。
      20170607_VPN接続の設定① - コピー.jpg
    • AWS側がVPNトンネルを2つ用意しているので、トンネル設定は2本分設定。
    • 「IKEバージョン」:「IKEv1」を指定(「IKEv2」だと疎通しない。AWSが未対応?)。
    • 「事前共有シークレット」:AWSが自動割り当てしたPre-Shared-Key値を設定。
    • 「ルーティングオプション」:まずは敷居の低い「静的」で…
    • 「リモートネットワークIPの範囲」:AWS VPCのCIDRを指定。
    • トンネル1本目用の設定
      20170607_VPN接続の設定② - コピー.jpg
    • トンネル2本目用の設定
      20170607_VPN接続の設定③ - コピー.jpg
  8. 「作成」ボタンを押し、下記の画面になればOK!!
    20170607_VPN接続の設定RES.jpg

  9. ICMPで疎通確認のためには、下記を確認:

    • AWS側のRouteTable(Propageted指定なら追加作業なし)
    • AWS側のSecurityGroup
    • gcp側のルート(VPN接続作成時に自動作成されているはずなので、追加作業なし)
    • gcp側のファイアウォールルール(サブNW作っているとハマりがちなので注意)

エピローグ

gcpとAWSのNW観点の差異

  • gcpでは、ひとつのインスタンスは複数のNICを持つことはできない?(ひとつのNW/サブNWにしか収容できない?)
    ⇒複数NIC持つことできます。訂正。
    ⇒複数NICを持たせたうえで、Windows-VPNに再挑戦★

  • gcpインスタンス上でipconfig/ifconfigを実行すると下記の結果が出てプチ衝撃:

ipconfig
C:\>ipconfig
Windows IP Configuration

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : c.xxx.internal
   IPv4 Address. . . . . . . . . . . : 10.xxx.0.100
   Subnet Mask . . . . . . . . . . . : 255.255.255.255
   Default Gateway . . . . . . . . . : 10.xxx.0.1

C:\>
ifconfig
$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc pfifo_fast state UP qlen 1000
    link/ether 42:01:0a:8c:00:02 brd ff:ff:ff:ff:ff:ff
    inet 10.xxx.0.2/32 brd 10.140.0.2 scope global dynamic eth0
       valid_lft 80364sec preferred_lft 80364sec
    inet6 fe80::xxxx:xxxx:xxxx:2/64 scope link 
       valid_lft forever preferred_lft forever

⇒サブネットマスクが「/32(IPv4)」「/64(IPv6)」?
⇒全てのインスタンスは、GWインスタンスに直接ぶら下がっている(ハブ&スポーク構成)?

AzureとAWSの間のSite-to-Site VPN通信(クラウド間VPN通信)

  • ぱっと見たところ、Azure側仮想ネットワークゲートウェイにおいて、

    • パブリックIPアドレスは指定できる(「どちらが先にグローバルIPアドレスを払い出す?」問題は解消)。
    • Pre-Shared-Keyが指定可能か不可か、依然調査中…

AWSリージョン間接続を、VGW同士で…

できないですよね。グローバルIPアドレス/Pre-Shared-Keyを自動で割り当てられてしまう(=Uncontrollable)ので★

最後にひとこと

「gcpとAWSの間のSite-to-Site VPN通信」の方が「AWSのリージョン間のSite-to-Site VPN通信」よりもシンプル・早・易だと思いました♪

続きを読む