Inhaltsverzeichnis
Ein Oracle Linux 8 Basis System für Ansible verwenden - eine Oracle Umgebung mit Ansible warten
Aufgabe:
Das Verteilen von Oracle Patchen soll über Ansible automatisiert werden, dazu ist es aber im ersten Schritt notwendig sich mit Anible vertraut zu machen.
Ansible (https://www.ansible.com/) ist ein Open-Source Werkzeug zur Konfiguration und Administration, insbesondere im Umfeld von RedHat basierenden Server Systemen.
Für die Verwaltung von Ansible steht als OpenSource Projekt Ansible AWX ( https://github.com/ansible/awx ) zur Verfügung , die gleiche Applikation mit Support von Red Hat als Ansible Tower (https://www.ansible.com/).
Siehe zur Installation und den ersten Schritten ⇒ Ansible Tower unter CentOS 8
Setup der Entwicklungs-Umgebung
In der produktiven Umgebung wird Ansible mit Ansible Tower als lizensierte Umgebung auf RedHat eingesetzt.
Aber um die Oracle Skripte im Vorfeld zu entwickeln und sich in die Materie einzuarbeiten, wird eine reine Ansible Open Source Umgebung unter Oracle Linux 8 aufgesetzt.
Im ersten Schritt wird ein Oracle Linux 8 als Standardsystem wie für eine DB Umgebung aufgesetzt ⇒ siehe dazu Ein Oracle Linux 8 Basis System .
Danach ist es wichtig eine gute vi Umgebung für das Erstellen der Ansible Scripts aufzusetzen ⇒ Mit Ansible YAML arbeiten ohne Nerven Zusammenbruch
Ansible über EPL unter Oracle Linux 8 installieren
EPL Repositorie einrichten
Wir benötigen noch das Oracle EPL Repostiory:
#Was ist bereits aktiviert? dnf repolist # EPL nachinstallieren dnf info oracle-epel-release-el8.x86_64 dnf install oracle-epel-release-el8.x86_64 # oder falls nur dekativiert # yum-config-manager --enable ol8_developer_EPEL dnf repolist repo id repo name ol8_UEKR6 Latest Unbreakable Enterprise Kernel Release 6 for Oracle Linux 8 (x86_64) ol8_appstream Oracle Linux 8 Application Stream (x86_64) ol8_baseos_latest Oracle Linux 8 BaseOS Latest (x86_64) ol8_developer_EPEL Oracle Linux 8 EPEL Packages for Development (x86_64)
Ansible installieren
dnf search ansible
dnf install ansible ansible-doc vim-ansible
Version und Pfade prüfen:
ansible --version ansible 2.9.21 config file = /etc/ansible/ansible.cfg configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3.6/site-packages/ansible executable location = /usr/bin/ansible python version = 3.6.8 (default, May 19 2021, 10:00:09) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1.0.1)]
Master User anlegen
Gruppen und User anlegen:
useradd ansible passwd ansible su - ansible #generate ssh key ssh-keygen -t rsa # Zugriff auf sich selbst konfigurieren! ssh ansible01.pipperr.local cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys #Auf die richtigen Rechte achten! chmod 600 ~/.ssh/authorized_keys
Den Ansible User in der Umgebung anlegen und die Schlüssel in der Umgebung verteilen
Ansible arbeitet per SSH Key, d.h. auf den jeweiligen Maschinen muss zuvor der SSH Key verteilt und ein User wie „ansible“ sollte auf den Maschinen existieren, das Arbeiten nur mit „root“ ist nicht zu empfehlen.
Der User Ansible muss auf der Maschine ohne Password sudo ausführen können, d.h. er muss in der Sudo Liste stehen!
Manuell anlegen
User manuell anlegen, diese Schritte wohlen wir aber im Anschluss automatisieren.
Auf dem ersten Zielsystem:
useradd ansible passwd ansible usermod -G wheel ansible visudo %wheel ALL=(ALL) NOPASSWD: ALL su - ansible ssh-keygen -t rsa
Key Austausch mit den Key vom Ansible Server:
# Vom Ansible Server aus! # Auf jedem Ziel System anmelden: ssh apex01.pipperr.local ssh ansible01.pipperr.local cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys exit
Ansible Grundlagen und die ersten Playbooks erstellen
Begrifflichkeiten:
- Playbook Kompletter Ablauf - enthält die Plays
- Plays last die eigentlichen Tasks zusammen und verbindet diese mit einer Gruppe von Hosts
- Tasks die eigentlichen konkreten Aufgaben die auf einem Host durchgeführt werden sollen
Die eigentlichen Play Books werden unter dem User „ansible“ erstellt.
Um ein zentrale Stelle für die Entwicklung der Playbooks zu verwenden, folgende Struktur unter /srv/ansible angelegt:
- /srv/ansible für alle ansible relevanten Daten
- /srv/ansible/inventory - Die Server Liste
- /srv/ansible/«PLAY_BOOK» - Projektverzeichnis für das Playbook
- Link /srv/ansible/«PLAY_BOOK»/inventory auf /srv/ansible/inventory um in allen Playbooks die gesamte Serverliste zu verwenden
#root mkdir /srv/ansible chown -R ansible:ansible /srv/ansible
Im Playbook empfiehlt die Dokumentation von Ansible hier die folgende Struktur ⇒ https://docs.ansible.com/ansible/latest/user_guide/sample_setup.html .
- README.md - Doku
- groups_vars - Gruppen Definitionen
- hosts_vars - Hosts Definitionen
- inventory - Inventar Listen
- side.yml - was wollen wir tun
- templates - Templates auf die in den Tasks zugegriffen wird
Aufbau einer Beispiel Umgebung, im ersten Schritt eine Template Struktur anlegen um diese immer wieder zu verwenden:
su - ansible touch /srv/ansible/inventory mkdir /srv/ansible/play_book_template cd /srv/ansible/play_book_template # Grund Struktur anlegen touch README.md mkdir group_vars mkdir hosts_vars ln -s /srv/ansible/inventory inventory touch site.yml mkdir templates
Zentrales Inventory hinterlegen
Um nicht in jedem Playbook alle Ziel pflegen zu müssen, wird diese Datei zentral angelegt und verlinkt:
Datei /srv/ansible/inventory
vi /srv/ansible/inventory [ORA_SERVER] apex01.pipperr.local [MANAGMENT] ansible01.pipperr.local #Obergruppe definieren [LAB:children] ORA_SERVER MANAGMENT
Inventory aus KeePass erzeugen
Mit Hilfe des Pyhton Moduls PyKeePass https://pypi.org/project/pykeepass/ „https://github.com/libkeepass/pykeepass“ lässt sich aus einer vorhanden Key Passdatei ein Inventroy erzeugen.
Siehe dazu ⇒ Keepass Datei mit Python auslesen um Ansible Konfiguration zu erzeugen
Ohne Playbook arbeiten - auf allen Server ein Kommando ausführen
Liegt ein Inventory vor und ist der Zugriff konfiguriert kann ein Befehl auch auf allen Knoten mit der „-a“ Option ausgeführt werden.
#Hier noch mit Passwort: ansible ORA_SERVER -a "/bin/uname -a" -k SSH password: apex01.pipperr.local | CHANGED | rc=0 >> Linux apex01.pipperr.local 5.4.17-2036.103.3.1.el8uek.x86_64 #2 SMP Sun Feb 14 12:54:18 PST 2021 x86_64 x86_64 x86_64 GNU/Linux
Oder ein einfaches PlayBook erstellen, und den Output ausgeben und in eine Datei schreiben lassen.
--- - name: Execute Command hosts: all tasks: - name: Execute Command command: "/bin/uname -a" register: serverInfo - debug: var=serverInfo.stdout_lines - name: Write variable to file local_action: copy content="{{serverInfo}}" dest=./server_info
[ansible@ansible01 deploy_ansible_user]$ ansible-playbook -l ALL execute.yml -k --verbose Using /srv/ansible/deploy_ansible_user/ansible.cfg as config file SSH password: PLAY [Execute Command] ********************************************************************************************************************* TASK [Gathering Facts] ********************************************************************************************************************* ok: [apex01.pipperr.local] ok: [ansible01.pipperr.local] TASK [Execute Command] ********************************************************************************************************************* changed: [ansible01.pipperr.local] => {"changed": true, "cmd": ["/bin/uname", "-a"], "delta": "0:00:00.003301", "end": "2021-06-12 17:47:09.810925", "rc": 0, "start": "2021-06-12 17:47:09.807624", "stderr": "", "stderr_lines": [], "stdout": "Linux ansible01.pipperr.local 5.4.17-2102.201.3.el8uek.x86_64 #2 SMP Fri Apr 23 09:05:57 PDT 2021 x86_64 x86_64 x86_64 GNU/Linux", "stdout_lines": ["Linux ansible01.pipperr.local 5.4.17-2102.201.3.el8uek.x86_64 #2 SMP Fri Apr 23 09:05:57 PDT 2021 x86_64 x86_64 x86_64 GNU/Linux"]} changed: [apex01.pipperr.local] => {"changed": true, "cmd": ["/bin/uname", "-a"], "delta": "0:00:00.004017", "end": "2021-06-12 17:47:09.864344", "rc": 0, "start": "2021-06-12 17:47:09.860327", "stderr": "", "stderr_lines": [], "stdout": "Linux apex01.pipperr.local 5.4.17-2036.103.3.1.el8uek.x86_64 #2 SMP Sun Feb 14 12:54:18 PST 2021 x86_64 x86_64 x86_64 GNU/Linux", "stdout_lines": ["Linux apex01.pipperr.local 5.4.17-2036.103.3.1.el8uek.x86_64 #2 SMP Sun Feb 14 12:54:18 PST 2021 x86_64 x86_64 x86_64 GNU/Linux"]} TASK [debug] ******************************************************************************************************************************* ok: [apex01.pipperr.local] => { "serverInfo.stdout_lines": [ "Linux apex01.pipperr.local 5.4.17-2036.103.3.1.el8uek.x86_64 #2 SMP Sun Feb 14 12:54:18 PST 2021 x86_64 x86_64 x86_64 GNU/Linux" ] } ok: [ansible01.pipperr.local] => { "serverInfo.stdout_lines": [ "Linux ansible01.pipperr.local 5.4.17-2102.201.3.el8uek.x86_64 #2 SMP Fri Apr 23 09:05:57 PDT 2021 x86_64 x86_64 x86_64 GNU/Linux" ] } PLAY RECAP ********************************************************************************************************************************* ansible01.pipperr.local : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 apex01.pipperr.local : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook Beispiel - Ansible User auf den zu überwachenden Knoten über Root anlegen
Über den User Root soll im ersten Schritt der Ansible User mit dem jeweiligen Root Passwort angelegt werden.
Wenn das Root Passwort aber nicht überall gleich ist muss das Password auf Host Ebene hinterlegt werden, falls gleich kann das auf der „all“ Ebene erfolgen.
Da das natürlich sehr unsicher ist, muss dann verschlüsselt abgelegt werden! Bzw. besser in diesem Schritt gar nicht hinterlegen und mit der Option -k interaktiv angeben (all wenigstens in einer Gruppe gleich!)!
Unser Template kopieren:
cp -r /srv/ansible/play_book_template /srv/ansible/deploy_ansible_user
Ansible konfigurieren
Um die -i Option zu sparen eine ansible.cfg anlegen
vi ansible.cfg [defaults] inventory = ./inventory remote_user = root #Vault Password vault_password_file = ./vault-pass.txt # avoid warning message python path interpreter_python = auto_silent #noch check host keys to avoid errors host_key_checking = false [privilege_escalation] become = false
Parameter für die Ziel Gruppe hinterlegen
Datei group_vars/«GROUP_NAME»
vi group_vars/ORACLE_SERVER
--- admin_group: wheel
Parameter für alle Gruppen hinterlegen
Datei group_vars/all
vi group_vars/all
--- #Access to all servers default ansible_connection: ssh ansible_ssh_user: root ansible_ssh_pass: <<my_mostly_used_root_pwd>> # management_user_pwd: Secret1!
Im nächsten Schritt wird das verschlüsselt dazu kann iAnsible Vault verwendet werden.
Vrschlüsseln mit:
ansible-vault encrypt ./group_vars/all New Vault password: Confirm New Vault password: Encryption successful #Bei Bedarf anpassen ansible-vault edit ./group_vars/all
Möglichkeiten nun das Vault Passwort beim Aufruf eines Playbooks zu hinterlegen:
- Interaktiv das Passwort eingeben werden, Option „–ask-vault-pass“
- Passwort in einer Datei wie vault-pass.txt hinterlegen, diese vor GIT und dem Zugriff schützen, beim Aufruf des Playbooks mit angeben - Option „– vault-password-file vault-pass.txt“
- Die Datei mit dem Passwort in der ansible.cfg hinterlege mit „vault_password_file = ./vault-pass.txt“
Zugriff testen
Test des Zugriffes über:
ansible all --list-hosts # mit der K Option für die Password Übergabe ansible all -m setup -u root -k #nur eine Gruppe aufrufen ansible ORA_SERVER -m ping -k
Die notwendigenTasks anlegen
- Erzeugeden Ansible User
- Sudo Konfiguration ausrollen
- SSH Public Key der Management Umgebung verteilen
Erzeugeden Ansible User vi create_user.yml:
- create_user.yml
--- - name: Create Ansible User hosts: ORA_SERVER tasks: - name: Create Ansible User ansible.builtin.user: name: ansible groups: "{{ admin_group }}" append: true create_home: true comment: "Ansible Management Account" expires: -1 password: "{{ management_user_pwd | password_hash('sha512','A512') }}" - name: Deploy Local User SSH Key authorized_key: user: ansible state: present manage_dir: true key: "{{ lookup('file', '/home/ansible/.ssh/id_rsa.pub') }}" - name: Setup Sudo Access for Devops User ansible.builtin.copy: dest: /etc/sudoers.d/ansible content: 'ansible ALL = NOPASSWD : ALL' validate: /usr/sbin/visudo -cf %s
Check:
ansible-playbook create_user.yml --syntax-check
Starten:
ansible-playbook create_user.yml -k SSH password: PLAY [Create Ansible User] ************************************************************************************************************* TASK [Gathering Facts] ***************************************************************************************************************** ok: [apex01.pipperr.local] TASK [Create Ansible User] ************************************************************************************************************* ok: [apex01.pipperr.local] TASK [Deploy Local User SSH Key] ******************************************************************************************************* ok: [apex01.pipperr.local] TASK [Setup Sudo Access for Devops User] *********************************************************************************************** changed: [apex01.pipperr.local] PLAY RECAP ***************************************************************************************************************************** apex01.pipperr.local : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Löschen des Ansible User
vi remove_user.yml
- remove_user.yml
--- - name: drop Ansible User hosts: ORA_SERVER tasks: - name: drop Ansible User user: name: ansible state: absent remove: true
Check:
ansible-playbook remove_user.yml --syntax-check
Ausführen:
ansible-playbook remove_user.yml -k SSH password: PLAY [drop Ansible User] *************************************************************************************************************** TASK [Gathering Facts] ***************************************************************************************************************** ok: [apex01.pipperr.local] TASK [drop Ansible User] *************************************************************************************************************** changed: [apex01.pipperr.local] TASK [Remove Sudo Entry] *************************************************************************************************************** changed: [apex01.pipperr.local] PLAY RECAP ***************************************************************************************************************************** apex01.pipperr.local : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook Beispiel - SQL*Plus aufrufen und Script ausführen
Unser Template kopieren:
cp -r /srv/ansible/play_book_template /srv/ansible/oracle_maintenance
Ansible konfigurieren
Ansible CFG auf das Projekt anpassen
vi ansible.cfg [defaults] inventory = ./inventory remote_user = ansible # avoid warning message python path interpreter_python = auto_silent
Parameter für die Ziel Hosts hinterlegen
Datei host_vars/«host_name»
vi host_vars/apex01.pipperr.local
--- hostname: apex01.pipperr.local IP: 10.10.10.90 roles: - common - dbserver virtual: true oracle_envs: - oracle_home: /opt/oracle/product/19c/dbhome_1 oracle_sid: - GPIDB1 - PRDDB - oracle_home: /opt/oracle/product/18c/dbhome_1 oracle_sid: - GPIDB
Pro Server so eine Datei anlegen, die Oracle Umgebungen werden als Listen angelegt da ja meherer Oracle Homes und Oracle Datenbaken auf dem Server liegen können.
Im Ansible Script wird dann mit „with_items“ bzw. „with_subelements“ über diese Liste itteriert.
Parameter für alle Gruppen hinterlegen
Datei group_vars/all
vi group_vars/all
--- #empty in this case
Zugriff testen
Test des Zugriffes über:
ansible all --list-hosts # mit der K Option für die Password Übergabe ansible all -m setup -u root -k #nur eine Gruppe aufrufen ansible ORA_SERVER -m ping -k
Die notwendigenTasks anlegen
- Verzeichnis für die Skripte anlegen
- Script auf dem Server kopieren
- Script in SQL*Plus ausführen
vi execute_set_pack_access.yml:
- execute_set_pack_access.yml
--- - name: Call SQL*Plus Script to disable all mangement packs hosts: ORA_SERVER tasks: - name: Create the Script Directory become: yes become_user: oracle ansible.builtin.file: owner: oracle group: oinstall path: "/home/oracle/ansible_scripts/" state: directory - name: Copy the sql*plus script become: yes become_user: oracle ansible.builtin.copy: src: ./scripts/set_pack_access.sql dest: /home/oracle/ansible_scripts - name: Call the script as oracle user become: yes become_user: oracle command: "$ORACLE_HOME/bin/sqlplus -s / as sysdba @/home/oracle/ansible_scripts/set_pack_access.sql" environment: ORACLE_HOME: "{{ item.0.oracle_home }}" ORACLE_SID: "{{ item.1 }}" with_subelements: - "{{ oracle_envs }}" - oracle_sid
Check:
ansible-playbook execute_set_pack_access.yml --syntax-check
SQL*Plus Script anlegen
vi ./scripts/set_pack_access.sql
SELECT USER FROM dual; exit
Starten:
ansible-playbook execute_set_pack_access.yml --verbose Using /srv/ansible/oracle_maintenance/ansible.cfg as config file PLAY [Call SQL*Plus Script to disable all mangement packs] ********************************************************************************* TASK [Gathering Facts] ********************************************************************************************************************* ok: [apex01.pipperr.local] TASK [Create the Script Directory] ********************************************************************************************************* ok: [apex01.pipperr.local] => {"changed": false, "gid": 54321, "group": "oinstall", "mode": "0755", "owner": "oracle", "path": "/home/oracle/ansible_scripts/", "size": 33, "state": "directory", "uid": 54321} TASK [Copy the sql*plus script] ************************************************************************************************************ ok: [apex01.pipperr.local] => {"changed": false, "checksum": "8353662eb6e8d7ee1b6979d949ba695779046674", "dest": "/home/oracle/ansible_scripts/set_pack_access.sql", "gid": 54321, "group": "oinstall", "mode": "0644", "owner": "oracle", "path": "/home/oracle/ansible_scripts/set_pack_access.sql", "size": 29, "state": "file", "uid": 54321} TASK [Call the script as oracle user] ****************************************************************************************************** changed: [apex01.pipperr.local] => {"changed": true, "cmd": ["$ORACLE_HOME/bin/sqlplus", "-s", "/", "as", "sysdba", "@/home/oracle/ansible_scripts/set_pack_access.sql"], "delta": "0:00:00.051674", "end": "2021-06-13 00:45:36.059234", "rc": 0, "start": "2021-06-13 00:45:36.007560", "stderr": "", "stderr_lines": [], "stdout": "\nUSER\n--------------------------------------------------------------------------------\nSYS", "stdout_lines": ["", "USER", "--------------------------------------------------------------------------------", "SYS"]} PLAY RECAP ********************************************************************************************************************************* apex01.pipperr.local : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Mit diesem ersten Elemente lassen sich nun einfach Scripte auf den Datenbank Server verteilen und ausführen.
Quellen
Blog Einträge
Code Beispiele
Tutorial
Oracle Beispiele
Tools und Erweiterungen für Ansible
Server Informationen sammen und als HTML Darstellen