Crear un entorno de pruebas con KVM I

Hoy vamos a ver la primera de una serie de entradas que nos llevarán a poder crear un pequeño entorno de pruebas virtual en el cual poder hacer nuestras pruebas de alta disponibilidad de plataformas Oracle .

Lo que buscamos con este entorno  es el tener una plataforma en la que poder replicar entornos para hacer pruebas de funcionamiento/parcheados/ migraciones. Si lo que se busca es una plataforma en la que hacer pruebas de rendimiento habrá que aumentar mucho las características del hardware que vamos a indicar en estas entradas.

Vamos a usar  el entorno de virtualizacion KVM en nuestro caso bajo una distribucion de Linux Centos y como servidor virtual sobre el que correran nuestros Oracles usaremos un Oracle Linux (la 6.1 en este caso) que descargaremos en formato ISO y qye depositaremos en el filesystem bajo el nombre   /mnt/virtual1/sources/OracleLinux-R6-U1-Server-x86_64-dvd.iso

Nuestro hypervisor contará con  una estructura de 3 discos, estos discos estarán montados bajo:

  • /mnt/virtual1/sources: Donde guardaremos las imágenes .iso de nuestros discos de fuentes
  • /mt/virtual1/raw .  Donde se ubicaran los discos de datos que utilizaran nuestras bases de datos
  • /mnt/virtual1. Donde guardaremos las imagenes de las máquinas virtuales.

Asímismo tendremos 3 entornos de red :

  • host: red básica por defecto, nateada a la tarjeta de red del hypervisor y que hará de direccionamiento IP del host, estará en la red 192.168.100.0/24
  • vip: Red que usaremos para el entorno virtual (VIP de oracle)  192.168.101.0/24
  • priv: Red privada entre los hostos (prov de oracle)   192.168.102.0/24

La configuracion de nuestro hypervisor quedará de la siguiente manera (usando la herramienta virt-manager)

Pestaña Virtual networks

Donde las redes priv y vip son «isolated»

Pestaña almacenamiento

Pestaña Interfaces

Una vez tenemos nuestro hypervisor instalado, procederemos a instalar nuestro primer servidor virtual.  Lo que buscamos es un servidor llamado rac1 que cuente con 1 Gb de memoria y cuyo fichero físico se encuentr en /mnt/virtual1/rac1/rac1.img

Así pues ejecutaremos :

virt-install \
--name rac1 \
--ram 1024 \
--os-variant=rhel6 \
--cdrom /mnt/virtual1/OracleLinux-R6-U1-Server-x86_64-dvd.iso \
--disk /mnt/virtual1/servidores/rac1.img,bus=virtio \
--disk /mnt/virtual1/raw/raw_1.img,perms=sh,format=raw,bus=virtio \

Lo que nos creará la máquina virtual, ahora solamente tenemos que arrancarla y hacer la instalacion de Oracle Linux.

Dado que nuestro fin no es probarla distribucion de Linux sino arquitecturas de Grid, Dataguard o RAC que vayamos a montar sobre ellas ,no vamos a detallar mucho la instalacion del Oracle Linux, haremos una instalacion completa deteniendo mas tarde todos los servicios innecesarios.

Una vez esté instalada y levantada, entraremos en las propiedades del servidor y le añadiremos los 3 nuevos interfaces de red, cada uno en una de nuestras redes (host,vip y priv)

Al finalizar esto iremos al directorio /etc/sysconfig/network-scripts y modificarremos los ficheros ifcfg-ethX de manera que queden:

 

 

 

Añadiremos en el /etc/hosts las lineas

#   Para el kvm
# Ip de host
192.168.100.1  hypervisor.pamplona.name
192.168.100.2  server1.pamplona.name
192.168.100.3  server2.pamplona.name
192.168.100.4  server3.pamplona.name
192.168.100.5  server4.pamplona.name
192.168.100.99 rac1.pamplona.name
# Virtual IP 
192.168.101.1  hypervisor-vip.pamplona.name
192.168.101.2  server1-vip.pamplona.name
192.168.101.3  server2-vip.pamplona.name
192.168.101.4  server3.pamplona.name
192.168.101.5  server4.pamplona.name
192.168.101.99 rac1.pamplona.name
# Private IP
192.168.102.1  hypervisor-priv.pamplona.name
192.168.102.2  server1-priv.pamplona.name
192.168.102.3  server2-priv.pamplona.name
192.168.102.4  server3.pamplona.name
192.168.102.5  server4.pamplona.name
192.168.102.99 rac1.pamplona.name

