initial commit

This commit is contained in:
Josh Lay 2019-02-25 21:49:51 -06:00
commit 800836b2d9
23 changed files with 609 additions and 0 deletions

143
README.md Normal file
View file

@ -0,0 +1,143 @@
## deploy_base
This playbook is used to test my misc. roles that I intend to use as a deployment framework.
### Known issues
The package updates for atomic aren't idempotent. Some previous ostree transactions register a change, regardless of the actual transactional activity.
Simply comment out the update-packages role in play.yml to avoid this, if desired.
### Example usage
```
[jlay@delta deploy_base]$ ansible-playbook -i hosts play.yml
username for the user you want to create [jlay]:
password for created user:
confirm password for created user:
PLAY [lan] ************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************
ok: [gitlab]
TASK [bootstrap : check if atomic] ****************************************************************************************************************************
ok: [gitlab]
TASK [bootstrap : check for cloud.cfg] ************************************************************************************************************************
ok: [gitlab]
TASK [bootstrap : set fact (atomic state)] ********************************************************************************************************************
ok: [gitlab]
TASK [bootstrap : set fact (cloud.cfg state)] *****************************************************************************************************************
ok: [gitlab]
TASK [bootstrap : install prereqs] ****************************************************************************************************************************
ok: [gitlab] => (item=libselinux-python)
ok: [gitlab] => (item=sudo)
TASK [bootstrap : remove update_etc_hosts from cloud.cfg] *****************************************************************************************************
skipping: [gitlab]
TASK [bootstrap : remove requiretty] **************************************************************************************************************************
ok: [gitlab]
TASK [bootstrap : install epel] *******************************************************************************************************************************
ok: [gitlab]
TASK [update-packages : update packages (atomic)] *************************************************************************************************************
skipping: [gitlab]
TASK [update-packages : update packages (non-atomic)] *********************************************************************************************************
ok: [gitlab]
TASK [update-packages : reboot updated hosts] *****************************************************************************************************************
skipping: [gitlab]
TASK [update-packages : wait for rebooted host to return] *****************************************************************************************************
skipping: [gitlab]
TASK [install-packages : include_tasks] ***********************************************************************************************************************
skipping: [gitlab]
TASK [install-packages : include_tasks] ***********************************************************************************************************************
included: /home/jlay/git/deploy_base/roles/install-packages/tasks/el.yml for gitlab
TASK [install-packages : install packages (RHEL/CentOS/Fedora)] ***********************************************************************************************
ok: [gitlab] => (item=bash-completion)
ok: [gitlab] => (item=htop)
ok: [gitlab] => (item=vim)
ok: [gitlab] => (item=strace)
ok: [gitlab] => (item=dmidecode)
ok: [gitlab] => (item=nethogs)
ok: [gitlab] => (item=sysbench)
ok: [gitlab] => (item=fio)
ok: [gitlab] => (item=rsync)
ok: [gitlab] => (item=iperf3)
ok: [gitlab] => (item=nmap)
ok: [gitlab] => (item=lvm2)
ok: [gitlab] => (item=bind-utils)
TASK [create-user : include_tasks] ****************************************************************************************************************************
skipping: [gitlab]
TASK [create-user : include_tasks] ****************************************************************************************************************************
included: /home/jlay/git/deploy_base/roles/create-user/tasks/el.yml for gitlab
TASK [create-user : creating user jlay in wheel group (RHEL/CentOS/Fedora)] ***********************************************************************************
ok: [gitlab]
TASK [create-user : enable nopasswd sudo (RHEL/CentOS/Fedora)] ************************************************************************************************
ok: [gitlab]
TASK [create-user : copy current pubkeys to ~jlay/.ssh/authorized_keys] ***************************************************************************************
ok: [gitlab] => (item=ssh-ed25519 [...] jlay@workstation)
ok: [gitlab] => (item=ssh-rsa [...] jlay@workstation)
TASK [hardening : disable services] ***************************************************************************************************************************
ok: [gitlab] => (item=postfix)
failed: [gitlab] (item=rpcbind) => {"changed": false, "item": "rpcbind", "msg": "Could not find the requested service rpcbind: host"}
ok: [gitlab] => (item=rsyncd.service)
ok: [gitlab] => (item=rsyncd.socket)
...ignoring
TASK [hardening : disable password auth] **********************************************************************************************************************
ok: [gitlab]
TASK [docker : install docker] ********************************************************************************************************************************
ok: [gitlab]
TASK [docker : add jlay to 'dockerroot' group] ****************************************************************************************************************
ok: [gitlab]
TASK [docker : copy daemon.json] ******************************************************************************************************************************
ok: [gitlab]
TASK [docker : enable/start docker] ***************************************************************************************************************************
ok: [gitlab]
TASK [zfs : install zfs-release package (RHEL/CentOS)] ********************************************************************************************************
ok: [gitlab]
TASK [zfs : install zfs-release package (Fedora)] *************************************************************************************************************
skipping: [gitlab]
TASK [zfs : install zfs and dkms] *****************************************************************************************************************************
ok: [gitlab] => (item=kernel-devel)
ok: [gitlab] => (item=@Development tools)
ok: [gitlab] => (item=dkms)
ok: [gitlab] => (item=zfs)
TASK [zfs : load zfs module] **********************************************************************************************************************************
ok: [gitlab]
TASK [zfs : add zfs to modules-load.d] ************************************************************************************************************************
ok: [gitlab]
TASK [zfs : set zfs_arc_max to 75% installed memory (11630000000 bytes)] **************************************************************************************
ok: [gitlab]
PLAY RECAP ****************************************************************************************************************************************************
gitlab : ok=26 changed=0 unreachable=0 failed=0
[jlay@delta deploy_base]$
```

