Bereitstellen einer Node.js-App mit Terraform unter Ubuntu 14.04

Ein Artikel von Stream

Einführung

Mithilfe von Orchestrierungstools können DevOps-Experten einen Stack mithilfe einiger API-Aufrufe bereitstellen. Terraform ist ein sehr einfaches, aber leistungsstarkes Tool, mit dem Sie Ihren Stack als Code schreiben, dann freigeben und auf dem neuesten Stand halten können, indem Sie die Definitionsdateien mit https festschreiben: //git-scm.com/[Git]. Terraform wird von HashiCorp erstellt, den Autoren beliebter Open-Source-Tools wie Vagrant, https://www.packer. io / [Packer] und Consul.

Terraform bietet eine allgemeine Konfiguration zum Starten Ihrer Infrastruktur, von physischen und virtuellen Servern bis hin zu E-Mail- und DNS-Anbietern. Nach dem Start ändert Terraform die Infrastruktur sicher und effizient, während sich die Konfiguration weiterentwickelt.

In diesem Tutorial erfahren Sie, wie Sie eine Umgebung für eine voll funktionsfähige, hochentwickelte Node.js -Anwendung mit https://digitalocean.com [DigitalOcean], https: // www einrichten. terraform.io/[Terraform], Cloud-init und PM2 unter Ubuntu 14.04. Als Beispielanwendung verwenden wir http://cabin.getstream.io [Cabin], eine Open-Source-Version von React & http: //redux.js. org / docs / basics / UsageWithReact.html [Redux] Node.js-Anwendung, entwickelt von http://getstream.io [GetStream.io]. Die endgültige Ausgabe wird eine funktionsreiche, skalierbare Social-Network-App sein!

Sie beginnen mit Terraform, um Cabin mit einer vordefinierten Konfiguration bereitzustellen. Dann tauchen Sie tief in diese Konfiguration ein, um sich mit der Funktionsweise vertraut zu machen.

Wenn Sie nur Terraform auf Ihrem DigitalOcean-Server installieren möchten, lesen Sie bitte How To Use Terraform with DigitalOcean.

Voraussetzungen

Um diesem Tutorial folgen zu können, benötigen Sie:

  • Ein 2 GB Ubuntu 14.04 Server, den Sie in diesem Tutorial mit Terraform erstellen.

  • Der Git -Client ist auf Ihrem lokalen Computer installiert.

  • Ein Facebook-Konto, mit dem Sie eine Facebook-Anwendung erstellen können, da Cabin Facebook für Anmeldungen verwendet.

  • Eine Domain wie + cabin.example.com +; Sie verweisen diese Domain auf die IPv4-Adresse, die Sie in Schritt 4 erhalten, und benötigen diese für die Site-URL in Facebook.

In diesem Tutorial wird davon ausgegangen, dass Sie http://cabin.getstream.io/[Streams Cabin-Tutorialserie abgeschlossen haben. Sie benötigen API-Schlüssel und -Einstellungen für mehrere Anbieter, die für das Funktionieren von Cabin in der Produktion erforderlich sind, da sie eine wesentliche Rolle für die Funktionalität von Cabin spielen.

Weitere Informationen zu diesen Diensten erhalten Sie in den folgenden Blogeinträgen von Stream:

Schritt 1 - Erhalten der Beispielanwendung

Klonen Sie die Cabin-Beispielanwendung von GitHub in ein Verzeichnis Ihrer Wahl auf Ihrem lokalen Computer. Wir verwenden einen Mac und gehen davon aus, dass Sie es auch sind.

Navigieren Sie zunächst zu Ihrem Home-Verzeichnis.

cd ~

Verwenden Sie dann "+ git +", um das Repository zu klonen:

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

Dadurch wird die Beispielanwendung in einen neuen Ordner mit dem Namen "+ stream-react-example" geklont. Navigieren Sie zum Ordner "+ stream-react-example / terraform / do / cabin +", der das Terraform-Projekt von Cabin enthält.

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

Wir werden in Kürze mit diesem Ordner arbeiten. Aber zuerst richten wir Terraform ein.

Schritt 2 - Terraform installieren

Für eine einfache Installation unter OSX können Sie Terraform mithilfe von Homebrew installieren, indem Sie den folgenden Befehl eingeben:

brew install terraform

