Zwei Server mit internem Netz via RESTful API installieren

In diesem Guide beschreibe ich, wie man zwei Server mit gemeinsamen internen Private-Netzwerk und Debian 8 über die gridscale RESTful API aufsetzt.
Dieses einfache Beispiel kann man leicht auf 4 Server erweitern, die sich über ein gemeinsames Private-Netzwerk erreichen können (zum Beispiel für ein Cluster aus 2 Web-Servern und 2 Datenbank-Servern).

Möchte man die Datenbank-Server aus Sicherheitsgründen nicht direkt öffentlich erreichbar betreiben, hilft dieser Guide hier weiter: Debian Router/Gateway in 10 Minuten.

TIPP: Du kannst dich parallel in dein gridscale Panel einloggen und während du die API-Befehle eingibst zusehen, wie deine Objekte erscheinen und konfiguriert werden!

Dieses Guide hat als einzige Voraussetzung, dass bereits ein API-Token generiert wurde (gridscale.io/APIs/Create) und die User-UUID bekannt ist (zu finden hier: gridscale.io/APIs)

Wir installieren 2 Server mit Debian 8 mit folgenden Annahmen:

  1. Erstellen eines Private-Netzwerks mit dem die beiden Server verbunden werden
  2. “Server 1” mit 2 Netzwerk-Interfaces
    • Public-Netzwerk (eth0)
    • Private-Netzwerk (eth1)
  3. “Server 2” mit 2 Netzwerk-Interfaces
    • Public-Netzwerk (eth0)
    • Private-Netzwerk (eth1)

Auf beiden Servern konfiguriere ich jeweils eine öffentliche IPv4 und IPv6 Adresse.

Ok, los gehts 🙂

Damit du die Beispiele einfach per Copy&Paste nutzen kannst, setzen wir für das Token sowie die User-UUID einfach Environment Variablen in der aktuellen Konsole (Linux-Terminal oder putty):

export X_USERID=deine_user_uuid
export X_TOKEN=dein_token

Zuerst suche ich eine Location in der mein Beispiel-Setup gebaut werden soll:

# Request
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId:$X_USERID" \
     -H "X-Auth-Token:$X_TOKEN" \
     -X GET \
     https://api.gridscale.io/objects/locations
# Response
{"locations": {"45ed677b-3702-4b36-be2a-a2eab9827950": {"iata": "fra", "object_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "country": "de", "name": "de/fra"}}}
 
# oder etwas hübscher formatiert:
{
    "locations": {
        "45ed677b-3702-4b36-be2a-a2eab9827950": {
            "country": "de",
            "iata": "fra",
            "name": "de/fra",
            "object_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950"
        }
    }
}

OK, nehmen wir also “de/fra” und setzen dafür wieder eine Environment Variable:

export X_LOCATION="45ed677b-3702-4b36-be2a-a2eab9827950"

Nun das Private-Netzwerk erstellen:

curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"name": "geschütztes Netzwerk", "location_uuid":"'$X_LOCATION'"}' \
     https://api.gridscale.io/objects/networks
 
# response
{"object_uuid": "6dd023d1-9d71-448a-ac80-d3e2c2aaf954"}

Die object_uuid die wir für das Private-Netzwerk erhalten haben wieder in eine Environment Variable:

export X_PRIVATE_NET="6dd023d1-9d71-448a-ac80-d3e2c2aaf954"

Das Public-Netzwerk müssen wir nicht erstellen, es existiert bereits – wir benötigen jedoch später die object_uuid davon, also holen wir uns erstmal eine Liste aller zur Verfügung stehenden Netzwerke:

curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId:$X_USERID" \
     -H "X-Auth-Token:$X_TOKEN" \
     -X GET \
     https://api.gridscale.io/objects/networks

Ok, da kommt bereits eine ganze Menge als Response – hier das ganze etwas aufgehübscht in dem ich den Output von vorher durch einen json-Parser schicke für “pretty-print”:

curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId:$X_USERID" \
     -H "X-Auth-Token:$X_TOKEN" \
     -X GET \
     https://api.gridscale.io/objects/networks | python -m json.tool
 
# response
{
    "networks": {
        "6dd023d1-9d71-448a-ac80-d3e2c2aaf954": {
            "change_time": "2016-01-28T15:51:03Z",
            "create_time": "2016-01-28T15:51:03Z",
            "labels": [],
            "location_country": "de",
            "location_iata": "fra",
            "location_name": "de/fra",
            "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950",
            "name": "gesch\u00fctztes Netzwerk",
            "object_uuid": "6dd023d1-9d71-448a-ac80-d3e2c2aaf954",
            "public_net": false,
            "relations": {
                "servers": []
            },
            "status": "active"
        },
        "d20386b7-5892-447b-9e40-917d9b7a4c44": {
            "change_time": "2015-10-02T23:29:56Z",
            "create_time": "2015-10-02T23:29:56Z",
            "labels": [],
            "location_country": null,
            "location_iata": null,
            "location_name": null,
            "location_uuid": null,
            "name": "Public Network",
            "object_uuid": "d20386b7-5892-447b-9e40-917d9b7a4c44",
            "public_net": true,
            "relations": {
                "servers": []
            },
            "status": "active"
        }
    }
}

Bei dem Public-Netzwerk interessiert uns erneut nur die object_uuid die wir wieder in einer Environment Variable speichern:

export X_PUBLIC_NET="d20386b7-5892-447b-9e40-917d9b7a4c44"

Jetzt die beiden Server erstellen:

# Server 1
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"name": "Server 1", "cores":1, "memory":1, "location_uuid":"'$X_LOCATION'"}' \
     https://api.gridscale.io/objects/servers
 
# response
{"object_uuid": "e25b9248-4efd-4654-97ca-526ebb0626a4"}

Die object_uuid die wir für den “Server 1” erhalten haben wieder in eine Environment Variable:

export X_SERVER1="e25b9248-4efd-4654-97ca-526ebb0626a4"
# Server 2
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"name": "Server 2", "cores":1, "memory":1, "location_uuid":"'$X_LOCATION'"}' \
     https://api.gridscale.io/objects/servers
 