15
TODO Normal file
View file

@ -0,0 +1,15 @@
- Break out common packages from play into local vars file
- Fix atomic package updates. Not idempotent if there are pending transactions. Maybe add a task to clean up pending transactions before updating.
- Make create-user role task 'copy pubkey to authorized_keys for user' more correct/idempotent. It currently copies the file ~/.ssh/id_rsa.pub to authorized_keys rather than the contents, clobbering what may be there.
- Extend glusterfs-server role. If K8s, ensure Heketi pod is deployed. If not K8s, deploy normal service.
If a new deploy of Heketi, use Jinja2 templating for Heketi topology and import it (task run_once/one node only).
This will setup the disks/bricks, Ansible won't need to do it (modules for Gluster aren't great)
- Test conditionals against more than CentOS to ensure it remains effective across Fedora (atomic/non), CentOS, and RHEL.
- Make the playbook prompt for user/password only when making a user - eg: variable named 'createuser' (yes/no) to decide. Ansible doesn't seem to natively do this with vars_prompt, may need hackery.
- Remove some cross-role dependencies. For example, the bootstrap role (which will likely always need to be included) defines is_atomic, used by other roles. Keeping things within their own roles helps keep them portable/reusable. Anything that is usable by many roles should be included in 'bootstrap'.

8
ansible.cfg Normal file
View file

@ -0,0 +1,8 @@
[defaults]
host_key_checking = False
retry_files_enabled = False
[ssh_connection]
pipelining = True
control_path = %(directory)s/%%h-%%p-%%r)
ssh_args =

37
play.yml Normal file
View file

@ -0,0 +1,37 @@
---
- hosts: all
vars:
common_pkgs:
- bash-completion
- htop
- vim
- strace
- dmidecode
- nethogs
- sysbench
- fio
- rsync
arc_size_mb: "{{ (ansible_memtotal_mb * 0.75)|int|abs }}"
arc_size_bytes: "{{ arc_size_mb }}000000"
pwgen: "{{ lookup('password', '/dev/null chars=ascii_letters,digits,hexdigits,punctuation length=32') }}"
vars_prompt:
- name: "username"
prompt: "username for the user you want to create"
default: jlay
private: no
roles:
- {role: bootstrap}
- {role: update-packages}
- {role: install-packages}
- {role: create-user}
- {role: hardening}
# - {role: docker}
# - {role: tuned}
# - {role: glusterfs-client}
# - {role: glusterfs-server}
- {role: zfs}
# - {role: rke}
- {role: sysctl}

