In this post, I will show how to create an NGINX controller that exposes the Dapr enabled applications in a Kubernetes cluster. Essentially, the NGINX controller will be configured with the same standard Dapr annotations to get injected with the daprd sidecar. By exposing this sidecar, it will allow external applications to communicate with the Dapr enabled applications in the cluster, see the Dapr API reference.
Note: There have been changes to what repo to use for the NGINX installation, the spec requirements for Kubernetes ingress resources, and the Dapr annotation names, so the information in this post is the updated version that should be followed.
Prerequisites
- Kubernetes 1.19+ cluster with Dapr configured.
- Helm CLI 3x installed.
- Kubectl CLI installed and configured to access the cluster.
- Optional: OpenSSL for creating self-signed certificates.
Prepare helm
Add the latest helm chart repo for the NGINX controller by running the following commands:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
Create an ingress namespace
Ensure that the current kubectl context is pointed to the correct Kubernetes cluster, and run the following command:
kubectl create namespace nginx
Install NGINX controller with Dapr support
Create a file called dapr-annotations.yaml
with the following content to set the annotations on the NGINX ingress controller pods:
controller:
podAnnotations:
dapr.io/enabled: "true"
dapr.io/app-id: "nginx-ingress"
dapr.io/app-port: "80"
Note: The port above tells the daprd sidecar which port the NGINX controller is listening on. See Dapr Kubernetes pod annotations spec for a complete list of supported annotations.
Run the following command, which references the file above:
helm install nginx-ingress ingress-nginx/ingress-nginx \
-f dapr-annotations.yaml \
--set controller.replicaCount=2 \
--namespace nginx
Add --set controller.service.loadBalancerIP=0.0.0.0
to the above command if a static IP is needed, for example, the last IP from a peered subnet with on-premise.
Create NGINX's daprd sidecar ingress resource
Create a file called ingress-dapr.yaml
with the following content:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-dapr
namespace: nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- api.example.com
secretName: tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-ingress-dapr
port:
number: 80
Dapr automatically creates the nginx-ingress-dapr
service being referenced above. Make sure to modify the hostname placeholders.
Remove the tls
section if TLS termination is not needed, otherwise, run the following commands to create a self-signed certificate for testing:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=api.example.com/O=TLS Example"
kubectl create secret tls tls-secret \
--key tls.key --cert tls.cert -n nginx
Optionally, inspect the created certificate with the following command:
openssl x509 -in tls.crt -text -noout
It is recommended to use the FREE Let's Encrypt certificates that are globally recognized by following the steps defined in the Securing NGINX-ingress or Encrypting the certificate for Kubernetes (Let’s Encrypt) articles.
Now, run the following command to create the ingress resource:
kubectl create -f ingress-dapr.yaml
Note: This will target the sidecar's service, not the NGINX's service for the load balancer.
Testing externally
If a static IP was not specified earlier, then get the external IP created as part of the NGINX controller setup running the following command:
kubectl get svc nginx-ingress-ingress-nginx-controller -n nginx
or,
kubectl get service --selector=app=nginx-ingress,component=controller \
-o jsonpath='{.items[*].status.loadBalancer.ingress[0].ip}' \
-n nginx
With the IP, run the follow test using cURL to see if the Dapr API for the cluster is reachable from outside the cluster:
curl http://<ingress ip>/v1.0/invoke/mathService/method/add \
-H "Content-Type: application/json"
-d '{ "arg1": 10, "arg2": 23}'
The above assumes that there is a microservice running using the Dapr app-id mathService
that has a POST endpoint called add
, which is an example taken from the Service invocation API reference.
To test without building an app, install redis, and use the redis state store building block following the How-To: Configure state store and pub/sub message broker article. After, perform the curl commands in this example to create and retrieve the key-value data in redis.
Delete the NGINX controller
For convenience, here is the command to delete the NGINX controller:
helm delete nginx-ingress -n nginx
Don't forget to delete the ingress resources and the nginx
namespace created earlier.
Limiting access
If additional security is required around which Dapr APIs or services should be exposed, then the scope of this can be configured globally, or at a very granular level as needed. For more information, see the following articles:
Top comments (1)
template:
metadata:
annotations:
dapr.io/app-id: nginx-ingress
dapr.io/app-port: '80'
dapr.io/enabled: 'true'
dapr.io/sidecar-listen-addresses: 0.0.0.0