Introducción
OpenShift es un producto que ofrece plataforma como servicio (o PaaS, en inglés platform as a service). Desarrollado por Redhat sobre Kubernetes, nos proporciona un sistema donde desplegar nuestras aplicaciones web, añadiendo funcionalidades adicionales a las que tenemos cuando utilizamos el “software base” de Kubernetes. Entre algunas de ellas tenemos source2image que se encargará de automatizar la creación de imágenes docker basándose en el repositorio github donde tendremos nuestra aplicación.
Sin más preámbulo, empezaremos con la instalación de Minishift.
Preparatorios
En esta ocasión usaremos la herramienta antes mencionada que nos proporcionará una instalación (de un solo nodo) de OpenShift. He de avisar que para hacer uso de esta aplicación, tendremos que tener un equipo con unos requisitos mínimos, debemos recordar que OpenShift es una aplicación pensada para desplegarse en un cluster. Podremos hacer uso de distintos sistemas de virtualización, pero en mi caso voy a utilizar KVM puesto que es el que más he usado durante mi formación y ha sido el “menos problemático”. Procedemos a instalar las dependencias:
apt update
# Instalamos las dependencias
apt install install qemu-kvm libvirt-daemon libvirt-daemon-system
# Añadimos a nuestro usuario al grupo libvirt
usermod -a -G libvirt $(whoami)
# Actualizamos nuestro grupo principal de forma temporal
newgroup libvirt
# Por último instalamos el driver correspondiente de KVM
curl -L https://github.com/dhiltgen/docker-machine-kvm/releases/download/v0.10.0/docker-machine-driver-kvm-ubuntu14.04 -o /usr/local/bin/docker-machine-driver-kvm
chmod +x /usr/local/bin/docker-machine-driver-kvmDescargamos la versión correspondiente de Minishift desde el repositorio oficial, lo descomprimimos y movemos la aplicación a nuestro directorio donde se encuentran los demás binarios.
tar -xf minishift-1.34.2-linux-amd64.tgz
cd minishift-1.34.2-linux-amd64
cp minishift /usr/local/bin/Después de todo esto ya podremos usar minishift como cualquier otro paquete que tengamos instalado. Por lo que ejecutamos:
minishift startEste proceso tardará un rato, ya que tiene que descargar la imagen ISO, crear la máquina virtual, etc. Una vez que finalice el proceso obtendremos una salida como esta:
OpenShift server started.
The server is accessible via web console at:
https://192.168.42.113:8443/console
You are logged in as:
User: developer
Password: <any value>
To login as administrator:
oc login -u system:adminComo es una herramienta para desarrollar o simplemente experimentar un poco con OpenShift, obviamente carece de sistemas de seguridad, por lo que podremos acceder al panel web con el usuario developer y cualquier contraseña. Una vez que hayamos iniciado sesión, creamos un proyecto.

Para empezar, vamos a desplegar simplemente un servidor web con una página estática html, y utilizaremos para ello el siguiente repositorio junto con la imagen base de php.


A la hora de gestionar nuestros proyectos tenemos, a grandes rasgos, tres opciones:
- Panel web
- Uso del cliente oc a través de linea de comandos
- Crear un programa que haga uso de la API
Panel web
Es el que tiene la funcionalidad más reducida de los tres, pero para empezar es el más intuitivo. En resumen vamos a probar las siguientes funciones:
- Balanceo de carga
- Rollback
- Despliegue continuo
Balanceo de carga
A partir de un despliegue de dos pods o más, OpenShift se encargará de balancear la carga entre ellos. Si queremos aumentar el número de pods de nuestro proyect, tan solo tendremos que dirigirnos a la sección Overview (el panel general del proyecto) y pulsar sobre la flecha hacia arriba.

Nosotros comprobaremos el balanceo de carga a través de un script php con el siguiente contenido:
<?php echo "Servidor:"; echo gethostname();echo "\n"; ?>Básicamente lo que hace es imprimir por pantalla el nombre de la máquina donde se está ejecutando. Utilizaré un bucle for para realizar 10 peticiones con curl de ese fichero:
for i in {1..10}; do curl curso-openshift-curso-openshift.192.168.42.113.nip.io/info.php; doneServidor:curso-openshift-4-m7pnb
Servidor:curso-openshift-4-vcz2m
Servidor:curso-openshift-4-m7pnb
Servidor:curso-openshift-4-vcz2m
Servidor:curso-openshift-4-m7pnb
Servidor:curso-openshift-4-vcz2m
Servidor:curso-openshift-4-m7pnb
Servidor:curso-openshift-4-vcz2m
Servidor:curso-openshift-4-m7pnb
Servidor:curso-openshift-4-vcz2mY efectivamente podemos comprobar como se van alternando las máquinas en cada petición.
Rollback
En este momento nos pondremos desde el punto de vista del desarrollador. En principio no tendríamos que saber como funciona todo esto por debajo, ya que para eso estamos utilizando esta capa de abstracción sobre docker, kubernetes, etc. Es por esto que a la hora de seguir un control de versiones, OpenShift nos facilita la vida. Realizaremos un cambio del código en nuestro repositorio remoto, algo tan simple como cambiar una linea del html. Después solo tendremos que dirigirnos al apartado builds, entrar en nuestro proyecto y seleccionar start build.