Alternativ können Sie Terraform von http://terraform.io herunterladen. Sobald Sie es heruntergeladen haben, stellen Sie es Ihrem Befehlspfad wie unten gezeigt zur Verfügung.

PATH=:$PATH

Dies fügt Ihrem Pfad vorübergehend Terraform hinzu. Wenn diese Änderung dauerhaft sein soll, bearbeiten Sie die Datei "+ ~ / .bash_profile +" unter OSX und fügen Sie diese Zeile hinzu:

~ / .bash_profile

export PATH=:$PATH

Führen Sie als Nächstes den folgenden Befehl aus, um zu überprüfen, ob Terraform ordnungsgemäß installiert wurde:

terraform

Sie sehen die folgende Ausgabe mit den Terraform-Optionen:

Outputusage: 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

Bevor Terraform Ihre Infrastruktur starten kann, müssen zwei Dinge konfiguriert werden:

Kümmern wir uns also zuerst um das DigitalOcean-Token.

Schritt 2 - Konfigurieren des DigitalOcean-Zugriffstokens

Terraform benötigt Ihr DigitalOcean-Zugriffstoken, um die DigitalOcean-API verwenden zu können.

Melden Sie sich bei Ihrem DigitalOcean-Konto an und klicken Sie auf den Link * API *. Klicken Sie dann auf die Schaltfläche * Neues Token erstellen *. Stellen Sie sicher, dass Sie * Write Access * (Schreibzugriff) aktivieren. Auf der Benutzeroberfläche wird ein neuer Zugriffsschlüssel angezeigt, den Sie in Ihre Zwischenablage kopieren sollten, da der Schlüssel nicht sichtbar ist, wenn Sie die Seite erneut aufrufen.

Öffnen Sie nun die Datei + variables.tf + mit Ihrem bevorzugten Texteditor und suchen Sie den Abschnitt + token +:

variables.tf

variable "token" {
 description = "DO Token"
}

Fügen Sie eine neue Zeile hinzu, die mit dem Text "+ default = +" beginnt, und fügen Sie Ihr DigitalOcean-API-Token hinzu. Denken Sie daran, das Token in Anführungszeichen zu setzen.

variables.tf

variable "token" {
 description = "DO Token"

}

Speichern und schließen Sie die Datei.

Jetzt konfigurieren wir Terraform so, dass unser SSH-Schlüsselpaar verwendet wird.

Schritt 3 - Fügen Sie Ihr SSH-Schlüsselpaar hinzu

Terraform benötigt einen SSH-Schlüssel, um eine Verbindung zu unserem Server herzustellen, sobald dieser erstellt wurde, damit Pakete installiert und die Anwendung bereitgestellt werden kann.

Sehen Sie in Ihrem + ~ / .ssh + Verzeichnis nach, ob Sie bereits ein Schlüsselpaar haben:

ls -al ~/.ssh

Höchstwahrscheinlich haben Sie mindestens ein Schlüsselpaar, das aus einem privaten und einem öffentlichen Schlüssel besteht. Zum Beispiel könnten Sie + id_rsa.pub + und + id_rsa + haben.

Wenn Sie keine Schlüsselpaare haben oder der Schlüssel bereits mit Ihrem DigitalOcean-Konto verknüpft ist, lesen Sie bitte https://www.digitalocean.com/community/tutorials/how-to-use-ssh- Keys-with-Digitalocean-Droplets [DigitalOceans Tutorial zum Einrichten von SSH-Schlüsseln], um einen einzurichten.

Sie müssen den Inhalt der + .pub + - Datei in die + variables.tf + - Datei einfügen, genau wie Sie es mit dem API-Token getan haben. Wenn Sie auf einem Mac arbeiten, können Sie Ihren öffentlichen SSH-Schlüssel in Ihre Zwischenablage kopieren, indem Sie den folgenden Befehl ausführen:

pbcopy < ~/.ssh/

Sie können den Inhalt des öffentlichen Schlüssels auch mit dem Befehl "+ cat +" auf dem Bildschirm anzeigen und manuell in Ihre Zwischenablage kopieren:

cat  ~/.ssh/

Öffnen Sie dann die Datei "+ variables.tf " in Ihrem Editor und fügen Sie den Inhalt Ihrer öffentlichen SSH-Schlüsseldatei zur Einstellung " sshkey +" hinzu:

variables.tf

