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.

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

Internal Load Balancer

spec:
  infrastructure:
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-type: "internal"
      service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"
spec:
  infrastructure:
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-internal: "true"
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>  # (1)!
  labels:
    component: "app"
    app.kubernetes.io/name: qmigrator
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
  1. Replace with your target Kubernetes namespace (e.g., qmigrator).
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: qmig-gateway
  namespace: <namespace>  # (2)!
  labels:
    component: "app"
    app.kubernetes.io/name: qmigrator
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt"  # (1)!
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
  - name: https
    hostnames: ["your-domain.com"] # (4)!
    protocol: HTTPS
    port: 443
    allowedRoutes:
      namespaces:
        from: Same
    tls:
      mode: Terminate
      certificateRefs:
        - name: qmig-tls-cert # (3)!
  1. Use your cert-manager ClusterIssuer or namespace-scoped Issuer name (e.g., letsencrypt).
  2. Replace with your target Kubernetes namespace (e.g., qmigrator).
  3. cert-manager will create this Secret automatically when the Gateway is applied.
  4. Replace with your domain name (e.g., qmigrator.example.com or use the gateway external IP).

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>  # (1)!
 labels:
   component: "app"
   app.kubernetes.io/name: qmigrator
spec:
 parentRefs:
 - name: qmig-gateway
   namespace: <namespace>
   sectionName: http
 hostnames: ["your-domain.com"]  # (2)!
 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
  1. Replace with your target Kubernetes namespace (e.g., qmigrator).
  2. Replace with your domain name (or use the gateway external IP).
route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
 name: qmig-route
 namespace: <namespace>  # (1)!
 labels:
   component: "app"
   app.kubernetes.io/name: qmigrator
spec:
 parentRefs:
 - name: qmig-gateway
   namespace: <namespace>
   sectionName: http
 - name: qmig-gateway
   namespace: <namespace>
   sectionName: https
 hostnames: ["your-domain.com"]  # (2)!
 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
  1. Replace with your target Kubernetes namespace (e.g., qmigrator).
  2. Replace with your domain name (e.g., qmigrator.example.com or use the gateway external IP).

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