Aus Linux-Magazin 03/2018

Hybrid-Cloud weitgehend automatisch ausrollen

© bogdan mircea hoda, 123RF

Die eigene IT als digitalen Mix aus eigenen Servern und Public oder Private Clouds gestalten, das wäre technisch elegant und auf Dauer kostengünstig – aber aufwändig in der Einrichtung. Dass dank Ansible der letzte Punkt nicht so schwer wiegt wie angenommen, zeigt der folgende Artikel.

Nach seriösen Schätzungen wird kommendes Jahr die Hälfte der Unternehmen eine hybride Cloudarchitektur betreiben. Offenbar überzeugen die Vorteile des Mixes aus physisch in der Firma verbleibender, gewachsener IT und Public sowie Private Clouds beim externen Dienstleister. Oft geben geringere laufende Kosten den Ausschlag für Hybrid. Vielfach stellen sich aber auch funktionelle Vorteile ein. Angeblich agieren Firmen mit solchen IT-Strukturen erfolgreicher als ihre Mitbewerber [1].

Dass die Hybrid-Cloud in der Praxis noch nicht verbreiteter ist, liegt wohl an dem Aufwand, sie einzuführen. Dieser Artikel will beweisen, dass jeder Admin mit wenig Mühe einen beachtlichen Schritt dorthin gehen und zugleich Erfahrungen sammeln kann, um weitere Teile der lokalen IT auszulagern. Der Beitrag wird am Beispiel von AWS zeigen, wie Admins mit zwei Linux-VMs eine sichere Infrastruktur bauen, die von ihrer Struktur her sogar mandantenfähig ist. Das für den Admin Charmante ist: Nicht er selbst manuell, sondern Ansible [2] wird die Arbeitsschritte des Setup umsetzen.

Viele Anwender meinen noch, dass virtuelle Maschinen in der Cloud stets öffentlich erreichbar sind. Administratoren, die sich etwas mit den virtuellen Netzwerkinfrastrukturen bei AWS oder Azure beschäftigt haben, wissen aber, dass dort neben öffentlich zugänglichen VMs auch private Netze, VPNs und Router gängig sind. AWS und Azure bieten sogar VPNs in das private Firmennetz As a Service (kostenpflichtig) an (siehe Kasten “Amazon-Netzwerk-Glossar”).

Amazon-Netzwerk-Glossar

AWS’ Elastic Cloud Service erlaubt es, VMs komplex zu vernetzen, wie es in Open Stack oder VMware auch möglich ist. Jedoch muss der Admin dabei Amazons Logik beachten. Damit die Zielarchitektur in diesem Artikel verstehbar wird, ist eine kurze Einführung in die Begrifflichkeiten hilfreich.

Die höchste Hierarchiestufe ist ein Account, er kann zum Beispiel einer Firma gehören. Mehrere Mitarbeiter genießen dann Zugriff auf die Umgebung, deren VMs und andere Ressourcen. Der Account ist dem Projekt bei Open Stack vergleichbar.

AWS unterteilt die dem Kunden angebotene Infrastruktur in Regionen. Dies bezeichnet, wo auf der Welt das Rechenzentrum und damit die Daten liegen. Auch jedes Netzwerksetup ist relativ zu einer Region. Will der Admin seine Hybrid-Cloud in Irland und Deutschland betreiben, muss er das in diesem Artikel vorgestellte Konzept auch zweimal aufbauen.

Innerhalb des Accounts gibt es so genannte Virtual Private Clouds (VPCs). Pro Region und Account sind fünf VPCs möglich. In einer VPC kann der Anwender bis zu 200 getrennte Subnetze anlegen ([3] zeigt die Limits). Zwischen VPCs (auch zwischen Accounts) lässt sich ein Peering anlegen, das gezielt Traffic routet. Beide Peering-Partner müssen zustimmen, was besonders wichtig ist, wenn man eine Verbindung zwischen zwei Accounts aufbaut.

