Skip to content

Exposing QMigrator via HTTP Endpoint

To make QMigrator accessible externally, you must expose it through an HTTP endpoint. This is typically achieved using the Kubernetes Gateway API, which provides a standardized way to manage ingress traffic.


Prerequisite: Gateway Controller

Before creating a Gateway, you need a Gateway Controller installed in your cluster.

Check for Existing Gateway Controller

Verify if a Gateway Controller is already installed:

kubectl get gatewayclasses

If gateway classes are found:

  • Note the NAME of the gateway class (e.g., nginx, azure-alb, gke-l7-global-external-managed)
  • Use this class name when creating your Gateway in the gateway.gatewayClassName field

If no gateway classes are found:

  • You need to install a Gateway Controller
  • Follow the Quick Setup section

Create a Gateway

The Gateway resource defines how external traffic enters your cluster.

Prepare Gateway Configuration

  1. Update the namespace ({{ Namespace }}) in the YAML below
  2. Update the gatewayClassName to match your Gateway Controller (from prerequisite check)
  3. Choose between Non-TLS (HTTP only) or TLS (HTTPS) configuration
  4. Customize infrastructure annotations for your cloud provider (see section below)

Gateway Class Name

Common gateway class names:

  • NGINX Gateway Fabric: nginx
  • AWS Load Balancer Controller: amazon-vpc-lattice
  • GCP GKE: gke-l7-global-external-managed
  • Azure: azure-alb

(Optional) Cloud-Specific Infrastructure Annotations

Configure spec.infrastructure.annotations based on your cloud provider and load balancer type.

AWS - Network Load Balancer (NLB)

spec:
  infrastructure:
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-type: "external"
      service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
      service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
      service.beta.kubernetes.io/aws-load-balancer-attributes: |
        load_balancing.cross_zone.enabled=true

AWS - Internal Load Balancer

spec:
  infrastructure:
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-type: "internal"
      service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"

Azure - Internal Load Balancer

spec:
  infrastructure:
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-internal: "true"

Google Cloud - Internal Load Balancer

spec:
  infrastructure:
    annotations:
      networking.gke.io/load-balancer-type: "Internal"

Apply Gateway Configuration

gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: qmig-gateway
  namespace: {{ Namespace }}
  labels:
    component: "app"
    app.kubernetes.io/name: qmig
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: qmig-gateway
  namespace: {{ Namespace }}
  labels:
    component: "app"
    app.kubernetes.io/name: qmig
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt"  # or use cert-manager.io/issuer for namespace-scoped Issuer
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
  - name: https
    protocol: HTTPS
    port: 443
    allowedRoutes:
      namespaces:
        from: Same
    tls:
      mode: Terminate
      certificateRefs:
        - name: qmig-tls

Apply the gateway:

kubectl apply -f gateway.yaml

Verify Gateway Creation

Check the gateway status:

kubectl get gateway -n <namespace>

Wait for the gateway to be in Programmed status and note the external IP/hostname.


(Optional) Map Domain to Gateway

If you want to use a custom domain instead of the external IP:

  1. Retrieve the gateway's external address:

    kubectl get gateway qmig-gateway -n <namespace>
    

  2. Create a DNS A record with your domain provider:

    • Type: A
    • Name: @ (root domain) or subdomain (e.g., qmigrator)
    • Value: <EXTERNAL-IP> from step 1
    • TTL: Use provider's default
  3. Wait for DNS propagation (typically 5-15 minutes)

  4. Verify DNS resolution:

    nslookup your-domain.com
    


Create HTTPRoute

HTTPRoute resources define how traffic from the Gateway is routed to QMigrator services.

Prepare HTTPRoute Configuration

  1. Update the namespace ({{ Namespace }})
  2. Replace your-domain.com with your actual domain (or use the gateway external IP)
  3. Verify service names in backendRefs match your deployed services

Service Name Verification

Ensure the service names exist in your namespace:

kubectl get services -n <namespace>

Common QMigrator service names:

  • qmig-app - UI service
  • qmig-eng - API service
  • qmig-airflow-webserver - Airflow UI (if enabled)

Apply HTTPRoute Configuration

route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
 name: qmig-route
 namespace: {{ Namespace }}
 labels:
   component: "app"
   app.kubernetes.io/name: qmig
spec:
 parentRefs:
 - name: qmig-gateway
   namespace: {{ Namespace }}
   sectionName: http
 hostnames:
 - "your-domain.com"
 rules:
 - matches:
   - path:
       type: PathPrefix
       value: /
   backendRefs:
   - name: qmig-app
     port: 4200
 - matches:
   - path:
       type: PathPrefix
       value: /api
   backendRefs:
   - name: qmig-eng
     port: 8080
 - matches:
   - path:
       type: PathPrefix
       value: /airflow
   backendRefs:
   - name: qmig-airflow-webserver
     port: 8080
route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
 name: qmig-route
 namespace: {{ Namespace }}
 labels:
   component: "app"
   app.kubernetes.io/name: qmig
spec:
 parentRefs:
 - name: qmig-gateway
   namespace: {{ Namespace }}
   sectionName: http
 - name: qmig-gateway
   namespace: {{ Namespace }}
   sectionName: https
 hostnames:
 - "your-domain.com"
 rules:
 - matches:
   - path:
       type: PathPrefix
       value: /
   backendRefs:
   - name: qmig-app
     port: 4200
 - matches:
   - path:
       type: PathPrefix
       value: /api
   backendRefs:
   - name: qmig-eng
     port: 8080
 - matches:
   - path:
       type: PathPrefix
       value: /airflow
   backendRefs:
   - name: qmig-airflow-webserver
     port: 8080

Apply the routes:

kubectl apply -f route.yaml

Verify HTTPRoute Creation

Check route status:

kubectl get httproute -n <namespace>

The route should show Accepted status with the gateway parent reference.


Access QMigrator

Retrieve Access Information

Get the gateway address:

kubectl get gateway qmig-gateway -n <namespace> -o jsonpath='{.status.addresses[0].value}'

Get route hostnames:

kubectl get httproute -n <namespace>

Test Access

Using External IP:

curl http://<EXTERNAL-IP>

Using Domain (if configured):

curl http://your-domain.com
# or for HTTPS
curl https://your-domain.com

Access in Browser:

  • UI: http://your-domain.com or http://<EXTERNAL-IP>
  • API: http://your-domain.com/api or http://<EXTERNAL-IP>/api
  • Airflow (if enabled): http://your-domain.com/airflow or http://<EXTERNAL-IP>/airflow