View file

@ -0,0 +1,66 @@
---
- block:
- name: check if atomic
stat:
path: /run/ostree-booted
register: ostree
- name: check for cloud.cfg
stat:
path: /etc/cloud/cloud.cfg
register: cloudcfg
- name: set fact (atomic state)
set_fact:
is_atomic: "{{ ostree.stat.exists }}"
- name: set fact (cloud.cfg state)
set_fact:
is_cloudy: "{{ cloudcfg.stat.exists }}"
- name: install prereqs
package:
name: "{{ item }}"
state: installed
with_items:
- libselinux-python
- sudo
when: ansible_distribution in ["CentOS", "Red Hat Enterprise Linux", "Fedora"] and not is_atomic
- name: enable fastestmirror (fedora - non-atomic)
lineinfile:
path: /etc/dnf/dnf.conf
regexp: "^fastestmirror="
line: "fastestmirror=True"
when: ansible_distribution in ["Fedora"] and not is_atomic
- name: remove update_etc_hosts from cloud.cfg
lineinfile:
line: ' - update_etc_hosts'
path: /etc/cloud/cloud.cfg
state: absent
when: is_cloudy
- name: add hosts to /etc/hosts
lineinfile:
path: /etc/hosts
state: present
line: "{{ hostvars[item].ip }} {{ hostvars[item].ansible_hostname }}"
regexp: "^{{ hostvars[item].ip }} "
with_items: "{{ groups.all }}"
- name: remove requiretty
lineinfile:
regexp: '^\w+\s+requiretty'
path: /etc/sudoers
state: absent
- name: install epel
package:
name: epel-release
state: latest
when: ansible_distribution in ["CentOS", "Red Hat Enterprise Linux"] and not is_atomic
tags:
- bootstrap

View file

@ -0,0 +1,23 @@
---
- name: creating user {{ username }} in sudo group (Debian/Ubuntu)
user:
name: "{{ username }}"
password: "{{ pwgen | password_hash('sha512') }}"
state: present
shell: /bin/bash
groups: sudo
append: yes
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
update_password: on_create
register: user_created
- name: enable nopasswd sudo (Debian/Ubuntu)
lineinfile:
dest: /etc/sudoers
regexp: '^%sudo'
line: "%sudo ALL=(ALL:ALL) NOPASSWD:ALL"
state: present
validate: 'visudo -cf %s'

View file

@ -0,0 +1,23 @@
---
- name: creating user {{ username }} in wheel group (RHEL/CentOS/Fedora)
user:
name: "{{ username }}"
password: "{{ pwgen | password_hash('sha512') }}"
state: present
shell: /bin/bash
groups: wheel
append: yes
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
update_password: on_create
register: user_created
- name: enable nopasswd sudo (RHEL/CentOS/Fedora)
lineinfile:
dest: /etc/sudoers
regexp: '^%wheel'
line: "%wheel ALL=(ALL) NOPASSWD: ALL"
state: present
validate: 'visudo -cf %s'

View file

@ -0,0 +1,20 @@
---
- include_tasks: deb.yml
when: ansible_distribution in ["Debian", "Ubuntu"]
- include_tasks: el.yml
when: ansible_distribution in ["CentOS", "Red Hat Enterprise Linux", "Fedora"]
- name: print generated password for {{ username }} on each host
debug: var=pwgen
when: user_created is changed
- name: copy current pubkeys to ~{{ username }}/.ssh/authorized_keys
authorized_key:
user: "{{ username }}"
state: present
key: "{{ item }}"
with_items:
- "{{ lookup('file','~/.ssh/id_ed25519.pub') }}"
- "{{ lookup('file','~/.ssh/id_rsa.pub') }}"