VMs in Subnetzen bekommen zunächst nur eine Adresse aus dem dem Subnetz zugeordneten Adressblock und sind von außen nicht erreichbar. Verwendet der Admin die Option Public IP Address, bekommt die VM zusätzlich eine IP-Adresse aus den öffentlichen Adressblöcken von AWS. Damit geschlossene VMs das Internet erreichen, muss dem Subnetz ein NAT-Gateway zugeordnet sein. Der Admin darf beim Erzeugen eines Subnetzes festlegen, dass jede VM, die er an dieses Netz bindet, automatisch eine öffentliche IP zugewiesen bekommt.

Routen speichert AWS wie erwartet in Routingtabellen. Die pflegt der Admin als separate Einheiten, die er einem VPC zuweist.

Security Groups beschreiben bei AWS eine Menge von IP-Filtern (ein- und ausgehend), die der Kunde auf eine VM anwendet, um von außen zu steuern, welche Pakete sie schicken darf beziehungsweise welche sie erreichen.

AWS bietet einen eigenen, recht kostenintensiven VPN as a Service. Daher verwendet das Setup des Artikels eine eigene VPN-VM, die preisgünstiger ausfällt – genauer: ausfallen kann, denn bei einer großen, teuren Amazon-Instanzgröße könnten die Kosten höher sein.

Die Zielarchitektur

Abbildung 1 zeigt die angestrebte Architektur, die der Autor als Projekt aufgebaut hat. Im lokalen Rechenzentrum rechts im Bild steht ein VPN-Gateway, das die Verbindung zum Gateway im AWS herstellt. Dies lässt sich zusammen mit der Firewall implementieren oder durch ein getrenntes Gateway. Außerdem konfiguriert Ansible eine lokale Open-VPN-Instanz, da der Autor schon VPN-Playbooks für Libre Swan, Fortinet und Juniper-Firewalls gebaut hat, könnte er die Komponente auch leicht austauschen.

Auf der AWS-Seite gestaltet sich der Aufbau etwas komplizierter, da der Autor eine mandantenfähige Lösung entwickeln wollte, also eine VM zum Internet, die an verschiedene geschlossene Umgebungen weiterleitet. Da die VPN-Daten in den geschlossenen Umgebungen dem Frontend nicht bekannt sein werden, dort aber trotzdem noch eine Eingangskontrolle auf Basis von IP-Adressen stattfindet, leitet die AWS-VM oben links die eingehenden Pakete per »socat« an den eigentlichen VPN-Service im geschlossenen Netz weiter, sodass trotzdem eine verschlüsselte Ende-zu-Ende-Verbindung entsteht. Wer keine Mandantenfähigkeit anstrebt, kann diese Indirektion aus dem Aufbau weglassen.

Im Subnetz im AWS existiert eine Routingtabelle, die dafür sorgt, dass das Routing zwischen dem lokalen Netze des eigenen Rechenzentrums und der AWS-VM mit Open VPN passiert.

Abbildung 1: Diese hybride Architektur ist das Ziel des vorgestellten Setup. Rechts ist der hier relevante Teil der IT im eigenen Haus zu sehen, links das anzulegende Setup in der Amazon-Cloud.

Abbildung 1: Diese hybride Architektur ist das Ziel des vorgestellten Setup. Rechts ist der hier relevante Teil der IT im eigenen Haus zu sehen, links das anzulegende Setup in der Amazon-Cloud.

Netze und Peering

Wie bei anderen Virtualisierungsumgebungen auch beginnt der Admin mit dem Setup der virtuellen Netzwerk-Infrastruktur, damit die VMs am Schluss in den richtigen Netzen landen. Bei AWS legt er zuerst zwei VPCs an, das innere für die geschlossene Umgebung, das äußere für die Gateway-VM (Abbildung 2). Zu beiden gehört ein privates IP-Netz.

Das innere sollte so gewählt sein, dass es nicht mit dem Netz im eigenen Rechenzentrum kollidiert, da auf lokaler Seite ja die Routen in diesen Netzbereich auf das lokale VPN-Gateway zeigen müssen. Im externen Block reicht es, einen kleinen Netzbereich zu wählen, da dieser ja nur als Übergang dient. AWS benötigt nun noch Subnet-Objekte, deren IP-Netze jeweils eine Teilmenge des Gesamtbereichs des VPC zu sein haben.