Si volvemos a acceder a la página podremos observar como se ha realizado el cambio una vez que se haya completado la “construcción” y el despliegue del nuevo pod con la nueva imagen:

Si quisiéramos volver a una versión anterior por cualquier motivo, solo tenemos que acceder a la sección deployments, elegir el despliegue que queramos y pulsar sobre el botón Roll back:


Despliegue Continuo
Como ya vimos en la entrada de integración continua con jekyll y Travis CI, github nos proporciona la posibilidad de hacer uso de webhooks para que aplicaciones como OpenShift realicen unas determinadas tareas en un determinado evento disparado por un git commit, un git push… en resumen, una modificación del repositorio. Para activar esta funcionalidad, entramos en la configuración de los builds de nuestro proyecto y copiamos el enlace indicado como Github Webhook URL.

Después nos dirigimos a la página de nuestro repositorio, accedemos a la configuración y seguidamente a Webhooks.

Lo único que tendremos que hacer es pegar el enlace que hemos copiado antes e indicar que la información que se va a mandar es en formato json.

A partir de ahora cada vez que hagamos un git push modificando este repositorio, se construirá automáticamente una nueva imagen y esta se desplegará.
Cliente OC
La instalación del cliente es aún más sencilla que la de minishift ya que solo tendremos que descargar el paquete de la siguiente página, descomprimirlo y mover el binario al path correspondiente. En mi caso lo moveré a /usr/local/bin. Una vez instalado, tendremos que iniciar sesión. La forma más sencilla es dirigirnos al panel web, hacer click en nuestro usuario y seleccionamos Copy login command. Después introducimos el comando en la terminal y deberíamos obtener una salida como esta:
oc login https://192.168.42.113:8443 --token=bxMkNw65lKmUyjTaY_r-8xgfCYAOR4w-jEc98NSy6gk
Logged into "https://192.168.42.113:8443" as "admin" using the token provided.
You have one project on this server: "curso-openshift"
Using project "curso-openshift".Lo primero que haremos será borrar el proyecto anterior. Para ello introducimos la siguiente instrucción:
oc delete project curso-openshift
project.project.openshift.io "curso-openshift" deletedActo seguido creamos uno nuevo:
oc new-project aplicacion-desde-oc
Now using project "aplicacion-desde-oc" on server "https://192.168.42.113:8443".
You can add applications to this project with the 'new-app' command. For example, try:
oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git
to build a new example application in Ruby.Si queremos crear una nueva aplicación, tendremos que seguir la siguiente sintaxis:
oc new-app plantilla:versión~repositorioGitHub --name nombre-aplicaciónEn mi caso voy a lanzar de nuevo una aplicación usando el mismo repositorio y plantilla que antes:
oc new-app php:7.1~https://github.com/LuisaoStuff/html_for_openshift.git --name pagina-estatica
--> Found image dc5aa55 (4 months old) in image stream "openshift/php" under tag "7.1" for "php:7.1"
Apache 2.4 with PHP 7.1
-----------------------
PHP 7.1 available as container is a base platform for building and running various PHP 7.1 applications and frameworks. PHP is an HTML-embedded scripting language. PHP attempts to make it easy for developers to write dynamically generated web pages. PHP also offers built-in database integration for several commercial and non-commercial database management systems, so writing a database-enabled webpage with PHP is fairly simple. The most common use of PHP coding is probably as a replacement for CGI scripts.
Tags: builder, php, php71, rh-php71
* A source build using source code from https://github.com/LuisaoStuff/html_for_openshift.git will be created
* The resulting image will be pushed to image stream tag "pagina-estatica:latest"
* Use 'start-build' to trigger a new build
* This image will be deployed in deployment config "pagina-estatica"
* Ports 8080/tcp, 8443/tcp will be load balanced by service "pagina-estatica"
* Other containers can access this service through the hostname "pagina-estatica"
--> Creating resources ...
imagestream.image.openshift.io "pagina-estatica" created
buildconfig.build.openshift.io "pagina-estatica" created
deploymentconfig.apps.openshift.io "pagina-estatica" created
service "pagina-estatica" created
--> Success
Build scheduled, use 'oc logs -f bc/pagina-estatica' to track its progress.
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose svc/pagina-estatica'
Run 'oc status' to view your app.Aunque aquí hemos creado la aplicación, deberemos dar un paso más y ejecutar oc expose svc/pagina-estatica para exponer el servicio y obtener una URL accesible. Después comprobamos el estado y vemos cuál es el link.
oc status
In project aplicacion-desde-oc on server https://192.168.42.113:8443
http://pagina-estatica-aplicacion-desde-oc.192.168.42.113.nip.io to pod port 8080-tcp (svc/pagina-estatica)
dc/pagina-estatica deploys istag/pagina-estatica:latest <
bc/pagina-estatica source builds https://github.com/LuisaoStuff/html_for_openshift.git on openshift/php:7.1
deployment #1 deployed 4 minutes ago - 1 pod
2 infos identified, use 'oc status --suggest' to see details.De la misma forma que en el panel web, podemos realizar múltiples tareas desde el cliente oc como escalar el número de pods, e incluso algunas más como obtener información de estos que está creando OpenShift con kubernetes.
oc scale dc pagina-estatica --replicas=3
deploymentconfig.apps.openshift.io/pagina-estatica scaled
oc get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
pagina-estatica-1-build 0/1 Completed 0 54m 172.17.0.6 localhost <none>
pagina-estatica-1-kqj6c 1/1 Running 0 10s 172.17.0.12 localhost <none>
pagina-estatica-1-trwxf 1/1 Running 0 54m 172.17.0.6 localhost <none>
pagina-estatica-1-wr8tw 1/1 Running 0 10s 172.17.0.10 localhost <none>Despliegue de aplicación python
De la misma forma que hemos desplegado una aplicación que contenía una página estática, también podemos desplegar una aplicación python. Desde la linea de comandos podemos comprobar que dicho lenguaje está soportado, e incluso algunos frameworks.
oc new-app --search python
Image streams (oc new-app --image-stream=<image-stream> [--code=<source>])
-----
python
Project: openshift
Tags: 2.7, 3.5, 3.6, latest
...En este ejemplo voy a usar la aplicación que desarrollé en primero de FP y que hacía uso de flask. Lo único que modificaré del código es definir un puerto fijo en lugar de utilizar la librería os. Después ejecutamos un comando parecido al que utilizamos con la página estática y, ¡listo!
# Creamos un nuevo proyecto
oc new-project aplicacion-python
# Y creamos la aplicación
oc new-app python:3.6~https://github.com/LuisaoStuff/Mountains-OpenShift.git --name ejemplo-pythonTardará unos instantes en desplegarla pero podemos ir creando la ruta para que sea accesible, ejecutando como antes oc expose svc/ejemplo-python.
Una vez finalizado el proceso, accedemos a la url indicada por la salida del comando oc status y comprobamos que, ¡efectivamente está en funcionamiento!