variable "sshkey" {
 description = "Public ssh key (for Cabin user)"

}

Wenn Sie diesen Schritt abgeschlossen haben, speichern und schließen Sie die Datei.

Wenn Sie einen neuen Schlüssel für Terraform und DigitalOcean generiert haben, müssen Sie diese beiden Befehle ausführen, damit Ihr neuer Schlüssel anstelle Ihres Standardschlüssels verwendet wird:

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

Sie müssen dies möglicherweise jedes Mal ausführen, wenn Sie eine neue Shell öffnen, wenn Sie ein alternatives Schlüsselpaar verwenden.

Nachdem Sie Terraform die erforderlichen Variablen bereitgestellt haben, können Sie Ihren Server erstellen und Ihre App mit Terraform bereitstellen.

Schritt 4 - Terraform ausführen

Hier kommt der lustige Teil! Werfen wir einen Blick auf die Infrastruktur, die wir bauen werden. Terraform wird eine Menge Arbeit für uns tun, vom Einrichten unseres Servers bis zur Bereitstellung unserer App. Terraform kann uns genau zeigen, was mit dem folgenden Befehl geschehen soll:

terraform plan

Die Ausgabe dieses Befehls ist sehr ausführlich. Konzentrieren Sie sich daher auf die folgenden Anweisungen:

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
...

Das "" - Symbol am Anfang einer Zeile bedeutet, dass die Ressourcen erstellt werden. Die Ressourcen mit dem Präfix " digitalocean +" sind die Ressourcen, die in DigitalOcean erstellt werden. In diesem speziellen Fall erstellt Terraform ein Droplet, eine Floating-IP, und fügt unseren SSH-Schlüssel hinzu.

Jetzt ist es an der Zeit, Terraform auszuführen und Cabin auf Ihrem Droplet zu drehen.

terraform apply

Nach kurzer Zeit wird Terraform folgendes ausdrucken:

OutputApply 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 =

+ web_ipv4 + ist die Floating-IP-Adresse, mit der Sie auf das Droplet zugreifen können.

Melden Sie sich beim neu erstellten Droplet mit dem Wert an, den Sie für "++" sehen:

ssh cabin@

Sie können auch den Befehl verwenden

terraform output web_ipv4

um die diesem Wert zugeordnete IP-Adresse anzuzeigen, wenn Sie sie verpasst haben.

Sie werden diese Willkommensnachricht sehen, wenn Sie sich anmelden:

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

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

Möglicherweise müssen Sie einige Minuten warten, bis DigitalOcean die Instanz bereitgestellt hat und bis + cloud-init + die erforderlichen Pakete für Cabin installiert hat. Sobald es fertig ist, wird Folgendes angezeigt:

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

Zeigen Sie nach dem Start von Cabin mit Ihrem mobilen Browser auf "+ http: // +". Die Kabine ist in Betrieb und Sie sollten einen Ladebildschirm sehen. Bis wir einige Änderungen am Code auf dem Server vornehmen, ist dies jedoch noch nicht geschehen.

Schritt 5 - (Optional) Kabine konfigurieren

Die Cabin-Anwendung wird bereitgestellt, ist jedoch noch nicht verwendbar. Wir müssen Facebook und mehrere andere Dienste konfigurieren, um Cabin voll funktionsfähig zu machen.

Zunächst müssen Sie eine Facebook-App mit einem gültigen Domain-Namen wie "+ cabin.example.com " erstellen, der der Adresse " web_ipv4 " zugeordnet ist, die während des Installationsvorgangs generiert wurde. Fügen Sie einen Eintrag zu Ihrem DNS hinzu oder fügen Sie einen Eintrag zu Ihrer ` / etc / hosts +` - Datei hinzu, der Ihre Domain der IP-Adresse zuordnet.

Gehen Sie folgendermaßen vor, um die Facebook-App zu erstellen:

  1. Besuchen Sie https://developers.facebook.com/docs/apps/register#step-by-step-guide.

  2. Loggen Sie sich bei Facebook ein.

  3. Klicken Sie unter "Meine Apps" auf "Neue App hinzufügen".

  4. Geben Sie einen Namen für Ihre Anwendung ein (z. + Cabin - My Example App +).

  5. Geben Sie Ihre * Kontakt-E-Mail * ein.

  6. Verwenden Sie für * Kategorie * das Dropdown-Menü, um eine Kategorie für die App auszuwählen. In unserem Fall ist es * Lifestyle *.

  7. Klicken Sie auf die Schaltfläche * App-ID erstellen *.

  8. Ergänzen Sie bei Bedarf das Captcha.

  9. Kopieren Sie die + appId +. Dies ist ein numerischer Wert, der oben auf dem Bildschirm angezeigt wird. Das werden Sie in Kürze brauchen.

  10. Wählen Sie in der linken Seitenleiste * Dashboard *.

  11. Klicken Sie unter der Überschrift "Erste Schritte mit dem Facebook SDK" auf "Plattform auswählen".

  12. Wählen Sie * Web * für die Plattform.

  13. Suchen Sie das Feld * Site URL * und geben Sie "+ http: // cabin.example.com +" ein.

  14. Weiter klicken*.

Wenn Sie auf Probleme stoßen, folgen Sie diese schrittweise Anleitung. Wenn Sie nicht weiterkommen, finden Sie einen großartigen Artikel zum Debuggen Ihres Anwendungs-Setups auf Facebook unter here.

Sobald Sie Ihre "+ appID " haben, müssen Sie die Standardeinstellung " appID +" auf dem Server ersetzen.

Stellen Sie daher sicher, dass Sie bei Ihrem Server angemeldet sind. Wenn nicht, melden Sie sich erneut an mit:

ssh cabin@

Sobald Sie eingeloggt sind, öffnen Sie die Datei + ~ / stream-react-example / app / views / index.ejs +:

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

Ändern Sie die Standardeinstellung "+ appId +" durch die von Facebook bereitgestellte.

strea-react-example / app / views / index.ejs

FB.init({
   appId   : ,
   xfbml   : true,
   version : 'v2.6',
   status  : true,
   cookie  : true,
})

Speichern Sie diese Datei und schließen Sie sie.

Als Nächstes müssen Sie das Datenbankkennwort für Cabin kennen, das von Terraform beim Erstellen des Servers generiert wurde. Geben Sie den folgenden Befehl ein, um diesen Wert abzurufen:

grep DB_PASSWORD processes.yml

Kopieren Sie dieses Passwort. Sie werden es in Kürze brauchen.

In der Datei "+ env.sh +" geben Sie Ihre Anmeldeinformationen für die verschiedenen Anbieter und Dienste ein, von denen Cabin abhängig ist. Diese Datei platziert diese Anmeldeinformationen in Umgebungsvariablen, die dann von der Anwendung gelesen werden. Dies ist eine Sicherheitsmaßnahme, da Passwörter und Schlüssel von Git ferngehalten werden.

Öffne + env.sh +:

nano env.sh

Sie sehen folgenden Inhalt:

Outputexport 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

Wie Sie sehen, exportiert diese Datei eine Reihe von Umgebungsvariablen, die Informationen zu verschiedenen Diensten enthalten, die Cabin benötigt. Damit Cabin in der Produktion funktioniert, müssen Sie alle diese Werte eingeben.

