Red Hat OpenShift Administration I · DO180

Chapter 7

Multi-Container Applications

Design · Service discovery · Podman pods · Deploying on OpenShift · ConfigMaps and Secrets
CIS271RH — Mesa Community College
Design an application made of several containers, test it locally with Podman pods, and deploy it on OpenShift with service discovery and external configuration.

Key Commands

  • podman pod create
  • podman kube play
  • oc new-app
  • oc create secret
  • oc set env
  • Real applications have several parts: a front end, a back end, a database.
  • In separate containers, each can be scaled, updated, and restarted independently.
  • A front-end fix doesn't require restarting the database.
Tip — One Main Process per ContainerSplit by component, but keep each container to one clear responsibility.
QuestionTypical Answer
How do components talk to each other?Over the network, by Service name
Which components keep data?Usually only the database, on a persistent volume
Where do settings and credentials go?In ConfigMaps and Secrets, not the image
Which components do users reach?Usually only the front end

Every Service gets a DNS name inside the cluster, so components find each other by name:

NameResolves From
inventory-dbPods in the same project
inventory-db.myprojectPods in other projects
inventory-db.myproject.svc.cluster.localAnywhere in the cluster (fully qualified)
Warning — Use Service Names, Never Pod IPsPods get new IP addresses whenever they're rescheduled. A Service name stays the same.
$ podman pod create --name myapp -p 8080:8080
$ podman run -d --pod myapp --name front quay.io/example/frontend
$ podman run -d --pod myapp --name back quay.io/example/backend
  • A Podman pod groups containers that share one network namespace, just like a Kubernetes pod.
  • Publish ports on the pod, not on individual containers.
NoteContainers in the same pod reach each other at localhost, on their own ports.
# Generate Kubernetes YAML from the running pod
$ podman kube generate myapp > myapp.yaml

# Recreate the pod from that YAML, locally
$ podman pod rm -f myapp
$ podman kube play myapp.yaml

The same YAML is a starting point for the cluster. In OpenShift, each component usually gets its own Deployment, so they can scale separately.

ComponentDeploymentServiceRoute
frontend✓✓✓
backend✓✓—
inventory-db✓✓ (plus a PVC)—
$ oc new-app --name=frontend quay.io/example/frontend
$ oc new-app --name=backend quay.io/example/backend
$ oc expose service frontend        # the only Route
# In the frontend Deployment's env, reference the database Service by name
env:
  - name: DB_HOST
    value: "inventory-db"   # resolves via cluster DNS to the database Service
  - name: DB_PORT
    value: "5432"

The front end never needs to know where the database pod is running. Cluster DNS turns inventory-db into the Service's stable address.

# Non-sensitive settings
$ oc create configmap frontend-config \
    --from-literal=DB_HOST=inventory-db --from-literal=DB_PORT=5432

# Credentials
$ oc create secret generic db-creds \
    --from-literal=DB_USER=app --from-literal=DB_PASSWORD='S3cret!'

# Inject both into the Deployment as environment variables
$ oc set env deployment/frontend --from=configmap/frontend-config
$ oc set env deployment/frontend --from=secret/db-creds
NoteChange a ConfigMap or Secret and the same image runs in dev, test, and production. Only the configuration differs.
Common Pitfall — Routes for EverythingA Route makes a component reachable from outside the cluster. Give one only to components users need, usually the front end. A database with a Route is an open door.
NoteSecrets are only base64-encoded, not encrypted, by default. Limit who can read them with RBAC.
multi-container application
An app made of independently deployable containers or components
service discovery
How components find each other, via cluster DNS resolving Service names
Podman pod
A group of containers sharing one network namespace, mirroring a Kubernetes pod
ConfigMap
A cluster resource for non-sensitive configuration kept outside the image
Secret
A cluster resource for sensitive data, such as credentials, kept outside the image
  1. Name two benefits of separating a front end and database into different containers.
  2. How does a frontend container locate a backend or database elsewhere in the cluster?
  3. What is a Podman pod, and how does it relate to a Kubernetes pod?
  4. Why should a database usually not have its own Route?
  5. Where should environment-specific configuration go instead of the container image?