Im nächsten Schritt legt der Admin ein VPC-Peering, womit er gewissermaßen ein virtuelles Kabel zwischen die beiden VPCs steckt (Abbildung 3). Dieses Peering muss der Admin in einem eigenen Arbeitsschritt akzeptieren. Damit die spätere VM im äußeren VPC hinausfindet, besteht der folgende Arbeitsschritt darin, ein Internetgateway anzulegen.

Abbildung 2: Zwei anzulegende VPCs bilden die Grundlage auf der AWS-Seite.

Abbildung 2: Zwei anzulegende VPCs bilden die Grundlage auf der AWS-Seite.

Abbildung 3: Hier erfolgt das Peering, das der Admin in einem extra Schritt bestätigen muss.

Abbildung 3: Hier erfolgt das Peering, das der Admin in einem extra Schritt bestätigen muss.

Das VPN-Routing

Die Konfigurationen bis hierhin bildet die Layer-2-Verkabelung nach, die auch bei einem physischen Aufbau notwendig wäre. Nun folgt das IP-Routing. In der Routingtabelle für das innere VPC setzt der Admin eine Route in das äußere Subnetz. Da die VPN-Verbindungen auf Applikationsebene (»socat«) weitergeleitet werden, besteht keine direkte IP-Verbindung zwischen dem VPN-Gateway und dem Internet. Das Ziel dieser Router ist das VPC-Peering – vergleichbar dem Setzen einer Interface-Route per »ip route add 1.2.3.0/24 dev eth0«.

Umgekehrt muss das externe VPC wissen, wie es zum internen findet. Das macht Routen zum internen Subnetz und ebenfalls zum VPC-Peering notwendig. Außerdem muss die Defaultroute des externen VPC auf das zuvor angelegte Internetgateway zeigen.

Die Konfiguration der Sicherheit schließt den Aufbau den virtuellen Netzwerks ab: Das VPN-Gateway im internen VPC braucht eingehend den Port für das VPN (im Falle Open VPN 1194/UDP, für IPsec mit NAT-Traversal 500/UDP und 4500/UDP). Damit der Admin noch auf die VM selber zugreifen darf, ist auch SSH-Zugang notwendig, also eingehend 22/TCP. Das Gleiche gilt für den externen Gatewayrechner. Hier lässt sich der VPN-Eingang dann auf die festen IPs der lokalen VPN-Gateways – so vorhanden – begrenzen. Das ist zwar kein sehr starker Schutz (vor allem bei UDP), es schränkt aber zumindest das Grundrauschen aus dem Internet etwas ein.

Zwei virtuelle Maschinen

Nun fehlen noch zwei VM-Instanzen, welche die Arbeit erledigen. Die bekommen die vorgesehene Software installiert und konfiguriert: Socat als Service auf der äußeren und Open VPN als VPN-Software auf der inneren.

Für das Anlegen einer VM benötigt der Admin eine Image-ID (»ami-id« in AWS-Sprache) und eine Instanzgröße. Für den Aufbau hier genügen die kleinen »t2.micro«-Instanzen vollkommen, da die Performance für die Internetanbindungen der meisten Firmen ausreicht. Wer einen 10-GBit-Anschluss ins Internet sein Eigen nennt, sollte die Größe der Instanz entsprechend anpassen. Den beiden Instanzen weist der Admin die richtigen VPCs und Subnetze sowie die vorher eingerichteten Security-Gruppen zu.

Beide VMs fußen auf einem Ubuntu-16.04-Server-Image (Abbildung 4). Die vordere VM erhält Socat als Portforwarder, den Systemd als Service startet. Für das VPN wäre dies bereits genug, aber die innere VM hat keinen Internetzugang, benötigt also zum Installieren der Pakete einen Proxy. Daher bekommt die vordere VM einen Squid-Webproxy verpasst, der allerdings so eingeschränkt ist, dass nur Clients aus dem internen Subnetz ihn verwenden dürfen. Entsprechend muss der Admin die Security Group noch um den Port 3128/TCP aus diesem Netz erweitern.

