Roll out hybrid clouds with Ansible  automation

Mixing Allowed

Role-Play

The playbook's second and third plays use a role to configure the software on the two VMs. The last play in Listing 4 is especially important. Because the inner VM is only accessible from the outer VM, it needs to reroute the SSH command via ansible_ssh_common_args so that the inner VM uses the outer as a proxy. I only packed the configuration into roles here because I wanted the configuration to be reusable on the VMs.

Listing 4

The Last Two 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 shows the front-end play or tasks from the role. The first task installs Python in raw mode, because Python was not installed on the AWS Ubuntu image I used. Then Ansible installs and configures the socat and squid packages. What is striking here is socat, which is not really a service. Only a systemd unit file makes it a service on UDP and 443/TCP. The target address of the inner VM for connecting is taken from the previous playbook run. The play starting in line 43 (Listing 5) activates the services and starts them.

Listing 5

Installing the Front End

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 handles the internal VM's configuration. This can't start with the installation of Python, because apt first has to get to know the upstream proxy; this again happens in raw mode here.

Listing 6

Internal VM Configuration

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

In terms of software packages, the role only installs OpenVPN and configures two instances: one on the UDP port and one on TCP/443. These instances set an entry in the /etc/default/openvpn file to AUTOSTART. The last play in the listing enables and starts the OpenVPN service. The SSL keys in this example were already preconfigured. It is up to the admin to generate and upload certificates with Ansible.

Objective Achieved

Extending your data center with resources from the cloud can significantly reduce total costs. You'll mainly see this benefit if you need to purchase very expensive services or the services are only occasionally needed, such as additional instances of your own web store or web server for a foreseeable customer rush.

However, to ensure that the cloud services – unless currently desired – are not freely available on the Internet, the infrastructure allows AWS to be connected almost like your own data center. However, for temporary resources, a manual assembly and disassembly would be labor intensive. Automation with Ansible, as shown in this article, or with something like the HashiCorp Terraform tool, lets the admin quickly deploy and dismantle a data center infrastructure.

Infos

  1. Hybrid IT structure advantages: https://www-01.ibm.com/common/ssi/cgi-bin/ssialias?htmlfid=GMW14087GBEN
  2. "Jira, Confluence, and GitLab" by Martin Loschwitz, ADMIN , issue 43, 2018, pp. 36-40, http://www.admin-magazine.com/Archive/2018/43/Jira-Confluence-and-GitLab.
  3. "DevOps with DebOps" by Martin Loschwitz, ADMIN , issue 42, 2017, pg. 30, http://www.admin-magazine.com/Archive/2017/42/DebOps-delivers-easy-Ansible-automation-for-Debian-based-systems2
  4. "What's New in Ansible 2.0" by Konstantin Agouros, ADMIN , issue 32, 2016, pg. 54: http://www.admin-magazine.com/Archive/2016/32/What-s-new-in-Ansible-2.0
  5. Amazon VPC limits: https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Appendix_Limits.html
  6. Ansible cloud modules: http://docs.ansible.com/ansible/latest/ec2_module.html

The Author

Konstantin Agouros is head of Open Source Projects at matrix technology AG, where he and his team advise customers on open source and cloud topics. His latest book, Software Defined Networking: Practical Applications with Controllers and Open Flow , is published by De Gruyter.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs



Support Our Work

ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.

Learn More”>
	</a>

<hr>		    
			</div>
		    		</div>

		<div class=