Instalando el grid infraesturcure con Ansible

Hoy vamos a ver los pasos a llevar a cabo y el codigo para llevar a cabo una instalación de un Grid Infraestructura de la versión 19c en un standalone server .

Como puntos importantes a esta instalación tenemos:

Condiciones

1- Tenemos configurado el sudores del equipo cliente tal y como explicamos en Requisitos de los equipos cliente para automatizar con Ansible: SUDO
2- Vamos a instalar y configurar solamente el GI y el listener, en este paso no vamos a crear en ASM, de esta manera nos va a servir tanto para llevar a cabo una instalación de ASM como para un oracle restart sobre filesystem
3-Tendremos un punto compartido de red donde podremos obtener los binarios descargados de oracle


Para poder ejecutar esta automatización necesitamos:

  • variable env: Nombre del servidor que debe de estar inventariado. En nuestro laboratorio va a ser alone.pamplona.name
  • variable type: Esta variable en nuestro caso va a estar fija a asm
  • Variable version: Variable con el numero de version que queremos instalar,en nuestro laboratorio va a ser la 19.0.0.3

Como veremos, mas adelante , estas tres variables van a ser parseadas enpracticamente todos nuestros playbooks.

Nuestra estructura de Playbooks va a ser muy similar a la de un role de Ansible, nuestros ficheros estarán distribuidos de la siguiente manera


Raiz
|
|- vars:      Ficheros/Inventario de variables
|- templates: Ficheros de templates  
|- file:       Ficheros específicos para  playbooks 

Como veremos mas adelante, el contenido de los directorios Vars y templates va a ser común a todas las ejecuciones, pero el del directorio temp será único por ejecución.

Directorio de variables

Este directorio va a tener los ficheros con información de los estándares que queremos aplicar, por decirlo de una manera sencilla, son los ficheros de nuestras normas

En el lenguaje de Ansible este directorio se podría llamar también inventario de variables

Entr elos ficheros que vamos a usar están:

oracle_standard.yaml

Este fichero va a ser el que contenga los estándares del departamento.
Va a ser común para todas las acciones que se llevan a cabo para las bases de datos de oracle, ya sea instalación de binarios, creación de bases de datos y/o parchados
El ejemplo de nuestro laboratorio es:

[code lang=»py»]
root_user: "root"
oracle_user: "oracle"
oracle_group: "dba"
media_dir: "/mnt/media"
root_directory: "/u01/app"
oracle_inventory: "{{root_directory}}/oraInventory"
oracle_base: "{{root_directory}}/oracle"
stage_directory: "{{oracle_base}}/stage"
oracle_home_directory:
db: "{{oracle_base}}/product/{{version}}/dbhome1"
asm: "{{oracle_base}}/product/{{version}}/grid"
response_file: "{{type}_{{action}}_{{version}}.rsp"
data_location:
FS: "/oradata/{{SID}}/data"
ASM: "+{{oracle_hostname}}_DATA"
fra_location:
FS: "/oradata/{{SID}}/data"
ASM: "+{{oracle_hostname}}_FRA"
redo1_location:
FS: "/oradata/{{SID}}/redo"
ASM: "+{{oracle_hostname}}_REDO1"
redo2_location:
FS: "/oradata/{{SID}}/redo2"
ASM: "+{{oracle_hostname}}_REDO2"
sysasm_passd: changueme2020
asmdbsnmp_passwd: changueme2020

[/code]
Como cosas curiosas podeis ver que

  • Nuestros directorios raices estarán como indican las Oracle Best Practices
  • Cuando la base de datos tenga ASM los diskgroups no se llamaran DATA,REDO y FRA, sino que tendrán como prefijo el nombre del equipo y tendremos dos REDOS
  • Al contrario de las best practices de Oracle vamos ha hacer el taller a lo «old style » todo bajo el grupo dba, el añadir los temas grupos es algo trivial una vez se ha visto la manera en la que funciona el playbook

asm_SO_precondition_19.0.0.3.yaml

La notación de este fichero va a ser $TYPE_SO_precondition_$VERSION.yaml, este este fichero es el que va a ser utilizado para comprobar las precondiciones de la instalación.

En el laboratorio vamos a incluir solamente a modo de ejemplo cinco de paquetes, pero podríamos extenderlo a todo lo que queramos que se compruebe como precondicion de la instalación, como parámetros del kernel, configuraciones del equipo ( selinux, firewall ) …

En caso de tener varias distribuciones de sistemas operativos (asumimos que trabajamos bajo linux) o versiones de los mismos, seria este único fichero el que guardaría las precondiciones tanto de los valores comunes como de los específicos para cada sistema distribución/version

[code lang=»py»]
package_name :
– binutils
– elfutils-libelf
– elfutils-libelf
– oracleasm
– oracleasm-support
[/code]

asm_binaries.yaml

La notación de este fichero va a ser $TYPE_binaries.yaml, aqui tenemos información física del paquete y del response file a usar.
Este fichero no dispone del sufijo version, ya que contendrá a modo de inventario la información de todos los binarios.

[code lang=»py»]
19.0.0.3:
response_file: "asm_binaries_19.0.0.3.rsp"
binary_name: "LINUX.X64_193000_grid_home.zip"
19.0.0.5:
response_file: "asm_binaries_19.0.0.5.rsp"
binary_name: "LINUX.X64_195000_grid_home.zip"[/code]
Otra información adicional que podríamos añadir es el MD5 del binario para comprobar su estado.

Playbooks

En este laboratorio vamos a ejecutar un trabajo en AWX-RPM que va a estar formado por una secuencia de playbooks independientes.
El orden y contenido de cada uno de ellos es:

so_packages

El primer playbook a ejecutar es el que va a comprobar los prerrequisitios de nuestra instalación.
Los chequeos básicos a llevar a cabo son los paquetes y usuarios y grupos

[code lang=»py»]
# Pamplona 2019
# Playbook which checks if required packages ares installed at the destination server
#
# requires
# env: name of the server which should be in the inventory
# type: type of installation [asm|db]
# vars/[type]_SO_precomdition_[version].yaml configuration file with the S.O preconditions

– hosts: "{{env}}"
remote_user: ansible
become: yes
become_user: root
tasks:
– fail: msg="Error no server definied, please define the env variable in the job"
when: env is not defined

– name: Including package
include_vars:
file: "{{type}}_SO_precondition_{{version}}.yaml"

– name: check packages "{{package_name}}"
yum:
name: "{{package_name}}"
state: latest
with_items:
– "{{ package_name }}"

[/code]
Como veíamos en el apartado de variables, carga los paquetes necesarios de un fichero de inventario {{type}}_SO_preconditions_{{version}}.yaml , de esta manera reutilizaremos el mismo fichero para todas las versiones, teniendo que añadir simplemente ficheros de requisitos para las distintas versiones que soportemos.

oracle_directories.yaml

Tenemos un sistema que cumple con los requisitos de configuración de sistema operativo, el siguiente paso es comprobar que nuestra estructura de directorios de oracle existe y en caso contrario crearla.
Para este playbook usaremos el fichero de inventario oracle_standard.yaml en el que , como explicábamos al principio tenemos todos los estándares de nuestra compañía.

[code lang=»py»]
# Pamplona 2019
# Playbook which create the required directories
#
# requires
# env: name of the server which should be in the inventory
# type: type of installation [asm|db]
# version: version of database or asm
# vars/oracle_standard.yaml standard values for Oracle
# ignore if it can ignore errors

– hosts: "{{env}}"
remote_user: ansible
become: yes
become_user: oracle
tasks:
# checking prerrequisites
– fail: msg="Error no server definied, please define the env,type and version variables in the job"
when: env is not defined or version is not defined or type is not defined
# End prerrequisites + check var file for improvement

# Loading env
– name: Including Standard_values
include_vars:
file: "vars/oracle_standard.yaml"

– set_fact:
oracle_home: "{{oracle_home_directory.db}}"
when: type == "db"

– set_fact:
oracle_home: "{{oracle_home_directory.asm}}"
when: type == "asm"

#
– name: create directories
file:
path: "{{ item }}"
state: directory
owner: "{{ oracle_user }}"
group: "{{ oracle_group }}"
mode: ‘0775’
with_items:
– "{{ root_directory }}"
– "{{ stage_directory }}"
– "{{ oracle_inventory }}"
– "{{ oracle_base }}"
– "{{ oracle_home }}"
ignore_errors: "{{ ignore}}"
tags:
– create_directories

[/code]

unzip_binaries.yaml

El propio nombre del playbook lo dice todo.
Vamos a obtener en el equipo cliente el fichero de binarios descargable de Oracle y lo descomprimiremos en la ubiacion que hayamos elegido como $ORACLE_HOME

[code lang=»py»]
# Pamplona 2020
# Playbook which unzips the requested file
#
# requires
# env: name of the server which should be in the inventory
# type: type of installation [asm|db]
# version: version of database or asm
# vars/oracle_standard.yaml standard values for Oracle
# vars/[type]_binaries.yaml configuration file with the variables requested for the extraction
#

– hosts: "{{env}}"
remote_user: ansible
become: yes
become_user: root
tasks:
# checking prerrequisites
– fail: msg="Error no server definied, please define the env and type variable in the job"
when: env is not defined or type is not defined
# Loading env
– name: Including Standard_values
include_vars:
file: "vars/oracle_standard.yaml"

– name: Including binaries info
include_vars:
file: "vars/{{type}}_binaries.yaml"

– name: check for required binaries
stat:
path: "{{media_dir}}/{{version.binary_name}}"
register: exsists
– debug:
msg: The file is availabe
when: exsists.stat.readable == True

– fail:
msg: "ERROR: Source zip file not found"
when: exsists.stat.readable == False
ignore_errors: False

– set_fact:
oracle_home: "{{oracle_home_directory.db}}"
when: type == ‘db’

– set_fact:
oracle_home: "{{oracle_home_directory.asm}}"
when: type == ‘asm’

