El propósito de este artículo es mostrar cómo se realiza un despliegue de una aplicación basada en microservicios inicialmente en un entorno Docker y luego desplegarlo en un sistema de orquestación de contenedores Openshift/OKD.
La arquitectura se compone por microservicios de 2 clases, el primero es Redis (Caché) y el segundo tipo una API REST Stateless replicable que provee acceso a la base de datos en Memoria RAM Redis en sus dos modos de trabajo HashOperations (Base de datos NoSQL) con operaciones GET, POST, PUT, DELETE y ListOperations (Listas/Colas) con operaciones POP y PUSH.
El esquema de la API rest es el siguiente:
Haciendo uso de esta API es posible almacenar datos temporalmente haciendo uso del poder de Redis de forma NoSQL.
Haciendo uso de esta API es posible implementar colas tipo LIFO: Last In/First Out y FIFO: First In/First Out.
Importante: Cada redis_key solo se puede usar en un esquema, es decir, como una cola o como una base de datos NoSQL.
Las expresiones cron en Spring constan de 6 campos que especifican una condición a cumplir.
Las fuentes están en repositorio OKD-Despliegue
Con los siguientes dos archivos y con Docker Compose podemos:
/docker-compose.yml
version: '3'
services:
redis-api:
build:
dockerfile: Dockerfile
context: ./redis-api
ports:
- "8080:8080"
networks:
- academia-pragma
restart: unless-stopped
deploy: # Este elemento es soportado por docker-swarm, no por docker-compose
replicas: 3
resources:
limits:
cpus: '0.50'
memory: 50M
environment:
- REDIS_DB_HOST=redis-db
- REDIS_DB_PORT=6379
- REDIS_DB_PASSWORD=
- REDIS_DB_DUMP_CRON=0 */1 * * * *
redis-db:
image: redis
ports:
- "6379:6379"
networks:
- academia-pragma
restart: unless-stopped
deploy:
resources:
limits:
cpus: '0.50'
memory: 50M
volumes:
- redis-data:/data
load-balancer:
image: nginx
ports:
- "8080:8080"
networks:
- academia-pragma
restart: unless-stopped
networks:
academia-pragma:
driver: bridge
volumes:
redis-data:
/redis/Dockerfile
# Clonando repositorio
FROM alpine/git
WORKDIR /app
RUN ["git", "clone", "https://git.pragma.com.co/sergio.martinez/OKD-Despliegue.git"]
# Construccion de artefacto con Maven
FROM maven:3.5-jdk-8-alpine
WORKDIR /app
COPY --from=0 /app/OKD-Despliegue/redis /app
# Necesario para agregar la configuracion de proxy para que maven pueda conectarse
COPY --from=0 /app/OKD-Despliegue/proxy-settings.xml /root/.m2/settings.xml
RUN mvn install
# Construcción de la imagen del contenedor
ARG REDIS_DB_HOST=app_redis_db
ARG REDIS_DB_PORT
ARG REDIS_DB_PASSWORD
ARG REDIS_DB_DUMP_CRON
FROM registry.redhat.io/redhat-openjdk-18/openjdk18-openshift
COPY --from=1 /app/target/redis-0.0.1-SNAPSHOT.jar app.jar
USER root
RUN chmod a+r app.jar
USER jboss
ENV REDIS_DB_HOST=$REDIS_DB_HOST
ENV REDIS_DB_PORT=$REDIS_DB_PORT
ENV REDIS_DB_PASSWORD=$REDIS_DB_PASSWORD
ENV REDIS_DB_DUMP_CRON=$REDIS_DB_DUMP_CRON
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","./app.jar"]
El primer objetivo es correr la aplicación en Docker.
docker-compose up
El siguiente objetivo es desplegar la arquitectura en Openshift de manera manual. Para hacer el despliegue en Openshift, tendríamos las posibilidades siguientes:
Con la imagen construida mediante el archivo Dockerfile Véase archivos de construccion
docker compose build .
docker login registry
docker tag redis-api registry/cuenta/redis-api
docker push registry/cuenta/redis-api
Variables de entorno
Cada campo está codificado en Base64
apiVersion: v1
data:
DATABASE_SERVICE_NAME: cmVkaXM=
MEMORY_LIMIT: NTEyTWk=
NAMESPACE: b3BlbnNoaWZ0
REDIS_PASSWORD: a2FwcGE=
REDIS_VERSION: My4y
VOLUME_CAPACITY: MUdp
kind: Secret
metadata:
name: redis-conf-secret
type: Opaque
Imagen de Redis
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
labels:
app: redis-db
name: redis-db
spec:
replicas: 1
selector:
app: redis-db
deploymentconfig: redis-db
strategy:
activeDeadlineSeconds: 21600
resources: {}
rollingParams:
intervalSeconds: 1
maxSurge: 25%
maxUnavailable: 25%
timeoutSeconds: 600
updatePeriodSeconds: 1
type: Rolling
template:
metadata:
labels:
app: redis-db
deploymentconfig: redis-db
spec:
containers:
- envFrom:
- secretRef:
name: redis-conf-secret
image: >-
docker-registry.default.svc:5000/openshift/redis:latest
imagePullPolicy: Always
name: redis-db
ports:
- containerPort: 6379
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/lib/redis/data
name: redis-db-1
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- emptyDir: {}
name: redis-db
test: false
Servicio
apiVersion: v1
kind: Service
metadata:
labels:
app: redis-db
name: redis-db
spec:
clusterIP: 172.30.184.126
ports:
- name: 6379-tcp
port: 6379
protocol: TCP
targetPort: 6379
selector:
deploymentconfig: redis-db
sessionAffinity: None
type: ClusterIP
Variables de entorno
apiVersion: v1
data:
REDIS_DB_HOST:
REDIS_DB_PORT: 6379
REDIS_DB_PASSWORD:
REDIS_DB_DUMP_CRON: 0 */1 * * * *
kind: Secret
metadata:
name: redis-conf-secret
type: Opaque
Imagen de REDIS API
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
labels:
app: redis-api
name: redis-api
spec:
replicas: 3
selector:
app: redis-api
deploymentconfig: redis-api
strategy:
activeDeadlineSeconds: 21600
resources: {}
rollingParams:
intervalSeconds: 1
maxSurge: 25%
maxUnavailable: 25%
timeoutSeconds: 600
updatePeriodSeconds: 1
type: Rolling
template:
metadata:
labels:
app: redis-api
deploymentconfig: redis-api
spec:
containers:
- envFrom:
- secretRef:
name: redis-conf-secret
image: >-
sergioamza/redis-api:latest
imagePullPolicy: Always
name: redis-api
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 8443
protocol: TCP
- containerPort: 8778
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
test: false
triggers:
- type: ConfigChange
- imageChangeParams:
automatic: true
containerNames:
- redis-api
from:
kind: ImageStreamTag
name: 'redis-api:latest'
type: ImageChange
Servicio
apiVersion: v1
kind: Service
metadata:
labels:
app: redis-api
name: redis-api
spec:
clusterIP: 172.30.150.51
ports:
- name: 8080-tcp
port: 8080
protocol: TCP
targetPort: 8080
- name: 8443-tcp
port: 8443
protocol: TCP
targetPort: 8443
- name: 8778-tcp
port: 8778
protocol: TCP
targetPort: 8778
selector:
deploymentconfig: redis-api
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
Enrutamiento
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: redis-api
name: redis-api
spec:
port:
targetPort: 8080-tcp
to:
kind: Service
name: redis-api
weight: 100
wildcardPolicy: None