In the first two parts of this little devops series, I showed build templates with Packer and deploying virtual-machines with Terraform .
Now we want to install some more packages on our new servers.
tl;dr
I started using Ansible for deployments some years ago. For example I showed deploying IBM Connections at Social Connections 12 in Vienna .
For more details on the functionality, have a look at the post How Ansible Works
Ansible uses plain ssh and doesn’t need any additional server or client component.
You can run Ansible as a separate task in your deployment pipeline, or add it as post-provisioning task to Terraform. So it runs automatically when Terraform deploys your systems.
Windows
You can use Ansible to deploy Windows Servers too. More interesting is running Ansible from a Windows machine to deploy Linux and Windows servers.
For Windows you can use WinRM or SSH to connect for remote management. The SSH support is experimental AFAIK.
Ansible
Installation
Ansible is available for all major Linux distributions. Check the documentation for installation instructions .
Little project
Directory structure of a little Ansible example
.
├── group_vars
│ └── all
│ └── main.yml
├── inventory
├── roles
│ ├── common
│ │ └── tasks
│ │ └── main.yml
│ └── ldap
│ ├── defaults
│ │ └── main.yml
│ └── tasks
│ └── main.yml
├── site.yml
└── templates
├── base.ldif.j2
├── db.ldif.j2
├── ldap-config.sh.j2
├── monitor.ldif.j2
└── user-ldap.ldif.j2
In the inventory file you define your servers and group them together.
inventory
[gpn19]
gpn19-server1
gpn19-server2
[ldap]
gpn19-server2
So gpn19-server1
is only in the group gpn19
, server gnp19-server2
is part of gpn19
and ldap
. There is always a group all
with all servers of an inventory file.
The Ansible playbook itself is defined as an Yaml-file:
site.yml
---
- hosts: all
roles:
- common
- hosts: ldap
roles:
- role: ldap
So for all hosts the role common
will run and on group ldap
the role ldap.
To make the roles independent of the environment, we use some variables. So it’s enough to just change the variable and the deployment will use different domain and passwords.
group_vars/all/task.yml
---
ldap:
domain: dc=devops,dc=example,dc=com
passwordencrypted: "{SSHA}CdGAzVNlrqgLbKo6pebBxuDBBkxokkHm"
passwordclear: "password"
To keep it simple, the password is defined here in the variable file. Have a look at Ansible Vault to keep your passwords encrypted.
Using template files
For the ldap deployment we need to change some files on the target server. These are already prepared in the directory templates
and use Jinga2 template engine .
templates/ldapconfig.sh.j2
#!/usr/bin/env bash
cd /etc/openldap/slapd.d
ldapmodify -Y EXTERNAL -H ldapi:/// -f db.ldif
ldapmodify -Y EXTERNAL -H ldapi:/// -f monitor.ldif
sleep 5
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
sleep 5
ldapadd -x -w {{ ldap.passwordclear }} -D "cn=ldapadm,{{ ldap.domain }}" -f /etc/openldap/slapd.d/base.ldif
sleep 10
ldapadd -x -w {{ ldap.passwordclear }} -D "cn=ldapadm,{{ ldap.domain }}" -f /etc/openldap/slapd.d/user-ldap.ldif
- We can use our variable in Jinga2 and these will be replaced during deployment
roles/common/tasks/main.yml
---
# Disable Firewall during Installation
- name: Disable Firewall
service:
name=firewalld
state=stopped
enabled=no
# Disabe SELinux, most IBM Software is not supported with it
- name: Disable SELinux
selinux:
state: disabled
# Increase limits.conf for IBM products
- name: Change limits.conf
pam_limits:
domain: root
limit_type: '-'
limit_item: nproc
value: '16384'
- pam_limits:
domain: root
limit_type: '-'
limit_item: nofile
value: '65536'
- pam_limits:
domain: root
limit_type: '-'
limit_item: stack
value: '10240'
# Install Unzip
- name: Install unzip to support unarchive function of ansible, add xauth
package:
name={{ item }}
state=latest
with_items:
- unzip
- xauth
- vim
# Configure SSH X11Forward
- name: Update SSH configuration to be more secure.
lineinfile:
dest: "/etc/ssh/sshd_config"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
with_items:
- regexp: "^X11Forwarding"
line: "X11Forwarding yes"
- regexp: "^X11UseLocalhost"
line: "X11UseLocalhost no"
- name: Restart SSH
service:
name=sshd
state=restarted
enabled=yes
Stop Firewalld and set to disabled
Configure some limits in
limits.conf
Install additional packages (independent of yum or apt)
roles/ldap/tasks/main.yml
---
- name: Install system packages for OpenLDAP
package:
name={{ item }}
state=latest
with_items:
- openldap-servers
- openldap-clients
- name: Enable Slapd service
service:
name=slapd
state=restarted
enabled=yes
- name: Initial ldap config, copy templates db.ldif
template: src=db.ldif.j2 dest=/etc/openldap/slapd.d/db.ldif
tags: parse
- name: Initial ldap config, copy templates monitor.ldif
template: src=monitor.ldif.j2 dest=/etc/openldap/slapd.d/monitor.ldif
tags: parse
- name: Create base.ldif
template: src=base.ldif.j2 dest=/etc/openldap/slapd.d/base.ldif
tags: parse
- name: Create user.ldif
template: src=user-ldap.ldif.j2 dest=/etc/openldap/slapd.d/user-ldap.ldif
tags: parse
- name: Copy sample db config
copy:
src: "/usr/share/openldap-servers/DB_CONFIG.example"
dest: "/var/lib/ldap/DB_CONFIG"
remote_src: yes
directory_mode: yes
owner: ldap
group: ldap
- name: Create LDAP Config Script
template:
src: ldap-config.sh.j2
dest: /tmp/ldap-config.sh
mode: 0755
tags: parse
- name: Configure LDAP and Import Users
shell: "/tmp/ldap-config.sh"
- name: Remove config script
file:
path: /tmp/ldap-config.sh
state: absent
Enable slapd service
Copy
db.ldif.j2
from templates todest
Run Ansible Playbook
To run this playbook with our inventory file, just run:
ansible-playbook -i inventory site.yml
So now you’re prepared to build new servers and deploy software on it. Have fun!
Ansible Galaxy
On Ansible Galaxy you can share and download Ansible roles. So start new projects searching there, don’t start from scratch.
Galaxy is a hub for finding and sharing Ansible content.
Use Galaxy to jump-start your automation project with great content from the Ansible community. Galaxy provides pre-packaged units of work known to Ansible as Roles, and new in Galaxy 3.2, Collections.
Roles can be dropped into Ansible PlayBooks and immediately put to work. You’ll find roles for provisioning infrastructure, deploying applications, and all of the tasks you do everyday. The new Collection format provides a comprehensive package of automation that may include multiple playbooks, roles, modules, and plugins.
Gulasch Programmiernacht
The content of this series was part of my talk at the GPN19. So you can watch a video of the talk too: