commit 8ec080008240420c892da63cc3ec315466f89a57 Author: Nicolas MASSE Date: Wed May 3 19:28:27 2017 +0200 initial commit 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"