20200820のAWSに関する記事は16件です。

[AWS] Private Subnet内のEC2インスタンスにローカルPCのターミナルからアクセスする

はじめに

EC2インスタンスにアクセスするには、

  • Public Subnetに配置してsshでアクセスする
  • Private Subnetに配置して、Public Subnet内のインスタンスを踏み台にして、そこからsshアクセスする

などがごく普通なアクセス経路ですが、Private Subnet上のEC2インスタンスに、ローカルPCのターミナルから直接アクセスする方法をまとめておきます。

準備

VPC

ルートテーブル

以下の設定で作成します。

  • 名前タグ:わかりやすい名称で
  • VPC:デフォルトのVPCでOKです

InternetGatewayにルーティングしていないことを確認してください。

サブネット

以下設定で作成します。

  • 名前タグ:わかりやすい名称で
  • VPC:デフォルトのVPCでOKです
  • アベイラリティゾーン:指定なし
  • IPv4 CIDRブロック:VPCのCIDR内の適当なCIDRを指定

ルートテーブルは、上で作成したルートテーブルに関連付けるようにしてください。

セキュリティグループ

以下設定で作成します。

  • セキュリティグループ名:わかりやすい名称で
  • 説明:適当にわかりやすい説明を
  • VPC:デフォルトのVPCでOKです
  • インバウンドルール:
    • タイプ:HTTPS
    • プロトコル:TCP
    • ポート範囲:443
    • ソース:サブネットのIPv4 CIDRブロックを指定
  • アウトバンドルール:なし

エンドポイント

以下のエンドポイントを作成してください。

  • com.amazonaws.[リージョン名].ssm
  • com.amazonaws.[リージョン名].ssmmessages
  • com.amazonaws.[リージョン名].ec2messages

上記インタフェースは、いずれも、

  • VPC:デフォルトのVPCでOKです
  • サブネット:上で作成したサブネット
  • アベイラリティゾーン:全部チェックでOKです
  • プライベートDNS名有効にする:チェック
  • セキュリティグループ:上で作成したセキュリティグループ

さらに、下記ゲートウェイを同様に作成してください。

  • com.amazonaws.[リージョン名].s3

各種設定は、以下のようになります。

  • VPC:デフォルトのVPCでOKです
  • ルートテーブル:上記で作成したルートテーブル
  • ポリシー:フルアクセス

EC2

インスタンスを作成します。
今回は、Amazon Linux 2 64bitのAMIを使用したいと思います。
インスタンスタイプは、t2.microで検証してみます。

デフォルトから変更が必要な項目は、以下です。

  • サブネット:上で作成したサブネット
  • IAMロール:AmazonSSMRoleForInstanceQuickSetup

セキュリティグループでは、デフォルトの「SSH」は削除してしまってください。
SSHで接続することはないので、キーペアの作成も不要です。
この状態でインスタンスが作成されるのを待ちましょう。

ec2.png

パブリックIPアドレス関連が未設定であることが確認できました。

接続確認

では、さっそくローカルPCのターミナルから、接続してみましょう。
事前に、アカウントのクレデンシャルを設定しておくようにしてください。

接続するコマンドは、

構文
$ aws ssm start-session --target [インスタンスID]

です。
早速、インスタンスIDを指定してコマンド実行すると、あっさり接続できました。

aws ssm start-session --target i-06157169f5c0e2463

Starting session with SessionId: **************
sh-4.2$

本当に、目的のインスタンスにつながっているか確認してみます。

sh-4.2$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 172.31.252.54  netmask 255.255.255.0  broadcast 172.31.252.255
        inet6 fe80::8c9:18ff:fe2f:bc94  prefixlen 64  scopeid 0x20<link>
        ether 0a:c9:18:2f:bc:94  txqueuelen 1000  (Ethernet)
        RX packets 33688  bytes 47456317 (45.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 13670  bytes 906178 (884.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 8  bytes 648 (648.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 648 (648.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

IPアドレスが、マネジメントコンソールのプライベートIPアドレスと同じであることが確認できますね。

なお、AWS Cliから、Session Managerでアクセスするためには、Session Manager Pluginが必要です。もしプラグインがインストールされていない場合は、下記よりクライアント環境にあったプラグインをインストールしてください。

(Optional) Install the Session Manager Plugin for the AWS CLI

まとめ

今回は、セキュリティグループのインバウンドもアウトバウンドも、極力設定しないように構築しましたが、必要に応じて、必要なポート、ソース(CIDR)を適宜(なるべく最小範囲)に設定して大丈夫です。

しかし、踏み台もなく、パブリック公開も必要なく、プライベートなネットワーク上のインスタンスにアクセスできる構成が簡単に組めるわけですから、セキュリティの観点からも、こういった構成が使えるところは使っていくよういしたいですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS] Private Subnet内のEC2インスタンスにローカルPCのターミナルからSession Managerでアクセスする

はじめに

EC2インスタンスにアクセスするには、

  • Public Subnetに配置してsshでアクセスする
  • Private Subnetに配置して、Public Subnet内のインスタンスを踏み台にして、そこからsshアクセスする

などがごく普通なアクセス経路ですが、Private Subnet上のEC2インスタンスに、ローカルPCのターミナルから直接アクセスする方法をまとめておきます。

準備

VPC

ルートテーブル

以下の設定で作成します。

  • 名前タグ:わかりやすい名称で
  • VPC:デフォルトのVPCでOKです

InternetGatewayにルーティングしていないことを確認してください。

サブネット

以下設定で作成します。

  • 名前タグ:わかりやすい名称で
  • VPC:デフォルトのVPCでOKです
  • アベイラリティゾーン:指定なし
  • IPv4 CIDRブロック:VPCのCIDR内の適当なCIDRを指定

ルートテーブルは、上で作成したルートテーブルに関連付けるようにしてください。

セキュリティグループ

以下設定で作成します。

  • セキュリティグループ名:わかりやすい名称で
  • 説明:適当にわかりやすい説明を
  • VPC:デフォルトのVPCでOKです
  • インバウンドルール:
    • タイプ:HTTPS
    • プロトコル:TCP
    • ポート範囲:443
    • ソース:サブネットのIPv4 CIDRブロックを指定
  • アウトバンドルール:なし

エンドポイント

以下のエンドポイントを作成してください。

  • com.amazonaws.[リージョン名].ssm
  • com.amazonaws.[リージョン名].ssmmessages
  • com.amazonaws.[リージョン名].ec2messages

上記インタフェースは、いずれも、

  • VPC:デフォルトのVPCでOKです
  • サブネット:上で作成したサブネット
  • アベイラリティゾーン:全部チェックでOKです
  • プライベートDNS名有効にする:チェック
  • セキュリティグループ:上で作成したセキュリティグループ

さらに、下記ゲートウェイを同様に作成してください。

  • com.amazonaws.[リージョン名].s3

各種設定は、以下のようになります。

  • VPC:デフォルトのVPCでOKです
  • ルートテーブル:上記で作成したルートテーブル
  • ポリシー:フルアクセス

EC2

インスタンスを作成します。
今回は、Amazon Linux 2 64bitのAMIを使用したいと思います。
インスタンスタイプは、t2.microで検証してみます。

デフォルトから変更が必要な項目は、以下です。

  • サブネット:上で作成したサブネット
  • IAMロール:AmazonSSMRoleForInstanceQuickSetup

セキュリティグループでは、デフォルトの「SSH」は削除してしまってください。
SSHで接続することはないので、キーペアの作成も不要です。
この状態でインスタンスが作成されるのを待ちましょう。

ec2.png

パブリックIPアドレス関連が未設定であることが確認できました。

接続確認

では、さっそくローカルPCのターミナルから、接続してみましょう。
事前に、アカウントのクレデンシャルを設定しておくようにしてください。

接続するコマンドは、

構文
$ aws ssm start-session --target [インスタンスID]

です。
早速、インスタンスIDを指定してコマンド実行すると、あっさり接続できました。

$ aws ssm start-session --target i-06157169f5c0e2463

Starting session with SessionId: **************
sh-4.2$

本当に、目的のインスタンスにつながっているか確認してみます。

sh-4.2$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 172.31.252.54  netmask 255.255.255.0  broadcast 172.31.252.255
        inet6 fe80::8c9:18ff:fe2f:bc94  prefixlen 64  scopeid 0x20<link>
        ether 0a:c9:18:2f:bc:94  txqueuelen 1000  (Ethernet)
        RX packets 33688  bytes 47456317 (45.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 13670  bytes 906178 (884.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 8  bytes 648 (648.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 648 (648.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

IPアドレスが、マネジメントコンソールのプライベートIPアドレスと同じであることが確認できますね。

なお、AWS Cliから、Session Managerでアクセスするためには、Session Manager Pluginが必要です。もしプラグインがインストールされていない場合は、下記よりクライアント環境にあったプラグインをインストールしてください。

(Optional) Install the Session Manager Plugin for the AWS CLI

まとめ

今回は、セキュリティグループのインバウンドもアウトバウンドも、極力設定しないように構築しましたが、必要に応じて、必要なポート、ソース(CIDR)を適宜(なるべく最小範囲)に設定して大丈夫です。

しかし、踏み台もなく、パブリック公開も必要なく、プライベートなネットワーク上のインスタンスにアクセスできる構成が簡単に組めるわけですから、セキュリティの観点からも、こういった構成が使えるところは使っていくよういしたいですね。

関連記事

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WebページのボタンからAWS MediaLiveを起動させる

はじめに

ライブ配信で利用するAWS MediaLiveの起動・停止は
通常、AWSコンソールやCLIから操作することが多いと思います。

ただ、開発者以外の人に操作してもらう場合は、それだとハードルが高いため、
Webページに配置したボタンから起動・停止を操作できるような仕組みを考えてみました。

構成図

S3にHTMLを配置して、CloudFrontで配信します。

Web利用者はHTML上に配置されたボタンを押します。
すると、APIが実行され、Lambdaがキックされて、MediaLiveが起動・停止する仕組みになります。
ScreenShot 2020-08-19 19.56.29.png

MediaLive

今回、操作対象とするMediaLiveチャンネルは、1つとします。

IAM

Lambda用のIAM Roleを作成しておきます。
必要なポリシーは下記になります。

  • AWSLambdaBasicExecutionRole
  • AWSElementalMediaLiveFullAccess

Lambda

ランタイム:Python3.8
環境変数:「channel_id」で、MediaLiveのチャンネルIDを設定します。

  • start関数

※すでにチャンネルが起動していた場合、strat処理を実行しないようにしています。

import boto3
import os

channelid = os.environ['channel_id']
medialive = boto3.client('medialive')

def lambda_handler(event, context):

    channels = medialive.describe_channel(ChannelId=channelid)

    if channels['State'] == 'RUNNING':
        ngmsg = ("チャンネルはすでに起動されています")
        return ngmsg
        pass

    else:
        medialive.start_channel(ChannelId=channelid)
        okmsg = ("チャンネルを起動しています")
        return okmsg
  • stop関数

※start関数と同様、すでにチャンネルが停止していた場合、stop処理を実行しないようにしています。

import boto3
import os

channelid = os.environ['channel_id']
medialive = boto3.client('medialive')

def lambda_handler(event, context):

    channels = medialive.describe_channel(ChannelId=channelid)

    if channels['State'] == 'IDLE':
        ngmsg = ("チャンネルはすでに停止されています")
        return ngmsg
        pass

    else:
        medialive.stop_channel(ChannelId=channelid)
        okmsg = ("チャンネルを停止しています")
        return okmsg

API Gateway

  • 1. APIの作成
  • 2. リソースの作成:startとstopをそれぞれ作成します。
  • 3. メソッドの作成:POSTやPUTなど
  • 4. CORSの有効化
  • 5. メソッドレスポンス:実行結果を日本語で表示させるため、application/json;charset=UTF-8を追記します。
  • 6. APIのデプロイ

すると、下記ようなURLが発行されます。

https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage名]

(詳しい設定方法は、本ページ最下部の参考文献の記事が参考になりました)

HTML

次にHTMLを作成します。

私はHTMLに詳しくなく、もっといい書き方がある気がしますので、
参考程度に載せておきます。

url: 」には、先ほどのAPI Gatewayで発行したURLの最後に、
startやstopのリソース名を加えたURLを記入します。

例:

url:"https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage]/start"

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
  <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <title>MediaLive操作Web</title>
</head>
<script>
  $(function(){
    // ボタンを押すと処理を開始する
    $("#btn1").on("click", function() {
    $.ajax({
        type: "POST",
        url: "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage]/start",
        cache : false,
    })
        .done(function(result) {
            console.log(result);
    })
        .fail(function(result) {
            console.log(result);
    })
            console.log = function (log) {

        // API実行結果と実行日時を表示させる
        var date = new Date();
        document.getElementById('console_log1').innerHTML = log + "<br>" + "(" + date.toLocaleString() + ")" + "<br>";
        }
    })
})

   function stop(){
    // ボタンを押下すると確認ダイアログを表示する
    ret = confirm("本当にチャンネル停止してよろしいですか?");
    if (ret == true){
    $.ajax({
        type: "PUT",
        url: "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage]/stop",
        cache : false,
    })
        .done(function(result) {
            console.log(result);
    })
        .fail(function(result) {
            console.log(result);
    })
            console.log = function (log) {

        // API実行結果と実行日時を表示させる
        var date = new Date();
        document.getElementById('console_log2').innerHTML = log + "<br>" + "(" + date.toLocaleString() + ")" + "<br>";
        }
    }
}
</script>
<button type="button" id="btn1" style="width:150px;height:50px">チャンネル起動</button>
<div id="console_log1" div class="disp-area" style="width:400px;height:50px;padding:15px;background-color: #f0f18b2c;"></div>
<br>
<button type="button" onClick="stop()" style="width:150px;height:50px">チャンネル停止</button>
<div id="console_log2" div class="disp-area" style="width:400px;height:50px;padding:15px;background-color: #f0f18b2c;"></div>
</html>

S3とCloudFront

HTMLを置くだけなので、この部分は省略します。

動作確認

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

API Endpointのエントリポイント・コードの書き方

API Gatewayとかから飛んできたリクエストをLambdaでいい感じに処理する、よくあるバックエンドコード
この辺のいい感じの記述を模索してて最近こんな感じになっています。

最近の自分の書き方

/**
 * フォーマットに関してはこいつに任せる。
 */
const run = async(event, hoehoe) => {
  // どでかいtry-catchで例外をアプリ内に封じ込める
  try {
    // 悩むけどこの辺の情報はこっちでいいかな
    const name = event.pathParameters.name;

    // 処理は極力別クラスに任せる
    const service = new Service(hoehoe);
    const pet =service.getPet(name);

    // 仕様と対応するので正常系の出口は一箇所
    return getSuccessResponse({
      color: pet.color.value,
      size: pet.size || 99999,
    });
  } catch(error) {
    console.error(error);

    // 最低限の整形をしてエラーを通知する。ここはアプリの最終防衛ラインなので重点的にテスト
    return getErrorResponse(error);
  }
} 

/**
 * エントリポイント
 * 外部プラットフォーム依存するコードを集約する
 * ここは結合テストのスコープ(LamndaやAPI Gatewayのテスト機構を使う)
 */
exports.handler = async(event) => {
  return await run(
    event,
    process.env.HOGEHOGE // 環境変数はスコープがでかいので入り口で捕まえて引き回す
  );
};
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ECS上のコンテナアプリをCircleCIでCI/CDする

この記事について

イケてる開発をするためにはCI/CDは欠かせません。
特にAWSを使って本番環境を作っている場合、デプロイ操作をいちいちWebコンソールでぽちぽちしながら行うのは結構面倒です。

そのため今回は、ECSを使ったコンテナアプリを、CircleCIを使ってCI/CDパイプラインにのせるための手順、主にCircleCIの設定周りについて詳しく解説します。

使用する環境・バージョン

macOS Mojave 10.14.5

前提条件

GitHub, CircleCI, AWSのアカウントは取得済みの状態から始めます。

読者に要求する前提知識

  • ECSへの手動デプロイが問題なくできること、およびECS用語(タスク・サービス等)の理解
  • gitの基本的な操作(add, commit, push, リモートリポジトリとの連携)
  • CircleCIでのプロジェクト作成(GitHubリポジトリとの連携)ができる
  • IAMユーザーの作成ができる

構築するCI/CDパイプライン

スクリーンショット 2020-08-19 23.56.23.png
今回構築するパイプライン全容は以上の図の通りです。言葉でも説明すると、

  1. 開発者がアプリのコードをGitHubにpushする
  2. CircleCIがGitHubにpushされたことを検知、以下3,4の手順でのデプロイを自動で行う
  3. GitHubにアップされたコードからコンテナイメージをビルド、それをECRの指定リポジトリにpush
  4. 3でpushされたコンテナイメージを使ったタスク・サービスに自動更新する

これが実現できるように、CircleCIの設定をすることが目標となります。

サンプルアプリの作成

最終的なファイル・ディレクトリ構造

ローカルでの最終的なファイル構造は以下のようになります。

.
├─.circleci
│  └─config.yml
├─main.go
├─main_test.go
└─Dockerfile

アプリのコードを作成

今回は、Goを用いて基本的なウェブサーバーを作りました。
main.goに以下のように記述します。

main.go
func main() {
    port := "8080"
    fmt.Printf("Server Listening on port %s\n", port)

    http.HandleFunc("/", handler)

    err := http.ListenAndServe(":"+port, nil)
    if err != nil {
        log.Fatal("fatal err: ", err)
    }
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

アプリのコンテナ化

コードを書いた後は、これをコンテナ化するためにDockerfileを作成します。

FROM golang:1.13

WORKDIR /go/src/app
COPY . .

CMD ["go", "run", "main.go"]

Dockerfile作成後は、docker buildコマンドを用いてビルドします。
ここではコンテナイメージに一回testserverという名前をつけました。

$ docker build -t testserver .

コンテナ化したアプリの動作を確認するためには、以下のコマンドを叩いてhttp://localhost:8080にアクセスすればOKです。

$ docker run -p 8080:8080 testserver

ECSへの初回デプロイをする

CircleCIでできるのは、「既にデプロイされているアプリを更新・アップデートすること」なので、初回デプロイは手動で済ませておく必要があります。

ECS手動デプロイ時の詳しい手順・設定については記事の本筋から外れてしまうため詳しくは説明せず、CircleCIの設定に絡む部分だけを記述します。
ECSの用語・概念・詳しいデプロイ手段について知りたい方は、別記事にまとめていますのでこちらをご覧ください(下記記事のvoting-appのデプロイがほぼそのままこれに適用できます)。
Dockerコンテナで作ったアプリをECS+RDSでデプロイする

  1. ECRリポジトリの作成→コンテナイメージのpush
    今回は「cicdtest」という名前のリポジトリを作成し、先ほど作ったサンプルアプリのコンテナイメージをpushしました。
  2. タスク定義作成
    先ほどpushしたコンテナイメージを使ってタスク定義を作成します。タスク名を「testserver」、コンテナ名を「testserverContainer」としました。
  3. クラスター作成
    今回は「circleciTest」という名前のクラスターにしました。
  4. サービス作成
    「CircleCItestService」という名前で、先ほどのタスクを起動するサービスを作りました。

CircleCIの設定

初回デプロイが終わったら、これを継続的にアップデートできるようにCircleCIを用いてCI/CDパイプラインを構築していきます。

参考:CircleCI Orbsで ECR/ECS にデプロイ
参考:CircleCI + GitHub + Amazon Elastic Container Registry (Amazon ECR) + Amazon Elastic Container Service (Amazon ECS) (+ AWS Fargate) で継続的デリバリー環境を構成する

IAMユーザー作成

CircleCIからAWSのリソースを扱うためには、CircleCI用のIAMユーザーを作成・権限付与をし、アクセスキーを払い出す必要があります。
ロールは以下の2つを付与します。

  • AmazonEC2ContainerRegistryFullAccess
  • AmazonEC2ContainerServiceFullAccess

作成したIAMユーザーのアクセスキーとシークレットアクセスキーは後ほど使うので、忘れないようにどこかに控えておきます。

configファイル作成

CircleCIの設定ファイルは、.circleci/config.ymlとして用意します。
このファイルを作成して、以下のように記述します。

config.yml
# circleciのバージョン。後述するorbsを利用するためには2.1以上が必要
version: 2.1

orbs:
    # circleci/aws-ecr@6.1.0というorbをaws-ecrというaliasをつけて扱う
    aws-ecr: circleci/aws-ecr@6.1.0
    aws-ecs: circleci/aws-ecs@0.0.8

workflows:
    # build_and_push_imageという名前のworkflowを定義
    build_and_push_image:
        # workflowで実行するjobの順番を定義
        jobs:
        - aws-ecr/build-and-push-image:
            region: AWS_REGION
            account-url: AWS_ECR_ACCOUNT_URL
            repo: 'cicdtest'
            tag: "${CIRCLE_SHA1}"
        - aws-ecs/deploy-service-update:
            requires:
                - aws-ecr/build-and-push-image
            family: 'testserver'
            cluster-name: 'circleciTest'
            service-name: 'CircleCItestService'
            container-image-name-updates: 'container=testserverContainer,tag=${CIRCLE_SHA1}'

設定内容について詳しく説明します。

CircleCI Orbsとは

本来ならば、CircleCIでのCI/CDを実現するためには、Githubへのpush確認後にどんな操作をするべきかというのを「コマンドベース」で指定していく必要があります。

例えば、今回のような「コードを元にコンテナイメージをビルド→ECRにpush」だったら、

  1. docker buildコマンドでコンテナイメージを作る
  2. docker loginでECRにログインする
  3. docker tagで1で作ったコンテナイメージに、AWS指定の名前・タグ付けを行う
  4. 3で作ったイメージをECRにdocker pushする

というように、いちいち何のコマンドを実行するのかをjobという形で定義しなくてはいけませんでした。

しかし、技術者・開発者がCircleCIでやりたい操作というのは皆似たり寄ったりです。そのため、みんながやりそうなjobについては「パッケージ」としてまとめて簡単に利用できるようにしよう、というのがOrbsです。

今回の場合は、「circleci/aws-ecr」と「circleci/aws-ecs」2つのOrbsを導入しています。

config.yml
orbs:
    aws-ecr: circleci/aws-ecr@6.1.0
    aws-ecs: circleci/aws-ecs@0.0.8

ただし、2つとも名前が長いので、それぞれ「aws-ecr」「aws-ecs」というエイリアスをつけて、以下のコードで簡単に名前を書けるようにしています。

参考:また車輪の再発明して消耗してるの?CircleCI Orbs使お?

workflowの作成

Orbsを用いて、CircleCIに自動でやって欲しい一連の処理(=workflow)について記述していきましょう。
今回は「build_and_push_image」という名前のworkflowを作成し、このworkflowでは2つのjobを順番に行ってもらうようにしました。

job1: aws-ecr/build-and-push-image

先ほど導入したOrbsのうち、aws-ecrの方で提供されている「build-and-push-image」というjobをまず行います。
これはその名の通り、pushされたコードからコンテナイメージをビルド→ECRにpushまでの一連の操作を行うjobです。
どのAWSアカウントのどのECRリポジトリにpushするかの設定を記述します。

config.yml
- aws-ecr/build-and-push-image:
    region: AWS_REGION
    account-url: AWS_ECR_ACCOUNT_URL
    repo: 'cicdtest'
    tag: "${CIRCLE_SHA1}"
  • region: AWSリージョンの指定。この後与える環境変数AWS_REGIONで値を渡す。
  • account-url: 使いたいECRアカウントの指定。環境変数AWS_ECR_ACCOUNT_URLで値を渡す。
  • repo: push先のECRリポジトリ名を指定。今回は先ほど作成したECRリポジトリ名cicdtestを指定。
  • tag: CircleCIがビルドしたコンテナイメージにどんなタグをつけるかを指定。今回は、commitごとにつくSHA1ハッシュの値をそのままタグにすることで、タグ重複を防止する。

job2: aws-ecs/deploy-service-update

導入したOrbsのうち、aws-ecsの方で提供されている「deploy-service-update」というjobを利用します。これで「ECSのタスク・サービスの更新」を自動でやってくれます。

設定内容は以下の通りです。

config.yml
- aws-ecs/deploy-service-update:
    requires:
        - aws-ecr/build-and-push-image
    family: 'testserver'
    cluster-name: 'circleciTest'
    service-name: 'CircleCItestService'
    container-image-name-updates: 'container=testserverContainer,tag=${CIRCLE_SHA1}'
  • require: aws-ecr/build-and-push-imageのjobをPASSしないとこのjobを実行しないようにする
  • family: 更新したいタスク名
  • cluster-name: 更新したいサービスがあるクラスター名
  • service-name: 更新したいサービス名
  • container-image-name-updates: familyで指定したタスクの中で、どのコンテナを更新するかを指定。ここでは、「testserverContainer」という名前で、「${CIRCLE_SHA1}」のタグがついているものという指定。

GitHubにリモートリポジトリを作成→CircleCIと連携

GitHubにリモートリポジトリを作り(名前は任意)、そこにコードをpushします。
その後、そのリポジトリと連携させたCircleCI projectを作成します。

CircleCIに環境変数を設定する

project作成後、CircleCIに以下の環境変数を設定します。

  • AWS_ACCESS_KEY_ID : さっき作成したIAMユーザーのアクセスキー
  • AWS_SECRET_ACCESS_KEY: さっき作成したIAMユーザーのシークレットアクセスキー
  • AWS_ACCOUNT_ID: 自分のAWSアカウントID(12桁の数字)
  • AWS_ECR_ACCOUNT_URL: [myaccountid].dkr.ecr.ap-northeast-1.amazonaws.com
  • AWS_REGION: ap-northeast-1

この環境変数の設定後、もう一度pipelineを実行すると、正しくCI/CDが行われます。

テスト実行をパイプラインに組み込む

せっかくのCI/CDなので、GitHubにpushしたら「コードテストを実行→テストにPASSしたときだけデプロイに移行」というフローに改良してみたいと思います。

テストコードを作成

main_test.goというファイルを作成し、以下のように記述します。

main_test.go
func TestMyHandler(t *testing.T) {
    reqBody := bytes.NewBufferString("request body")
    req := httptest.NewRequest(http.MethodGet, "http://localhost:8080", reqBody)

    got := httptest.NewRecorder()
    handler(got, req)

    if got.Code != http.StatusOK {
        t.Errorf("want OK, but %d", got.Code)
    }
    wantBody := "Hello"
    if got := got.Body.String(); !strings.Contains(got, wantBody) {
        t.Errorf("get %s : response body does not contain %s", got, wantBody)
    }
}

これで、「アクセス時にhttpレスポンスコード200が返ってくるか」「レスポンスボディに"Hello"という文字が含まれているか」がテストできるようになりました。
ディレクトリ直下でgo testコマンドを叩くことでテスト実行ができます。

configファイルの作成

テストを行うjobを新たに定義して、CircleCIのworkflowに組み込みます。
前述したconfig.ymlに追記してテストを組み込んだものがこちらです。

config.yml
version: 2.1

orbs:
    aws-ecr: circleci/aws-ecr@6.1.0
    aws-ecs: circleci/aws-ecs@0.0.8

# 追加、testという名前のjobを定義
jobs:
    test:
        docker:
            - image: circleci/golang:1.13
        working_directory: /go/src/github.com/myname/mydirectory
        steps:
            - checkout
            - run: go get -v -t -d ./...
            - run: go test -v ./...


workflows:
    build_and_push_image:
        jobs:
        - test  # 追加、デプロイ操作前にテストを実行
        - aws-ecr/build-and-push-image:
            requires:
                - test # 追加、テストに成功したときだけデプロイ操作に移るようにする
            region: AWS_REGION
            account-url: AWS_ECR_ACCOUNT_URL
            repo: 'cicdtest'
            tag: "${CIRCLE_SHA1}"
        - aws-ecs/deploy-service-update:
            requires:
                - aws-ecr/build-and-push-image
            family: 'testserver' # タスク名
            cluster-name: 'circleciTest'
            service-name: 'CircleCItestService'
            container-image-name-updates: 'container=testserverContainer,tag=${CIRCLE_SHA1}'

参考:CI/CDパイプライン – GitHub, CircleCIの連携とGCP(GCR)へのプッシュ

masterブランチへのpushのときだけデプロイされるように制限する

このままだと、どのリモートブランチにpushされたとしてもECSへのデプロイが行われてしまいます。つまり、「まだリリースできる段階じゃないけど、とりあえずブランチを切ってリモートにもpushしておかないと」というときにもデプロイが動いてしまいます。
そのため、「テストはどのブランチへのpushでも行う」「デプロイ操作はmasterへのmerge/pushのときだけ行う」という風に設定しておくことができれば素敵なパイプラインになります。

そのために、config.ymlに以下のように追記します。

config.yml
(略)
workflows:
    build_and_push_image:
        jobs:
        - test
        - aws-ecr/build-and-push-image:
            (略)
            filters:    # ここを追加
                branches:
                    only:
                    - master
        - aws-ecs/deploy-service-update:
            (略)
            filters:    # ここを追加
                branches:
                    only:
                    - master

これで、「aws-ecr/build-and-push-image」「aws-ecs/deploy-service-update」のjobはmasterへのpushのときのみ動くようになりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudFormation を使ってVPC + サブネット + EC2構成を作る

SysOps のWeb問題集を解いていたら、やたらとCloudFormation の問題が出てきました。
「これは実際にさわってみたほうがよさそうだな」と感じたので、やってみました:raised_hands:

「CloudFormation ってなんなの」という方は以下をご覧ください。
概要をつかむきっかけになれば、とてもうれしいです。
【AWS】CloudFormation についてざっくりまとめる:学習メモ

この構成をつくるぞ

aws-cfn.png

今回は諸事情(※)によりオハイオリージョンで作成します。
みなさま適宜お好きなリージョンでやってみてください。
※自社のsandbox環境で東京リージョンに作成しようとしたら、VPCの上限数に達していて作れなかった

事前準備①:テンプレートの用意

YAML / JSON どちらの形式でもだいじょうぶです。
コメントを入れられるという点でYAMLの方がいいかなと思うので、今回はYAMLにしました。

test-template.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: Test cfn Template

# ----------------------------------------------------------------
#     Parameters
# ----------------------------------------------------------------
Parameters:
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t2.small
      - t2.medium
    Description: Select EC2 instance type.
  KeyPair:
    Description: Select KeyPair Name.
    Type: AWS::EC2::KeyPair::KeyName


# ----------------------------------------------------------------
#     Resources
# ----------------------------------------------------------------

# --------------------  VPCの定義ここから --------------------
Resources:
  cfnVpc:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: '192.168.0.0/16'
      Tags:
        - Key: 'Name'
          Value: 'test-vpc'
# --------------------  VPCの定義ここまで --------------------

# --------------------  サブネットの定義ここから --------------------
  cfnSubnet:
    Type: 'AWS::EC2::Subnet'
    Properties:
      CidrBlock: '192.168.1.0/24'
      MapPublicIpOnLaunch: true
      Tags:
        - Key: 'Name'
          Value: 'test-cfn-subnet'
      VpcId: !Ref cfnVpc
# --------------------  サブネットの定義ここまで --------------------

# --------------------  ネットワーク周りの定義ここから --------------------
  cfnInternetGateway:
    Type: 'AWS::EC2::InternetGateway'
    Properties:
      Tags:
      - Key: 'Name'
        Value: 'test-cfn-igw'
  cfnAttachGateway:
    Type: 'AWS::EC2::VPCGatewayAttachment'
    Properties:
      VpcId: !Ref cfnVpc
      InternetGatewayId: !Ref cfnInternetGateway
  cfnRouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'test-cfn-rt'
      VpcId: !Ref cfnVpc
  cfnRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: cfnInternetGateway
    Properties:
      RouteTableId: !Ref cfnRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref cfnInternetGateway
  cfnSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref cfnSubnet
      RouteTableId: !Ref cfnRouteTable
# --------------------  ネットワーク周りの定義ここまで --------------------

# --------------------  EC2の定義ここから --------------------
  cfnEC2Instance:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: "ami-07c8bc5c1ce9598c3" # オハイオリージョンの最新のAmazon Linux 2 AMI にしています
      InstanceType: !Ref InstanceType
      SubnetId: !Ref cfnSubnet
      BlockDeviceMappings:
        - DeviceName: '/dev/xvda'
          Ebs:
            VolumeType: 'gp2'
            VolumeSize: 8
      Tags:
        - Key: 'Name'
          Value: 'test-cfn-ec2-instance'
      SecurityGroupIds:
        - !Ref cfnSecurityGroup
      KeyName: !Ref KeyPair
  cfnSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "cfnSecurityGroup"
      VpcId: !Ref cfnVpc
      Tags:
        - Key: 'Name'
          Value: 'test-cfn-ssh-sg'
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '22'
        ToPort: '22'
        CidrIp: 0.0.0.0/0
# --------------------  EC2の定義ここまで --------------------

※ 上記だとネットワークのセキュリティがゆるゆるなので、適宜修正してお使いください
※ 参考:AWS公式のサンプルテンプレートが多数公開されているようです

事前準備②:キーペアの作成

今回作成するEC2インスタンスにSSH接続できるようにしたいので、あらかじめキーペアを作っておきます。
「キーペアどこから作るんだっけ?」ってなっちゃったので、こちらを見つつ作りました。

作業手順

1. AWSコンソール にログイン

2. [CloudFormation] と入力し、Enterキーを押す

CloudFormation でスタックを作成する

1. [スタックの作成] をクリック

2. [スタックの作成] > [新しいリソースを使用 (標準)] をクリック
Screenshot 2020-08-19 22.51.54.png

ステップ1:テンプレートの指定

1. 以下を設定し、[次へ] をクリック
Screenshot 2020-08-19 22.52.09.png

  • テンプレートの準備:テンプレートの準備完了
  • テンプレートの指定:テンプレートのファイルのアップロード (事前に準備しておいたテンプレートを選択します)

ステップ2:スタックの詳細を指定

今回テンプレート内に[Parameters] を定義したため、パラメータ欄が表示されています。
EC2インスタンスタイプ・SSH接続する際に使うキーペアを選びます。

1. 任意のスタック名を入力し、[次へ] をクリック
Screenshot 2020-08-19 23.24.43.png

ステップ3:スタックオプションの設定

1. 任意の項目を入力し、[次へ] をクリック

ここでタグを設定しておくと、今回作成するリソース全部に同じタグが付くのでとても便利です:ok_woman:
(テンプレート内でいちいち書くよりも、ここで設定した方が楽)
私は社内のSandbox環境で実行したので、自分のものだとわかるように以下のタグを付けました。

  • キー:[Owner]
  • 値:自分の名前 Screenshot 2020-08-19 23.25.12.png

ステップ4:レビュー

1. 設定値に誤りがないか確認し、[スタックの作成] をクリック
Screenshot 2020-08-19 23.26.21.png

スタック作成中はこんな感じ

[イベント] 欄で作成の進捗状況を確認することができます。
Screenshot 2020-08-19 23.27.36.png

ステータスが[CREATE_COMPLETE] になれば完成です!

EC2インスタンスへのSSHログインもばっちり

以下のコマンドでSSHログインできます。

ssh -i [秘密鍵のパス] ec2-user@[EC2のIPv4パブリックIP]

Screenshot 2020-08-19 23.33.11.png

今回作ったやつを全部消したいんだけど?

スタックごと削除すれば、全部消えます。
地道に削除していかなくていいのでべんり。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Certificate Managerで長時間【検証保留中】となる原因

AWS Route 53でドメインを購入した。その後、AWS Certificate Manager(ACM)で証明書を発行しようとしたら、ACM側で1日以上検証保留中(pending)となってしまった。

本来なら数分から30分程度で成功するという記事も見たので、これは何かがおかしいと思い原因を調べた。

原因

ドメインのネームサーバーと、ホストゾーンのネームサーバーが異なっていた。

詳細

私はRoute 53が自動で作ったホストゾーンを削除し、新しくホストゾーンを手動で作り直してしまった。

ホストゾーンを作り直した際、レコード(タイプ:NS)に示されたネームサーバーと、ドメインに登録されたネームサーバーが異なっていた。これが原因だった。

私はTerraformで証明書を管理しようとして、ホストゾーンを何度も作り直していたので、このような事態に陥った。

解決方法

Route 53のコンソールに移動する。

左のメニューから「ホストゾーン」をクリック。該当のホストゾーンを選択し、そのレコード(NS)を見て、ネームサーバーを全てコピーする。

左のメニューから「登録済みドメイン」をクリック。「ネームサーバーの追加/編集」をクリック。そこで既存のネームサーバーをすべて削除し、先ほどコピーしたものに差し替える。

ほどなくして証明書のステータスが「成功」に代わるはず。

参考

AWSのDeveloper Guide

When you create a hosted zone, Route 53 automatically creates a name server (NS) record and a start of authority (SOA) record for the zone. The NS record identifies the four name servers that Route 53 associated with your hosted zone.

自動で作成されるホストゾーンには正しいネームサーバーが記録されている。そもそもそのホストゾーンを削除しなければこのような事態にはならないことがわかる。


redditの似た現象についてのスレッド

In my case, it turned out to be the mismatch in nameserver(NS) lists between the new hosted zone and the registered domain. Apparently, a new hosted zone is created with different NS list each time, so I've copied them into the one of my registered domain. Thanks though, this comment guided me to dig up there :)

本記事での解決方法はここから頂いた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CodeBuild で AWS CLI 2 を使う

はじめに

CodeBuild で使用できる AWS CLI のバージョンはデフォルトでは 1 です。
そのため、 --output yaml 等の一部のオプションが使用できません。
そこで、CodeBuild で AWS CLI のバージョンを 2 にアップデートする方法を調べました。

概要

Installing the AWS CLI version 2 on Linux に則り AWS CLI version 2 にアップデートするだけです。

buildspec.yml
version: 0.2

phases:
  install:
    commands:
      - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
      - unzip awscliv2.zip
      - ls -l /root/.pyenv/shims/aws
      - ./aws/install --bin-dir /root/.pyenv/shims --install-dir /usr/local/aws-cli --update
  build:
    commands:
      - aws --version

出力結果抜粋

[Container] 2020/08/20 06:25:10 Running command aws --version
aws-cli/2.0.41 Python/3.7.3 Linux/4.14.186-110.268.amzn1.x86_64 exec-env/AWS_ECS_EC2 exe/x86_64.ubuntu.18

補足

aws command のパスは以下の通り

[Container] 2020/08/20 06:25:07 Running command which aws
/root/.pyenv/shims/aws
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DRBDの性能検証(AWS編)

1.はじめに

オンプレでのHAクラスタをクラウド上で実現する際、単純には共有ディスク構成を作ることができません(2020.8)。一応、AWSではマルチアタッチを使用して複数インスタンスにEBSを割当てたり、Azureでも同様な機能は提供されてはいますが、制約もあるためそのまま共有ディスクの変わりというわけにはいかないようです。
※上記AWS/Azureいずれの機能も(アベイラビリティ)ゾーンを跨いだ構成は組めません。

img1.png

従って、共有ディスクを使わずに、ノード間でデータをリアルタイムに同期させて共有するミラーリング方式や、リアルタイムではなく、一定間隔でデータの同期をとるレプリケーション方式といった他のやり方を考える必要があります(その他にも、Cephなど分散ストレージを使うというのも一手かもしれません)。
それぞれの方式にはメリット・デメリットがありますが、ここでは「ミラーリング方式」について検討してみたいと思います。

ミラーリング方式では、複数箇所にデータを書込むため、1箇所に書込むよりオーバーヘッドが発生します(他方、読込みはどこか1箇所を参照するだけなので、読込み負荷は分散させることが可能です)。さらに、AWSなどパブリッククラウドで、AZを跨いだ場合には、物理的な距離が遠くなるため、書込み性能への影響が気になるところです。

本記事では、AWS上にDRBDというミラーリングソフトウェア(OSS/Active-Backup構成)を使った場合の書込み性能を調べてみたいと思います。

2. Disclaimer

本記事は、ツールを用いた測定のやり方の情報提供(メモ)が目的であり、性能測定の結果も、簡単に動かして得られた結果になります。測定結果の正確性、有用性などにつきましては、一切保証するものではない点ご了承ください。

3.システム構成

3-1.測定イメージ

測定は、下記の2パターンでの影響を試してみました。

  • [アプリケーション負荷テスト]PostgreSQLと、そのベンチマークツールpgbenchを使ったテスト
  • [ディスク負荷テスト]ディスク負荷ツールfioを使ったテスト

img2.png

3-2.AWS構成図

img3.png

3-3.ホスト情報

  • host1-3共通:

    • t2/medium
    • CentOS 8.2.2004
    • Linux version 4.18.0-193.6.3.el8_2.x86_64
  • host1:

    • IP アドレス: 172.16.1.50
    • ディスク:
      • /dev/xvda - OS
      • /dev/xvdb – DRBD (/dev/drbd0)
      • /dev/xvdc – DRBD (/dev/drbd1)
      • /dev/xvdd – ローカル
  • host2:

    • IP アドレス: 172.16.1.60
    • ディスク:
      • /dev/xvda - OS
      • /dev/xvdb – DRBD (/dev/drbd0)
  • host3:

    • IP アドレス: 172.16.2.50
    • ディスク:
      • /dev/xvda - OS
      • /dev/xvdb – DRBD (/dev/drbd1)

図にすると、このような感じになります。

img7.png

4.環境構築

4-1.OS準備

# dnf update
# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# dnf install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
# dnf install -y sysstat
# dnf install -y dstat
# dnf install -y fio

4-2.DRBDのインストール&セットアップ

DRBDパッケージのインストール

# dnf install -y kmod-drbd90
# dnf install -y drbd90

DRBDの設定

host1-host2間の同期設定。host1で作成し、host2へコピーします。

/etc/drbd.d/r0.res
resource r0{
  net {
   protocol C;
  }
  options {
  }
  on ip-172-16-1-50.ap-northeast-1.compute.internal {
    address 172.16.1.50:7789;
    device /dev/drbd0;
    disk /dev/xvdb;
    meta-disk internal;
  }
  on ip-172-16-1-60.ap-northeast-1.compute.internal {
    address 172.16.1.60:7789;
    device /dev/drbd0;
    disk /dev/xvdb;
    meta-disk internal;
  }
}

host1-host3間の同期設定。host1で作成し、host3へコピーします。

/etc/drbd.d/r1.res
resource r1{
  net {
   protocol C;
  }
  options {
  }
  on ip-172-16-1-50.ap-northeast-1.compute.internal {
    address 172.16.1.50:7790;
    device /dev/drbd1;
    disk /dev/xvdc;
    meta-disk internal;
  }
  on ip-172-16-2-50.ap-northeast-1.compute.internal {
    address 172.16.2.50:7790;
    device /dev/drbd1;
    disk /dev/xvdb;
    meta-disk internal;
  }
}

リソース作成と有効化

host1-host2間のリソース作成と有効化。host1, 2で実行します。

# drbdadm create-md r0
# drbdadm up r0

host1-host3間のリソース作成と有効化。host1, 3で実行します。

# drbdadm create-md r1
# drbdadm up r1

同期実行

下記はhost1のみで実施します。

// host1-host2間同期開始
# drbdadm primary --force r0
// host1-host3間同期開始
# drbdadm primary --force r1

// 同期中
# drbdadm status
r0 role:Primary
  disk:UpToDate
  ip-172-16-1-60.ap-northeast-1.compute.internal role:Secondary
    replication:SyncSource peer-disk:Inconsistent done:83.70

r1 role:Primary
  disk:UpToDate
  ip-172-16-2-50.ap-northeast-1.compute.internal role:Secondary
    replication:SyncSource peer-disk:Inconsistent done:73.31

// 同期完了
# drbdadm status
r0 role:Primary
  disk:UpToDate
  ip-172-16-1-60.ap-northeast-1.compute.internal role:Secondary
    peer-disk:UpToDate

r1 role:Primary
  disk:UpToDate
  ip-172-16-2-50.ap-northeast-1.compute.internal role:Secondary
    peer-disk:UpToDate

最後に、ファイルシステムを作成し、適当なディレクトリにマウントして置きます。

// ファイルスシステム作成
mkfs -t xfs /dev/drbd0
mkfs -t xfs /dev/drbd1
mkfs -t xfs /dev/xvdd

// マウント
mount /dev/drbd0 /mnt/drbd0-fs/
mount /dev/drbd1 /mnt/drbd1-fs/
mount /dev/xvdd /mnt/local-fs/

// 確認
# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G  8.0K  1.9G   1% /dev/shm
tmpfs           1.9G   17M  1.9G   1% /run
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/xvda2      8.0G  1.3G  6.7G  17% /
tmpfs           378M     0  378M   0% /run/user/1000
/dev/xvdd       100G  858M  100G   1% /mnt/local-fs
/dev/drbd0      100G  858M  100G   1% /mnt/drbd0-fs
/dev/drbd1      100G  826M  100G   1% /mnt/drbd1-fs

4-3.PostgreSQLのインストール&セットアップ

PostgreSQLのインストール

PostgreSQLは、CentOS標準リポジトリから、下記でインストールしました。今回は性能測定にpgbenchというツールを使うため、合せてそちらもインストールしておきます。

# dnf install -y postgresql
# dnf install -y postgresql-server
# dnf install -y postgresql-contrib  //pgbench用

セットアップ

次に、pgbenchを使うためのデータベースの設定を行います。今回は、1.AZ内レプリケーション(DRBD0)、2.AZ跨ぎレプリケーション(DRBD1)、3.ローカルディスクの3パターンで測定を実施するため、データベースは下記マウントしたファイルシステムをそれぞれ利用します。DRBDのセットアップ時に作成した、/mnt以下のディレクトリを確認します。

// mountポイント確認
# cd /mnt
//postgreSQLは、デフォルトpostgresユーザを利用するため、所有者とパーミッションを下記の通り変更します。
# chown -R postgres:postgres drbd0-fs drbd1-fs local-fs
# chmod -R 700 drbd0-fs drbd1-fs local-fs
// 結果はこんな感じになります
# ll
total 0
drwxr-xr-x 2 postgres postgres 6 Jul 26 04:06 drbd0-fs
drwxr-xr-x 2 postgres postgres 6 Jul 26 04:06 drbd1-fs
drwxr-xr-x 2 postgres postgres 6 Jul 26 04:08 local-fs

3つのデータベースは、今回はSystemdの設定を使って切替える事にしました(もっとうまい方法があるかと思いますが。。)。下記のようにUnit定義の中の「PGDATA」として3つ準備します。

/usr/lib/systemd/system/postgresql.service
(中略)
#Environment=PGDATA=/var/lib/pgsql/data
Environment=PGDATA=/mnt/drbd0-fs 
#Environment=PGDATA=/mnt/drbd1-fs
#Environment=PGDATA=/mnt/local-fs
(中略)

その後、上記各設定ファイルのコメントアウトを(1つずつ)削除し、下記コマンドを実行しデータベースの初期化を行います(3回実施することになります)。

# systemctl daemon-reload   #Unit定義更新
# postgresql-setup initdb   #データベース初期化

データベースのセットアップは以上になります。

5.アプリ性能測定(pgbench)

5-1.測定方法

こちらのサイトを参考に、pgbenchによる測定を行います。

このツールの特徴としましては、マニュアルによるとTCP-B(銀行のバッチ処理)を模したベンチマークとのことです。

pgbenchはPostgreSQL上でベンチマーク試験を行う単純なプログラムです。 これは同一のSQLコマンドの並びを何度も実行します。複数の同時実行データベースセッションで実行することもできます。 そして、トランザクションの速度(1秒当たりのトランザクション数)の平均を計算します。 デフォルトでpgbenchは、1トランザクション当たり5つのSELECT、UPDATE、INSERTコマンドを含むおおよそTPC-Bに基いたシナリオを試験します

# systemctl daemon-reload   #使うデータベース格納場所(PGDATA)をコメントアウトし、Unit定義を更新
# systemctl start postgresql.service   # データベース起動
# sudo su - postgres
$ createdb test   #testという名のデータベース作成
$ pgbench -i test   #pgbench用のテストデータをtestデータベースへロード
$ pgbench -c 10 -t 1000 -l test   #測定実行
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
latency average = 9.111 ms
tps = 1097.529558 (including connections establishing)
tps = 1097.770942 (excluding connections establishing)
$ exit   #postgresユーザから抜ける
# systemctl start postgresql.service   #データベース停止

上記より性能(TPS)は1097程度出ている事がわかります(PostgreSQLへの接続オーバーヘッド有り/無しで2パターンTPSは表示さる)。また、オプションとして「-l」を指定している事により実行後ローカルに「pgbench_log.1163」というトランザクション詳細結果ファイルが作成されます(詳細につきましては、上記サイトを確認ください)。これをデータベースを切替えてそれぞれ実行します。

5-2.測定結果(TPS&応答時間)

ざっくり、共有ディスク方式と比較した場合の処理性能(TPS)は、AZ内で62.5%(37.%減)、AZ跨ぎで26.9%(73.1%減)という結果となりました。

img6.png

6.ディスク性能測定(fio)

6-1.測定方法

ディスク性能測定に使えるベンチマークツールとしては、詳解 システム・パフォーマンスによると、dd、Bonnie、Bonnie++、iozone、tiobench、SysBench、fio、FileBenchなど多々ありますが、今回はfio(Flexible IO Tester)を使ってみました(著者のJens Axboe氏は同年代だそうで少し親しみもありますw)。高機能なのですが、全く使いこなせていないため、今後勉強していきたいと思います。。。

ジョブファイルという設定ファイルを設定し、カレントディレクトリに格納します。※各種詳細はこちら

fio設定ファイル

fio.conf
[global]
ioengine=libaio
iodepth=1
size=1g
direct=1
runtime=30
stonewall

[Seq-Write-1M]
bs=1m
rw=write

[Rand-Write-1M]
bs=1m
rw=randwrite

[Rand-Write-512K]
bs=512k
rw=randwrite

[Rand-Write-4K]
bs=4k
rw=randwrite

次に、負荷をかけている間のプロファイリングには「iostat」と「dstat」というツールを利用しました。Terminalを3つ立上げ、先にiostatとdstatを起動した上でfioを実行。fioの実行が終わったら、iostatとdstatをCtl+Cで止めます。fioの実行では、「--filename」オプションではディレクトリだけでなくデバイスも指定できるようです。

//Terminal1で実行
iostat -mx 1 | grep --line-buffered drbd0 |  awk '{print strftime("%y/%m/%d %H:%M:%S"), $0}' | tee iostat_drbd0.txt
//Terminal2で実行
dstat -t | tee dstat_drbd0.txt
//Terminal3で実行
fio --filename=/dev/drbd0 fio.conf

これを、drbd0、drbd1、ローカルディスクそれぞれで実行してプロファイルした結果は次の通りです。

6-2.測定結果(1)(スループット)

こちらはiostatでの集計結果になります。ブロックサイズとして1M、512K、4Kとバリエーション指定してみたのですが、残念ながらEC2インスタンスのネットワーク帯域の制限がかかってしまっているようで、1Mと512Kのブロックサイズ指定は有効ではなかったようです。。。(今回あまり考えずにt2.mediumタイプを選んだのが失敗でした。また、EBS自体もボリュームサイズによりIOPS制約が異なるため、次回は測定条件の見直しから必要だと反省)

4Kブロックの結果より、ローカルが性能が一番よく、続いてAZ内、AZ跨ぎの順番が確認できました。

img4.png

【注意】
今回の測定で、もう一点よく分からないことは、1Mと512Kのブロックサイズについて、IOPSがfioとiostatで結果が異なりました。いずれもスループットは60MB/sなのですが、iostatの方をみると、writeのブロックサイズは(fioで1Mや512Kを指定しているにも関わらず)128Kとなっていました(その結果、IOPSが500前後のグラフとなっています)。fioのレポートでは、IOPSは64となっているので、違いはなんだろう?と少し気になりました(4Kブロックの結果は一致しているのですが。。。)

●DRBD0のRAWデータの一部抜粋↓
img8.png

5-3.測定結果(2)(write待ち時間)

iostatの「w_await」結果はこのようになりました。

w_awaitの定義は、iostat manual↓になります。

The average time (in milliseconds) for write requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.

img5.png

7.まとめ

共有ディスク方式をDRBDを用いたミラーリング方式に変更し、AWS上に単純リフトした場合の性能を少し実験してみました。結果につきましては、要件次第で「この程度なら問題ないね」や、「ちょっと厳しいかも」など変わるかと思います。
また、アーキテクチャ見直しや(クラウドであればもう少しクラウドネイティブな等)、様々なレイヤにおけるチューニング方法もあり(RAIDを使うなど)、これをもって一概に「性能が悪くなる」と言えないところがエンジニアリングの楽しみかと思います。ではどうすれば良いのか、についきましては追々勉強していきたいと思います。

8. 測定データ

今回の測定結果(生データ)はこちらにあります。
https://github.com/t-tkm/drbd-perf-on-aws

9.参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

通常のCloudFormationテンプレートをServerless Frameworkで読み込んで実行する

きっかけ

AWS での Linux 踏み台ホスト作るときに、クイックスタートのテンプレートがあるのですが
できればServerless Frameworkで叩ける様にしたいと思ったけど
そのまま読み込めないのかなと探したら、素晴らしいプラグインあるじゃないですか!というこで記事に残しておく

AWS での Linux 踏み台ホスト - クイックスタート

このクイックスタートのソースコードを見る

Serverless Plugin Nested Stacks

https://www.serverless.com/plugins/serverless-plugin-nested-stacks

ネストされたスタックを通常のcloudformationとして記述し、それらをサーバーレスフレームワークと簡単に統合します。

いつものごとくインストール

$ npm install serverless-aws-nested-stacks --save-dev

serverless.ymlにプラグインとして、追加

serverless.yml
plugins:
  - serverless-aws-nested-stacks

customに、nested-stacksを記述

custom:
  nested-stacks:    
    location: nested-stacks # location:スタックファイルを配置するディレクトリ
                            # 1箇所しか指定できないので、ここにテンプレートを集めるしかない
    stacks:
      - id: VPCStack # Logical ID (Required)
                     # ${self:service}-${self:provider.stage}-VPCStack-XXXXXXXXXXXX
                     # この様なスタック名になる
        template: aws-vpc.template.yaml # テンプレートファイル名 (Required)
        enabled: true # optional flag for enabled/disabling substack
        timeout: 60 # Minutes before stack creation times out.
        parameters: # スタックに渡すパラメータを指定できる
          - AvailabilityZones: 'ap-northeast-1a,ap-northeast-1d'
          - KeyPairName: bastion_key
          - NumberOfAZs: '2'
          - PrivateSubnet1ACIDR: 10.0.0.0/19
          - PrivateSubnet2ACIDR: 10.0.32.0/19
          - PublicSubnet1CIDR: 10.0.128.0/20
          - PublicSubnet2CIDR: 10.0.144.0/20
          - VPCCIDR: 10.0.0.0/16
          - VPCTenancy: default
      - id: BastionStack # Logical ID (Required)
                         # 2つめのスタック
                         # ${self:service}-${self:provider.stage}-BastionStack-XXXXXXXXXXXX
                         # この様なスタック名になる
        template: linux-bastion.template # テンプレートファイル名 (Required)
        enabled: true # optional flag for enabled/disabling substack
        timeout: 60 # Minutes before stack creation times out.
        parameters: # スタックに渡すパラメータを指定できる
          - BastionAMIOS: Amazon-Linux2-HVM
          - BastionHostName: LinuxBastion
          - BastionBanner: 'Welcome! Bastion'
          - BastionInstanceType: t2.micro
          - BastionTenancy: default
          - EnableBanner: false
          - EnableTCPForwarding: false
          - EnableX11Forwarding: false
          - KeyPairName: bastion_key
          - NumBastionHosts: 1
          - PublicSubnet1ID: !GetAtt 
            - VPCStack
            - Outputs.PublicSubnet1ID
          - PublicSubnet2ID: !GetAtt 
            - VPCStack
            - Outputs.PublicSubnet2ID
          - QSS3BucketRegion: ap-northeast-1
          - QSS3BucketName: aws-quickstart
          - QSS3KeyPrefix: quickstart-linux-bastion/
          - RemoteAccessCIDR: 0.0.0.0/0
          - VPCID: !GetAtt 
            - VPCStack
            - Outputs.VPCID

実行すると、3つのスタックが作成される

  1. bastion-prod
  2. bastion-prod-VPCStack-XXXXXXXXXXXX
  3. bastion-prod-BastionStack-XXXXXXXXXXXX
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[失敗談] AWSでフリーゲームをやろうとしたけどできませんでした

やりたかったこと

フリーゲームが大好きなのですが。
Macにしたため、Windowsのゲームができず辛かった。
なので、AWS のEC2サービスを使ったwindowsサーバーでゲームしたいと思った。

 やったこと

AWSで t2.microというのが1年間無料枠で使えそうだったので選択。
「AWSでWindowsを立ち上げRDPで作業する方法(2018年版)」(https://qiita.com/peace098beat/items/0850a942e5843823b1bb)
を参考にさせていただき、windwosにリモート接続。

t2.micro はCPU 1GBで不安でしたが、ストレージ自体は10GBくらいは行けるので、フリーゲームをやる分には容量は大丈夫だと思いました。

ブラウザでつまづく

接続先のwindowsにはIEがあり、google choromeにデフォルトを変更しようとするが、IEがブロックしまくる設定になっている。
「googleサイトが危険です!」みたいなアラートがでまくる⇨安全サイトだよとaddしまくっていく。
Google Chromeダウンロード寸前までたどり着くも、「このファイルはダウンロードできませんよ!の警告」
⇨IE右上の歯車ボタン>セキュリティー>インターネット>download>fileをダウンロードに
⇨ダウンロードできた

フリーゲームが実行できない

「カイダン実ハ」というフリーゲームをダウンロード。。。文字化けしてて嫌な予感
実行しようとするも「このexeファイルは他のファイルと一緒に使うんじゃないの?」⇨実行しても変な画面がでるだけで実行できず

ギブアップ

おそらくですが、日本語のwindowsでないと厳しいのかもしれないと思います。
僕みたいにフリーゲーム好きでMacにすると辛いのですが、AWSのEC2サービスで乗り切れる方法がググっても出てこなかったので、解決策が見つかることを望みます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

クラウドサービスとは?

クラウドサービスは「どこ?」が分からないサービス

クラウドという言葉を耳にすると、多くの人が「クラウド=雲」を想像します。実は、この「雲」のイメージが先立ってしまい、クラウドの理解を妨げていることが多いようです。ここではまず一旦「雲」のことは忘れ、例えとして「ピザの宅配」を取り上げて、話をしてみます。

宅配ピザを注文するとき、大体の方は、自宅の郵便受けに入っていたピザ屋さんのチラシを見て、電話で注文します。30分もすると、バイクに乗ったピザ屋さんが箱入りのピザを届けてくれます。

ここにはちょっとした不思議があります。多くの人は、ピザが自宅に届けられるまで、ピザ屋さんを見ることがありません。自分が電話したピザ屋さんがどこにあるのか?どんな場所でピザが焼かれているのか?そういったことが分からないまま注文しています。

クラウドサービスは、このような、「どこにあるのか?」「どんな場所で作られているのか?」「どこの人が作業をしているのか?」が分からないけれども利用できるサービスのひとつです。私たちは「どこ?」が分からなくても、多くの商品やサービスを利用しています。

クラウドサービスとは?

クラウド(クラウド・コンピューティング)は、コンピューターの利用形態のひとつです。インターネットなどのネットワークに接続されたコンピューター(サーバー)が提供するサービスを、利用者はネットワーク経由で手元のパソコンやスマートフォンで使います。

クラウドの特長のひとつは、利用にあたって、コンピューター(サーバー)の所在地(どこ?)が意識されない点です。たとえるならば、雲(クラウド)の中にあるコンピューターを地上から利用しているようなイメージです。そして、クラウドの形態で提供されるサービスを「クラウドサービス」と言います。

従来のコンピューターの利用形態では、利用者は手元のパソコンの中にあるソフトウェアやデータを利用していました。しかしクラウドサービスでは、ネットワークを経由して、雲(クラウド)の中にあるソフトウェアやデータをサービスの形でつかうのです。

「どこ?」がわからないまま使っているクラウドサービスの例

クラウドサービスの代表的な例にはWebメールがあります。「Gmail」や「Yahoo!メール」などが有名です。これらのWebメールサービスは、サーバーがどこにあるかを意識させません。一般的なメールとどのように違うのかを、もう少し詳しく見てみましょう。

例えば、多くの会社ではメールサーバーを、自社の中や自社が利用しているデータセンターなどに持っていたり、レンタルのメールサーバーを利用していたりします。そしてメールを受送信・閲覧するためには、自分のパソコンにインストールしてある「Windows Liveメール」や「Outlook」や「Thunderbird」などのソフトウエアを使っています。

Webメールではまず、このようなソフトウエアを自分のパソコンにインストールする必要がありません。Webの閲覧に使用している「Internet Explorer」や「Chrome」などのブラウザーがあればサービスを利用できます。また、自前のメールサーバーを用意する必要もなく、ユーザー登録だけすれば、「どこにあるかは分からないが、どこかにあるだろうサーバーとメールソフト」を使って、メールの受送信や閲覧ができます。

このように、ネット上のどこかにあって仕事をしてくれているが、どこにあるかはよく分からないサービスを、クラウドと呼びます。

クラウドではないことが普通だったから、クラウドという言葉ができた

Webメールのような誰でも使っているサービスがクラウドなら、どうして今さら"クラウド"などという言葉が出きたのでしょうか?それは、これまでのパソコンやシステムの多くが"クラウド"ではなかったからなのです。特に、会社の業務に使っていたソフトウエアは、ほとんどがクラウドではありませんでした。

最も分かりやすい例として、エクセルやワードといったアプリケーションについて説明しましょう。これらのアプリケーション(ソフトウエア)は、どこにあるのでしょう?ほとんどの方は、自分のパソコンの中にあるとお答えになると思います。そして、そのアプリケーションで作った表やワープロ文章のデータも、パソコンやサーバの中など明確な場所に置いていると思います。この状態は、クラウドではありません。

最近、このような「クラウドでないサービス」も、クラウドにした方がメリットがあることがわかりはじめました。そのため、従来の「特定の場所にソフトウエアやデータを持つシステムの使い方」に対して、「どこか分からない場所にソフトウエアやデータを持つシステムの使い方」を、簡単に言い表すために、クラウドという言葉が使われはじめたのです。

※「クラウド」という言葉は、米Google社 エリック・シュミットCEOの2006年8月の発言に由来すると一般的に言われています。また、エンジニアたちがネットワーク図を作成する際に、ネット上のどこかにあるものを雲の絵を使って表わすからとも言われています。

引用元記事
https://jpn.nec.com/cloud/smb/column/01/index.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS RDSへのデータインポート

今回は、前回作成したAWS上のRDSにCSVデータのインポートを行った際の手順を以下に記載します。

前提

・前回作成したEC2インスタンスとRDSが起動されていること
・RDBにインポートしたいCSVファイルを作成されていること(※文字コードはUTF8であること)

CSVファイルをEC2に転送

① 前回作成したEC2インスタンスのパブリックIPアドレスをコピーしておきます。
EC2インスタンス
② 次に、rLoginで接続情報の設定を行い、EC2に接続します。(ここでは、rLoginを使用していますが、Tera Term等の他のターミナルソフトでも構いません。)
rLoginサーバ設定
rLoginクリップボード
③ EC2インスタンスに接続できたら、CSVファイルを格納するディレクトリを作成します。また、作成したディレクトリに移動します。

$ pwd
/home/ubuntu
$ mkdir csv
$ cd csv
/home/ubuntu/csv

④ rLoginのツールバーにある「転送」ボタンを押下します。
転送ボタン
⑤ 転送ダイアログが表示されますので、対象ファイルをドラッグして転送します。
転送ダイアログ
転送矢印
image-20200813160731100.png
⑥ EC2インスタンスにCSVファイルが転送されたことを確認します。
転送確認
以上で、EC2インスタンスへのCSVファイルの転送は終了です。

EC2インスタンスにMySQLクライアントをインストールし、RDSのMySQLデータベースに接続

① 以下のコマンドでMySQLクライアントをEC2インスタンスにインストールします。

$ sudo apt install mysql-client-core-5.7

インストール時に、"E:Unable to correct problems, you have held broken packages. "というエラーメッセージが表示された場合は、以下のコマンドを実行後、再度インストールを実行してください。

$ sudo apt-get autoclean
$ sudo apt-get clean all
$ sudo apt-get update

② RDSに作成したMySQL DBインスタンスのエンドポイントをコピーします。
RDSエンドポイント
③ 以下のコマンドでMySQLデータベースに接続します。

$ mysql -h RDSエンドポイント -P 3306 -u admin -p
Enter password: RDS作成時のパスワード

DB接続
以上で、MYSQLデータベースに接続できました。

データベース、テーブルを作成し、CSVを取り込む

① 以下のコマンドでデータベースを作成し、使用するデータベースを選択します。

mysql> CREATE DATABASE データベース名 DEFAULT CHARACTER SET utf8mb4;
mysql> use データベース名;

DB作成
② 続いて、テーブルを作成します。
tbl作成
③ テーブルを作成したら、EC2のCSVフォルダに転送したCSVファイルをMySQLデータベースに取り込みます。

$ load data local infile "/home/ubuntu/csv/ファイル名" into table テーブル名 fields terminated by ',';

データロード
以上で、RDSのMySQL DBインスタンスへのデータインポートが終了です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS EC2 AmazonLinux2 インスタンスの日時を日本に合わせる

目的

  • AWS EC2 AmazonLinux2のインスタンスにて日時設定を日本に設定する方法をまとめる

実施環境

  • ハードウェア環境(ssh接続元)
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • EC2インスタンス環境(ssh接続先)
項目 情報 備考
インスタンス種類 AmazonLinux2 こちらの方法で構築→AWS EC2 をMacで使ってみよう!

前提条件

  • 下記、または下記に準ずる方法でAWS EC2 AmazonLinux2インスタンスが作成されてること。
  • インスタンスに対しssh接続することができること。

前提情報

  • インスタンス内で保持している現在の日時データは下記コマンドで確認することができる。

    $ date
    

読後感

  • インスタンスが現在の日本時間を保持する様になる。

概要

  1. 設定ファイルのバックアップ
  2. 設定ファイルの修正とシンボリックリンクの作成
  3. cronの時間設定の変更
  4. 確認

詳細

  1. 設定ファイルのバックアップ

    1. 下記コマンドを実行して時刻設定ファイルのバックアップを作成する。

      $ sudo cp /etc/sysconfig/clock /etc/sysconfig/clock_org
      
  2. 設定ファイルの修正とシンボリックリンクの作成

    1. 下記コマンドを実行して時刻設定ファイルを開く

      $ sudo vi /etc/sysconfig/clock
      
    2. ZONE="UTC"#を用いてコメントアウトし下記の行を追記する。

      ZONE="Asia/Tokyo"
      
    3. 修正後のファイルの内容を下記に記載する。修正後保存して設定ファイルを閉じる。

      #ZONE="UTC"
      ZONE="Asia/Tokyo"
      UTC=true
      
    4. 下記コマンドを実行してシンボリックリンクを作成する。

      $ sudo ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
      
  3. cronの時間設定の変更

    1. 下記コマンドを実行してcronを再起動する。

      $ sudo systemctl restart crond.service
      
  4. 確認

    1. 下記コマンドを実行して設定が反映されていることを確認する。現在の日本の時間が出力されれば作業完了である。

      $ date
      
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSのARNからアカウントIDを抽出するワンライナー

概要

AWSのARNを基に正規表現を使用してアカウントIDを抽出します。
ググっても見つからない&なんだかんだ使う場面が多いのでメモ

スクリプト

echo <ARN> | sed -e 's/^.*::\([0-9]*\).*$/\1/'

実行結果

$ echo "arn:aws:iam::123456789012:role/one-liner-role" | sed -e 's/^.*::\([0-9]*\).*$/\1/'
123456789012
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSEC2でただrails sをするとこうなってしまう!解決策は・・・

ターミナル
[ec2-user@ip-172-31-38-149 fleamarket_sample_80d]$ rails s
Usage:
  rails new APP_PATH [options]

Options:
      [--skip-namespace], [--no-skip-namespace]              # Skip namespace (affects only isolated applications)
  -r, [--ruby=PATH]                                          # Path to the Ruby binary of your choice
                                                             # Default: /home/ec2-user/.rbenv/versions/2.6.5/bin/ruby
  -m, [--template=TEMPLATE]                                  # Path to some application template (can be a filesystem path or URL)
  -d, [--database=DATABASE]                                  # Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)
                                                             # Default: sqlite3
      [--skip-gemfile], [--no-skip-gemfile]                  # Don't create a Gemfile
  -G, [--skip-git], [--no-skip-git]                          # Skip .gitignore file
      [--skip-keeps], [--no-skip-keeps]                      # Skip source control .keep files
  -M, [--skip-action-mailer], [--no-skip-action-mailer]      # Skip Action Mailer files
      [--skip-action-mailbox], [--no-skip-action-mailbox]    # Skip Action Mailbox gem
      [--skip-action-text], [--no-skip-action-text]          # Skip Action Text gem
  -O, [--skip-active-record], [--no-skip-active-record]      # Skip Active Record files
      [--skip-active-storage], [--no-skip-active-storage]    # Skip Active Storage files
  -P, [--skip-puma], [--no-skip-puma]                        # Skip Puma related files
  -C, [--skip-action-cable], [--no-skip-action-cable]        # Skip Action Cable files
  -S, [--skip-sprockets], [--no-skip-sprockets]              # Skip Sprockets files
      [--skip-spring], [--no-skip-spring]                    # Don't install Spring application preloader
      [--skip-listen], [--no-skip-listen]                    # Don't generate configuration that depends on the listen gem
  -J, [--skip-javascript], [--no-skip-javascript]            # Skip JavaScript files
      [--skip-turbolinks], [--no-skip-turbolinks]            # Skip turbolinks gem
  -T, [--skip-test], [--no-skip-test]                        # Skip test files
      [--skip-system-test], [--no-skip-system-test]          # Skip system test files
      [--skip-bootsnap], [--no-skip-bootsnap]                # Skip bootsnap gem
      [--dev], [--no-dev]                                    # Setup the application with Gemfile pointing to your Rails checkout
      [--edge], [--no-edge]                                  # Setup the application with Gemfile pointing to Rails repository
      [--rc=RC]                                              # Path to file containing extra configuration options for rails command
      [--no-rc], [--no-no-rc]                                # Skip loading of extra configuration options from .railsrc file
      [--api], [--no-api]                                    # Preconfigure smaller stack for API only apps
  -B, [--skip-bundle], [--no-skip-bundle]                    # Don't run bundle install
  --webpacker, [--webpack=WEBPACK]                           # Preconfigure Webpack with a particular framework (options: react, vue, angular, elm, stimulus)
      [--skip-webpack-install], [--no-skip-webpack-install]  # Don't run Webpack install

このような表記になってしまいますが解決策は
rails s RAILS_ENV=production です。

以上。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む