Auf die innere VM kommt Open VPN im Server-Modus. VMs im inneren Netz benötigen eine Route durch das Open-VPN-Gateway hindurch auf das lokale Netz des heimischen Rechenzentrums.

Abbildung 4: Beide anzulegenden VMs fußen auf einem von Amazon bereitgestellten Ubuntu-16.04-Server-Image.

Abbildung 4: Beide anzulegenden VMs fußen auf einem von Amazon bereitgestellten Ubuntu-16.04-Server-Image.

Ansible vereinfacht und automatisiert das Ganze

Konfiguriert der Admin dies alles per Hand, bedeutet das schon einige Arbeit im AWS-Web-GUI. Dazu kommt noch, dass die Parameter auch alle zusammenpassen müssen, etwa die IP-Adressen der Netze und die entsprechenden Einträge in den Routingtabellen. Später gehen die Adressen auch in die Konfiguration der Services auf den VMs ein. Hier bieten sich dem Admin viele Möglichkeiten für Fehler, zumal das Nachgucken “Wie war noch mal die Adresse?” den Arbeitsfluss im Web-GUI unterbricht.

Ansibles Cloudmodule decken dagegen alles ab, was zum Anlegen notwendig ist. Dabei muss das Playbook immer die Ergebnisse des Anlegens einer Komponente speichern, da die IDs der einzelnen Komponenten notwendig sind, um die nächste anzulegen. Die von Amazon zugewiesene IP-Adresse der inneren VM muss der Admin zum Beispiel auch in der Socat-Konfiguration auf der äußeren VM eintragen.

Dank Ansible entsteht die ganze Konfiguration aus einem Guss und es passieren weniger Fehler. Das Gesamtensemble besitzt zwei Rollen für die Konfiguration auf der inneren und der äußeren VM. Am Anfang baut das Playbook die gesamte Infrastruktur auf.

Ein paar Daten sind parametrisiert, etwa die AWS-Region, der Adressraum für das innere VPC und das Subnetz sowie die Subnetz im lokalen LAN, damit das Generieren der VPN-Konfiguration gelingt. Diese Daten liest das Playbook aus einer Yaml-Datei ganz am Anfang.

Damit das Playbook überhaupt auf AWS zugreifen darf, muss der Admin entweder eine Datei in »~.aws/credentials« besitzen, die die Einträge »aws_access_key« und »aws_secret_access_key« enthält. Oder er setzt die Werte im Playbook als Variablen (besser über einen Ansible-Vault für die Sicherheit) oder hinterlegt sie in Environment-Variablen. Die Dokumentation der Cloudmodule (etwa unter [4]) erläutert die Varianten.

Die einzige Möglichkeit, auf eine VM in AWS zuzugreifen, ist eine SSH-Verbindung. Eine Konsole wie bei anderen Hostern gibt es nicht. Daher sollte auch der SSH-Schlüssel des Admin bei AWS hinterlegt sein. Listing 1 zeigt die Liste der Tasks, um den Schlüssel hochzukopieren (das geschieht nur, wenn er dort noch nicht vorhanden ist), die VPCs mit je einem Subnetz anzulegen und das VPC-Peering zu erzeugen.

Am Ende jeder »ec2«-Anweisung steht ein »register«-Block, der das Ergebnis der Operation in einer Variablen speichert. Zum Anlegen eines Subnet ist die ID des VPC notwendig, in dem das Subnet liegen soll. Das Gleiche passiert ab Zeile 49 auch fürs Peering, um es erst anzulegen und dann zu akzeptieren. Die letzte Task erzeugt das Internetgateway.

Listing 1

Tasks für die Basis und das Netzwerk