– name: Extract "{{media_dir}}/{{version.binary_name}} {{ oracle_home }}"
unarchive:
src: "{{media_dir}}/{{version.binary_name}}"
remote_src: yes
dest: "{{ oracle_home }}"
become: yes
become_user: "{{ oracle_user}}"

[/code]

asm_binaries_instal.yaml

Este es el playbook que lleva a cabo la acción real, veamos los pasos que lleva a cabo

  • carga de entornos comprueba los prerrequisitos y carga los ficheros de variables
  • Genera un response file: Este paso es importante ya que, utiliza una template en Jinja para , con las variables obtenidas de nuestro inventario de variables oracle_standard generar un fichero de response en el formato especifico para nuestra version de asm
  • Instalación de binarios: Ejecuta el comando de instalación con el response file generado anteriormente, esta instalación da muchos warnings, entre otras cosas por que , en este laboratorio no estamos cumpliendo todas las Oracle Best practices ( usuarios, grupos, ubicaciones), de ahí que le añadamos la calusula ignore Errors: True
  • Ejecutamos el conocido root.sh
  • Registro del CRS: Hemos instalado e inventariado los binarios, pero el CRS no esta instalado, este paso DEBE de tener ASM, pero, nosotros vamos a llevarlo a cabo sin la necesidad de decirle que tenemos uno, de ahí que lo hagamos ahora en un paso separado , como podemos observar, este paso se lleva a cabo como root, no como usuario oracle
  • Creación de un Listener: Tenemos nuestro CRS instalado y registrado, pero esta vacío, por lo que , vamos a crear un listener bajo esta rama de binarios
  • Habiitar un Listener: Este paso es redundante y da error , ya que el paso anterior lo deja habilitado, simplemente lo ejecutamos como guarda de seguridad
  • Arrancar el Listener: Aunque el objetivo de nuestro laboratorio de hoy era el de tener instalado un cls que funcione, hemos de pensar que , en un futuro crearemos el asm y probablemente instalemos las bases de datos, por lo que, es importante asegurarse que una vez acabamos esta todo encendido

[code lang=»py»]
# Pamplona 2020
# Playbook which sends a respone file and uses it to install Oracle restart/ CRS / Grid on alone server
# requires
# env: name of the server which should be in the inventory
# type: asm or dba
# version: version of database or asm
# vars/oracle_standard.yaml standard values for Oracle
# vars/asm_binaries.yaml: Info with the asm binaries

– hosts: "{{ env }}"
remote_user: ansible
become: yes
become_user: root
tasks:
# checking prerrequisites
– fail: msg="Error no server definied, please define the env variable in the job"
when: env is not defined or version is not defined or type is not defined
# Loading env
– name: Including Standard_values
include_vars:
file: "vars/oracle_standard.yaml"

– name: Including binaries info
include_vars:
file: "vars/{{type}}_binaries.yaml"
– set_fact:
oracle_home: "{{oracle_home_directory.db}}"
when: type == ‘db’

– set_fact:
oracle_home: "{{oracle_home_directory.asm}}"
when: type == ‘asm’
#
– name: generate response file
template:
src: "templates/{{ version.response_file }}.j2"
dest: "{{ stage_directory }}/{{version.response_file}}"
mode: ‘0644’

– name: Install Grid 19c Software
shell: "{{ oracle_home }}/gridSetup.sh -silent -responseFile {{ stage_directory }}/{{version.response_file}}"
become: yes
become_user: "{{ oracle_user }}"
args:
chdir: "{{ oracle_home }}"
ignore_errors: True

– name: execute root.sh
shell: "{{ oracle_home }}/root.sh"
become: yes
become_user: root
args:
chdir: "{{ oracle_home }}"

– name: Configure CRS
shell: $GI_HOME/perl/bin/perl -I $GI_HOME/perl/lib -I $GI_HOME/crs/install $GI_HOME/crs/install/roothas.pl
become: yes
become_user: root
args:
chdir: "{{ oracle_home }}"
environment:
GI_HOME: "{{ oracle_home }}"
ignore_errors: True

– name: Create listener
shell: "$GI_HOME/bin/srvctl add listener -listener LISTENER -oraclehome {{ oracle_home }}"
become: yes
become_user: "{{oracle_user}}"
args:
chdir: "{{ oracle_home }}"
environment:
GI_HOME: "{{ oracle_home }}"
ORACLE_BASE: "{{ oracle_base}}"
ignore_errors: False

– name: Enable listener
shell: $GI_HOME/bin/srvctl enable listener -listener LISTENER
become: yes
become_user: "{{oracle_user}}"
args:
chdir: "{{ oracle_home }}"
environment:
GI_HOME: "{{ oracle_home }}"
ORACLE_BASE: "{{ oracle_base}}"
ignore_errors: True

– name: Start listener
shell: $GI_HOME/bin/srvctl start listener -listener LISTENER
become: yes
become_user: "{{oracle_user}}"
args:
chdir: "{{ oracle_home }}"
environment:
GI_HOME: "{{ oracle_home }}"
ORACLE_BASE: "{{ oracle_base}}"
ignore_errors: False

[/code]

Como siempre, las ultimas versiones de este codigo están disponibles en el proyecto provisioning en GITHUB

Deja una respuesta