Con esto tenemos un servidor llamado rac1 , con las ips que se ven en el  /etc/hosts

Ahora podremos utilizar este servidor para clonarlo tantas veces como queramos y tendremos una máquina base para poder hacer nuestras pruebas con Oracle.

En nuestro caso vamos a empezar clonandolo 2 veces para crear los servidores server1 y server2

Una vez clonadas las máquinas, habrá que cambiarles las MAC,IP y elnombre del servidor, esto se cambia mediante:

  • /etc/systconfig-network-scripts/ifcfg-eth0:  cambiar la MAC y la IP
  • /etc/systconfig-network-scripts/ifcfg-eth1:  cambiar la MAC y la IP
  • /etc/systconfig-network-scripts/ifcfg-eth2:  cambiar la MAC y la IP
  • /etc/sysconfig/network  donde cambiaremos el nombre del host

Con esto tenemos la infraestructura básica para nuestras pruebas, en los siguientes post iremos instalando diversas arquitecturas para hacer pruebas sobre ellas.

Añadir un recurso a grid control /clusterware

Una de las ventajas que nos ofrece Oracle clusterware o Oracle Grid control es el gestionar una serie de elementos/procesos/aplicaciones arrancándolas o parándolas de manera centralizada.

Si instalamos nuestras bases con  la infraestructura de grid control, podemos aprovecharnos de la misma para gestionar en el arranque otros elementos como servidores de aplicaciones o la consola de administracion.Esto puede sernos muy util por ejemplo en caso de reinicio del servidor ya que grid control se puede encargar de levantar estos procesos.

En esta entrada vamos a ver como añadir la consola de administracion a el grid control, pero puede ser igualmente valido para cualquier procesos/servidor como podría ser un tomcat, apache o cualquier cosa por el estilo.

Como pasos prvios necesitaremos:

  • Script de arranque/parada/check de nuestra aplicacion, en nuestro caso estará en /opt/oracle/app/admin/PRUEBAS/consola/dbconsole
  • SID del grid  en nuestro caso +ASM
  • SID de la instancia en nuestro caso PRUEBAS
  • Nombre del servidor: En nuestro caso  pruebas.org

Vamos primero a ver el script que arranca/para /chequea la consola

#! /bin/sh
# Author:    Clemente Pamplona
# Date:      15-10-2012
# Usage:     dbconsole [start|stop|status|check]
# Purpose:   Arranca ,para y quequea la dbconsole 
# Copyright: GNU GPL

export ORACLE_SID=PRUEBAS
export ORAENV_ASK=NO
export ORACLE_BASE=/opt/oracle
export ORACLE_HOSTNAME=pruebas.org
. oraenv 
case $1 in
    START|start)
        emctl start dbconsole
         ;;
    STOP|stop)
        emctl stop dbconsole
        ;;
    STATUS|status)
        emctl status dbconsole
        ;;
    CHECK|check)
      rm /var/tmp/consola_status.txt
      emctl status dbconsole 
      if [ $? != 0 ]
        then exit 1;
        fi
        ;;

    *) echo "Usage: dbconsole [start|stop|status|check]"
       exit
     ;;
   esac

Este script podemos probarlo como usuario oracle en el servidor.

Una vez tenemos nuestro script creado que es capaz de arrancar y parar la consola, cargaremos el entorno del grid.

[oracle@pruebas.org consola]$ . oraenv
ORACLE_SID = [oracle] ? +ASM

Lo primero que vamos ha hacer es comprobar que elementos tiene corriendo nuestro grid

[oracle@pruebas.org consola]$ crs_stat -t
Name              Type                Target    State     Host
-----------------------------------------------------------------
ora.DATA.dg       ora.diskgroup.type ONLINE    ONLINE    pruebas.org
ora.LISTENER.lsnr ora.listener.type  ONLINE    ONLINE    pruebas.org
ora.asm           ora.asm.type       ONLINE    ONLINE    pruebas.org
ora.cssd          ora.cssd.type      ONLINE    ONLINE    pruebas.org
ora.pruebas.db    ora.database.type  ONLINE    ONLINE    pruebas.org
ora.diskmon       ora.diskmon.type   OFFLINE   OFFLINE
ora.evmd          ora.evm.type       ONLINE    ONLINE    pruebas.org
ora.ons           ora.ons.type       OFFLINE   OFFLINE

