Skip to content

gRPC on Kubernetes — Deploying, Scaling, and Managing gRPC Services in Containers

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about grpc on kubernetes. We cover key concepts, practical examples, and best practices to help you master this topic.

Deploying gRPC on Kubernetes requires specific configuration for HTTP/2 transport, gRPC-specific load balancing, health checks, and service discovery to ensure reliable communication between gRPC microservices.

What You'll Learn

  • Containerizing gRPC services for Kubernetes
  • gRPC load balancing with headless services
  • Kubernetes liveness and readiness probes
  • Ingress controllers for gRPC
  • Autoscaling gRPC services
  • gRPC-Web with Kubernetes ingress

Why It Matters

gRPC's HTTP/2 multiplexing and long-lived connections behave differently from REST under Kubernetes load balancing. Without proper configuration, gRPC connections can fail, traffic can be unbalanced, and deployments can break. DodaTech's Durga Antivirus Pro runs 50+ gRPC microservices on Kubernetes with automatic scaling, rolling deployments, and 99.99% uptime.

Real-World Use

A gRPC threat analysis service is deployed with 10 replicas. When traffic spikes, Kubernetes autoscales to 50 replicas. The gRPC clients use headless service DNS to discover all replicas and distribute connections using round-robin or least-loaded client-side load balancing.

flowchart TB
    A["Client Pod"] --> B["Headless Service\n(no cluster IP)"]
    B --> C["Pod 1\n(10.0.0.1:50051)"]
    B --> D["Pod 2\n(10.0.0.2:50051)"]
    B --> E["Pod 3\n(10.0.0.3:50051)"]
    A -->|Client-side LB| C
    A -->|Client-side LB| D
    A -->|Client-side LB| E
    F["HPA"] --> G["Scale Pods"]
    style B fill:#fef3c7,stroke:#d97706

Code Examples

Example 1: Kubernetes Deployment for gRPC

apiVersion: apps/v1
kind: Deployment
metadata:
  name: threat-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: threat-service
  template:
    metadata:
      labels:
        app: threat-service
    spec:
      containers:
      - name: threat-service
        image: dodatech/threat-service:latest
        ports:
        - containerPort: 50051
          name: grpc
        - containerPort: 8080
          name: health
        env:
        - name: GRPC_GO_LOG_SEVERITY_LEVEL
          value: "info"
        - name: GRPC_GO_LOG_VERBOSITY_LEVEL
          value: "2"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          grpc:
            port: 50051
            service: threat-service
          initialDelaySeconds: 10
          periodSeconds: 15
        readinessProbe:
          grpc:
            port: 50051
            service: threat-service
          initialDelaySeconds: 5
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: threat-service
spec:
  clusterIP: None  # Headless for gRPC
  ports:
  - port: 50051
    targetPort: 50051
    name: grpc
  selector:
    app: threat-service

Example 2: Client-Side Load Balancing with Headless Service

package main

import (
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "google.golang.org/grpc/resolver"
)

func main() {
    // Register Kubernetes DNS resolver
    resolver.SetDefaultScheme("dns")
    
    // Use headless service DNS name
    conn, _ := grpc.Dial(
        "dns:///threat-service.default.svc.cluster.local:50051",
        grpc.WithTransportCredentials(insecure.NewCredentials()),
        grpc.WithDefaultServiceConfig(`{
            "loadBalancingConfig": [
                { "round_robin": {} }
            ]
        }`),
    )
    
    client := pb.NewThreatServiceClient(conn)
    
    // gRPC automatically distributes calls across all
    // pods resolved from the headless service DNS
}

Example 3: gRPC Ingress with Contour

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: grpc-ingress
spec:
  virtualhost:
    fqdn: api.dodatech.com
  routes:
  - conditions:
    - prefix: /threat.v1.ThreatService
    services:
    - name: threat-service
      port: 50051
    permitInsecure: true
  - conditions:
    - prefix: /scan.v1.ScanService
    services:
    - name: scan-service
      port: 50051
    permitInsecure: true
---
# Alternative: Envoy-based ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: grpc-ingress
  annotations:
    kubernetes.io/ingress.class: "contour"
    ingress.kubernetes.io/protocol: "h2c"
spec:
  rules:
  - host: api.dodatech.com
    http:
      paths:
      - path: /threat.v1.ThreatService
        pathType: Prefix
        backend:
          service:
            name: threat-service
            port:
              number: 50051

Common Mistakes

  1. Using ClusterIP service for gRPC — ClusterIP uses kube-proxy which doesn't support HTTP/2 load balancing correctly. Use headless services with client-side load balancing.
  2. Not setting HTTP/2 in ingress controllers — default ingress controllers (nginx) proxy HTTP/1.1. Configure HTTP/2 support or use Envoy/Contour for gRPC ingress.
  3. Using default kube-proxy mode — iptables mode load-balances per connection, not per request, causing imbalance with gRPC's long-lived connections.
  4. Not configuring readiness probes correctly — without gRPC health probes, Kubernetes may route traffic to pods that aren't ready to serve.
  5. Setting CPU limits too low — gRPC's HTTP/2 framing and protobuf serialization need CPU. Under-provisioned pods can cause latency spikes and timeouts.

Practice Questions

  1. Why does gRPC need headless services on Kubernetes?
  2. How does client-side load balancing work with DNS resolution?
  3. What ingress controllers support gRPC natively?
  4. How do you configure autoscaling for gRPC services?
  5. Why might gRPC connections become unbalanced across pods?

Challenge: Design a Kubernetes deployment Strategy for a gRPC microservice architecture with 10 services. Include headless services, client-side load balancing with round-robin, gRPC health probes, HPA based on CPU and request rate, and rolling update strategy with zero downtime.

Mini Project

Deploy a complete gRPC microservice on Kubernetes with: Docker container with gRPC health checks, headless service for client-side load balancing, HPA autoscaling, Contour ingress with HTTP/2 support, Prometheus monitoring, and Grafana dashboard for gRPC metrics.

FAQ

Does Kubernetes support gRPC natively?

Kubernetes supports gRPC at the network level (TCP). For gRPC-specific features like HTTP/2 routing and load balancing, you need ingress controllers like Contour or Envoy.

Why does gRPC need a headless service?

Headless services return all pod IPs via DNS, enabling client-side load balancing. Regular ClusterIP services hide pod IPs and use kube-proxy which breaks gRPC's HTTP/2 multiplexing.

Can I use NGINX Ingress for gRPC?

NGINX Ingress supports gRPC since version 1.9. Enable with nginx.ingress.kubernetes.io/backend-protocol: GRPC annotation.

How do I monitor gRPC on Kubernetes?

Export Prometheus metrics from gRPC services via interceptors, use kube-state-metrics for pod metrics, and set up Grafana dashboards for request rates and latency.

How do I handle gRPC rolling updates?

Use readiness probes to ensure new pods are serving before old pods are terminated. Set podDisruptionBudget to prevent all pods from being unavailable during updates.

What's Next

Learn about Dockerizing gRPC services

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro