DEV Community

Steven Jenkins De Haro
Steven Jenkins De Haro

Posted on

Create a Kubernetes NGINX controller with Dapr support

NGINX dapr architecture

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Optionally, inspect the created certificate with the following command:

openssl x509 -in tls.crt -text -noout
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

or,

kubectl get service --selector=app=nginx-ingress,component=controller \
    -o jsonpath='{.items[*].status.loadBalancer.ingress[0].ip}' \
    -n nginx
Enter fullscreen mode Exit fullscreen mode

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}'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
wilsonliu78 profile image
wilsonliu78

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