Hier ist eine kurze Aufschlüsselung dieser Einstellungen:

  1. * NODE_ENV *: Die Umgebung, in der Node.js ausgeführt wird. (Die Produktion wird eine Geschwindigkeitsverbesserung bieten).

  2. * JWT_SECRET *: Authentifizierungsgeheimnis für die JSON-Web-Token-Authentifizierung zwischen der API und der Web (App) -Schnittstelle.

  3. * DB_USERNAME *: Der Benutzername für die Datenbank.

  4. * DB_HOST *: Der Hostname der Datenbank.

  5. * DB_PASSWORD *: Das Passwort für die Datenbank, das Sie gerade unter + process.yml + angezeigt haben.

  6. * DB_PORT *: Datenbankport (Standardport 3306 für MySQL).

  7. * MAPBOX_ACCESS_TOKEN *: Zugriffstoken für MapBox (zum Zuordnen von Fotostandorten).

  8. * S3_KEY *: Amazon S3-Schlüssel für die Bildspeicherung.

  9. * S3_SECRET *: Amazon S3-Geheimnis für die Speicherung von Bildern.

  10. * S3_BUCKET *: Amazon S3-Bucket für die Speicherung von Bildern. Stellen Sie sicher, dass dieser Bucket vorhanden ist.

  11. * STREAMAPPID *: App-ID streamen. Stellen Sie sicher, dass alle erforderlichen Feedgruppen in der App vorhanden sind, die dieser ID zugeordnet ist.

  12. * STREAM_KEY *: Stream-API-Schlüssel.

  13. * STREAM_SECRET *: App-Geheimnis streamen.

  14. * ALGOLIA_APP_ID *: Algolia-App-ID für die Suche.

  15. * ALGOLIA_SEARCH_ONLY_KEY *: Nur Algolia-Suchschlüssel für die Suche.

  16. * ALGOLIA_API_KEY *: Algolia-API-Schlüssel für die Suche.

  17. * KEEN_PROJECT_ID *: Projekt-ID für scharfes Tracking (für Statistiken).

  18. * KEEN_WRITE_KEY *: Scharfes Verfolgen des Schreibschlüssels (für Statistiken).

  19. * KEEN_READ_KEY *: Fleißiger Tracking-Leseschlüssel (für Statistiken).

  20. * IMGIX_BASE_URL *: Imgix-Basis-URL (zum Rendern von Fotos in bestimmten Größen).

  21. * API_URL *: Die von dieser Anwendung für ihre API verwendete URL. Sie müssen dies von "+ localhost " in die Domain ändern, die auf Ihre IP-Adresse verweist, z. B. " cabin.example.com +".

Weitere Informationen zu den Umgebungsvariablen und -diensten, auf die verwiesen wird, finden Sie in den folgenden Blogeinträgen. Stellen Sie sicher, dass Sie jede Anwendung wie angegeben konfiguriert haben:

Nachdem Sie alle Anbieter konfiguriert haben, geben Sie das Kennwort für Ihre Datenbank und die Werte für die Anbieter in die Datei "+ env.sh +" ein.

Beenden und speichern Sie die Datei + env.sh +. Dann geben Sie eine Quelle für die Datei ein und laden Sie die Werte in die Umgebungswerte, die Cabin verwenden wird:

source ./env.sh

Als nächstes müssen Sie den Befehl "+ webpack " ausführen. Webpack ist ein JavaScript-Build-Tool, das den Frontend-Code für Cabin verwaltet. Webpack generiert JavaScript- und CSS-Dateien basierend auf den Werten neu, die in der soeben geänderten Datei ` env.sh ` festgelegt wurden. Wechseln Sie also in das Verzeichnis " app +":

cd app

Führen Sie dann den Befehl + webpack + aus, um die Front-End-JavaScript-Dateien neu zu erstellen. Dadurch werden einige der Provider-Token in den Front-End-Code eingefügt.

webpack --progress --color

Sie werden die folgende Ausgabe sehen:

OutputHash: 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

Führen Sie mit den vorgenommenen Einstellungen PM2 aus, um alle Anwendungsprozesse neu zu laden und sicherzustellen, dass alle Komponenten die neuen Einstellungen verwenden:

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 │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────────────┴──────────┘

Das ist es! Sie können sich jetzt von Ihrem Remote-Server abmelden.

exit

Besuchen Sie abschließend "+ http: // +" in Ihrem Browser, um die Site erneut anzuzeigen. Daraufhin wird ein Titelbild mit einem Link zum Anmelden bei Facebook angezeigt. Sobald Sie sich angemeldet haben, können Sie die App später erkunden.

Schauen wir uns nun die Terraform-Konfiguration an, die diese Bereitstellung ermöglicht hat.

Schritt 6 - Erkunden der Konfigurationskacheln

Wie funktioniert das alles? Schauen wir uns die Dateien im Repository an, die wir auf unseren lokalen Computer geklont haben. In diesem Abschnitt müssen Sie zwar nichts ändern, aber Sie sollten trotzdem auf Ihrem eigenen Computer mitarbeiten, um ein Gefühl dafür zu bekommen, wie die Teile zusammenpassen.

Das Terraform-Projekt ist in mehrere Dateien und Verzeichnisse unterteilt, um die Anwendung übersichtlich und verständlich zu halten. Wir haben alle unsere DigitalOcean-Dateien im Verzeichnis "+ terraform / do +" des Repository abgelegt, das die folgende Struktur aufweist:

terraform ordner