01 - name: Load Data
02   include_vars: "{{ datafile }}"
03   tags: getdata
04
05 - name: SSH Key
06   ec2_key:
07     name: ansible-admin-key
08     key_material: "{{ item }}"
09     state: present
10     region: "{{ region }}"
11   with_file: /home/user/.ssh/id_rsa.pub
12   register: sshkey
13   tags: sshkey
14
15 - name: Create VPC INT
16   ec2_vpc_net:
17     name: "{{ netname }}-int"
18     cidr_block: "{{ cidr_master }}"
19     region: "{{ region }}"
20   tags: create_vpc_int
21   register: myvpcint
22
23 - name: Create Subnet INT
24   ec2_vpc_subnet:
25     cidr: "{{ subnet }}"
26     vpc_id: "{{ myvpcint.vpc.id }}"
27     region: "{{ region }}"
28     state: present
29   tags: create_subnet_int
30   register: mysubnetint
31
32 - name: Create VPC Ext
33   ec2_vpc_net:
34     name: "{{ netname }}-ext"
35     cidr_block: 172.25.0.0/28
36     region: "{{ region }}"
37   tags: create_vpc_ext
38   register: myvpcext
39
40 - name: Create Subnet Ext
41   ec2_vpc_subnet:
42     cidr: 172.25.0.0/28
43     vpc_id: "{{ myvpcext.vpc.id }}"
44     region: "{{ region }}"
45     state: present
46   tags: create_subnet_ext
47   register: mysubnetext
48
49 - name: Create VPC Peering
50   ec2_vpc_peer:
51     region: "{{ region }}"
52     vpc_id: "{{ myvpcint.vpc.id }}"
53     peer_vpc_id: "{{ myvpcext.vpc.id }}"
54     state: present
55   register: myvpcpeering
56   tags: createvpcpeering
57
58 - name: Accept VPC Peering
59   ec2_vpc_peer:
60     region: "{{ region }}"
61     peering_id: "{{ myvpcpeering.peering_id }}"
62     state: accept
63   register: action_peer
64
65 - name: Create Internet Gateway
66   ec2_vpc_igw:
67     vpc_id: "{{ myvpcext.vpc.id }}"
68     region: "{{ region }}"
69     state: present
70   register: igw
71   tags: igw

Routing und VMs anlegen

Listing 2 zeigt den zweiten Teil des Playbook. Die Gather-Routes-Task sucht im internen VPC die Routingtabelle raus, um in diese die Route auf das äußere Netz einzutragen. Dann setzt das Playbook die Route von innen nach außen und in der umgekehrten Richtung. Die nächsten zwei Tasks erzeugen die Security-Gruppen für beide VMs.

Die letzte Task im Listing ist bedingt durch eine Eigenheit von Ansible, die ohne dieses laut AWS-API nicht notwendig ist. Das API kann einem Subnet mitgeben, ob Hosts in diesem Subnetz auch immer automatisch eine Public-IP zugewiesen bekommen sollen. Das geht in Ansible nur durch die im Listing gezeigte, nachträgliche Änderung.

Listing 3 sorgt für das Anlegen der beiden VMs. Die Tasks erzeugen die VMs und fügen sie jeweils zu einer Gruppe hinzu. Diese Gruppen werden gleich die folgenden Plays verwenden, um per SSH die Software zu installieren und zu konfigurieren. Die letzte Task des ersten Play wartet jetzt noch ab, bis die äußere VM per SSH erreichbar ist.

Listing 2

Routen und Filterregeln