Vemos como tenemos claramente identificados el ASM, el Listener y la instancia . Así pues vamos  a añadrir un recurso local  tal y como dice la documentacion del crsctl

crsctl add resource dbconsola_pruebas -type local_resource \
-attr "ACTION_SCRIPT=/opt/oracle/app/admin/PRUEBAS/consola/dbconsole,\
 CHECK_INTERVAL='300',\
 RESTART_ATTEMPTS='2',\
 START_DEPENDENCIES=hard(ora.pruebas.db)"

Con esto le indicamos que cree:

  • recurso llamado pruebas
  • del tipo local_resource
  • usará nuestro script para actuar sobre él
  • chequeará su funcionamiento cada 5 minutos (300 segundos)
  • Intentará rearrancarlo 2 veces
  • Para arrancarlo deberá de estar la base de datos pruebas activa

Ahora podremos arrancarlo /pararlo /monitorizarlo desde las herramientas del grid.

$ORACLE_HOME/bin/crsctl start resource dbconsola_pruebas

$ORACLE_HOME/bin/crsctl stop resource dbconsola_pruebas

$ORACLE_HOME/bin/crsctl status resource dbconsola_pruebas

O bien con la salida total del sistema

[oracle@pruebas.org consola]$ crs_stat -t
Name              Type                Target    State     Host
-----------------------------------------------------------------
dbco..._pruebas  local_resource      ONLINE    ONLINE    pruebas.org
ora.DATA.dg       ora.diskgroup.type ONLINE    ONLINE    pruebas.org
ora.LISTENER.lsnr ora.listener.type  ONLINE    ONLINE    pruebas.org
ora.asm           ora.asm.type       ONLINE    ONLINE    pruebas.org
ora.cssd          ora.cssd.type      ONLINE    ONLINE    pruebas.org
ora.pruebas.db    ora.database.type  ONLINE    ONLINE    pruebas.org
ora.diskmon       ora.diskmon.type   OFFLINE   OFFLINE
ora.evmd          ora.evm.type       ONLINE    ONLINE    pruebas.org
ora.ons           ora.ons.type       OFFLINE   OFFLINE

 

P.D uede parecer algo evidente, pero, nuestro recurso nunca podrá llamarse ora.

Funcionamiento de las variables NLS

Hoy vamos a ver una de las cosas mas simples que hay en Oracle y de las que mas quebraderos de cabeza traen, la globalizacion.

Las variables que definen el idioma, numeros,fechas, ordenacion… de Oracle son las llamadas variables de globalización de Oracle o  mas comumente parámetros NLS.

Para evitar problemas con los acentos, eñes, puntos/comas,fechas…. deberias de tener claro cual es el NLS_LANG que tienes/quieres . Pero vamos a dejar este NLS_LANG para un poco mas adelante

Las principales variables para un entorno de oracle son:
•    NLS_LANGUAJE: Se usa para los mensajes (incluidos los de error)
•    NLS_DATE_LANGUAJE: Para los nombres de día y mes
•    NLS_SORT: (Binary) para la ordenación lingüística
Adicionalmente, tenemos una variable de entorno que nos define un amplio número de variables , este prámetro es NLS_TERRITORY , esta variable define las  siguientes subvariables
•    NLS_CURRENCY
•    NLS_DUAL_CURRENCY
•    NLS_ISO_CURRENCY
•    NLS_DATE_FORMAT
•    NLS_NUMERICA_CHARACTERS
•    NLS_TIMESTAMP_FORMAT
•    NLS_TIMESTAMP_TZ_FORMAT

Una vez visto esto, volvemos a NLS_LANG que se define como:
NLS_LANG=<language>_<territory>.<character set>  (por ejemplo export NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1 o en español  export NLS_LANG=SPANISH_SPAIN.WE8MSWIN1252 )
Así pues, si definimos correctamente nuestra variable NLS_LANG tendremos practicamente todas las variables de entorno definidas y conseguiremos que nuestras consultas tengan los caracteres que queremos.

Las variables de globalización de una base de datos se pueden fijar a 5 niveles:

  • Database
  • Instancia
  • Cliente
  • Sesión
  • Sentencia

Cada nivel inferior anula a un superior, es decir, si yo fijo una variable de entorno en una sentencia esta variable prevalecerá sobre las variables de base de datos, instancia o sesion.

Llegados a este punto, sabemos que queremos, pero, no sabemos que tenemos. ¿Como podemos saber que parámetros NLS tenemos definidos en nuestro cliente/aplicacion?