do
└── cabin
   ├── files
   │   ├── cabin-web-nginx.conf
   │   └── cabin_mysql_init.sh
   ├── main.tf
   ├── outputs.tf
   ├── templates
   │   ├── processes.tpl
   │   └── web.tpl
   └── variables.tf

Schauen wir uns die obigen Dateien an, beginnend mit "+ main.tf +". Öffnen Sie es in Ihrem bevorzugten Texteditor.

Als Erstes teilen wir Terraform mit, welchen Cloud-Anbieter wir verwenden werden.

main.tf

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

So einfach ist das Definieren des DigitalOcean-Providers. Eine vollständige Liste der unterstützten Anbieter finden Sie unter Terraform documentation.

Variable Konfiguration

Mit Terraform können Sie Variablen definieren, dh Sie können Standardeinstellungen für Ihre Bereitstellung festlegen. Auf diese Weise müssen Sie nicht jedes Mal die Details oder die Hardcode-Werte in Ihrer Konfiguration eingeben. Schauen wir uns an, wie Sie die Variablen für die Bereitstellung auf DigitalOcean festlegen.

Schauen Sie sich "+ variables.tf +" an, den Ort, an dem wir die Variablen definiert haben, die zum Ausführen der Cabin-Anwendung erforderlich sind.

variables.tf

variable "token" {
 description = "DO Token"
}

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

Um besser zu verstehen, wie die Variablen in Terraform verarbeitet werden, gehen wir das obige Beispiel durch.

Für die Regionsvariable haben wir einen Standardwert angegeben. Wenn Sie keinen Standardwert angeben, fordert Terraform Sie zur Eingabe eines solchen Werts auf, wie im folgenden Beispiel gezeigt:

Outputterraform plan
var.token
 DO Token

 Enter a value:

Sie können auch Variablen angeben, wenn Sie "+ terraform apply " ausführen. Wenn Sie beispielsweise eine andere Region angeben möchten, können Sie Terraform mit dem Argument ` var +` ausführen:

terraform -var 'region=ams3' apply

Dadurch werden alle konfigurierten Einstellungen überschrieben.

Tröpfchen-Setup

In + main.tf + weisen wir Terraform an, ein Droplet auf DigitalOcean bereitzustellen. Standardmäßig stellen wir einen Server mit den folgenden Merkmalen bereit:

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}"
}

Wir erstellen ein neues DigitalOcean Droplet mit 2 GB RAM namens * cabin-web * und verwenden das Image * ubuntu-14-04-x64 *. Anhand der obigen Ressourcendefinition können Sie erkennen, dass das Image und die Größe des Servers leicht geändert werden können.

Benutzerdaten & Cloud-Init

Okay, was genau ist "+ Benutzerdaten"? Dies ist der einfachste Weg, um Befehle und Anweisungen beim Booten an eine Cloud-Instanz zu senden. In Verbindung mit "+ cloud-init +" wird es zu einer leistungsstarken Möglichkeit, Ihre Instanz zu konfigurieren, ohne unnötige Anwendungen von Drittanbietern wie Chef oder https://puppet.com/ zu nutzen. [Marionette].

Das Programm + cloud-init + ist in vielen Linux-Distributionen enthalten. Es enthält eine kleine Reihe von Anweisungen, mit denen Sie einfache Aufgaben wie das Hinzufügen von Benutzern, das Verwalten von Gruppen, das Erstellen von Dateien und das Ausführen von Skripten oder Shell-Befehlen mit Root-Rechten ausführen können.

Tauchen wir in das Attribut "+ user_data +" ein, damit Sie besser verstehen, was es ist:

main.tf

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

Unser Ziel ist es, ein neues Droplet mit laufendem Cabin zu starten und "+ cloud-init " für uns das schwere Heben zu erledigen. Das Feld ` user_data ` verweist auf eine Vorlagendatei, wobei eine Variable auf eine andere Deklaration in ` main.tf +` verweist:

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 bietet Funktionen, mit denen Sie Text transformieren können. Mit dieser Funktion können Sie Werte in Vorlagen einfügen, indem Sie Dateien lesen und den Inhalt dann in Base64-codierte Zeichenfolgen konvertieren, damit sie über API-Aufrufe übertragen werden können.

Dieser spezielle Abschnitt bereitet die Daten für die Vorlage "+ templates / web.tpl +" vor, die alle Einstellungen und Befehle enthält, die auf dem Server ausgeführt werden sollen.