# response
{"object_uuid": "f11aac20-0a96-4434-b637-204da08fc4ea"}

Und nun die beiden Server mit den Netzwerken verbinden – beide antworten mit Statuscode 204 (No Content):

# Server 1 -> Public-Netzwerk
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"'$X_PUBLIC_NET'"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER1/networks
 
# Server 1 -> Private-Netzwerk
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"'$X_PRIVATE_NET'"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER1/networks
 
# Server 2 -> Public-Netzwerk
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"'$X_PUBLIC_NET'"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER2/networks
 
# Server 2 -> Private-Netzwerk
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"'$X_PRIVATE_NET'"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER2/networks

Bist du bereit zu starten?

Oder hast du noch Fragen? Lasse dir jetzt dein Konto erstellen oder dich in einem persönlichen Gespräch beraten.

Die Server sind nun konfiguriert und mit den passenden Netzwerken verbunden. Nun installieren wir für jeden der Server ein Storage mit einem Debian 8 Template.

Zuerst jedoch brauchen wir die object_uuid des passenden Templates und rufen dafür eine Liste aller für uns verfügbaren Templates ab:

curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId:$X_USERID" \
     -H "X-Auth-Token:$X_TOKEN" \
     -X GET \
     https://api.gridscale.io/objects/templates | python -m json.tool
 
# response (gekürzt)
[...]
        "a5112c72-c9fa-4a23-8115-5f6303eb047b": {
            "capacity": 1,
            "change_time": "2015-10-03T12:57:21Z",
            "create_time": "2015-10-03T12:57:21Z",
            "current_price": 0.0,
            "description": "no swap",
            "location_country": "de",
            "location_iata": "fra",
            "location_name": "de/fra",
            "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950",
            "name": "Debian 8 (64bit)",
            "object_uuid": "a5112c72-c9fa-4a23-8115-5f6303eb047b",
            "ostype": "linux",
            "private": false,
            "status": "active",
            "version": "8.1"
        },
[...]

Und wieder eine Environment Variable für das Template:

export X_TEMPLATE="a5112c72-c9fa-4a23-8115-5f6303eb047b"

Man kann Templates entweder mit SSH-Keys oder mit Passwörtern installieren – um das Beispiel einfach zu halten nutzen wir ein zufällig generiertes Passwort (wieder als Environment Variable gesetzt):

export X_ROOTPW="$(pwgen 8 1)"
echo "Root-Passwort: $X_ROOTPW"

Jetzt die beiden Storages installieren – jeweils 10GB Kapazität reichen für unser Beispiel:

# Server 1
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"name": "Server 1 Storage", "location_uuid":"'$X_LOCATION'", "capacity": 10, "template": {"hostname": "server1", "template_uuid": "'$X_TEMPLATE'", "password": "'$X_ROOTPW'", "password_type": "plain"}}' \
     https://api.gridscale.io/objects/storages
 
# response:
{"object_uuid": "3ee3be75-a7c0-4d07-9815-b2345c9f6290"}
 