View file

@ -0,0 +1,3 @@
{
"group": "dockerroot"
}

View file

@ -0,0 +1,32 @@
---
- name: install docker
package:
name: docker
state: latest
when: ansible_distribution in ["CentOS", "Fedora", "Red Hat Enterprise Linux"] and not is_atomic
register: docker_installed
- name: add {{ username }} to 'dockerroot' group
user:
name: "{{ username }}"
groups: dockerroot
append: yes
when: ansible_distribution in ["CentOS", "Red Hat Enterprise Linux"] and not is_atomic
- name: copy daemon.json
copy:
src: roles/docker/files/daemon.json
dest: /etc/docker/daemon.json
owner: root
group: root
mode: 0644
when: ansible_distribution in ["CentOS", "Red Hat Enterprise Linux"] and not is_atomic
- name: enable/start docker
service:
name: docker
state: started
enabled: yes
when: ansible_distribution in ["CentOS", "Fedora", "Red Hat Enterprise Linux"] and not is_atomic

View file

@ -0,0 +1,13 @@
---
- name: install glusterfs 4.1 LTS SIG package (CentOS)
package:
name: centos-release-gluster41
state: latest
when: ansible_distribution == 'CentOS'
- name: install heketi-client (CentOS/Fedora)
package:
name: heketi-client
state: latest
when: ansible_distribution in ["CentOS", "Fedora"] and not is_atomic

View file

@ -0,0 +1,42 @@
---
- name: install glusterfs 4.1 LTS SIG package (CentOS)
package:
name: centos-release-gluster41
state: latest
when: ansible_distribution == 'CentOS'
- name: install glusterfs-server
package:
name: glusterfs-server
state: present
when: ansible_distribution in ["CentOS", "Red Hat Enterprise Linux", "Fedora"] and not is_atomic
register: gluster_installed
- name: start glusterd
service:
name: glusterd
state: started
enabled: yes
when: gluster_installed is changed
- name: add hosts to /etc/hosts
lineinfile:
path: /etc/hosts
state: present
line: "{{ hostvars[item].ip }} {{ hostvars[item].gluster_hostname }}"
regexp: "^{{ hostvars[item].ip }} "
with_items: "{{ groups.all }}"
- name: create glusterfs-server container (atomic)
docker_container:
name: glusterfs-server
image: gluster/gluster-centos:gluster4u0_centos7
hostname: glusterfs-server
network_mode: host
privileged: yes
restart_policy: always
shm_size: 2G
devices:
- "{{ gluster_dev }}:{{ gluster_dev }}:rwo"
when: is_atomic

View file

@ -0,0 +1,3 @@
---
- name: restart sshd
systemd: name=sshd state=restarted

View file

@ -0,0 +1,32 @@
---
#- name: Disallow root SSH access
# lineinfile:
# dest: /etc/ssh/sshd_config
# regexp: "^PermitRootLogin"
# line: "PermitRootLogin no"
# state: present
# notify: Restart ssh
# untested on debian/ubuntu
- name: disable services
service:
name: "{{ item }}"
state: stopped
enabled: no
with_items:
- postfix
- rpcbind
- rsyncd.service
- rsyncd.socket
ignore_errors: true
- name: disable password auth
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^PasswordAuthentication"
line: "PasswordAuthentication no"
state: present
notify: restart sshd

View file

@ -0,0 +1,9 @@
---
- name: install packages (Debian/Ubuntu)
package:
name: "{{ item }}"
state: latest
with_items:
- "{{ common_pkgs }}"
- dnsutils

View file

@ -0,0 +1,14 @@
---
- name: install packages (RHEL/CentOS/Fedora)
package:
name: "{{ item }}"
state: latest
with_items:
- "{{ common_pkgs }}"
- iperf3
- nmap
- lvm2
- bind-utils
- psmisc # may work on deb/ubuntu also? - provides killall
- wget