Sehen wir uns die Datei "+ web.tpl +" an und sehen, was sie tut.

Der erste Teil richtet den Erstbenutzer ein und deaktiviert den Root-Zugriff:

templates / 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

Die allererste Anweisung in "+ web.tpl " muss " # cloud-config " sein. Wenn Sie dies vergessen, wird ` cloud-init +` die Konfiguration nicht übernehmen und die angegebenen Befehle werden nicht auf der Zielinstanz ausgeführt.

Die Befehle in diesem Abschnitt führen Folgendes aus:

  • Fügen Sie dem System den Benutzer "+ cabin +" mit einer Erlaubnis hinzu, ein Superuser zu werden

  • + lock-passwd: true + verweigert die Kennwortauthentifizierung, sodass der Benutzer + cabin + die SSH-Schlüsselauthentifizierung verwenden muss, um auf den Server zuzugreifen.

  • + ssh-authorized-keys + installiert den ssh-key des Benutzers in die authorized_keys-Datei.

  • + disable_root: true + wird verwendet, um den SSH-Zugriff als root zu deaktivieren

Denken Sie daran, dass "+ $ {userdata_sshkey} " eine Variable ist, die festgelegt wurde, als wir die Vorlage in " main.tf +" aufriefen.

Als nächstes installieren wir MySQL, Nginx, Git und andere Pakete, die wir für unsere Anwendung benötigen:

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

Die einfachste Möglichkeit, Pakete mit "+ cloud-init " zu installieren, besteht darin, mithilfe des Package-Moduls eine Liste der angegebenen Pakete zu installieren. Dieses Modul verwendet den Standardpaket-Manager für die Verteilung. Da wir Ubuntu verwenden, werden bei diesem Vorgang Pakete mit " apt +" installiert.

Als Nächstes schreiben wir einige Dateien in das Dateisystem, wobei wir die an die Vorlage übergebenen Daten als Dateiinhalt verwenden:

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'

In diesem Abschnitt wird das Modul "+ write_file +" verwendet, um die Dateien zu erstellen. Im obigen Beispiel erstellen wir die folgenden Dateien:

  • + cabin-web.conf + enthält die NGINX-Konfiguration.

  • + process.yml + wird von PM2 zur Behandlung der Node.js-Prozesse verwendet.

  • + cabin_mysql_init.sh + ist ein benutzerdefiniertes Skript zum Initialisieren der MySQL-Datenbank.

Denken Sie daran, dass wir die Daten bei der Übergabe an die Vorlage als Base64 verschlüsselt haben. Wir legen die Kodierung beim Schreiben der Dateien fest, damit der Inhalt dekodiert werden kann.

Im nächsten Abschnitt verwenden wir das Modul "+ runcmd ", um einige Shell-Befehle zum Erstellen von Firewall-Regeln mit " iptables +" auszuführen:

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
…

Der Code verwendet dann "+ iptables-persistent +", um die Firewall-Konfiguration für den Fall verfügbar zu machen, dass die Instanz neu gestartet wird.

Nachdem die Firewall-Regeln festgelegt wurden, werden die restlichen Befehle zum Einrichten und Starten von Cabin ausgeführt:

- 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

Alle diese Befehle werden mit Root-Rechten ausgeführt und werden nur beim ersten Start ausgeführt. Wenn Sie die Maschine neu starten, wird + runcmd + nicht erneut ausgeführt.

Nachdem Sie mehr über Terraform erfahren haben, erfahren Sie, wie Sie mit dem Lebenszyklus Ihrer Infrastruktur umgehen.

Schritt 7 - Verwalten des Stack-Lebenszyklus

Mit Terraform können Sie den Status Ihres Stacks speichern, Ihren Stack aktualisieren, zerstören und Codeänderungen implementieren.

Möglicherweise haben Sie bemerkt, dass nach dem Ausführen von "+ terraform apply " eine Datei mit dem Namen " terraform.tfstate " im Verzeichnis " cabin +" erstellt wird.

Diese Datei ist sehr wichtig, da sie die Verweise auf die in DigitalOcean erstellten Ressourcen enthält. Grundsätzlich teilt diese Datei Terraform die Kennungen der von ihr verwalteten Ressourcen mit.