01 - name: Gather Route tables
02   ec2_vpc_route_table_facts:
03     region: "{{ region }}"
04     filters:
05       vpc-id: "{{ myvpcint.vpc.id }}"
06   register: inttables
07   tags: gatherroutes
08
09 - name: Set Route out
10   ec2_vpc_route_table:
11     vpc_id: "{{ myvpcint.vpc.id }}"
12     region: "{{ region }}"
13     route_table_id: "{{ inttables.route_tables[0].id }}"
14     tags:
15       Name: "{{ netname }}-int"
16     subnets:
17       - "{{ mysubnetint.subnet.id }}"
18     routes:
19       - dest: 172.25.0.0/28
20         vpc_peering_connection_id: "{{ myvpcpeering.peering_id }}"
21   register: outboundroutetable
22   tags: routeout
23
24 - name: Set Route in
25   ec2_vpc_route_table:
26     vpc_id: "{{ myvpcext.vpc.id }}"
27     region: "{{ region }}"
28     tags:
29       Name: "{{ netname }}-ext"
30     subnets:
31       - "{{ mysubnetext.subnet.id }}"
32     routes:
33       - dest: "{{ subnet }}"
34         vpc_peering_connection_id: "{{ myvpcpeering.peering_id }}"
35       - dest: 0.0.0.0/0
36         gateway_id: igw
37   register: outboundroutetable
38   tags: routein
39
40 - name: internal Secgroup
41   ec2_group:
42     name: "{{ netname }}-int-secgroup"
43     vpc_id: "{{ myvpcint.vpc.id }}"
44     region: "{{ region }}"
45     purge_rules: true
46     description: Ansible-Generated internal rule
47     rules:
48       - proto: udp
49         from_port: 12345
50         to_port: 12345
51         cidr_ip: 0.0.0.0/0
52       - proto: tcp
53         from_port: 22
54         to_port: 22
55         cidr_ip: 0.0.0.0/0
56       - proto: tcp
57         from_port: 443
58         to_port: 443
59         cidr_ip: 0.0.0.0/0
60   register: intsecg
61   tags: internalsec
62
63 - name: external Secgroup
64   ec2_group:
65     name: "{{ netname }}-ext-secgroup"
66     vpc_id: "{{ myvpcext.vpc.id }}"
67     region: "{{ region }}"
68     purge_rules: true
69     description: Ansible-Generated internal rule
70     rules:
71       - proto: udp
72         from_port: 12345
73         to_port: 12345
74         cidr_ip: 0.0.0.0/0
75       - proto: tcp
76         from_port: 22
77         to_port: 22
78         cidr_ip: 0.0.0.0/0
79       - proto: tcp
80         from_port: 443
81         to_port: 443
82         cidr_ip: 0.0.0.0/0
83       - proto: tcp
84         from_port: 3128
85         to_port: 3128
86         cidr_ip: "{{ subnet }}"
87   register: extsecg
88   tags: externalsec
89
90 - name: Update Auto
91   ec2_auto_assign_public_ip_for_subnet:
92     subnet: "{{ mysubnetext.subnet.id }}"
93     region: "{{ region }}"
94     state: present

Listing 3

Ausrollen der VMs

01 - name: Deploy Backend
02   ec2:
03     key_name: ansible-user-key
04     instance_type: t2.micro
05     image: ami-d15a75c7
06     region: "{{ region }}"
07     wait: yes
08     id: test-backend
09     assign_public_ip: no
10     vpc_subnet_id: "{{ mysubnetint.subnet.id }}"
11     group_id: "{{ intsecg.group_id }}"
12   register: backendvm
13   tags: createbackend
14
15 - name: add frontend to group
16   add_host:
17     hostname: "{{ item.private_ip }}"
18     groupname: backend
19   with_items: "{{ backendvm.instances }}"
20
21
22 - name: Deploy Frontend
23   ec2:
24     key_name: ansible-user-key
25     instance_type: t2.micro
26     image: ami-d15a75c7
27     region: "{{ region }}"
28     wait: yes
29     id: test-frontend
30     assign_public_ip: yes
31     vpc_subnet_id: "{{ mysubnetext.subnet.id }}"
32     group_id: "{{ extsecg.group_id }}"
33   register: frontendvm
34   tags: createfrontend
35
36 - name: add frontend to group
37   add_host:
38     hostname: "{{ item.public_ip }}"
39     groupname: frontend
40   with_items: "{{ frontendvm.instances }}"
41
42 - name: Wait for ssh of frontend
43   wait_for:
44     host: "{{ item.public_dns_name }}"
45     port: 22
46     state: started
47   with_items: "{{ frontendvm.instances }}"

Von der Rolle

Das zweite und das dritte Play im Playbook konfigurieren die Software auf beiden VMs über jeweils eine Rolle. Besonders wichtig ist das letzte Play in Listing 4, da die innere VM nur über die äußere erreichbar ist, muss sie das SSH-Kommando über »ansible_ssh_common_args« umbiegen, damit die innere VM die äußere als Proxy verwendet. Das Einpacken in Rollen hat der Autor hier nur vorgenommen, da er die Konfiguration auf den VMs recycelbar haben wollte.

