ストリームからの記事

序章

オーケストレーションツールの助けを借りて、DevOpsの専門家はいくつかのAPI呼び出しを活用してスタックをデプロイできます。 Terraform は非常にシンプルでありながら強力なツールであり、スタックをコードとして記述し、 Git を使用して定義ファイルをコミットすることで、スタックを共有して最新の状態に保つことができます。 Terraformは、 HashiCorp Vagrant Packer Consulなどの人気のあるオープンソースツールの作成者によって作成されています。

Terraformは、物理サーバーや仮想サーバーから電子メールやDNSプロバイダーまで、インフラストラクチャを起動するための一般的な構成を提供します。 起動すると、Terraformは、構成の進化に応じてインフラストラクチャを安全かつ効率的に変更します。

このチュートリアルでは、 DigitalOcean Terraform Cloud-init [を使用して、完全に機能する洗練されたNode.jsアプリケーションの環境をセットアップする方法を示します。 Ubuntu 14.04では、およびPM2。 サンプルアプリケーションとして、を使用しますキャビン 、オープンソース React 戻ってきたによって開発されたNode.jsアプリケーション GetStream.io 。 最終的な出力は、機能が豊富でスケーラブルなソーシャルネットワークアプリになります。

まず、Terraformを使用して、事前定義された構成を使用してキャビンをデプロイします。 次に、その構成を深く掘り下げて、その機能を理解できるようにします。

DigitalOceanサーバーへのTerraformのインストールのみに関心がある場合は、DigitalOceanでTerraformを使用する方法を参照してください。

前提条件

このチュートリアルに従うには、次のものが必要です。

  • このチュートリアルでTerraformを使用して作成する2GBのUbuntu14.04サーバー1台。
  • ローカルマシンにインストールされているGitクライアント。
  • キャビンはログインにFacebookを使用するため、Facebookアカウント。Facebookアプリケーションを作成できます。
  • などのドメイン cabin.example.com; このドメインをステップ4で取得するIPv4アドレスにポイントし、FacebookのサイトURLにこれが必要になります。

必須ではありませんが、このチュートリアルは、Streamのキャビンチュートリアルシリーズを完了していることを前提としています。 キャビンの機能に不可欠な役割を果たすため、キャビンが本番環境で機能するために必要ないくつかのプロバイダーのAPIキーと設定が必要になります。

これらのキーを取得しなくても、このチュートリアルは引き続き機能します。 Terraformを使用してキャビンアプリケーションをプロビジョニングおよびデプロイすることはできますが、必要なすべてのコンポーネントを構成するまで、アプリケーションは使用できません。

これらのサービスの詳細については、Streamの次のブログ投稿にアクセスしてください。

ステップ1—サンプルアプリケーションを入手する

キャビンサンプルアプリケーションをGitHubから、ローカルマシン上の選択したディレクトリにクローンします。 私たちはMacを使用していますが、あなたもそうだと思います。

まず、ホームディレクトリに移動します。

  1. cd ~

次に、 git リポジトリのクローンを作成するには:

  1. git clone https://github.com/GetStream/stream-react-example.git

これにより、サンプルアプリケーションがという新しいフォルダに複製されます。 stream-react-example. に移動します stream-react-example/terraform/do/cabin キャビンのテラフォームプロジェクトを含むフォルダ。

  1. cd stream-react-example/terraform/do/cabin

このフォルダについては、後ほど説明します。 しかし、最初に、Terraformを設定しましょう。

ステップ2—Terraformをインストールする

OSXに簡単にインストールするには、次のコマンドを発行してHomebrewを使用してTerraformをインストールできます。

  1. brew install terraform

または、http://terraform.ioからTerraformをダウンロードすることもできます。 ダウンロードしたら、以下に示すように、コマンドパスで使用できるようにします。

  1. PATH=location/of/terraform:$PATH

これにより、一時的にTerraformがパスに追加されます。 この変更を永続的にする場合は、ファイルを編集します ~/.bash_profile OSXで、次の行を追加します。

〜/ .bash_profile
export PATH=location/of/terraform:$PATH

次に、Terraformが正しくインストールされていることを確認するには、次のコマンドを実行します。

  1. terraform

Terraformのオプションを示す次の出力が表示されます。

Output
usage: terraform [--version] [--help] <command> [<args>] Available commands are: apply Builds or changes infrastructure destroy Destroy Terraform-managed infrastructure fmt Rewrites config files to canonical format get Download and install modules for the configuration graph Create a visual graph of Terraform resources init Initializes Terraform configuration from a module output Read an output from a state file plan Generate and show an execution plan push Upload this Terraform module to Atlas to run refresh Update local state file against real resources remote Configure remote state storage show Inspect Terraform state or plan taint Manually mark a resource for recreation untaint Manually unmark a resource as tainted validate Validates the Terraform files version Prints the Terraform version

Terraformがインフラストラクチャを開始する前に、次の2つの設定を行う必要があります。

  1. DigitalOceanトークン
  2. SSHキーペア

それでは、最初にDigitalOceanトークンを処理しましょう。

ステップ2—DigitalOceanアクセストークンの構成

Terraformは、DigitalOcean APIを使用するために、DigitalOceanアクセストークンを必要とします。

DigitalOceanアカウントにログインし、APIリンクをクリックします。 次に、新しいトークンの生成ボタンをクリックします。 書き込みアクセスを必ず確認してください。 ページに再度アクセスするとキーが表示されないため、ユーザーインターフェイスに新しいアクセスキーが表示されます。これをクリップボードにコピーする必要があります。

ファイルを開きます variables.tf お気に入りのテキストエディタを使用して、 token セクション:

変数.tf
variable "token" {
  description = "DO Token"
}

テキストで始まる新しい行を追加します default = DigitalOceanAPIトークンを含めます。 トークンを引用符で囲むことを忘れないでください。

変数.tf
variable "token" {
  description = "DO Token"
  default = "57eaa5535910eae8e9359c0bed4161c895c2a40284022cbd2240..."
}

ファイルを保存して閉じます。

次に、SSHキーペアを使用するようにTerraformを構成しましょう。

ステップ3—SSHキーペアを追加する

Terraformは、作成後にサーバーに接続するためにSSHキーを必要とします。これにより、Terraformはパッケージをインストールし、アプリケーションをデプロイできます。

あなたを見てください ~/.ssh すでにキーペアがあるかどうかを確認するディレクトリ:

  1. ls -al ~/.ssh

ほとんどの場合、秘密鍵と公開鍵で構成される少なくとも1つの鍵ペアがあります。 たとえば、 id_rsa.pubid_rsa.

警告:既存のキーペアがすでにDigitalOceanアカウントに関連付けられている場合は、競合を避けるために、DigitalOceanダッシュボードを使用して削除するか、新しいキーペアを生成する必要があります。

キーペアがない場合、または持っているキーがすでにDigitalOceanアカウントに関連付けられている場合は、SSHキーの設定に関するDigitalOceanのチュートリアルを参照して設定してください。

内容を貼り付ける必要があります .pub ファイルに variables.tf APIトークンで行ったのと同じようにファイル。 Macを使用している場合は、次のコマンドを発行してSSH公開鍵をクリップボードにコピーできます。

  1. pbcopy < ~/.ssh/your_key.pub

公開鍵の内容を画面に表示することもできます cat コマンドを実行し、クリップボードに手動でコピーします。

  1. cat ~/.ssh/your_key.pub

次に、ファイルを開きます variables.tf エディタで、SSH公開鍵ファイルのコンテンツをに追加します sshkey 設定:

変数.tf
variable "sshkey" {
  description = "Public ssh key (for Cabin user)"
  default = "ssh-rsa AAAAB3NzaC1yc2EAAAADA...== [email protected]"
}

この手順を完了したら、ファイルを保存して終了します。

TerraformとDigitalOceanで使用する新しいキーを生成した場合は、次の2つのコマンドを実行して、デフォルトのキーの代わりに新しいキーが使用されるようにする必要があります。

  1. eval "$(ssh-agent -s)"
  2. ssh-add ~/.ssh/your_id_rsa

代替キーペアを使用している場合は、新しいシェルを開くたびにこれを実行する必要がある場合があります。

Terraformに必要な変数を提供したので、サーバーを作成し、Terraformを使用してアプリをデプロイする準備が整いました。

ステップ4—Terraformを実行する

ここに楽しい部分があります! 構築するインフラストラクチャを見てみましょう。 Terraformは、サーバーのセットアップからアプリのデプロイまで、多くの作業を行います。 次のコマンドを使用して、Terraformに正確に何を実行するかを表示させることができます。

  1. terraform plan

このコマンドの出力は非常に冗長なので、次のステートメントに注目してください。

Output
+ digitalocean_droplet.cabin-web ... + digitalocean_floating_ip.cabin-web-ip ... + digitalocean_ssh_key.cabin-ssh-key ... + template_file.pm2_processes_conf ... + template_file.userdata_web ...

行頭の「+」記号は、リソースが作成されることを意味します。 接頭辞が付いたリソース digitalocean DigitalOceanで作成されるリソースです。 この特定のケースでは、TerraformはDroplet、予約済みIPを作成し、SSHキーを追加します。

警告お客様のインスタンスまたはサードパーティのサービスがオンラインである間に発生する可能性のある料金について、当社は責任を負いません。 コマンド terraform apply 2GBのRAM(〜$ 0.03 /時間)とDigitalOceanが無料で提供する予約済みIPを備えたドロップレットを作成します。 正確な数値については、DigitalOceanのWebサイトで更新された価格を再確認してください。

次に、Terraformを実行し、ドロップレットでキャビンをスピンアップします。

  1. terraform apply

しばらくすると、Terraformが次のように出力します。

Output
Apply complete! Resources: 6 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: terraform.tfstate Expected output: web_ipv4 = 111.111.111.111

web_ipv4 ドロップレットへのアクセスに使用できる予約済みIPアドレスです。

次の値を使用して、新しく作成されたドロップレットにログインします。 web_ipv4:

  1. ssh cabin@your_value_for_web_ipv4

コマンドを使用することもできます

  1. terraform output web_ipv4

見逃した場合は、その値に関連付けられたIPアドレスを表示します。

ログインすると、次のウェルカムメッセージが表示されます。

   _____      _     _
  / ____|    | |   (_)
 | |     __ _| |__  _ _ __
 | |    / _` | '_ \| | '_ \
 | |___| (_| | |_) | | | | |
  \_____\__,_|_.__/|_|_| |_|

Initializing Cabin. Please wait... (up 1 minute) | CTRL+C to interrupt

DigitalOceanがインスタンスをプロビジョニングし、 cloud-init キャビンに必要なパッケージをインストールします。 しかし、準備ができたら、次のように表示されます。

Cabin initialized!
Check running processes...
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid   │ status │ restart │ uptime │ memory      │ watching │
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ api      │ 0  │ fork │ 14105 │ online │ 0       │ 36s    │ 75.898 MB   │  enabled │
│ app      │ 1  │ fork │ 14112 │ online │ 0       │ 36s    │ 34.301 MB   │  enabled │
│ www      │ 2  │ fork │ 14119 │ online │ 0       │ 36s    │ 50.414 MB   │  enabled │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

キャビンが起動して実行されたら、モバイルブラウザで http://your_value_for_web_ipv4. キャビンはライブで、ロード画面が表示されます。 しかし、サーバー上のコードにいくつかの変更を加えるまでは、これで十分です。

ステップ5—(オプションで)キャビンの構成

キャビンアプリケーションはデプロイされていますが、まだ使用できません。 キャビンを完全に機能させるには、Facebookやその他のいくつかのサービスを構成する必要があります。

まず、次のような有効なドメイン名を使用してFacebookアプリを作成する必要があります。 cabin.example.com にマッピングされます web_ipv4 インストールプロセス中に生成されたアドレス。 DNSにレコードを追加するか、DNSにエントリを追加します /etc/hosts ドメインをIPアドレスにマップするファイル。

Facebookアプリを作成するには、次の手順に従います。

  1. https://developers.facebook.com/docs/apps/register#step-by-step-guideにアクセスします。
  2. Facebookにログインします。
  3. [マイアプリ]で、新しいアプリを追加をクリックします。
  4. アプリケーションの名前を入力します(例: Cabin - My Example App).
  5. 連絡先メールアドレスを入力してください。
  6. カテゴリの場合、ドロップダウンメニューを使用してアプリのカテゴリを選択します。 私たちの場合、それはライフスタイルです。
  7. アプリIDの作成ボタンをクリックします。
  8. 必要に応じて、キャプチャを完了します。
  9. をコピーします appId. 画面上部にある数値になります。 すぐに必要になります。
  10. 左側のサイドバーからダッシュボードを選択します。
  11. Facebook SDKの使用開始という見出しの下で、プラットフォームの選択をクリックします。
  12. プラットフォームにはWebを選択します。
  13. サイトのURLフィールドを見つけて、次のように入力します http://cabin.example.com.
  14. 次へをクリックします。

問題が発生した場合は、このステップバイステップガイドに従うことができます。 行き詰まった場合は、Facebookでのアプリケーション設定のデバッグに関するすばらしい記事があります。これはここにあります。

あなたがあなたを持ったら appID デフォルトを置き換える必要があります appID サーバーの設定。

したがって、サーバーにログインしていることを確認してください。 そうでない場合は、次のコマンドで再度ログインしてください。

  1. ssh cabin@your_value_for_web_ipv4

ログインしたら、ファイルを開きます ~/stream-react-example/app/views/index.ejs:

  1. nano ~/stream-react-example/app/views/index.ejs

デフォルトを変更する appId Facebookが提供するもので。

strea-react-example / app / views / index.ejs
FB.init({
    appId   : 'your_facebook_app_id',
    xfbml   : true,
    version : 'v2.6',
    status  : true,
    cookie  : true,
})

このファイルを保存して閉じます。

次に、サーバーの作成時にTerraformによって生成されたCabinのデータベースパスワードを知る必要があります。 この値を取得するには、次のコマンドを入力します。

  1. grep DB_PASSWORD processes.yml

このパスワードをコピーします。 すぐに必要になります。

ファイル env.sh ここで、キャビンが依存するさまざまなプロバイダーとサービスのクレデンシャルを入力します。 このファイルは、これらのクレデンシャルを環境変数に配置し、アプリケーションによって読み取られます。 これは、パスワードとキーをGitに入れないようにするため、セキュリティ上の予防措置です。

開ける env.sh:

  1. nano env.sh

次のコンテンツが表示されます。

Output
export NODE_ENV=production export JWT_SECRET=ABC123 export DB_USERNAME=cabin export DB_HOST=localhost export DB_PASSWORD=VALUE export DB_PORT=3306 export MAPBOX_ACCESS_TOKEN=ADD_VALUE_HERE export S3_KEY=ADD_VALUE_HERE export S3_SECRET=ADD_VALUE_HERE export S3_BUCKET=ADD_VALUE_HERE export STREAM_APP_ID=ADD_VALUE_HERE export STREAM_KEY=ADD_VALUE_HERE export STREAM_SECRET=ADD_VALUE_HERE export ALGOLIA_APP_ID=ADD_VALUE_HERE export ALGOLIA_SEARCH_ONLY_KEY=ADD_VALUE_HERE export ALGOLIA_API_KEY=ADD_VALUE_HERE export KEEN_PROJECT_ID=ADD_VALUE_HERE export KEEN_WRITE_KEY=ADD_VALUE_HERE export KEEN_READ_KEY=ADD_VALUE_HERE export IMGIX_BASE_URL=https://react-example-app.imgix.net/uploads export API_URL=http://localhost:8000

ご覧のとおり、このファイルは、キャビンが必要とするさまざまなサービスに関する情報を保持する一連の環境変数をエクスポートします。 キャビンが本番環境で機能するためには、これらの値をすべて入力する必要があります。

これらの設定の簡単な内訳は次のとおりです。

  1. NODE_ENV :Node.jsが実行される環境。 (本番環境では速度が向上します)。
  2. JWT_SECRET :APIとWeb(アプリ)インターフェース間のJSONWebトークン認証の認証シークレット。
  3. DB_USERNAME :データベースのユーザー名。
  4. DB_HOST :データベースのホスト名。
  5. DB_PASSWORD :データベースのパスワード。 processes.yml.
  6. DB_PORT :データベースポート(MySQLのデフォルトポート3306)。
  7. MAPBOX_ACCESS_TOKEN :MapBoxのアクセストークン(写真の場所をマッピングするため)。
  8. S3_KEY :画像ストレージ用のAmazonS3キー。
  9. S3_SECRET :画像ストレージ用のAmazonS3シークレット。
  10. S3_BUCKET :画像ストレージ用のAmazonS3バケット。 このバケットが存在することを確認してください。
  11. STREAM_APP_ID :ストリームアプリID。 必要なすべてのフィードグループが、このIDに関連付けられたアプリに存在することを確認してください。
  12. STREAM_KEY :ストリームAPIキー。
  13. STREAM_SECRET :ストリームアプリシークレット。
  14. ALGOLIA_APP_ID :検索用のAlgoliaアプリID。
  15. ALGOLIA_SEARCH_ONLY_KEY :アルゴリアは検索用のキーのみを検索します。
  16. ALGOLIA_API_KEY :検索用のAlgoliaAPIキー。
  17. KEEN_PROJECT_ID :鋭い追跡プロジェクトID(統計用)。
  18. KEEN_WRITE_KEY :キーントラッキング書き込みキー(統計用)。
  19. KEEN_READ_KEY :キーントラッキング読み取りキー(統計用)。
  20. IMGIX_BASE_URL :ImgixベースURL(特定のサイズで写真をレンダリングするため)。
  21. API_URL :このアプリケーションがAPIに使用するURL。 これをから変更する必要があります localhost IPアドレスを指すドメイン(例: cabin.example.com.

参照される環境変数とサービスの詳細については、次のブログ投稿にアクセスし、各アプリケーションが指定どおりに構成されていることを確認してください。

すべてのプロバイダーを構成したら、データベースのパスワードとプロバイダーの値をに入力します。 env.sh ファイル。

終了して保存します env.sh ファイル。 次に、ファイルをソースし、Cabinが使用する環境値に値をロードします。

  1. source ./env.sh

次に、を実行する必要があります webpack 指図。 Webpackは、キャビンのフロントエンドコードを管理するJavaScriptビルドツールです。 Webpackは、によって設定された値に基づいてJavaScriptおよびCSSファイルを再生成します。 env.sh 変更したばかりのファイル。 だから、に変更します app ディレクトリ:

  1. cd app

そして、 webpack フロントエンドJavaScriptファイルを再構築するコマンド。 これにより、プロバイダートークンの一部がフロントエンドコードに挿入されます。

  1. webpack --progress --color

次の出力が表示されます。

Output
Hash: 64dcb6ef9b46a0243a8c Version: webpack 1.13.1 Time: 21130ms Asset Size Chunks Chunk Names ./public/js/app.js 2.22 MB 0 [emitted] app ./public/css/styles.css 23 kB 0 [emitted] app [0] multi app 28 bytes {0} [built] + 685 hidden modules Child extract-text-webpack-plugin: + 2 hidden modules Child extract-text-webpack-plugin: + 2 hidden modules

設定が整ったら、PM2を実行してすべてのアプリケーションプロセスをリロードし、すべてのコンポーネントが新しい設定を使用するようにします。

  1. pm2 restart all
Output
[PM2] Applying action restartProcessId on app [all](ids: 0,1,2) [PM2] [api](0) ✓ [PM2] [app](1) ✓ [PM2] [www](2) ✓ ┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────────────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │ ├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────────────┼──────────┤ │ api │ 0 │ fork │ 30834 │ online │ 516 │ 0s │ 39.027 MB │ enabled │ │ app │ 1 │ fork │ 30859 │ online │ 9 │ 0s │ 22.504 MB │ enabled │ │ www │ 2 │ fork │ 30880 │ online │ 9 │ 0s │ 19.746 MB │ enabled │ └──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────────────┴──────────┘

それでおしまい! これで、リモートサーバーからログアウトできます。

  1. exit

最後に、 http://your_value_for_web_ipv4 もう一度ブラウザでサイトを表示します。 これにより、Facebookにログインするためのリンクを含むカバー画像が表示されます。 ログインすると、後でアプリを探索できるようになります。

PM2はキャビンのプロセスを管理し、問題のデバッグに役立つ優れたツールになる可能性があります。 使用できます pm2 list アプリケーションのコンポーネントのステータスを確認し、 pm2 logs アプリのログのストリームを表示します。これは、構成エラーの診断に役立ちます。

それでは、この展開を可能にしたTerraform構成について詳しく見ていきましょう。

ステップ6—構成タイルを調べる

では、これはどのように機能しますか? ローカルマシンに複製したリポジトリ内のファイルを見てみましょう。 このセクションで変更することは何もありませんが、ピースがどのように組み合わされているかを感じることができるように、自分のマシンをフォローする必要があります。

Terraformプロジェクトは、アプリケーションをクリーンで理解しやすい状態に保つために、複数のファイルとディレクトリに分割されています。 すべてのDigitalOceanファイルを内部に配置しました terraform/do 次の構造を持つリポジトリのディレクトリ:

terraformフォルダー
do
└── cabin
    ├── files
    │   ├── cabin-web-nginx.conf
    │   └── cabin_mysql_init.sh
    ├── main.tf
    ├── outputs.tf
    ├── templates
    │   ├── processes.tpl
    │   └── web.tpl
    └── variables.tf

上記のファイルを見てみましょう。 main.tf. お気に入りのテキストエディタで開きます。

最初に行うことは、使用するクラウドプロバイダーをTerraformに通知することです。

main.tf
provider "DigitalOcean" {
  token = "${var.token}"
}

DigitalOceanプロバイダーの定義はそれと同じくらい簡単です。 サポートされているプロバイダーの完全なリストは、Terraformのドキュメントにあります。

可変構成

Terraformを使用すると、変数を定義できます。つまり、デプロイメントのデフォルトを設定できます。 そうすれば、毎回詳細を入力したり、構成全体で値をハードコーディングしたりする必要がなくなります。 DigitalOceanにデプロイするための変数を設定する方法を見てみましょう。

見て variables.tf、キャビンアプリケーションの実行に必要な変数を定義した場所。

変数.tf
variable "token" {
  description = "DO Token"
}

variable "region" {
  description = "DO Region"
}

Terraform内で変数がどのように処理されるかをよりよく理解するために、上記の例を見てみましょう。

領域変数には、デフォルト値を指定しました。 デフォルト値を指定しない場合、次の例に示すように、Terraformはデフォルト値の入力を求めます。

Output
terraform plan var.token DO Token Enter a value:

実行時に変数を指定することもできます terraform apply. たとえば、別の地域を指定したい場合は、Terraformを次のように実行できます。 var 口論:

  1. terraform -var 'region=ams3' apply

これにより、構成された設定が上書きされます。

ドロップレットの設定

main.tf DigitalOceanにドロップレットをプロビジョニングするようにTerraformに指示します。 デフォルトでは、次の特性を持つサーバーをデプロイします。

main.tf
resource "digitalocean_droplet" "cabin-web" {
  image = "ubuntu-14-04-x64"
  name = "cabin-web"
  region = "${var.region}"
  size = "2gb"
  ssh_keys = [ "${digitalocean_ssh_key.cabin-ssh-key.id}" ]
  user_data = "${template_file.userdata_web.rendered}"
}

Cabin-web と呼ばれる2GBのRAMを備えた新しいDigitalOceanドロップレットを作成し、イメージubuntu-14-04-x64を使用しています。 上記のリソース定義を見ると、サーバーのイメージとサイズを簡単に変更できることがわかります。

ユーザーデータとクラウド-Init

さて、正確には何ですか user-data? これは、起動時にクラウドインスタンスにコマンドと命令を送信する最も簡単な方法です。 と相まって cloud-initChefPuppetなどの不要なサードパーティアプリケーションを利用せずに、インスタンスを構成するための強力な方法になります。

The cloud-init プログラムは多くのLinuxディストリビューションに組み込まれています。 これには、ユーザーの追加、グループの管理、ファイルの作成、root権限を持つスクリプトまたはシェルコマンドの実行などの簡単なタスクを実行できる小さな一連の命令が含まれています。

に飛び込みましょう user_data 属性を使用すると、それが何であるかをよりよく理解できます。

main.tf
resource "digitalocean_droplet" "cabin-web" {
  ...
  user_data = "${template_file.userdata_web.rendered}"
}

私たちの目標は、キャビンを稼働させた状態で新しいドロップレットを開始し、 cloud-init 私たちのために重い物を持ち上げてください。 The user_data フィールドはテンプレートファイルを指し、変数は別の宣言を指します。 main.tf:

main.tf
resource "template_file" "userdata_web" {
  template = "${file("${path.module}/templates/web.tpl")}"

  vars {
    userdata_sshkey = "${var.sshkey}"
    userdata_nginx_conf = "${base64encode(file("${path.module}/files/cabin-web-nginx.conf"))}"
    userdata_mysql_init = "${base64encode(file("${path.module}/files/cabin_mysql_init.sh"))}"
    userdata_pm2_conf = "${base64encode("${template_file.pm2_processes_conf.rendered}")}"
    userdata_env = "${base64encode("${template_file.env.rendered}")}"
    userdata_motd = "${base64encode(file("${path.module}/files/motd"))}"
    userdata_motd_script = "${base64encode(file("${path.module}/files/motd.sh"))}"
    userdata_giturl = "${var.git_url}"
    userdata_index = "${base64encode(file("${path.module}/files/index.html"))}"
  }
}

Terraformは、テキストを変換できる関数を提供します。 この機能を使用して、ファイルを読み取り、コンテンツをBase64でエンコードされた文字列に変換して、API呼び出しを介して値を転送できるようにすることで、値をテンプレートに挿入できます。

この特定のセクションでは、テンプレートのデータを準備します templates/web.tpl これには、サーバーで実行するすべての設定とコマンドが含まれています。

を歩きましょう web.tpl ファイルして、それが何をするかを見てください。

最初の部分では、初期ユーザーを設定し、ルートアクセスを無効にします。

テンプレート/web.tpl
#cloud-config
users:
  - name: cabin
    groups: sudo
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    shell: /bin/bash
    home: /home/cabin
    lock_passwd: true
    ssh-authorized-keys:
      - ${userdata_sshkey}

disable_root: true

の最初のステートメント web.tpl でなければなりません #cloud-config. これを追加するのを忘れた場合は、 cloud-init は構成を取得せず、指定されたコマンドはターゲットインスタンスで実行されません。

このセクションのコマンドは次のことを行います。

  • 追加します cabin スーパーユーザーになるための助成金を持ったシステムへのユーザー
  • lock-passwd: true パスワード認証を拒否するため、 cabin ユーザーは、サーバーにアクセスするためにSSHキー認証を使用する必要があります。
  • ssh-authorized-keys ユーザーのssh-keyをauthorized_keysファイルにインストールします。
  • disable_root: true ルートとしてのSSHアクセスを無効にするために使用されます

それを覚えておいてください ${userdata_sshkey} でテンプレートを呼び出したときに設定された変数です main.tf.

次に、MySQL、Nginx、Git、およびアプリケーションに必要なその他のパッケージをインストールします。

package_update: true
packages:
 - mysql-server-5.6
 - libmysqlclient-dev
 - iptables-persistent
 - git
 - nginx
 - npm
 - pwgen

でパッケージをインストールする最も簡単な方法 cloud-init パッケージモジュールを利用して、特定のパッケージのリストをインストールします。 このモジュールは、ディストリビューションにデフォルトのパッケージマネージャーを使用します。 Ubuntuを使用しているため、このプロセスでは次のパッケージがインストールされます apt.

次に、テンプレートに渡したデータをファイルコンテンツとして使用して、いくつかのファイルをファイルシステムに書き込みます。

write_files:
 - encoding: b64
   content: ${userdata_nginx_conf}
   path: /tmp/cabin-web.conf
 - encoding: b64
   content: ${userdata_pm2_conf}
   path: /tmp/processes.yml
 - encoding: b64
   content: ${userdata_mysql_init}
   path: /tmp/cabin_mysql_init.sh
   permissions: '0554'

このセクションでは、 write_file ファイルを作成するモジュール。 上記の例では、次のファイルを作成しています。

  • cabin-web.conf NGINX構成が含まれています。
  • processes.yml PM2がNode.jsプロセスを処理するために使用します。
  • cabin_mysql_init.sh MySQLデータベースを初期化するために使用されるカスタムスクリプトです。

データをテンプレートに渡すときに、Base64としてエンコードしたことを思い出してください。 内容をデコードできるように、ファイルを書き込むときにエンコーディングを指定します。

次のセクションでは、 runcmd いくつかのシェルコマンドを実行してファイアウォールルールを作成するモジュール iptables:

runcmd:
 - iptables -A INPUT -i lo -j ACCEPT
 - iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 - iptables -A INPUT -p tcp --dport ssh -j ACCEPT
 - iptables -A INPUT -p tcp --dport 80 -j ACCEPT
 - iptables -A INPUT -p tcp --dport 8000 -j ACCEPT
 - iptables -A INPUT -p tcp --dport 3000 -j ACCEPT
 - iptables -A INPUT -j DROP
 - iptables -A OUTPUT -j ACCEPT
 - invoke-rc.d iptables-persistent save
…

次に、コードは iptables-persistent インスタンスが再起動した場合にファイアウォール構成を使用できるようにします。

ファイアウォールルールが設定された後、キャビンを設定および開始するための残りのコマンドが実行されます。

 - apt-get update --fix-missing
 - curl -sL https://deb.nodesource.com/setup_5.x | bash && apt-get install -y nodejs
 - npm install pm2 webpack -g
 - cd /home/cabin && sudo -u cabin git clone ${userdata_giturl}
 - mv /tmp/env.sh /home/cabin/stream-react-example/env.sh
 - cd /home/cabin/stream-react-example/api && sudo -u cabin npm install
 - cd /home/cabin/stream-react-example/app && sudo -u cabin npm install
 - cd /home/cabin/stream-react-example/www && sudo -u cabin npm install
 - chown cabin.cabin /home/cabin/stream-react-example/env.sh && /home/cabin/stream-react-example/env.sh
 - mv /tmp/processes.yml /home/cabin/stream-react-example/processes.yml
 - chown cabin.cabin /home/cabin/stream-react-example/processes.yml
 - /tmp/cabin_mysql_init.sh
 - cd /home/cabin/stream-react-example && sudo -u cabin pm2 start processes.yml
 - mv /tmp/cabin-web.conf /etc/nginx/sites-available/cabin-web
 - rm /etc/nginx/sites-enabled/default
 - ln -s /etc/nginx/sites-available/cabin-web /etc/nginx/sites-enabled
 - service nginx reload

これらのコマンドはすべてroot権限で実行され、は最初の起動でのみ発生します。 マシンを再起動すると、 runcmd 再度実行されることはありません。

Terraformについて詳しく学習したので、インフラストラクチャのライフサイクルを処理する方法を見ていきましょう。

ステップ7—スタックのライフサイクルを管理する

Terraformを使用すると、スタックの状態を保存し、スタックを更新し、破棄し、コード変更をデプロイすることができます。

実行した後、あなたはそれに気づいたかもしれません terraform apply、というファイル terraform.tfstate で作成されます cabin ディレクトリ。

このファイルには、DigitalOceanで作成された実際のリソースへの参照が含まれているため、非常に重要です。 基本的に、このファイルはTerraformに管理するリソースの識別子を通知します。

実行した場合 terraform apply 繰り返しになりますが、Terraformは最初からやり直して、作成したものをすべて消去することはありません。 代わりに、まだ完了していない部分のみを実行します。 したがって、ネットワークの問題またはAPIの問題が原因でプロセスが途中で失敗した場合は、問題に対処してコマンドを再実行できます。 Terraformは、中断したところから再開します。

ドロップレット構成の変更

使用することもできます terraform apply ドロップレットの構成を変更します。 たとえば、より多くのトラフィックに対応するためにデータセンターやリージョンを変更したり、Dropletが使用するメモリを増やしたりする必要がある場合、Terraformを使用すると両方のタスクが非常に簡単になります。

ドロップレット領域を調整するには、 terraform apply コマンドとオーバーライド regiondroplet_size 変数。 これにより、Terraformは、既存のドロップレットを破棄する必要があり、要件を満たすために新しいドロップレットをプロビジョニングする必要があることを認識できます。

警告Terraformは既存のドロップレットを破棄します。 アプリケーションと同じサーバーでMySQLデータベースを実行している場合、これによりMySQLデータも破棄されます。。 これを回避するには、この手順の前にデータベースエクスポートを実行するか、専用のDropletでMySQLデータベースを実行することをお勧めします。

ドロップレットを保持するリージョンまたはデータセンターを変更する場合は、次のコマンドを実行します。

  1. terraform apply -var "region=sfo2"

また、ユーザーベースが拡大するにつれて、追加のトラフィックに対応するためにドロップレットのサイズを変更する必要があります。 あなたはそれをすることができます droplet_size このような変数:

  1. terraform apply -var "droplet_size=4gb"

ドロップレットが削除されて新しいドロップレットに置き換えられ、アプリケーションが再デプロイされて構成されます。

スタックを破壊する

Terraformの驚くべき点の1つは、スタックのライフサイクル全体を処理することです。 1つの単純なTerraformコマンド(破棄)を実行することで、作成したものを簡単に破棄できます。

  1. terraform destroy

次に、Terraformは、実際にすべてのリソースを破棄することを確認するように求めるプロンプトを表示します。

Output
Do you really want to destroy? Terraform will delete all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes

Terraformが完了すると、最終的な出力は次のようになります。

Output
digitalocean_droplet.cabin-web: Destroying... digitalocean_droplet.cabin-web: Still destroying... (10s elapsed) digitalocean_droplet.cabin-web: Destruction complete digitalocean_ssh_key.cabin-ssh-key: Destroying... template_file.userdata_web: Destroying... template_file.userdata_web: Destruction complete template_file.pm2_processes_conf: Destroying... template_file.pm2_processes_conf: Destruction complete digitalocean_ssh_key.cabin-ssh-key: Destruction complete Apply complete! Resources: 0 added, 0 changed, 5 destroyed.

ご覧のとおり、すべてのリソースが破壊されました。

新しいバージョンのコードのデプロイ

コードベースに変更を加えた場合、ダウンタイムをほとんどまたはまったく発生させずに、変更をサーバーに反映させる必要があります。 サーバーにPM2がインストールされており、これで手間のかかる作業を処理できます。

PM2は、アプリケーションのファイルシステムの変更をリッスンします。 新しいバージョンのコードを実行するには、DropletにSSHで接続し、 git pull アプリケーションを含むディレクトリのコマンド。 これにより、リポジトリからプルするようにサーバーに指示されます。 ファイルが変更されると、PMZはノードプロセスを自動的に再開します。

たとえば、新しいバージョンのCabinがあり、最新バージョンのコードをサーバーにデプロイする場合は、サーバーにログインします。

ssh cabin@your_value_for_web_ipv4

次に、サーバーで、キャビンアプリケーションを含むフォルダーに移動します。

  1. cd ~/stream-react-example

そして最後に最新バージョンをプルダウンします。

  1. git pull

新しいコードが配置されると、アプリは自動的に再起動し、訪問者には最新バージョンが表示されます。 何らかの理由でPM2が変更をキャッチしない場合は、手動で再起動します。

  1. pm2 restart all

すべてのコンポーネントが再起動します。

結論

DigitalOcean、Terraform、Cloud-init、およびPM2を使用して、キャビンの本番環境を正常にセットアップしました。

Terraformを使用する場合、すべてのインフラストラクチャがコードとして保存されます。 これにより、チームは変更を追跡して共同作業を行うことが容易になります。 また、比較的簡単に大規模なインフラストラクチャの変更を行うことができます。