Despliegue de aplicación php
Esta vez instalaremos un cms cuyo sistema de base de datos es sqlite. Algo que no hemos comentado hasta ahora es la efimeridad de los datos. Cuando se elimina un pod, todos los datos y modificaciones realizadas durante su existencia, se borran. Es por esto que existen los volúmenes persistentes, y es por ello que he escogido el despliegue de un cms.
Vamos a hacer un par de comprobaciones. Primero instalaremos el cms sin el uso de volúmenes persistentes. Después realizaremos una modificación (comprobando que sí que se ha hecho), y borraremos el pod para poder observar cómo, al crearse un pod sustituto, el cms vuelve al estado original. Para instalar el cms, introducimos con oc el siguiente comando:
oc new-project php-app
oc new-app php:7.1~https://github.com/ilosuna/phpsqlitecms --name appphp
oc expose svc/appphpAccedemos a la web y realizamos una modificación de la página principal:


Eliminamos el pod:
oc delete pod/appphp-1-gmhh4
pod "appphp-1-gmhh4" deletedY comprobamos como no se ha guardado la modificación que hicimos antes.

Para solucionar esto, vamos a crear un volumen persistente y cambiando la estrategia del despliegue de la aplicación de rolling a recreate. Después accederemos al pod con rsh para ver cuál es la ruta donde se guardan los ficheros sqlite.
oc get pods
NAME READY STATUS RESTARTS AGE
appphp-1-build 0/1 Completed 0 34m
appphp-1-ntkp8 1/1 Running 0 13m
oc rsh appphp-1-ntkp8
sh-4.2$ cd cms/data/
sh-4.2$ pwd
/opt/app-root/src/cms/data
exit
oc get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
vol1 Bound pv0030 1Gi RWO,ROX,RWX 5sUna vez que tenemos la ruta donde se guardan los datos, accedemos al apartado de deployments y en el menú desplegable actions seleccionamos add storage

Por último ya solo nos quedaría clonar el repositorio de la aplicación y copiar el contenido de /data con oc cp:
oc get pods
NAME READY STATUS RESTARTS AGE
appphp-1-build 0/1 Completed 0 44m
appphp-2-6dnr9 1/1 Running 0 4m
luis@kutulu:~/phpsqlitecms/cms$ oc cp data appphp-2-6dnr9:cms/Probamos a modificar la página principal:


Eliminamos el pod.
oc delete pod/appphp-2-6dnr9
pod "appphp-2-6dnr9" deletedY volvemos a acceder a la página!