Wenn Sie "+ terraform apply +" erneut ausführen, beginnt Terraform nicht von vorne und löscht alles, was Sie erstellt haben. Stattdessen werden nur die Teile ausgeführt, die noch nicht fertig sind. Wenn Ihr Prozess aufgrund eines Netzwerkproblems oder eines API-Problems in der Mitte fehlschlägt, können Sie die Probleme beheben und den Befehl erneut ausführen. Terraform wird dort weitermachen, wo es aufgehört hat.

Ändern der Tropfenkonfiguration

Sie können auch "+ terraform apply +" verwenden, um die Konfiguration des Droplets zu ändern. Wenn Sie beispielsweise Rechenzentren oder Regionen ändern oder den von Ihrem Droplet verwendeten Speicher erhöhen müssen, um mehr Verkehr aufzunehmen, vereinfacht Terraform beide Aufgaben ganz erheblich.

Sie können die Droplet-Region anpassen, indem Sie den Befehl + terraform apply + ausführen und die Variablen + region + und + droplet_size + überschreiben. Auf diese Weise weiß Terraform, dass das vorhandene Droplet zerstört werden muss und ein neues Droplet bereitgestellt werden muss, um die Anforderungen zu erfüllen.

Wenn Sie die Region oder das Datencenter ändern möchten, in dem sich Ihr Droplet befindet, führen Sie den folgenden Befehl aus:

terraform apply

Und wenn Ihre Benutzerbasis wächst, müssen Sie wahrscheinlich die Tröpfchengröße ändern, um dem zusätzlichen Datenverkehr Rechnung zu tragen. Sie können dies mit der Variablen "+ droplet_size +" wie folgt tun:

terraform apply

Das Droplet wird entfernt und durch ein neues ersetzt, und die Anwendung wird erneut bereitgestellt und konfiguriert.

Den Stapel zerstören

Das Erstaunliche an Terraform ist, dass es den gesamten Lebenszyklus des Stapels abdeckt. Sie können einfach zerstören, was Sie erstellt haben, indem Sie einen einfachen Terraform-Befehl ausführen (destroy).

terraform destroy

Terraform fordert Sie dann auf, zu bestätigen, dass Sie tatsächlich alle Ressourcen zerstören möchten:

OutputDo 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

Sobald Terraform abgeschlossen ist, sieht die endgültige Ausgabe folgendermaßen aus:

Outputdigitalocean_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.

Wie Sie sehen, wurden alle Ressourcen zerstört.

Bereitstellen neuer Codeversionen

Für den Fall, dass Sie Änderungen an Ihrer Codebasis vornehmen, müssen Sie die Änderungen ohne Ausfallzeiten auf den Server übertragen. Wir haben PM2 auf unserem Server installiert und es wird das schwere Heben für uns erledigen.

PM2 wartet auf Dateisystemänderungen in der Anwendung. Um eine neuere Version Ihres Codes auszuführen, geben Sie einfach SSH in das Droplet ein und geben Sie den Befehl + git pull + in dem Verzeichnis ein, das die Anwendung enthält. Dadurch wird der Server angewiesen, aus Ihrem Repository zu ziehen. Wenn sich die Dateien ändern, startet PMZ den Knotenprozess automatisch neu.

Wenn es beispielsweise eine neue Version von Cabin gibt und Sie die neueste Version des Codes auf dem Server bereitstellen möchten, melden Sie sich bei Ihrem Server an:

ssh cabin@

Navigieren Sie dann auf dem Server zu dem Ordner, der die Cabin-Anwendung enthält:

cd ~/stream-react-example

Und schließlich ziehen Sie die neueste Version nach unten.

git pull

Sobald der neue Code vorhanden ist, wird Ihre App automatisch neu gestartet und den Besuchern wird die neueste Version angezeigt. Wenn PM2 aus irgendeinem Grund keine Änderung feststellt, starten Sie die Dinge manuell mit

pm2 restart all

und alle Komponenten werden neu gestartet.

Fazit

Mit DigitalOcean, Terraform, Cloud-init und PM2 haben Sie erfolgreich eine Produktionsumgebung für Cabin eingerichtet.

Bei der Verwendung von Terraform wird Ihre gesamte Infrastruktur als Code gespeichert. Dies erleichtert Ihrem Team das Nachverfolgen von Änderungen und die Zusammenarbeit. Sie können damit auch relativ einfach umfangreiche Änderungen an der Infrastruktur vornehmen.

Related