Define and implement specs for bootstrap-os (#4455)

* Add README to bootstrap-os role

* Rework bootstrap-os once more

* Document workarounds for bugs/deficiencies in Ansible modules
* Unify and document role variables
* Remove installation of additional packages and repositories
* Merge Ubuntu and Debian tasks
* Remove pipelining setting from default playbooks
* Fix OpenSUSE not running its required tasks
This commit is contained in:
MarkusTeufelberger 2019-04-24 00:46:02 +02:00 committed by Kubernetes Prow Robot
parent d588532c9b
commit 76db060afb
12 changed files with 175 additions and 229 deletions

View file

@ -22,10 +22,6 @@
- hosts: k8s-cluster:etcd:calico-rr - hosts: k8s-cluster:etcd:calico-rr
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
gather_facts: false gather_facts: false
vars:
# Need to disable pipelining for bootstrap-os as some systems have requiretty in sudoers set, which makes pipelining
# fail. bootstrap-os fixes this on these systems, so in later plays it can be enabled.
ansible_ssh_pipelining: false
roles: roles:
- { role: kubespray-defaults} - { role: kubespray-defaults}
- { role: bootstrap-os, tags: bootstrap-os} - { role: bootstrap-os, tags: bootstrap-os}

View file

@ -0,0 +1,59 @@
# bootstrap-os
Bootstrap an Ansible host to be able to run Ansible modules.
This role will:
* configure the package manager (if applicable) to be able to fetch packages
* install Python
* install the necessary packages to use Ansible's package manager modules
* set the hostname of the host to `{{ inventory_hostname }}` when requested
## Requirements
A host running an operating system that is supported by Kubespray.
See https://github.com/kubernetes-sigs/kubespray#supported-linux-distributions for a current list.
SSH access to the host.
## Role Variables
Variables are listed with their default values, if applicable.
### General variables
* `http_proxy`/`https_proxy`
The role will configure the package manager (if applicable) to download packages via a proxy.
This is currently implemented for CentOS/RHEL (`http_proxy` only) as well as Debian and Ubuntu (both `http_proxy` and `https_proxy` are respected)
* `override_system_hostname: true`
The role will set the hostname of the machine to the name it has according to Ansible's inventory (the variable `{{ inventory_hostname }}`).
### Per distribution variables
#### CoreOS
* `coreos_locksmithd_disable: false`
Whether `locksmithd` (responsible for rolling restarts) should be disabled or be left alone.
#### CentOS/RHEL
* `centos_fastestmirror_enabled: false`
Whether the [fastestmirror](https://wiki.centos.org/PackageManagement/Yum/FastestMirror) yum plugin should be enabled.
## Dependencies
The `kubespray-defaults` role is expected to be run before this role.
## Example Playbook
Remember to disable fact gathering since Python might not be present on hosts.
- hosts: all
gather_facts: false # not all hosts might be able to run modules yet
roles:
- kubespray-defaults
- bootstrap-os
## License
Apache 2.0

View file

@ -1,16 +1,14 @@
--- ---
pip_python_coreos_modules: ## CentOS/RHEL specific variables
- httplib2
- six
override_system_hostname: true
coreos_auto_upgrade: true
# Install epel repo on Centos/RHEL # Install epel repo on Centos/RHEL
epel_enabled: false centos_epel_enabled: false
# Use the fastestmirror yum plugin
centos_fastestmirror_enabled: false
# CentOS/RedHat Extras repo ## CoreOS specific variables
extras_rh_repo_base_url: "http://mirror.centos.org/centos/$releasever/extras/$basearch/" # Disable locksmithd or leave it in its current state
extras_rh_repo_gpgkey: "http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-7" coreos_locksmithd_disable: false
# Caching extras packages after installation
extras_rh_rpm_keepcache: 0 ## General
# Set the hostname to inventory_hostname
override_system_hostname: true

View file

@ -1,10 +1,13 @@
--- ---
- name: Check if atomic host # CentOS ships with python installed
- name: Check if this is an atomic host
stat: stat:
path: /run/ostree-booted path: /run/ostree-booted
register: ostree register: ostree
- set_fact: - name: Store the fact if this is an atomic host
set_fact:
is_atomic: "{{ ostree.stat.exists }}" is_atomic: "{{ ostree.stat.exists }}"
- name: Check presence of fastestmirror.conf - name: Check presence of fastestmirror.conf
@ -12,79 +15,34 @@
path: /etc/yum/pluginconf.d/fastestmirror.conf path: /etc/yum/pluginconf.d/fastestmirror.conf
register: fastestmirror register: fastestmirror
# fastestmirror plugin actually slows down Ansible deployments # the fastestmirror plugin can actually slow down Ansible deployments
- name: Disable fastestmirror plugin - name: Disable fastestmirror plugin if requested
lineinfile: lineinfile:
dest: /etc/yum/pluginconf.d/fastestmirror.conf dest: /etc/yum/pluginconf.d/fastestmirror.conf
regexp: "^enabled=.*" regexp: "^enabled=.*"
line: "enabled=0" line: "enabled=0"
state: present state: present
become: true become: true
when: fastestmirror.stat.exists when:
- fastestmirror.stat.exists
- not centos_fastestmirror_enabled
- name: Add proxy to /etc/yum.conf if http_proxy is defined - name: Add proxy to /etc/yum.conf if http_proxy is defined
lineinfile: lineinfile:
path: "/etc/yum.conf" path: "/etc/yum.conf"
line: "proxy={{ http_proxy }}" line: "proxy={{ http_proxy }}"
create: yes create: true
state: present state: present
become: true become: true
when: http_proxy is defined when:
- http_proxy is defined
- name: Install libselinux-python and yum-utils for bootstrap # libselinux-python is required on SELinux enabled hosts
yum: # See https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#managed-node-requirements
name: - name: Install libselinux-python
- libselinux-python package:
- yum-utils name: libselinux-python
state: present state: present
become: true become: true
when: when:
- not is_atomic - not is_atomic
- name: Check python-pip package
yum:
list=python-pip
register: package_python_pip
when:
- not is_atomic
- name: Install epel-release for bootstrap
yum:
name: epel-release
state: present
become: true
when:
- epel_enabled
- not is_atomic
- package_python_pip.results | length != 0
- name: check python-httplib2 package
yum:
list: "python-httplib2"
register: package_python_httplib2
when:
- not is_atomic
- name: Configure extras repository if python-httplib2 not avaiable in current repos
yum_repository:
name: extras
description: "CentOS-7 - Extras"
state: present
baseurl: "{{ extras_rh_repo_base_url }}"
file: "extras"
gpgcheck: yes
gpgkey: "{{extras_rh_repo_gpgkey}}"
keepcache: "{{ extras_rh_rpm_keepcache | default('1') }}"
proxy: " {{ http_proxy | default('_none_') }}"
when:
- not is_atomic
- package_python_httplib2.results | length == 0
- name: Install pip for bootstrap
yum:
name: python-pip
state: present
become: true
when:
- not is_atomic
- package_python_pip.results | length != 0

View file

@ -1,16 +1,16 @@
--- ---
- name: Install basic packages to run containers # ClearLinux ships with Python installed
- name: Install basic package to run containers
package: package:
name: "{{ item }}" name: containers-basic
state: present state: present
with_items:
- containers-basic
- name: Make sure docker service is enabled - name: Make sure docker service is enabled
systemd: systemd:
name: docker name: docker
masked: no masked: false
enabled: yes enabled: true
daemon_reload: yes daemon_reload: true
state: started state: started
become: true become: true

View file

@ -1,4 +1,6 @@
--- ---
# CoreOS ships without Python installed
- name: Check if bootstrap is needed - name: Check if bootstrap is needed
raw: stat /opt/bin/.bootstrapped raw: stat /opt/bin/.bootstrapped
register: need_bootstrap register: need_bootstrap
@ -16,39 +18,20 @@
- name: Run bootstrap.sh - name: Run bootstrap.sh
script: bootstrap.sh script: bootstrap.sh
when: need_bootstrap.rc != 0 become: true
when:
- need_bootstrap.rc != 0
- set_fact: - name: Set the ansible_python_interpreter fact
set_fact:
ansible_python_interpreter: "{{ bin_dir }}/python" ansible_python_interpreter: "{{ bin_dir }}/python"
tags: tags:
- facts - facts
- name: Install pip3
command: "{{ ansible_python_interpreter }} -m ensurepip"
args:
creates: "{{ bin_dir }}/pypy3/bin/pip3"
register: pip_installed
- name: Install pip3 link
file:
src: "{{ bin_dir }}/pypy3/bin/pip3"
dest: "{{ bin_dir }}/pip3"
mode: 0755
state: link
when: pip_installed.changed
- name: Install required python modules
pip:
name: "{{ item }}"
extra_args: "{{ pip_extra_args | default(omit) }}"
with_items: "{{ pip_python_coreos_modules }}"
environment:
PATH: "{{ ansible_env.PATH }}:{{ bin_dir }}"
- name: Disable auto-upgrade - name: Disable auto-upgrade
systemd: systemd:
name: locksmithd.service name: locksmithd.service
masked: true masked: true
state: stopped state: stopped
when: when:
- not coreos_auto_upgrade - coreos_locksmithd_disable

View file

@ -1,17 +1,16 @@
--- ---
# Some Debian based distros ship without Python installed
- name: Check if bootstrap is needed - name: Check if bootstrap is needed
raw: which "{{ item }}" raw: which python
register: need_bootstrap register: need_bootstrap
failed_when: false failed_when: false
changed_when: false changed_when: false
# This command should always run, even in check mode # This command should always run, even in check mode
check_mode: false check_mode: false
with_items:
- python
- pip
- dbus-daemon
environment: {} environment: {}
tags: facts tags:
- facts
- name: Check http::proxy in /etc/apt/apt.conf - name: Check http::proxy in /etc/apt/apt.conf
raw: grep -qsi 'Acquire::http::proxy' /etc/apt/apt.conf raw: grep -qsi 'Acquire::http::proxy' /etc/apt/apt.conf
@ -51,15 +50,18 @@
- https_proxy is defined - https_proxy is defined
- need_https_proxy.rc != 0 - need_https_proxy.rc != 0
- name: Install python, pip, and dbus - name: Install python
raw: raw:
apt-get update && \ apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y python-minimal python-pip dbus DEBIAN_FRONTEND=noninteractive apt-get install -y python-minimal
become: true become: true
environment: {} environment: {}
when: when:
need_bootstrap.results | map(attribute='rc') | sort | last | bool - need_bootstrap.rc != 0
- set_fact: # Workaround for https://github.com/ansible/ansible/issues/25543
ansible_python_interpreter: "/usr/bin/python" - name: Install dbus for the hostname module
tags: facts package:
name: dbus
state: present
become: true

View file

@ -1,22 +1,46 @@
--- ---
# Some Fedora based distros ship without Python installed
- name: Check if this is an atomic host
raw: stat /run/ostree-booted
register: ostree
environment: {}
failed_when: false
changed_when: false
tags:
- facts
- name: Store the fact if this is an atomic host
set_fact:
is_atomic: "{{ ostree.rc == 0 }}"
tags:
- facts
- name: Check if bootstrap is needed - name: Check if bootstrap is needed
raw: which "{{ item }}" raw: which python
register: need_bootstrap register: need_bootstrap
failed_when: false failed_when: false
changed_when: false changed_when: false
with_items:
- python
environment: {} environment: {}
tags: facts tags:
- facts
# Fedora's policy as of Fedora 30 is to still install python2 as /usr/bin/python
# See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3 for the current status
- name: Install python on fedora - name: Install python on fedora
raw: "dnf install --assumeyes --quiet python" raw: "dnf install --assumeyes --quiet python2"
become: true become: true
environment: {} environment: {}
when: need_bootstrap.results | map(attribute='rc') | sort | last | bool when:
- need_bootstrap.rc != 0
- not is_atomic
- name: Install required python packages # libselinux-python is required on SELinux enabled hosts
dnf: # See https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#managed-node-requirements
- name: Install libselinux-python
package:
name: libselinux-python name: libselinux-python
state: present state: present
become: true become: true
when:
- not is_atomic

View file

@ -1,13 +1,10 @@
--- ---
- name: Ensure zypper cache is updated (SUSE) # OpenSUSE ships with Python installed
zypper_repository:
repo: "*"
runrefresh: yes
- name: Install required packages (SUSE) # Without this package, the get_url module fails when trying to handle https
package: - name: Install python-cryptography
name: "{{ item }}" zypper:
name: python-cryptography
state: present state: present
with_items: update_cache: true
- python-cryptography
become: true become: true

View file

@ -1,72 +0,0 @@
---
- name: List ubuntu_packages
set_fact:
ubuntu_packages:
- python
- python-apt
- python-pip
- dbus
- name: Check if bootstrap is needed
raw: dpkg -l | cut -d' ' -f3 | grep -e ^{{ item }}$
register: need_bootstrap
failed_when: false
changed_when: false
# This command should always run, even in check mode
check_mode: false
with_items: "{{ ubuntu_packages }}"
environment: {}
tags:
- facts
- name: Check http::proxy in /etc/apt/apt.conf
raw: grep -qsi 'Acquire::http::proxy' /etc/apt/apt.conf
register: need_http_proxy
failed_when: false
changed_when: false
# This command should always run, even in check mode
check_mode: false
environment: {}
when:
- http_proxy is defined
- name: Add http_proxy to /etc/apt/apt.conf if http_proxy is defined
raw: echo 'Acquire::http::proxy "{{ http_proxy }}";' >> /etc/apt/apt.conf
become: true
environment: {}
when:
- http_proxy is defined
- need_http_proxy.rc != 0
- name: Check https::proxy in /etc/apt/apt.conf
raw: grep -qsi 'Acquire::https::proxy' /etc/apt/apt.conf
register: need_https_proxy
failed_when: false
changed_when: false
# This command should always run, even in check mode
check_mode: false
environment: {}
when:
- https_proxy is defined
- name: Add https_proxy to /etc/apt/apt.conf if https_proxy is defined
raw: echo 'Acquire::https::proxy "{{ https_proxy }}";' >> /etc/apt/apt.conf
become: true
environment: {}
when:
- https_proxy is defined
- need_https_proxy.rc != 0
- name: Install python and pip
raw:
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y {{ ubuntu_packages | join(" ") }}
become: true
environment: {}
when:
- need_bootstrap.results | map(attribute='rc') | sort | last | bool
- set_fact:
ansible_python_interpreter: "/usr/bin/python"
tags:
- facts

View file

@ -7,58 +7,61 @@
check_mode: false check_mode: false
environment: {} environment: {}
- include_tasks: bootstrap-ubuntu.yml - include_tasks: bootstrap-centos.yml
when: '"Ubuntu" in os_release.stdout' when: '"CentOS" in os_release.stdout or "Red Hat Enterprise Linux" in os_release.stdout'
- include_tasks: bootstrap-debian.yml - include_tasks: bootstrap-clearlinux.yml
when: '"Debian" in os_release.stdout' when: '"Clear Linux OS" in os_release.stdout'
- include_tasks: bootstrap-coreos.yml - include_tasks: bootstrap-coreos.yml
when: '"CoreOS" in os_release.stdout' when: '"CoreOS" in os_release.stdout'
- include_tasks: bootstrap-debian.yml
when: '"Debian" in os_release.stdout or "Ubuntu" in os_release.stdout'
- include_tasks: bootstrap-fedora.yml - include_tasks: bootstrap-fedora.yml
when: '"Fedora" in os_release.stdout' when: '"Fedora" in os_release.stdout'
- include_tasks: bootstrap-centos.yml
when: '"CentOS" in os_release.stdout or "Red Hat Enterprise Linux" in os_release.stdout'
- include_tasks: bootstrap-opensuse.yml - include_tasks: bootstrap-opensuse.yml
when: '"openSUSE" in os_release.stdout' when: '"openSUSE" in os_release.stdout'
- include_tasks: bootstrap-clearlinux.yml
when: '"Clear Linux OS" in os_release.stdout'
- name: Create remote_tmp for it is used by another module - name: Create remote_tmp for it is used by another module
file: file:
path: "{{ ansible_remote_tmp | default('~/.ansible/tmp') }}" path: "{{ ansible_remote_tmp | default('~/.ansible/tmp') }}"
state: directory state: directory
mode: 0700 mode: 0700
- name: Gather nodes hostnames # Workaround for https://github.com/ansible/ansible/issues/42726
# (1/3)
- name: Gather host facts to get ansible_os_family
setup: setup:
gather_subset: '!all' gather_subset: '!all'
filter: ansible_* filter: ansible_*
- name: Assign inventory name to unconfigured hostnames (non-CoreOS and Tumbleweed) - name: Assign inventory name to unconfigured hostnames (non-CoreOS, Suse and ClearLinux)
hostname: hostname:
name: "{{ inventory_hostname }}" name: "{{ inventory_hostname }}"
when: when:
- override_system_hostname - override_system_hostname
- ansible_os_family not in ['Suse', 'CoreOS', 'Container Linux by CoreOS', 'ClearLinux'] - ansible_os_family not in ['Suse', 'Container Linux by CoreOS', 'ClearLinux']
- name: Assign inventory name to unconfigured hostnames (CoreOS and Tumbleweed only) # (2/3)
- name: Assign inventory name to unconfigured hostnames (CoreOS, Suse and ClearLinux only)
command: "hostnamectl set-hostname {{ inventory_hostname }}" command: "hostnamectl set-hostname {{ inventory_hostname }}"
register: hostname_changed register: hostname_changed
changed_when: false
when: when:
- override_system_hostname - override_system_hostname
- ansible_os_family in ['Suse', 'CoreOS', 'Container Linux by CoreOS', 'ClearLinux'] - ansible_os_family in ['Suse', 'Container Linux by CoreOS', 'ClearLinux']
- name: Update hostname fact (CoreOS and Tumbleweed only) # (3/3)
- name: Update hostname fact (CoreOS, Suse and ClearLinux only)
setup: setup:
gather_subset: '!all' gather_subset: '!all'
filter: ansible_hostname filter: ansible_hostname
when: when:
- hostname_changed.changed - override_system_hostname
- ansible_os_family in ['Suse', 'Container Linux by CoreOS', 'ClearLinux']
- name: "Install ceph-commmon package" - name: "Install ceph-commmon package"
package: package:

View file

@ -23,8 +23,6 @@
hosts: kube-node hosts: kube-node
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
gather_facts: false gather_facts: false
vars:
ansible_ssh_pipelining: false
roles: roles:
- { role: kubespray-defaults} - { role: kubespray-defaults}
- { role: bootstrap-os, tags: bootstrap-os} - { role: bootstrap-os, tags: bootstrap-os}