# geschützter Server
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"name": "Server 2 Storage", "location_uuid":"'$X_LOCATION'", "capacity": 10, "template": {"hostname": "server2", "template_uuid": "'$X_TEMPLATE'", "password": "'$X_ROOTPW'", "password_type": "plain"}}' \
     https://api.gridscale.io/objects/storages
 
# response:
{"object_uuid": "3d152618-7547-4f34-b957-1afac9d29ede"}

Und die Environment Variablen für die Storages:

export X_STORAGE_SERVER1="3ee3be75-a7c0-4d07-9815-b2345c9f6290"
export X_STORAGE_SERVER2="3d152618-7547-4f34-b957-1afac9d29ede"

Fast geschafft – jetzt noch die fertigen Storages mit den Servern verbinden:

curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"'$X_STORAGE_SERVER1'"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER1/storages
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"'$X_STORAGE_SERVER2'"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER2/storages

Und damit wir die Server auch erreichen können über das Internet noch jeweils eine IPv4- und eine IPv6-Adresse anfordern und zuweisen.

# Server 1
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"family": 4, "location_uuid":"'$X_LOCATION'"}' \
     https://api.gridscale.io/objects/ips
 
# response:
{"object_uuid": "2f811423-371b-4694-aed4-ec57003b9600", "ip": "185.102.95.70"}
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"family": 6, "location_uuid":"'$X_LOCATION'"}' \
     https://api.gridscale.io/objects/ips
 
# response:
{"object_uuid": "a08bb5a1-3ae4-408a-abe8-f6e241829c68", "ip": "2a06:2380:0:1::26"}
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"2f811423-371b-4694-aed4-ec57003b9600"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER1/ips
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"a08bb5a1-3ae4-408a-abe8-f6e241829c68"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER1/ips
# Server 2
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"family": 4, "location_uuid":"'$X_LOCATION'"}' \
     https://api.gridscale.io/objects/ips
 
# response:
{"object_uuid": "364b4769-28e7-4e15-9d17-62d2f131b776", "ip": "185.102.95.71"}
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"family": 6, "location_uuid":"'$X_LOCATION'"}' \
     https://api.gridscale.io/objects/ips
 
# response:
{"object_uuid": "ced650c5-2007-48a1-839b-5f7a383bb66a", "ip": "2a06:2380:0:1::27"}
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"364b4769-28e7-4e15-9d17-62d2f131b776"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER2/ips
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X POST \
     -d '{"object_uuid":"ced650c5-2007-48a1-839b-5f7a383bb66a"}' \
     https://api.gridscale.io/objects/servers/$X_SERVER2/ips

So – als letzten Schritt nun beide Server starten. Du kannst den Servern auf der Systemkonsole im Panel beim Booten zusehen:

curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X PATCH \
     -d '{"power":true}' \
     https://api.gridscale.io/objects/servers/$X_SERVER1/power
 
curl -H "Content-Type: application/json" \
     -H "X-Auth-UserId: $X_USERID" \
     -H "X-Auth-Token: $X_TOKEN" \
     -X PATCH \
     -d '{"power":true}' \
     https://api.gridscale.io/objects/servers/$X_SERVER2/power

Warte ein paar Sekunden und schon kannst du dich auf beide Server mit den eingerichteten IPs per SSH verbinden.
Beide Server sind jetzt bereit und wir richten als letzten Schritt nur noch das interne Netzwerk ein.

Ändere die Werte für “address”, “netmask” und “broadcast” passend für dein internes Netzwerk. Im internen Netzwerk ist außerdem eine MTU von 9000 sinnvoll, um einen höheren Datendurchsatz zwischen deinen Servern zu erreichen.

Server 1

# nano -w /etc/network/interfaces
 
source /etc/network/interfaces.d/*
 
# The loopback network interface
auto lo
iface lo inet loopback
 
# The primary network interface
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp
iface eth0 inet6 dhcp
 
# The internal LAN interface (eth1)
allow-hotplug eth1
iface eth1 inet static
   address 10.0.0.1
   netmask 255.255.255.0
   network 10.0.0.0
   broadcast 10.0.0.255
   mtu 9000

Server 2

# nano -w /etc/network/interfaces
 
source /etc/network/interfaces.d/*
 
# The loopback network interface
auto lo
iface lo inet loopback
 
# The primary network interface
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp
iface eth0 inet6 dhcp
 
# The internal LAN interface (eth1)
allow-hotplug eth1
iface eth1 inet static
   address 10.0.0.2
   netmask 255.255.255.0
   network 10.0.0.0
   broadcast 10.0.0.255
   mtu 9000