Deliver assets from Object Storage
Overview
This How-To will show you how to deliver assets from the S3 compatible Object Storage with ingress-nginx. As the Object Storage does not support CORS headers at this time, this is necessary to avoid CORS errors.
For more detailed information about CORS, check out Mozilla's great documentation.
Prerequisites
- A MetaKube Cluster with ingress-nginx installed
- A public Object Storage bucket (all assets need to be public, too), see the reference for details
- (optional) A deployed application
For this configuration to work, your assets have to be served at one or more distinct paths, for example /assets or /img as all requests to those paths will be served from the S3 bucket.
Create a Service for the S3 bucket
To use the S3 bucket as upstream for the ingress-nginx, we need to make it available as a Service:
apiVersion: v1
kind: Service
metadata:
name: assets
spec:
type: ExternalName
externalName: $BUCKET.s3.$REGION.cloud.syseleven.net
Replace
$BUCKETwith the name of your bucket, for exampleassets-test$REGIONwith the region where your bucket is located (for exampledbl)
Create an ingress for the asset paths
Then we only need to add an Ingress resource for the paths that the assets have:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/upstream-vhost: $BUCKET.s3.$REGION.cloud.syseleven.net
name: assets-ingress
spec:
# No TLS config needed, only one ingress for a hostname needs to have the TLS config, see https://github.com/kubernetes/ingress-nginx/issues/4106#issuecomment-494305090
rules:
- host: $APPLICATION_HOSTNAME
http:
paths:
- path: /img/
backend:
serviceName: assets
servicePort: 443
- path: /css/
backend:
serviceName: assets
servicePort: 443
Replace
- as above:
$BUCKETwith the name of your bucket, for exampleassets-test - as above:
$REGIONwith the region where your bucket is located (for exampledbl) $APPLICATION_HOSTNAMEwith the hostname your application is served at
and add as many elements to path as you need.
Once you've applied both resources, all requests to the specified paths for your hostname will be served from the bucket, all other requests will still go to your application.
Please note that for this to work, the asset paths in the Ingress above must always be the most specific paths. If the Ingress resource of your application has for example configuration for the path /img/backend, requests to this path will still go to your application.
Additional notes
To use this in production, you need to consider that this adds the Object Storage bucket as a dependency on the server-side. Therefore, faults of the backend should be handled gracefully by tuning timeouts and retry values for the Ingress object.
For assets, allowing them to be cached for a very long time is usually desirable. Consider adding the relevant headers with a nginx.ingress.kubernetes.io/configuration-snippet annotation.
As resources are served indirectly from the bucket, this will introduce a small latency overhead.