Listing 5 zeigt das Frontend-Play beziehungsweise die Tasks aus der Rolle. Die erste Task installiert Python im Raw-Modus, da auf dem verwendeten AWS-Ubuntu-Image kein Python installiert ist. Dann installiert und konfiguriert Ansible die Pakete Socat und Squid. Auffällig zeigt sich hier Socat, das ja eigentlich kein Service ist. Erst ein Systemd-Unitfile macht es zu einem Dienst auf UDP und 443/TCP. Die Zieladresse der inneren VM zum Weiterverbinden holt sich das Template aus dem vorherigen Playbook-Lauf. Das Play ab Zeile 43 schaltet die Dienste scharf und startet sie.

Das Listing 6 übernimmt die Konfiguration der inneren VM. Die kann nicht mit der Installation von Python beginnen, da »apt« erst mal mit dem vorgelagerte Proxy Bekanntschaft schließen muss, was hier auch im Raw-Modus geschieht.

Als Softwarepaket installiert die Rolle dann lediglich Open VPN und konfiguriert zwei Instanzen, eine auf dem UDP-Port und eine auf TCP/443. Diese Instanzen setzt ein Eintrag in der Datei »/etc/default/openvpn« auf Autostart. Das letzte Play im Listing schaltet den Open-VPN-Dienst an und startet ihn. Die SSL-Schlüssel waren in diesem Beispiel schon vorkonfiguriert. Es ist dem Admin selbst überlassen, per Ansible Zertifikate zu generieren und hochzuladen.

Listing 4

Die letzten beiden Plays

01 - name: Configure Frontend
02   hosts: frontend
03   remote_user: ubuntu
04   gather_facts: no
05   roles:
06     - agouros.aws.frontend
07
08 - name: Configure Backend
09   hosts: backend
10   remote_user: ubuntu
11   gather_facts: no
12   vars:
13     ansible_ssh_common_args: "-o ProxyCommand='ssh -W %h:%p -q ubuntu@{{ hostvars['localhost']['frontendvm']['instances'][0]['public_ip'] }}'"
14   roles:
15     - agouros.aws.backend

Listing 5

Die Installation des Frontends

01 - name: Install Python
02   raw: test -e /usr/bin/python || (sudo -s apt-get -y install python)
03
04 - name: Install Software
05   become: true
06   become_method: sudo
07   apt:
08     name: "{{ item }}"
09     state: present
10     cache_valid_time: 86400
11   with_items:
12     - socat
13     - squid
14
15 - name: Configure Squid
16   become: true
17   become_method: sudo
18   template:
19     src: templates/squid.conf.j2
20     dest: /etc/squid/squid.conf
21   notify: restart squid
22
23 - name: Configure socat
24   become: true
25   become_method: sudo
26   template:
27     src: templates/socat.service.j2
28     dest: /etc/systemd/system/socat.service
29   notify:
30     - daemon-reload
31     - start socat
32
33 - name: Configure socat443
34   become: true
35   become_method: sudo
36   template:
37     src: templates/socat443.service.j2
38     dest: /etc/systemd/system/socat443.service
39   notify:
40     - daemon-reload
41     - start socat
42
43 - name: Start and enable Services
44   become: true
45   become_method: sudo
46   systemd:
47     enabled: yes
48     state: started
49     daemon-reload: yes
50     name: "{{ item }}"
51   with_items:
52     - squid
53     - socat
54     - socat443

Listing 6

Die Konfiguartion der inneren VM

01 - name: Debug1
02   debug: msg="{{ inventory_hostname }}"
03
04 - name: Set Proxy
05   raw: test -e /etc/apt/apt.conf.d/80proxy || (sudo sh -c 'echo "Acquire::http::proxy \"http://{{ hostvars['localhost']['frontendvm']['instances'][0]['private_ip']  }}:3128\";" >  /etc/apt/apt.conf.d/80proxy')
06
07 - name: Install Python
08   raw: test -e /usr/bin/python || (sudo -s apt-get -y install python)
09
10 - name: Install Software
11   become: true
12   become_method: sudo
13   apt:
14     name: "{{ item }}"
15     state: present
16     cache_valid_time: 86400
17   with_items:
18     - openvpn
19
20 - name: Set OpenVPN Name
21   become: true
22   become_method: sudo
23   lineinfile:
24     path: /etc/default/openvpn
25     regexp: "^AUTOSTART"
26     line: "AUTOSTART=\"{{ hostvars['localhost']['netname'] }} {{ hostvars['localhost']['netname'] }}-443\""
27
28 - name: Send SSL Files
29   become: true
30   become_method: sudo
31   copy:
32     src: "{{ item }}"
33     dest: /etc/openvpn
34     owner: root
35     mode: 0600
36   with_fileglob:
37     - "files/*"
38
39 - name: ccd-dir
40   become: true
41   become_method: sudo
42   file:
43     dest: /etc/openvpn/ccd
44     state: directory
45     mode: 0755
46     owner: root
47     group: root
48
49 - name: clientfile
50   become: true
51   become_method: sudo
52   template:
53     src: templates/clientfile.j2
54     dest: /etc/openvpn/ccd/clientfile
55
56 - name: OpenVPN Group
57   become: true
58   become_method: sudo
59   group:
60     name: openvpn
61     state: present
62
63 - name: OpenVPN user
64   become: true
65   become_method: sudo
66   user:
67     name: openvpn
68     state: present
69     groups: openvpn
70     system: yes
71
72 - name: Configure Openvpn
73   become: true
74   become_method: sudo
75   template:
76     src: templates/openvpn.conf.j2
77     dest: "/etc/openvpn/{{ hostvars['localhost']['netname']}}.conf"
78
79 - name: Configure Openvpn
80   become: true
81   become_method: sudo
82   template:
83     src: templates/openvpn.conf-443.j2
84     dest: "/etc/openvpn/{{ hostvars['localhost']['netname']}}-443.conf"
85
86 - name: Enable and start service
87   become: true
88   become_method: sudo
89   systemd:
90     name: openvpn
91     enabled: true
92     state: restarted

Ziel erreicht

Das Erweitern des eigenen Rechenzentrums um Ressourcen aus der Cloud kann deutlich Gesamtkosten sparen. Der Effekt tritt vor allem bei in der Anschaffung sehr teurer Dienste ein und bei Diensten, welche die eigene Firma nur gelegentlich braucht. Zu letzteren gehören auch zusätzliche Instanzen zum eigenen Webshop oder Webserver, wenn absehbar ein Kundenansturm droht.

Damit die Clouddienste aber – außer dies ist gerade gewünscht – nicht frei im Internet stehen, erlaubt es die Infrastruktur durchaus, AWS fast wie ein weiteres eigenes Rechenzentrum anzubinden. Für temporäre Ressourcen wäre ein händischer Auf- und Abbau aber sehr mühselig. Automation mit Ansible wie hier im Artikel, Terraform oder anderen Werkzeugen erlauben es dem Admin, schnell die Infrastruktur bereitzustellen und auch wieder abzubauen.

Infos

  1. IBM, “Growing up hybrid: Accelerating digital transformation”: https://www-01.ibm.com/common/ssi/cgi-bin/ssialias?htmlfid=GMW14087GBEN
  2. Ausgewählte Linux-Magazin-Artikel zu Ansible: Martin Loschwitz, “Operation Knopfdruck” und “Famose Automaten”: Linux-Magazin 11/17, S. 70 und 08/17, S. 60; Konstantin Agouros, “Zweite Runde”: Linux-Magazin 04/16, S. 58
  3. “Amazon VPC Limits” im VPC User Guide:https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Appendix_Limits.html
  4. “ec2 – create, terminate, start or stop an instance in ec2” in der Ansible-Dokumentation: http://docs.ansible.com/ansible/latest/ec2_module.html

Der Autor

Konstantin Agouros arbeitet als Head of Open Source Projects bei der Matrix technology AG und berät dort mit seinem Team Kunden zu Open-Source- und Cloud-Themen. Sein neues Buch “Software Defined Networking: Praxis mit Controllern und Open Flow” ist bei de Gruyter erschienen.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 7 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben