skip to Main Content

Scenario

I’m using the CQRS pattern for REST services that deal with Sales as in the diagram below. (The question focuses on the REST services.)

CQRS example

On K8S I have:

  • A microservice for GET endpoints (queries) that runs on a given pod.
  • Another microservice for POST and PUT endpoints (commands) tat runs on a different pod.

Both operate on the same resource: Sales. The natural URL mapping would be:

  • GET endpoints on mydomain.com/api/sales/* should go to the first pod.
  • POST and PUT endpoints on mydomain.com/api/sales/* should go to the second pod.

Ingress

To deploy these two microservices to a K8S cluster, I define a separate Service and Deployment for each. Then I create an Ingress definition to route requests to the Services:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: mydomain.com
      http:
        paths:
          - path: /api/sales
            pathType: Prefix
            backend:
              service:
                name: sales-queries-service
                port:
                  name: 80
          - path: /api/sales
            pathType: Prefix
            backend:
              service:
                name: sales-commands-service
                port:
                  name: 80     
  ingressClassName: ingress-nginx

Problem

The ingress definition above does not work because it has the mapping of the same path /api/sales to two different services. As such, it’s non deterministic.

It’s a feature desired by many that the ingress spec can allow the specification of the HTTP methods. In fact, when I asked ChatGPT it suggested adding this snippet to my ingress yaml, but unfortunately it’s a parameter that doesn’t exist… yet.

    httpMethods:
      - GET

Is there any other option to specify the routing in a K8S cluster (without installing an API gateway product)?

2

Answers


  1. I think it is better to route based on the URL (like /queries/xxxx and /commands/xxxx) and not on the HTTP verb/method because it might be useful to be able to do GET requests to the command service.

    For example, you might want to do GET requests to the /health endpoint for health checks.

    Or if you do want to do some specific READ queries against the write sides, yes, that is actually OK to do for some specific scenarios when you need an immediately consistent answer.

    Just as Greg says:

    "Your aggregate state IS a read model just one that often has a very short life time and is used to process transactions"
    https://twitter.com/gregyoung/status/1275467796177137670

    The key here is to be agile, flexible and don’t be too strict.

    Login or Signup to reply.
  2. You can Install and Traefik and use IngressRoutes which supports Http method routing.

    so you can Method() rule to point your requests toward desired services.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search