I have a small java webapp comprising of three microservices - api-service,book-service and db-service all of which are deployed on a kubernetes cluster locally using minikube.
I am planning to keep separate UIs for api-service and book-service , with the common static files served from a separate pod, probably an nginx:alpine
image.
I was able to create a front end that serves the static files from nginx:alpine
referring to this tutorial.
I would like to use ingress-nginx
controller for routing requests to the two services.
The below diagram crudely shows where I am now.
I am confused as to where I should place the pod that serves the static content, and how to connect it to the ingress resource.I guess that keeping a front end pod before ingress defeats the purpose of ingress-nginx controller. What is the best practice to serve static files. Appreciate any help. Thanks.
[
Answers
Looks like you are confusing the fact that users, browsing online, will trigger standard requests to both "download" your static content, and use your 2 APIs (book and api). It's not the NGINX service serving the static content that is accessing your APIs, but the users browsers/applications, and they do that exactly the same for both static content and APIs (former has more/specific headers and data, like auth...).
On your diagram you'll want to put your new static-service
at the exact same level as your book-service
and api-service
, ie behind the ingress. But your static-service
won't have a link with the db-service
like the other 2. Then just complete your ingress rules, with the static-service at the end as in this example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: your-global-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /book-service
backend:
serviceName: book-service
servicePort: 80
- path: /api-service
backend:
serviceName: api-service
servicePort: 80
- path: /
backend:
serviceName: static-service
servicePort: 80
You'll have to adjust your services names and ports, and pick the paths you want your users to access your APIs, in the example above you'd have:
foo.bar.com/book-service
for your book-servicefoo.bar.com/api-service
for the api-servicefoo.bar.com/
ie everything else going to the static-service
To serve static files efficiently in a Kubernetes setup using an Ingress controller, you can leverage the NGINX Ingress controller itself to serve the static files directly, eliminating the need for an additional NGINX pod. This approach simplifies the architecture and takes full advantage of the Ingress capabilities.
Here’s how you can set it up:
-
Deploy your microservices and static files service:
- Ensure your
api-service
,book-service
, anddb-service
are deployed as individual services in your Kubernetes cluster. - Deploy an NGINX pod that serves your static files. This pod will be responsible for hosting your frontend assets.
- Ensure your
-
Create a ConfigMap for static files (optional):
- If your static files are small and infrequently changed, you can include them in a ConfigMap. For larger or frequently changing files, use a PersistentVolume or a Docker image with the static files.
-
Define the Ingress resource:
- Configure the Ingress resource to route traffic to your
api-service
,book-service
, and the static files service.
- Configure the Ingress resource to route traffic to your
Here’s a step-by-step guide:
Step 1: Deploy the Microservices
Ensure you have your deployments and services set up for api-service
and book-service
. Here’s a simple example for one of the services:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
replicas: 2
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
spec:
containers:
- name: api-service
image: your-docker-registry/api-service:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api-service
ports:
- protocol: TCP
port: 80
targetPort: 8080
Repeat this for the book-service
and db-service
.
Step 2: Deploy the Static Files Service
Create a deployment for the NGINX pod to serve static files. You can create a Docker image with your static files or use a PersistentVolume.
Using a Docker Image
Create a Dockerfile for your static files:
FROM nginx:alpine
COPY ./static-files /usr/share/nginx/html
Build and push the Docker image to your registry:
docker build -t your-docker-registry/static-files:latest .
docker push your-docker-registry/static-files:latest
Create a deployment for the static files service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: static-files
spec:
replicas: 1
selector:
matchLabels:
app: static-files
template:
metadata:
labels:
app: static-files
spec:
containers:
- name: static-files
image: your-docker-registry/static-files:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: static-files
spec:
selector:
app: static-files
ports:
- protocol: TCP
port: 80
targetPort: 80
Step 3: Create the Ingress Resource
Configure the Ingress resource to route traffic to your services and static files. Here’s an example:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.local
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /books
pathType: Prefix
backend:
service:
name: book-service
port:
number: 80
- path: /static
pathType: Prefix
backend:
service:
name: static-files
port:
number: 80
Step 4: Test the Setup
- Ensure the Ingress controller is running in your cluster.
- Add an entry to your
/etc/hosts
file to mapmyapp.local
to your Minikube IP:
echo "$(minikube ip) myapp.local" | sudo tee -a /etc/hosts
-
Access your services via the browser:
http://myapp.local/api
for theapi-service
http://myapp.local/books
for thebook-service
http://myapp.local/static
for the static files
This setup uses the NGINX Ingress controller to route requests to your services and static files, ensuring a simple and efficient architecture.