The latest release of Red Hat OpenShift Service Mesh, 2.6, was announced on August 8th, 2024, and it brings notable changes and new features. This blog covers all the new features and changes introduced in OpenShift Service Mesh 2.6. In this article, we will focus on the Kubernetes Gateway API 1.0 feature and how to implement it on Red Hat OpenShift.
Enable the Gateway API feature
This is a technical article covering the steps involved in enabling the Gateway API feature and making use of it for configuring traffic into an application running on OpenShift clusters. For this exercise, a new OpenShift cluster with version 4.16 has been installed on AWS:
# oc version
Client Version: 4.16.5
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: 4.16.5
Kubernetes Version: v1.29.6+aba1e8d
# openshift-install version
openshift-install 4.16.5
built from commit 38d2f1de5d5a03aafb7419f587b0a241de1e3ae0
release image quay.io/openshift-release-dev/ocp-release@sha256:ac78ebf77f95ab8ff52847ecd22592b545415e1ff6c7ff7f66bf81f158ae4f5e
release architecture amd64
# oc get clusterversion
NAME VERSION AVAILABLE PROGRESSING SINCE STATUS
version 4.16.5 True False 73m Cluster version is 4.16.5
In the new cluster, there will not be any CRDs for the Gateway API:
# oc get crd |grep gateway
Install operators
As a first step, install the required operators. Figure 1 below shows the installed operators for OpenShift Service Mesh.
Create a ServiceMeshControlPlane
Once the operators are successfully installed, create a new ServiceMeshControlPlane
(SMCP). We will use SMCP and ServiceMeshControlPlane
interchangeably for the rest of this article. For simplicity, we use the following for this demonstration, but this is not recommended for production use:
kind: ServiceMeshControlPlane
apiVersion: maistra.io/v2
metadata:
name: basic
namespace: istio-system
spec:
mode: ClusterWide
version: v2.6
policy:
type: Istiod
telemetry:
type: Istiod
addons:
prometheus:
enabled: true
kiali:
enabled: true
grafana:
enabled: true
Gateway API will be enabled by default if cluster-wide mode is set (spec.mode: ClusterWide
). Create a new SMCP using the sample YAML provided above and make sure the ServiceMeshControlPlane
and ServiceMeshMemberRoll
are created and the status is Ready
.
Figure 2 shows the successful creation of ServiceMeshControlPlane
and Figure 3 shows the successful creation of ServiceMeshMemberRoll
from the OpenShift Console.
Install CRDs
As soon as a new SMCP is created, you will notice that the new gateway CRD is created:
# oc get crd gateways.networking.istio.io
NAME CREATED AT
gateways.networking.istio.io 2024-08-08T17:58:44Z
But there is a manual step required to install the additional CRDs which are required to make use of this feature. Please refer to the official documentation here. In the case of OpenShift ServiceMesh 2.6, we need to install the Gateway API 1.0.0 version as below:
# ./kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ ./kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.0.0" | ./kubectl apply -f -; }
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created
Make sure that the additional CRDs are created:
# oc get crd |grep gateway
gatewayclasses.gateway.networking.k8s.io 2024-08-08T17:58:44Z
gateways.gateway.networking.k8s.io 2024-08-08T17:58:44Z
gateways.networking.istio.io 2024-08-08T17:41:10Z
httproutes.gateway.networking.k8s.io 2024-08-08T17:58:44Z
referencegrants.gateway.networking.k8s.io 2024-08-08T17:58:45Z
With this, we have set up the basic things needed for making use of the Gateway API feature. In the following steps, we will deploy a sample bookinfo
application.
Deploy the sample application
Create a new project called bookinfo
:
# oc new-project bookinfo
Now using project "bookinfo" on server "https://api.gwapi.sandbox3250.opentlc.com:6443".
You can add applications to this project with the 'new-app' command. For example, try:
oc new-app rails-postgresql-example
to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:
kubectl create deployment hello-node --image=k8s.gcr.io/e2e-test-images/agnhost:2.33 -- /agnhost serve-hostname
Label the newly created project so as to add this project as a SMCP member automatically:
# oc label namespace bookinfo istio-injection=enabled
namespace/bookinfo labeled
Figure 4 shows that the namespace bookinfo
is automatically added to the Service Mesh as a member.
For the demonstration purpose, we used the sample bookinfo
application from the upstream Maistra repository:
# oc apply -n bookinfo -f https://raw.githubusercontent.com/Maistra/istio/maistra-2.6/samples/bookinfo/platform/kube/bookinfo.yaml
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
# oc apply -n bookinfo -f https://raw.githubusercontent.com/Maistra/istio/maistra-2.6/samples/bookinfo/gateway-api/bookinfo-gateway.yaml
gateway.gateway.networking.k8s.io/bookinfo-gateway created
httproute.gateway.networking.k8s.io/bookinfo created
Once the application is deployed, you will notice that the resources are all running in the project including a SVC type LoadBalancer which will route traffic from outside the cluster:
# oc get all
Warning: apps.openshift.io/v1 DeploymentConfig is deprecated in v4.14+, unavailable in v4.10000+
NAME READY STATUS RESTARTS AGE
pod/bookinfo-gateway-istio-795cd9c6bf-6mw4f 1/1 Running 0 14m
pod/details-v1-7b49464bc-m42wv 2/2 Running 0 27m
pod/productpage-v1-58556ccc75-7wshh 2/2 Running 0 27m
pod/ratings-v1-d6f449f59-t69xp 2/2 Running 0 27m
pod/reviews-v1-686cd989df-4bccg 2/2 Running 0 27m
pod/reviews-v2-785b8b48fc-kkgsj 2/2 Running 0 27m
pod/reviews-v3-67889ffd49-ngjxt 2/2 Running 0 27m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/bookinfo-gateway-istio LoadBalancer 172.30.214.55 aa0e89735e11c4b97a8fd16a6c4b059b-598583681.eu-west-1.elb.amazonaws.com 15021:30266/TCP,80:30583/TCP 14m
service/details ClusterIP 172.30.135.81 <none> 9080/TCP 27m
service/productpage ClusterIP 172.30.250.30 <none> 9080/TCP 27m
service/ratings ClusterIP 172.30.53.98 <none> 9080/TCP 27m
service/reviews ClusterIP 172.30.142.6 <none> 9080/TCP 27m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/bookinfo-gateway-istio 1/1 1 1 14m
deployment.apps/details-v1 1/1 1 1 27m
deployment.apps/productpage-v1 1/1 1 1 27m
deployment.apps/ratings-v1 1/1 1 1 27m
deployment.apps/reviews-v1 1/1 1 1 27m
deployment.apps/reviews-v2 1/1 1 1 27m
deployment.apps/reviews-v3 1/1 1 1 27m
NAME DESIRED CURRENT READY AGE
replicaset.apps/bookinfo-gateway-istio-795cd9c6bf 1 1 1 14m
replicaset.apps/details-v1-7b49464bc 1 1 1 27m
replicaset.apps/productpage-v1-58556ccc75 1 1 1 27m
replicaset.apps/ratings-v1-d6f449f59 1 1 1 27m
replicaset.apps/reviews-v1-686cd989df 1 1 1 27m
replicaset.apps/reviews-v2-785b8b48fc 1 1 1 27m
replicaset.apps/reviews-v3-67889ffd49 1 1 1 27m
You will also notice that a new Gateway resource is created as below:
# oc get gtw
NAME CLASS ADDRESS PROGRAMMED AGE
bookinfo-gateway istio aa0e89735e11c4b97a8fd16a6c4b059b-598583681.eu-west-1.elb.amazonaws.com True 14m
# oc wait --for=condition=programmed gtw bookinfo-gateway
gateway.gateway.networking.k8s.io/bookinfo-gateway condition met
Access the application
There are a number of ways we can access the application, as demonstrated below.
Access using DNS name of the SVC type ClusterIP:
# oc exec "$(oc get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
Or access using SVC type LB:
# oc exec "$(oc get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -it -- curl bookinfo-gateway-istio:80/productpage | grep '<title>'
<title>Simple Bookstore App</title>
Next, let's try to access the application from outside:
# export INGRESS_HOST=$(oc get gtw bookinfo-gateway -o jsonpath='{.status.addresses[0].value}')
# export INGRESS_PORT=$(oc get gtw bookinfo-gateway -o jsonpath='{.spec.listeners[?(@.name=="http")].port}')
# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
# echo $GATEWAY_URL
aa0e89735e11c4b97a8fd16a6c4b059b-598583681.eu-west-1.elb.amazonaws.com:80
# curl -s "http://${GATEWAY_URL}/productpage" | grep -o "<title>.*</title>"
Accessing the application from outside is not working as expected because Red Hat OpenShift Service Mesh automatically creates and manages a number of NetworkPolicies resources in the Service Mesh control plane and application namespaces. This enables ingress to all pods in the mesh from the other mesh members and the control plane. This also restricts ingress to only member projects. If you require ingress from non-member projects or from outside, you need to create a NetworkPolicy to allow that traffic through.
Figure 5 shows the NetworkPolicies created automatically in the bookinfo
namespace and Figure 6 shows the NetworkPolicies created automatically in the istio-system
namespace.
For simplicity, we can disable the automatic NW policy creation to be able to allow the traffic. There is an option to disable automatic NetworkPolicy creation as per documentation here by setting spec.security.manageNetworkPolicy to false
in the SMCP. Once this is disabled, you will notice that the NW policies disappeared and you can access the application from outside the cluster.
Figure 7 and Figure 8 shows that the NetworkPolicies are removed from bookinfo
and istio-system
namespaces respectively when the automatic creation is disabled in the SMCP.
Accessing the application using a curl
command:
# curl -s "http://${GATEWAY_URL}/productpage" | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
Figure 9 shows that the application is accessible from the web browser.
Conclusion
In this article, we discussed the technical details on how to enable the Gateway API feature in OpenShift Service Mesh 2.6 and make use of it for accessing the applications running on OpenShift.