La solucion es muy sencilla, solamente tenemos que conectarnos y preguntar.

Para ver todas las variables de nuestra conexion de cliente

SQL> set pagesize 200;
column parameter format a25;
column value format a40;
select * from v$nls_parameters;

PARAMETER                 VALUE
------------------------- ----------------------------------------
NLS_LANGUAGE              SPANISH
NLS_TERRITORY             SPAIN
NLS_CURRENCY              
NLS_ISO_CURRENCY          SPAIN
NLS_NUMERIC_CHARACTERS    ,.
NLS_CALENDAR              GREGORIAN
NLS_DATE_FORMAT           DD/MM/RR
NLS_DATE_LANGUAGE         SPANISH
NLS_CHARACTERSET          WE8MSWIN1252
NLS_SORT                  SPANISH
NLS_TIME_FORMAT           HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT      DD/MM/RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT        HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT   DD/MM/RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY         
NLS_NCHAR_CHARACTERSET    AL16UTF16
NLS_COMP                  BINARY
NLS_LENGTH_SEMANTICS      BYTE
NLS_NCHAR_CONV_EXCP       FALSE

19 rows selected.

o la variable languaje exportada del entorno

 SQL> SELECT USERENV ('language') FROM DUAL;

USERENV('LANGUAGE')
----------------------------------------------------
SPANISH_SPAIN.WE8MSWIN1252

Con esto seguramente encontremos la explicación de por que las fechas no nos salen como queremos, vemos caracteres extraños en las ñ o nos fallan las inseciones por culpa de los . y ,

oracleasm cuando no tienes la versión excta del kernel

Hoy vamos a ver una solucion casera y no soportada para cuando no tenemos la versión exacta del kernel y el módulo oracleasm.

El módulo oracleasm viene empaquetado (para RedHat,Centos) en un fichero .rpm y lo deja en el directorio /lib/modules/2.6.XX/kernel/drivers/addon/oracleasm/  . El problema lo tenemos cuando por algun motivo es necesario el actualizar la version del kernel y no hay un paquete específico de asmlib para este kernel.

En la mayoría de las veces, la nueva  version del kernel es un cambio menor de versión, y el módulo de la asmlib funcionará correctamente, nuestro problemas será que el sistema operativo intentará montar ese módulo para la versión del kernel que tenemos . Si tenemos la version YY  el sistema operativo lo buscará en /lib/modules/2.6.YY/kernel/drivers/addon/oracleasm/  y,  como hemos dicho antes, el módulo estará en /lib/modules/2.6.XX/kernel/drivers/addon/oracleasm/  lo que significa que en el arranque no cargará el módulo –> No ira el ASM –> No arrancará las instancias.

La solucion (como decía antes no soportada ) es simlemente asegurarnos que, vamos a tener nuestro modulo en el directorio que lo va a buscar el sistema operativo en el arranque.

Para ello miraremos al arrancar si exsiste el fichero  del módulo para  nuestro kernel  /lib/modules/2.6.YY/kernel/drivers/addon/oracleasm/oracleasm.ko , si no exsiste creamos el directorio y lo copiamos, si exsite, salimos y listo .

El script quedaría tal que:

#!/bin/bash
#
#  Script que copia el módulo de  oracleasm a directorio
#   kernel/drivers/addon/oracle de nuestro kernel actual
#
case "$1" in
start )
  ORIG_MODULE="/lib/modules/2.6.18-308.13.1.el5/kernel/drivers/addon/oracleasm/oracleasm.ko"
  MODULE_DIR=/lib/modules/`uname -r`/kernel/drivers/addon/oracle
  if [ ! -f ${MODULE_DIR} ]
  then
      mkdir -p ${MODULE_DIR}
      cp -p ${ORIG_MODULE} ${MODULE_DIR}
  fi
  depmod -a
;;
stop)
   true
;;
*)
    echo $"Usage: $0 {start|stop}"
    RETVAL=1
;;
esac

Una de las cosas que tenemos que tener en cuenta es que esto funcionará solo para versiones menores del kernel.

He de advertir de nuevo que, esta solución no es una solución soportada , con lo que su uso  podría limitar el soporte que oracle pueda darnos en caso de surgir algún problema, sin embargo puede ser una solucion muuy cómoda en máquinas de desarrollo,test o servidores en los que, la base de datos comparte equipo con servidores de aplicaciones o frontales web y la actualizacion de kernel no es una opcion sino una necesidad.