View file

@ -0,0 +1,20 @@
---
- include_tasks: deb.yml
when: ansible_distribution in ["Debian", "Ubuntu"]
- include_tasks: el.yml
when: ansible_distribution in ["CentOS" , "Red Hat Enterprise Linux", "Fedora"] and not is_atomic
# Need an idempotent way to install packages on atomic
# command module isn't idempotent and the package module insists on installing containers.
#- name: install packages (fedora - atomic)
# command: rpm-ostree install '{{ item }}'
# with_items:
# - htop
# - vim
# - iperf3
# - strace
# - nmap
# when: ansible_distribution == 'Fedora' and is_atomic

6
roles/rke/tasks/main.yml Normal file
View file

@ -0,0 +1,6 @@
---
- name: enable net.bridge.bridge-nf-call-iptables
sysctl:
name: net.bridge.bridge-nf-call-iptables
value: 1

View file

@ -0,0 +1,5 @@
---
- name: raise somaxconn
sysctl:
name: net.core.somaxconn
value: 512

15
roles/tuned/tasks/el.yml Normal file
View file

@ -0,0 +1,15 @@
---
- name: install packages
package:
name: "{{ item }}"
state: latest
with_items:
- tuned
- tuned-utils
- name: start service
service:
name: tuned
enabled: yes
state: started

View file

@ -0,0 +1,7 @@
---
- include_tasks: deb.yml
when: ansible_distribution in ["Debian", "Ubuntu"]
- include_tasks: el.yml
when: ansible_distribution in ["CentOS" , "Red Hat Enterprise Linux", "Fedora"] and not is_atomic

View file

@ -0,0 +1,29 @@
---
- block:
- name: update packages (atomic)
atomic_host:
revision: latest
when: ansible_distribution == 'Fedora' and is_atomic
register: atomic_host_upgraded
- name: update packages (non-atomic)
package:
name: '*'
state: latest
when: ansible_distribution in ["CentOS", "Red Hat Enterprise Linux", "Fedora", "Debian", "Ubuntu"] and not is_atomic
register: host_upgraded
- name: reboot updated hosts
shell: nohup bash -c "sleep 2 && shutdown -r now" &
register: host_reset
when: (atomic_host_upgraded is changed) or (host_upgraded is changed)
- name: wait for rebooted host to return
wait_for_connection:
timeout: 300
delay: 20
when: host_reset is changed
tags:
- update

44
roles/zfs/tasks/main.yml Normal file
View file

@ -0,0 +1,44 @@
---
- name: install zfs-release package (RHEL/CentOS)
yum:
name: "http://download.zfsonlinux.org/epel/zfs-release.el7_5.noarch.rpm"
state: present
when: ansible_distribution in ["CentOS" , "Red Hat Enterprise Linux" ]
- name: install zfs-release package (Fedora)
dnf:
name: "http://download.zfsonlinux.org/fedora/zfs-release.fc29.noarch.rpm"
state: present
when: ansible_distribution in ["Fedora"] and not is_atomic
- name: install zfs and dkms
package:
name: "{{ item }}"
state: present
with_items:
- kernel-devel
- "@Development tools"
- dkms
- zfs
register: zfs_installed
when: not is_atomic
- name: load zfs module
modprobe:
name: zfs
state: present
- name: add zfs to modules-load.d
copy:
dest: "/etc/modules-load.d/zfs.conf"
content: |
zfs
#- name: set zfs_arc_max to 75% installed memory ({{ arc_size_bytes }} bytes)
# lineinfile:
# path: "/etc/modprobe.d/zfs.conf"
# regexp: '^options zfs zfs_arc_max='
# line: 'options zfs zfs_arc_max="{{ arc_size_bytes }}"'
# create: yes
# commented out, does not adjust to 75% of each host, leading to disproportionate allocations