From 8ec080008240420c892da63cc3ec315466f89a57 Mon Sep 17 00:00:00 2001 From: Nicolas MASSE Date: Wed, 3 May 2017 19:28:27 +0200 Subject: [PATCH] initial commit --- .gitignore | 2 + .gitmodules | 4 ++ LICENSE | 21 ++++++ README.md | 14 ++++ ansible | 67 ++++++++++++++++++++ ansible.cfg | 3 + bootstrap.yml | 9 +++ group_vars/all | 7 ++ roles/base/handlers/main.yml | 4 ++ roles/base/tasks/main.yml | 58 +++++++++++++++++ roles/bootstrap/tasks/main.yml | 32 ++++++++++ roles/bootstrap/templates/sudoers | 3 + roles/docker/tasks/main.yml | 60 ++++++++++++++++++ roles/docker/templates/docker-storage-setup | 9 +++ roles/iptables/tasks/main.yml | 11 ++++ roles/name-resolution/tasks/main.yml | 48 ++++++++++++++ roles/name-resolution/templates/dnsmasq.conf | 28 ++++++++ roles/name-resolution/templates/hosts | 9 +++ roles/name-resolution/templates/resolv.conf | 5 ++ roles/openshift-prereq/tasks/main.yml | 18 ++++++ test.hosts | 63 ++++++++++++++++++ test.yml | 16 +++++ 22 files changed, 491 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 LICENSE create mode 100644 README.md create mode 100755 ansible create mode 100644 ansible.cfg create mode 100644 bootstrap.yml create mode 100644 group_vars/all create mode 100644 roles/base/handlers/main.yml create mode 100644 roles/base/tasks/main.yml create mode 100644 roles/bootstrap/tasks/main.yml create mode 100644 roles/bootstrap/templates/sudoers create mode 100644 roles/docker/tasks/main.yml create mode 100644 roles/docker/templates/docker-storage-setup create mode 100644 roles/iptables/tasks/main.yml create mode 100644 roles/name-resolution/tasks/main.yml create mode 100644 roles/name-resolution/templates/dnsmasq.conf create mode 100644 roles/name-resolution/templates/hosts create mode 100644 roles/name-resolution/templates/resolv.conf create mode 100644 roles/openshift-prereq/tasks/main.yml create mode 100644 test.hosts create mode 100644 test.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2cc9421 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +admin.pub +*.retry diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..50832f0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "openshift-ansible"] + path = openshift-ansible + url = https://github.com/openshift/openshift-ansible.git + branch = release-1.5 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3153fe0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Nicolas MASSE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1908c28 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# OpenShift-Lab +This project is the Ansible Playbook to install OpenShift in a Lab Environment. + +## Preparation work + +1. Pull the "openshift-ansible" sub-project using `git submodule init && git submodule update` +2. Review \*.hosts and change hostnames to target your Virtual Machines + +## Example + +``` +./ansible bootstrap vm.openshift.test +./ansible play allinone +``` diff --git a/ansible b/ansible new file mode 100755 index 0000000..e6ff3ae --- /dev/null +++ b/ansible @@ -0,0 +1,67 @@ +#!/bin/bash + +options="" +ssh_key="$HOME/.ssh/id_rsa" +initial_user="root" + +target="$1" +shift +case "$target" in + "bootstrap") + if [ -z "$1" ]; then + echo "Please specify the target host(s) !" + exit 1 + fi + echo "Bootstraping $@..." + echo + echo -n "Please enter the initial $initial_user password: " + read -s password + echo # Add a Line Feed since the "read -s" do not output it ! + echo + + # Pre-register SSH Host Keys + for host; do + echo "Connecting to $host to register the SSH Host Key !" + LC_ALL=C sshpass -p "$password" ssh -i $ssh_key -o StrictHostKeyChecking=no "$initial_user@$host" /bin/true + done + + # Setup authentication + if [ -n "$password" ]; then + options="$options -e ansible_ssh_pass=$password" + else + options="$options -e ansible_ssh_private_key_file=$ssh_key" + fi + + # Setup the ssh user + options="$options -e ansible_ssh_user=$initial_user " + + # Generate an inventory file "on the fly" + echo "[bootstrap]" > "bootstrap.hosts" + for host; do + echo -e "$host" + done >> "bootstrap.hosts" + + ansible-playbook -i "bootstrap.hosts" $options bootstrap.yml + + rm -f "bootstrap.hosts" + ;; + "play") + if [ -z "$1" ]; then + echo "Please specify the playbook to run !" + exit 1 + fi + + playbook="$1" + shift + + ansible-playbook -i "$playbook.hosts" $options "$@" $playbook.yml + ;; + *) + echo "Usage: $0 {bootstrap|play} [options]" + echo + echo "Samples: " + echo " $0 bootstrap machine.example.com" + echo " $0 play allinone" + exit 1 + ;; +esac diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..ceb1027 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +# This is needed by the openshift-ansible installer +deprecation_warnings=False diff --git a/bootstrap.yml b/bootstrap.yml new file mode 100644 index 0000000..86c155b --- /dev/null +++ b/bootstrap.yml @@ -0,0 +1,9 @@ +--- + + - name: Bootstrap one or more CentOS 7 nodes + hosts: bootstrap + become: no + vars_files: + - private/private_vars.yml + roles: + - bootstrap diff --git a/group_vars/all b/group_vars/all new file mode 100644 index 0000000..5768d69 --- /dev/null +++ b/group_vars/all @@ -0,0 +1,7 @@ +--- + timezone: Europe/Paris + ansible_python_interpreter: /usr/bin/python2 + ansible_ssh_user: redhat + ansible_ssh_private_key_file: "{{ lookup('env','HOME') }}/.ssh/id_rsa" + ansible_ssh_public_key: "{{ lookup('file', ansible_ssh_private_key_file + '.pub' ) }}" + ansible_connection: ssh diff --git a/roles/base/handlers/main.yml b/roles/base/handlers/main.yml new file mode 100644 index 0000000..1e9c2c7 --- /dev/null +++ b/roles/base/handlers/main.yml @@ -0,0 +1,4 @@ +--- + + - name: restart sshd + service: name=sshd state=reloaded diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml new file mode 100644 index 0000000..cf15dc2 --- /dev/null +++ b/roles/base/tasks/main.yml @@ -0,0 +1,58 @@ +--- + + - name: Tell SSHD not to use DNS + lineinfile: dest=/etc/ssh/sshd_config regexp="^#* *UseDNS +" line="UseDNS no" + notify: restart sshd + tags: config + + - name: Tell SSHD to forbid root accesses + lineinfile: dest=/etc/ssh/sshd_config regexp="^#* *PermitRootLogin +" line="PermitRootLogin no" + notify: restart sshd + tags: config + + - name: Tell SSHD to forbid password accesses + lineinfile: dest=/etc/ssh/sshd_config regexp="^#* *PasswordAuthentication +" line="PasswordAuthentication no" + notify: restart sshd + tags: config + + - name: Install some software + yum: name={{ item }} state=installed + with_items: + - vim-enhanced + - tmux + - unzip + - tcpdump + - telnet + - strace + - man-pages + - man + - iptraf + - wget + - openssh-clients + tags: rpm + + - name: Install Open-VM tools + yum: name=open-vm-tools state=installed + tags: rpm + + - name: Fix /etc/environment to include PATH + lineinfile: dest=/etc/environment regexp="^PATH=" line="PATH=/bin:/usr/bin:/sbin:/usr/sbin" + tags: config + + - name: Persist the hostname + lineinfile: dest=/etc/sysconfig/network regexp="^HOSTNAME=" line="HOSTNAME={{ inventory_hostname_short }}" + tags: + - config + - dns + + - name: Set the hostname + command: hostnamectl set-hostname {{ inventory_hostname_short }} --static + tags: + - config + - dns + + - name: Ensure consistent locale across systems (1/2) + lineinfile: dest=/etc/locale.conf regexp="^LANG=" line="LANG=en_US.utf8" + + - name: Ensure consistent locale across systems (2/2) + lineinfile: dest=/etc/locale.conf line="LC_CTYPE=en_US.utf8" diff --git a/roles/bootstrap/tasks/main.yml b/roles/bootstrap/tasks/main.yml new file mode 100644 index 0000000..f169318 --- /dev/null +++ b/roles/bootstrap/tasks/main.yml @@ -0,0 +1,32 @@ +--- + + - name: Create groups + group: name={{ item.name }} state=present + with_items: "{{ itix_groups }}" + tags: bootstrap + + - name: Create users + user: state=present name={{ item.login }} group={{ item.group }} groups={{ item.groups }} uid={{ item.uid }} comment={{ item.comment }} password={{ item.password }} + with_items: "{{ itix_users }}" + tags: bootstrap + + - name: Create the .ssh directory for users + file: state=directory owner={{ item.login }} group={{ item.group }} mode=0700 path=/home/{{ item.login }}/.ssh + with_items: "{{ itix_users }}" + tags: bootstrap + + - name: Set a strong root password (only usable from console) + user: name=root password={{ root_password }} + tags: bootstrap + + - name: Set SSH key for users + authorized_key: user={{ item.login }} key="{{ item.ssh_public_key }}" + with_items: "{{ itix_users }}" + when: "item.ssh_public_key is defined" + tags: bootstrap + + - name: Configure SUDO + template: src=sudoers dest=/etc/sudoers owner=root group=root mode=0440 validate="/usr/sbin/visudo -cf %s" + tags: + - bootstrap + - config diff --git a/roles/bootstrap/templates/sudoers b/roles/bootstrap/templates/sudoers new file mode 100644 index 0000000..697aecc --- /dev/null +++ b/roles/bootstrap/templates/sudoers @@ -0,0 +1,3 @@ +# {{ ansible_managed }} +%wheel ALL=(ALL) NOPASSWD: ALL +root ALL=(ALL) NOPASSWD: ALL diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml new file mode 100644 index 0000000..d17a51c --- /dev/null +++ b/roles/docker/tasks/main.yml @@ -0,0 +1,60 @@ +--- + + - name: Check for mandatory variables required by this playbook + fail: + msg: "This playbook requires {{item}} to be set." + when: "{{ item }} is not defined or {{ item }} == ''" + with_items: + - docker_storage_vg + tags: docker-storage + + - name: Install Docker + yum: name=docker state=installed + tags: rpm + + - name: Start docker + service: name=docker state=started + tags: docker-storage + + - name: Determine if docker storage driver == devicemapper + shell: docker info | grep 'Storage Driver:.*devicemapper' + register: correct_storage_driver + changed_when: false + ignore_errors: yes + + - debug: + var: correct_storage_driver + + - name: set docker_storage_setup_needs_to_run + set_fact: + docker_storage_setup_needs_to_run: '{{ correct_storage_driver.rc == 1 }}' + tags: docker-storage + + - name: stop docker + service: + name: docker + state: stopped + when: docker_storage_setup_needs_to_run + tags: docker-storage + + - name: delete /var/lib/docker + command: rm -rf /var/lib/docker + when: docker_storage_setup_needs_to_run + tags: docker-storage + + - name: Configure docker-storage-setup to use LVM + template: dest=/etc/sysconfig/docker-storage-setup src=docker-storage-setup + register: docker-storage-setup + when: docker_storage_setup_needs_to_run + tags: docker-storage + + - name: Run docker-storage-setup + command: docker-storage-setup + environment: + PATH: /bin:/usr/bin:/sbin:/usr/sbin # Fix buggy PATH on RHEL7 + when: docker_storage_setup_needs_to_run + tags: docker-storage + + - name: Start Docker + service: name=docker state=started enabled=yes + tags: docker-storage diff --git a/roles/docker/templates/docker-storage-setup b/roles/docker/templates/docker-storage-setup new file mode 100644 index 0000000..8519c7f --- /dev/null +++ b/roles/docker/templates/docker-storage-setup @@ -0,0 +1,9 @@ +STORAGE_DRIVER=devicemapper +DOCKER_ROOT_VOLUME=yes + +{% if docker_storage_disk is defined %} +DEVS={{ docker_storage_disk }} +{% endif %} +{% if docker_storage_vg is defined %} +VG={{ docker_storage_vg }} +{% endif %} diff --git a/roles/iptables/tasks/main.yml b/roles/iptables/tasks/main.yml new file mode 100644 index 0000000..3d2c277 --- /dev/null +++ b/roles/iptables/tasks/main.yml @@ -0,0 +1,11 @@ +--- + + - name: Install iptables-services + yum: name=iptables-services state=installed + tags: rpm + + - name: Disable firewalld + service: name=firewalld state=stopped enabled=no + + - name: Enable iptables + service: name=iptables state=started enabled=yes diff --git a/roles/name-resolution/tasks/main.yml b/roles/name-resolution/tasks/main.yml new file mode 100644 index 0000000..b4a51ab --- /dev/null +++ b/roles/name-resolution/tasks/main.yml @@ -0,0 +1,48 @@ +--- + + - name: Check for mandatory variables required by this playbook + fail: + msg: "This playbook requires {{item}} to be set." + when: "{{ item }} is not defined or {{ item }} == ''" + with_items: + - lab_dns_suffix + - openshift_master_default_subdomain + + - name: Make sure each machine has an up-to-date /etc/hosts + template: dest=/etc/hosts src=hosts + tags: config + + - name: Install dnsmasq + yum: name=dnsmasq state=installed + when: "'name-server' in group_names" # Only on admin server + tags: rpm + + - name: Set dnsmasq config + template: src=dnsmasq.conf dest=/etc/dnsmasq.conf + when: "'name-server' in group_names" # Only on admin server + tags: config + + - name: Generate an /etc/hosts with all hosts + template: dest=/etc/hosts.dnsmasq src=hosts + when: "'name-server' in group_names" # Only on admin server + tags: config + + - name: Make sure dnsmasq daemon is enabled and started + service: name=dnsmasq state=started enabled=yes + when: "'name-server' in group_names" # Only on admin server + tags: config + + - name: Add an iptable rule to allow DNS queries from other hosts + lineinfile: dest=/etc/sysconfig/iptables line="-A INPUT -p udp --dport 53 -j ACCEPT" insertafter="-A INPUT -i lo -j ACCEPT" + when: "'name-server' in group_names" # Only on admin server + tags: iptables + + - name: Restart iptables + service: name=iptables enabled=yes state=restarted + when: "'name-server' in group_names" # Only on admin server + tags: iptables + + - name: Fix the /etc/resolv.conf of other hosts + template: dest=/etc/resolv.conf src=resolv.conf + when: "'name-server' in groups and 'name-server' not in group_names" # On all other nodes (if a name server has been setup) + tags: config diff --git a/roles/name-resolution/templates/dnsmasq.conf b/roles/name-resolution/templates/dnsmasq.conf new file mode 100644 index 0000000..0b066f1 --- /dev/null +++ b/roles/name-resolution/templates/dnsmasq.conf @@ -0,0 +1,28 @@ +# {{ ansible_managed }} + +domain-needed +bogus-priv +expand-hosts +log-queries +local-ttl=60 + +# Do not read the default /etc/hosts +no-hosts + +# But read this one... +addn-hosts=/etc/hosts.dnsmasq + +# Default suffix for all machines +domain={{ lab_dns_suffix }} + +# +# Wildcard DNS entries (see lab_route_suffix variable) +# +# note: will generate something like this : +# address=/app.openshift.test/192.168.23.20 +# +{% if 'lb' in groups %} +address=/{{ openshift_master_default_subdomain }}/{{ hostvars[groups['lb'][0]]['ansible_default_ipv4']['address'] }} +{% else %} +address=/{{ openshift_master_default_subdomain }}/{{ hostvars[groups['masters'][0]]['ansible_default_ipv4']['address'] }} +{% endif %} diff --git a/roles/name-resolution/templates/hosts b/roles/name-resolution/templates/hosts new file mode 100644 index 0000000..418d718 --- /dev/null +++ b/roles/name-resolution/templates/hosts @@ -0,0 +1,9 @@ +# {{ ansible_managed }} +127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 +::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 + +{% if "name-server" not in groups %} +{% for item in groups['all'] %} +{{ hostvars[item]['ansible_default_ipv4']['address'] }} {{ hostvars[item]['inventory_hostname']}} {{ hostvars[item]['inventory_hostname_short']}} +{% endfor %} +{% endif %} diff --git a/roles/name-resolution/templates/resolv.conf b/roles/name-resolution/templates/resolv.conf new file mode 100644 index 0000000..2b16196 --- /dev/null +++ b/roles/name-resolution/templates/resolv.conf @@ -0,0 +1,5 @@ +# {{ ansible_managed }} +search {{ lab_dns_suffix }} +{% for item in groups['name-server'] %} +nameserver {{ hostvars[item]['ansible_default_ipv4']['address'] }} +{% endfor %} diff --git a/roles/openshift-prereq/tasks/main.yml b/roles/openshift-prereq/tasks/main.yml new file mode 100644 index 0000000..cea7d75 --- /dev/null +++ b/roles/openshift-prereq/tasks/main.yml @@ -0,0 +1,18 @@ +--- + + - name: Install centos-release-openshift-origin + yum: name=centos-release-openshift-origin state=installed + tags: rpm + + - name: Install required RPMs + yum: name={{ item }} state=installed + with_items: + - git + - net-tools + - bind-utils + - bridge-utils + - bash-completion + - origin-clients + - NetworkManager + - nfs-utils + tags: rpm diff --git a/test.hosts b/test.hosts new file mode 100644 index 0000000..e8615bc --- /dev/null +++ b/test.hosts @@ -0,0 +1,63 @@ +# +# Variables used by my playbook +# +[allinone:vars] +lab_dns_suffix=itix.test +docker_storage_vg=docker + +[allinone:children] +masters + +# +# Shared variables used by both openshift-ansible and my playbook +# +[all:vars] +# Default route suffix +openshift_master_default_subdomain=app.itix.test + +[masters] +openshift.itix.test + +[nodes] +openshift.itix.test openshift_node_labels='{ "workload": "infra", "workload": "app" }' + +# +# The rest is used only by the OpenShift installer playbook +# +[OSEv3:children] +masters +nodes + +[OSEv3:vars] +# Yes, we need to use sudo +ansible_become=yes + +# what to install +deployment_type=origin + +# New installation method : everything in containers ! +contenairized=true + +# Clustering method +openshift_master_cluster_method=native + +# Bypass Registry Security Checks +openshift_docker_insecure_registries=172.30.0.0/16 + +# Disable any authentication +openshift_master_identity_providers=[{'name': 'allow_all', 'login': 'true', 'challenge': 'true', 'kind': 'AllowAllPasswordIdentityProvider'}] + +# default project node selector +osm_default_node_selector='workload=app' + +# Make sure NTP is enabled +openshift_clock_enabled=true + +# default router +openshift_hosted_router_selector='workload=infra' + +# Do not create the default project "my-project" +openshift_additional_projects={} + +# Enable the multitenant SDN +os_sdn_network_plugin_name='redhat/openshift-ovs-multitenant' diff --git a/test.yml b/test.yml new file mode 100644 index 0000000..6c321fc --- /dev/null +++ b/test.yml @@ -0,0 +1,16 @@ +--- + + - name: Prepare an "All-in-one" VM for OpenShift + hosts: allinone + become: yes + vars_files: + - private/private_vars.yml + roles: + - { name: 'base', tags: 'base' } + - { name: 'iptables', tags: 'iptables' } + - { name: 'name-resolution', tags: 'name-resolution' } + - { name: 'docker', tags: 'docker' } + - { name: 'openshift-prereq', tags: 'openshift-prereq' } + + # Launch the OpenShift Installer Playbook + - include: "./openshift-ansible/playbooks/byo/config.yml"