MuleSoft Flex Gateway Automatic Deployment in RedHat OpenShift using GitHub Actions
MuleSoft Flex Gateway is a very lightweight API Gateway that can be deployed on top of different platforms: either you deploy it directly on a compute instance running Linux, or on top of Kubernetes, OpenShift. Also, it can be established as an Ingress Controller for Kubernetes and OpenShift. But if your use case is to have the Gateway inside OpenShift just as a deployment exposed as a service that can route requests to a set of microservices within a project, then this article may be useful. Also, if you intend to automate when you add a new policy, route, etc to your gateway, then we will share with you how to do so with GitHub actions.
The pre-requisites for this lab are:
- GitHub account
- MuleSoft 30-day trial account. We will need it for creating our Flex Gateway.
- Openshift. We recommend you use a single-node for CodeReady Containers (CRC). We are not going to describe the process of deploying CRC in this article. In our case, we’ve deployed it using a Digital Ocean Droplet.
Let’s first create a Flex Gateway using the MuleSoft Anypoint Platform.
Creating the Flex Gateway
Login into your 30-day trial MuleSoft Anypoint Platform account and head into Runtime Manager:
Click on the Flex Gateways option and then on the Add Gateway blue button. You will get all the following options:
As we’ve mentioned in previous paragraphs there are plenty of options for the Flex Gateway deployment, we will use the one labeled as Container. If you are wondering: Why not OpenShift? The answer is: that we do not want -for this use case- to deploy it as an Ingress Controller.
Once you click on the Container button you will be presented with a set of steps that you will execute on your laptop:
docker pull mulesoft/flex-gateway
And then:
docker run --entrypoint flexctl -u $UID \
-v "$(pwd)":/registration mulesoft/flex-gateway \
registration create --organization=ac584c40-1bf7-4c08d871 \
--token=5858b5068d8959437 \
--output-directory=/registration \
--connected=false\
myFlexGateway
In the previous command we need to highlight the following:
a) The last line is the name of your Gateway. You can decide whatever you want
b) The connected flag is set to false. We are going to work in disconnected mode and feed the gateway configuration with yaml-based files.
c) The organization and token will be different, they will be generated for your specific gateway
After executing the command you will have a file by the name registration.yaml in the directory where you are executing the commands.
With the registration.yaml file, plus a configuration file that we are about to create we can deploy our Flex Gateway inside OpenShift.
Please have the registration.yaml file close to you, since we are going to need it in the next steps.
Deploy the Flex Gateway in OpenShift
First, create a project in OpenShift by the name Flex:
All the next steps are going to be performed inside that project.
Now we need to create a manifest file that describes our deployment. That manifest file looks like this:
apiVersion: apps/v1
kind: Deployment
metadata:
name: flexmulesoft
labels:
app: flexmulesoft
spec:
replicas: 1
selector:
matchLabels:
app: flexmulesoft
template:
metadata:
labels:
app: flexmulesoft
spec:
containers:
- name: flexmulesoft
image: docker.io/mulesoft/flex-gateway:latest
securityContext:
allowPrivilegeEscalation: true
ports:
- containerPort: 7080
volumeMounts:
- name: config-volume
mountPath: "/usr/local/share/mulesoft/flex-gateway/conf.d/config/"
readOnly: true
- name: registration-volume
mountPath: "/usr/local/share/mulesoft/flex-gateway/conf.d/"
readOnly: true
volumes:
- name: config-volume
secret:
secretName: config
- name: registration-volume
secret:
secretName: registration
Copy the previous yaml and name it flex.yaml.
We need a couple of secrets that represent two things for our deployment:
a) The registration information which was generated in the last step of the previous section (registration.yaml file)
b) The configuration information of our Flex Gateway, that is: Listener, Routes, Policies, etc.
Also, as you’ve probably noticed, those secrets are used as volumeMounts which point to the local directory of the Flex Gateway container. We are copying the configuration and registration from a couple of secrets.
With that clear, let’s proceed to:
- Create the secrets from the configuration and registration files
- Create a deployment with the yaml presented in previous lines (flex.yaml)
- Create a service for the deployment
- Create a public route for the service
Let’s create the secrets. We’ll first create the registration secret. For that purpose, you need to transform the registration.yaml file contents into base64. Once you have created the base64 string, use the following yaml to create the secret (copy the base64 string that you have created and replace the one that is the following yaml file):
kind: Secret
apiVersion: v1
metadata:
name: registration
namespace: flex
data:
registration.yaml: >-
YXBpVmVyc2lvbjogZ2F0ZXdheS5tdWxlc29mXAuaW8rdExTMHRMUW89
type: Opaque
Once you have updated the secret with your registration.yaml file (converted into base64), create the secret:
Now let’s create the configuration secret. But first, let’s take a look at our configuration:
apiVersion: gateway.mulesoft.com/v1alpha1
kind: ApiInstance
metadata:
name: config
spec:
address: http://0.0.0.0:7080
services:
customers:
address: http://my-microservice1:8080/customers
routes:
- rules:
- path: /customers(.*)
config:
destinationPath: /customers
products:
address: http://my-microservice2:8080/products
routes:
- rules:
- path: /products(.*)
config:
destinationPath: /products
policies:
- policyRef:
name: jwt-validation-flex
config:
signingMethod: none
signingKeyLength: 256
textKey: MIIMO8=
jwksServiceTimeToLive: 60
jwksServiceConnectionTimeout: 10000
validateAudClaim: false
mandatoryAudClaim: false
mandatoryNbfClaim: false
mandatoryExpClaim: false
validateCustomClaim: false
mandatoryCustomClaims: []
nonMandatoryCustomClaims: []
skipClientIdValidation: true
order: 2
- policyRef:
name: cors-flex
config:
publicResource: true
order: 1
Our Gateway will be listening on port 7080, and has a couple of routes pointing to a couple of microservices running in the same OpenShift Project (Flex), It also includes a couple of policies: one for JWT token validation and the second for CORS. (The policies are just for sample purposes, in this case, you may need other policies).
Now that you have your configuration file, transform it into base64 as well, and then create this second secret:
kind: Secret
apiVersion: v1
metadata:
name: config
namespace: flex
data:
config.yaml: >-
YXBpVmVyc2lvbjogZ2F0ZXdheS5tdWxlc29mdC5jb20vdjFhbHBoYTEKa2lu
type: Opaque
Change the base64 you’ve generated for your specific configuration file and paste it into the previous sample yaml file. Once you have it, create the secret:
Now is the time to create the deployment, go to the deployment section at the OpenShift console and paste the flex.yaml contents that we created in previous steps:
With that, you should have a deployment with a Pod running MuleSoft Flex Gateway, like this:
And if you click in the Pod and then in Logs:
You will see that your Gateway is up and running.
Now just create a Service and a Route if you want to make it accessible from outside the cluster. Which would be very normal, in my case:
And for the route:
If I try to request that route, I get:
Because, as we pointed out, the configuration is validating a JWT token that on that request I did not include.
Now, let’s see how can we automate the deployment using GitHub Actions.
Automating the Flex Gateway deployments with GitHub Actions
Which changes can trigger a new deployment of our Flex Gateway? Well, we can think of:
a) A route is added, changed, or deleted
b) A policy is added, changed, or deleted
c) A listener is added, changed, or deleted
c) Etcetera.
We do not want someone to edit the configuration directly in secret, let’s make their lives easier.
You can copy and use the following GitHub action:
# Basic Workflow for MuleSoft Flex Gateway
name: CI - Demo mulesoft flex-gateway
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch:
jobs:
yaml-validation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate YAML
uses: GrantBirki/json-yaml-validate@v2.6.0
with:
files: "./config.yaml"
comment: "true"
Oc-openshift-Install:
runs-on: ubuntu-latest
needs: yaml-validation
if: ${{ success()}}
steps:
- name: Install oc openshift
uses: redhat-actions/oc-installer@v1
with:
oc_version: '4.6'
Login:
runs-on: ubuntu-20.04
needs: Oc-openshift-Install
if: ${{ success() }}
steps:
- uses: actions/checkout@v4
- name: Authenticate and set context
uses: redhat-actions/oc-login@v1
with:
# URL to your OpenShift cluster.
openshift_server_url: ${{ secrets.OPENSHIFT_SERVER }}
# Credentials, if desired instead of token
openshift_username: ${{ secrets.TEST_USER }}
openshift_password: ${{ secrets.OPENSHIFT_PASSWORD }}
insecure_skip_tls_verify: true
certificate_authority_data: ${{ secrets.CA_DATA }}
namespace: ${{ env.OPENSHIFT_NAMESPACE }}
- name: Test
run: |
oc api-resources
- name: Delete secret
run: |
oc delete secret config -n flex
- name: Create secret
run: |
oc create secret generic config --from-file=config.yaml=config.yaml -n flex
- name: Rollout
run: |
oc rollout restart deployment flexmulesoft -n flex
Validate:
runs-on: ubuntu-latest
needs: Login
if: ${{ success() }}
steps:
- uses: actions/checkout@v4
- name: REST API with curl
run: |
curl -X GET "http://flex-route-flex.apps-crc.testing/health"
This is a very basic action but it does the work. It takes the config.yaml file and validates it first, then it connects to OpenShift (you need to create the secrets that we’ve specified in the yaml file) and finally updates the secret and restarts the deployment. An extra step is testing with a cURL a health resource.
For the secrets that are used in the action:
Give it a try if you would like to start automating your MuleSoft Flex Gateway deployments.
Thank you for your reading!