Multidomain and Path Routing with Nginx
In this step-by-step tutorial, we will use CloudFlow and Nginx to create microservices with multidomain and multipath routing. We will outline how we can have multiple services and deployments all talking to each other within a CloudFlow application.
You will create two different deployments - hello-node-deployment.yaml and hello-ruby-deployment.yaml, as well as a service for each. Each deployment will return “hello world” in either node or ruby based on the routing.
Prerequisites
Before starting, create a new CloudFlow Project and then delete the default Deployment and ingress-upstream Service to prepare the project for your new deployment.
Add the Domains
Add the domains you’d like to handle the routing for in your CloudFlow application. In this example, we will add the domains www.example-domain-1.com and www.example-domain-2.com.
Setup Project Structure
Create the following /k8s directory and structure:
.
└── /k8s/
├── /base
├── hello-node-deployment.yaml
├── hello-ruby-deployment.yaml
├── hello-node-service.yaml
├── hello-ruby-service.yaml
├── ingress-service.yaml
├── kustomization.yaml
├── router.yaml
└── router.conf
Create Deployment Files
Create hello-node-deployment.yaml and hello-ruby-deployment.yaml as two nginx pods running different versions.
Copy the following code into hello-node-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-node-deployment
labels:
app: hello-node
spec:
replicas: 1
selector:
matchLabels:
app: hello-node
template:
metadata:
labels:
app: hello-node
spec:
containers:
- name: hello-node
image: pvermeyden/nodejs-hello-world:a1e8cf1edcc04e6d905078aed9861807f6da0da4
imagePullPolicy: Always
ports:
- containerPort: 80
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "500m"
Copy the following code into hello-ruby-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-ruby-deployment
labels:
app: hello-ruby
spec:
replicas: 1
selector:
matchLabels:
app: hello-ruby
template:
metadata:
labels:
app: hello-ruby
spec:
containers:
- name: hello-ruby
image: sebp/ruby-hello-world
imagePullPolicy: Always
ports:
- containerPort: 80
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "500m"
Create Service Files
Create hello-node-service.yaml and hello-ruby-service.yaml files.
Copy the following code into hello-node-service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
app: hello-node-service
name: hello-node-service
namespace: default
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
app: hello-node
sessionAffinity: None
type: ClusterIP
Copy the following code into hello-ruby-service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
app: hello-ruby-service
name: hello-ruby-service
namespace: default
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
app: hello-ruby
sessionAffinity: None
type: ClusterIP
Use configMapGenerator to Apply the Nginx Configuration
Create a kustomization.yaml file in the /k8s directory and add the following content:
configMapGenerator:
- name: router-config-mount
files:
- ./router.conf
resources:
- hello-node-deployment.yaml
- hello-node-service.yaml
- hello-ruby-deployment.yaml
- hello-ruby-service.yaml
- router.yml
- ingress-service.yml
The configMapGenerator defines the name and location of the file to mount. In this case the file path is ./router.conf with the name router-config-mount.
Create Router Deployment
Create a router.yaml file in the /k8s directory and add the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.6
imagePullPolicy: Always
volumeMounts:
- name: router-config
mountPath: "/etc/nginx/conf.d"
resources:
requests:
memory: ".5Gi"
cpu: "500m"
limits:
memory: ".5Gi"
cpu: "500m"
ports:
- containerPort: 80
volumes:
- name: router-config
configMap:
name: router-config-mount
Create Nginx Configuration
Create a router.conf file in the /k8s directory and add the following content:
server {
listen 80;
listen [::]:80;
server_name www.example-domain-1.com;
location /node {
proxy_pass http://hello-node-service;
}
location /ruby {
proxy_pass http://hello-ruby-service;
}
}
server {
listen 80;
listen [::]:80;
server_name www.example-domain-2.com;
location /node {
proxy_pass http://hello-node-service;
}
location /ruby {
proxy_pass http:/hello-ruby-service;
}
}
This configuration controls the routing for the two different domains. Both domains return the same applications for each location block. However these can point to different services. The important thing to note here is that we can use proxy_pass to point our routing to different services that we’ve created.
Apply the Configuration
Now that you have created all the necessary files, apply the configuration using kubectl:
kubectl apply -k /path/to/your/k8s/directory
This architecture allows us to have multiple applications and microservices all in one CloudFlow application. With relatively simple configuration, we can communicate back and forth between different pods and services.