# How to Integrate Kratos Services with Modern Service Mesh Platforms Like Istio and Linkerd

> Integrate Kratos services with Istio and Linkerd. Learn how to enable distributed tracing, mTLS, and observability with your service mesh for enhanced control and insights.

- Repository: [Kratos/kratos](https://github.com/go-kratos/kratos)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Integrate Kratos services with Istio or Linkerd by deploying the Kubernetes registry to annotate pods with protocol metadata, enabling OpenTelemetry tracing middleware for distributed context propagation, and exposing Prometheus metrics, which allows the mesh sidecar to automatically handle traffic routing, mTLS, and observability.**

The [go-kratos/kratos](https://github.com/go-kratos/kratos) framework provides transport-agnostic servers and pluggable middleware that align perfectly with service mesh architectures. By leveraging the `contrib/registry/kubernetes` package to patch pod annotations and using first-class observability middleware, your Kratos applications become native citizens in Istio or Linkerd environments without invasive code changes.

## Core Components for Mesh Integration

Service meshes rely on sidecar proxies (Envoy for Istio, Linkerd-proxy for Linkerd) intercepting network traffic based on Kubernetes metadata. Kratos provides specific components that satisfy these requirements.

### Kubernetes Registry for Metadata Enrichment

The **[`contrib/registry/kubernetes/registry.go`](https://github.com/go-kratos/kratos/blob/main/contrib/registry/kubernetes/registry.go)** implementation automatically patches the running pod with labels and annotations that service meshes use for protocol detection and service discovery. When you instantiate `registryk8s.NewRegistry()`, it updates the pod with:

- **`kratos-service-protocols`**: A JSON annotation mapping container ports to protocols (e.g., `{"8080":"http","9090":"grpc"}`)
- **Labels**: `kratos-service-id`, `kratos-service-app`, and `kratos-service-version` for identity

This metadata allows Istio and Linkerd to distinguish HTTP from gRPC traffic without additional configuration.

### Observability Middleware

Service meshes aggregate telemetry from application workloads. Kratos exposes this data through:

- **[`middleware/tracing/tracing.go`](https://github.com/go-kratos/kratos/blob/main/middleware/tracing/tracing.go)**: Implements OpenTelemetry trace propagation, ensuring the `traceparent` header flows through the mesh to your backends
- **[`middleware/metrics/metrics.go`](https://github.com/go-kratos/kratos/blob/main/middleware/metrics/metrics.go)**: Exposes Prometheus-format metrics on the `/metrics` endpoint for mesh scrapers

Both middlewares integrate with the HTTP and gRPC server implementations found in **[`transport/http/server.go`](https://github.com/go-kratos/kratos/blob/main/transport/http/server.go)** and **[`transport/grpc/server.go`](https://github.com/go-kratos/kratos/blob/main/transport/grpc/server.go)**.

## Step-by-Step Integration Guide

### Configure the Kubernetes Registry

Initialize the registry inside your main function to enable automatic pod annotation. The registry uses in-cluster configuration to patch the current pod.

```go
import (
    "github.com/go-kratos/kratos/v2"
    registryk8s "github.com/go-kratos/kratos/contrib/registry/kubernetes/v2"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
)

func main() {
    // Create in-cluster Kubernetes client
    cfg, err := rest.InClusterConfig()
    if err != nil {
        log.Fatal(err)
    }
    clientSet, err := kubernetes.NewForConfig(cfg)
    if err != nil {
        log.Fatal(err)
    }
    
    // Instantiate registry (empty string for current pod)
    reg := registryk8s.NewRegistry(clientSet, "")
    
    // Continue with app construction...
}

```

### Instrument Servers with Tracing and Metrics

Apply the OpenTelemetry and Prometheus middleware to both HTTP and gRPC transports. This ensures the mesh can collect consistent telemetry regardless of protocol.

```go
import (
    "github.com/go-kratos/kratos/v2/middleware/metrics"
    "github.com/go-kratos/kratos/v2/middleware/tracing"
    "github.com/go-kratos/kratos/v2/transport/grpc"
    "github.com/go-kratos/kratos/v2/transport/http"
)

app := kratos.New(
    kratos.Name("ordersvc"),
    kratos.Version("v1.0.0"),
    kratos.Registry(reg),
    kratos.Server(
        http.NewServer(
            http.Address(":8080"),
            http.Middleware(
                tracing.Server(), // OpenTelemetry
                metrics.Server(), // Prometheus
            ),
        ),
        grpc.NewServer(
            grpc.Address(":9090"),
            grpc.Middleware(
                tracing.Server(),
                metrics.Server(),
            ),
        ),
    ),
)

```

### Deploy with Mesh-Ready Annotations

Your Kubernetes Deployment must expose the ports and allow the registry to annotate the pod template. The `kratos-service-protocols` annotation is automatically populated by the registry, but you can pre-declare it for clarity.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ordersvc
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ordersvc
  template:
    metadata:
      labels:
        app: ordersvc
        kratos-service-version: "v1.0.0"
      annotations:
        kratos-service-protocols: |
          {"8080":"http","9090":"grpc"}
        kratos-service-metadata: |
          {"team":"payment"}
    spec:
      containers:
      - name: ordersvc
        image: myrepo/ordersvc:latest
        ports:
        - containerPort: 8080
        - containerPort: 9090

```

### Inject the Mesh Sidecar

**For Istio**, enable injection at the namespace or deployment level:

```bash
kubectl label namespace default istio-injection=enabled

# Or annotate specific deployment

kubectl annotate deployment ordersvc sidecar.istio.io/inject="true"

```

**For Linkerd**, use the CLI to patch the deployment:

```bash
linkerd inject deployment/ordersvc | kubectl apply -f -

```

## Verifying Mesh Integration

### Check Protocol Detection

Once deployed, verify the mesh recognizes the protocols correctly. For Istio, check the proxy configuration:

```bash
istioctl dashboard proxy-config pod ordersvc-<hash>

```

Look for listener entries on ports 8080 (HTTP) and 9090 (gRPC) based on the `kratos-service-protocols` annotation.

### Validate Telemetry Export

Confirm that Prometheus metrics are accessible on the `/metrics` endpoint:

```bash
kubectl port-forward pod/ordersvc-<hash> 8080:8080
curl localhost:8080/metrics

```

For distributed tracing, ensure your OpenTelemetry Collector or Jaeger instance receives traces by checking the Kratos middleware configuration:

```go
tp := sdktrace.NewTracerProvider(
    sdktrace.WithSampler(sdktrace.TraceIDRatioBased(1.0)),
)
// Pass tp to tracing.Server(tracing.WithTracerProvider(tp))

```

## Complete Working Example

Here is a minimal, production-ready [`main.go`](https://github.com/go-kratos/kratos/blob/main/main.go) that combines all integration points:

```go
package main

import (
    "log"

    "github.com/go-kratos/kratos/v2"
    "github.com/go-kratos/kratos/v2/middleware/metrics"
    "github.com/go-kratos/kratos/v2/middleware/tracing"
    "github.com/go-kratos/kratos/v2/transport/grpc"
    "github.com/go-kratos/kratos/v2/transport/http"
    
    registryk8s "github.com/go-kratos/kratos/contrib/registry/kubernetes/v2"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
)

func main() {
    // Kubernetes client configuration
    cfg, err := rest.InClusterConfig()
    if err != nil {
        log.Fatalf("failed to create k8s config: %v", err)
    }
    cs, err := kubernetes.NewForConfig(cfg)
    if err != nil {
        log.Fatalf("failed to create k8s client: %v", err)
    }
    
    // Mesh-aware registry
    reg := registryk8s.NewRegistry(cs, "")
    
    // Build application with observability middleware
    app := kratos.New(
        kratos.Name("ordersvc"),
        kratos.Version("v1.0.0"),
        kratos.Metadata(map[string]string{"team": "payment"}),
        kratos.Registry(reg),
        kratos.Server(
            http.NewServer(
                http.Address(":8080"),
                http.Middleware(
                    tracing.Server(),
                    metrics.Server(),
                ),
            ),
            grpc.NewServer(
                grpc.Address(":9090"),
                grpc.Middleware(
                    tracing.Server(),
                    metrics.Server(),
                ),
            ),
        ),
    )
    
    if err := app.Run(); err != nil {
        log.Fatalf("app exited: %v", err)
    }
}

```

## Summary

- **Use the Kubernetes registry** ([`contrib/registry/kubernetes/registry.go`](https://github.com/go-kratos/kratos/blob/main/contrib/registry/kubernetes/registry.go)) to automatically annotate pods with protocol metadata and service identities required by Istio and Linkerd.
- **Enable OpenTelemetry tracing** via `middleware/tracing` to ensure distributed trace context propagates through the mesh sidecar to downstream services.
- **Expose Prometheus metrics** using `middleware/metrics` so the mesh control plane can scrape standard metrics from the `/metrics` endpoint.
- **Deploy standard HTTP/gRPC servers** from `transport/http` and `transport/grpc` without TLS inside the pod; the mesh sidecar terminates mTLS automatically.
- **Inject sidecars** using native Istio annotations or Linkerd CLI commands; no application code changes are required for traffic management or security.

## Frequently Asked Questions

### Does Kratos require code modifications to work with Istio?

No. According to the source code in [`transport/http/server.go`](https://github.com/go-kratos/kratos/blob/main/transport/http/server.go) and [`transport/grpc/server.go`](https://github.com/go-kratos/kratos/blob/main/transport/grpc/server.go), Kratos servers work transparently with Istio once you configure the Kubernetes registry and inject the sidecar. The mesh handles traffic routing, retries, and mTLS termination externally.

### How does the Kubernetes registry help with service mesh integration?

The registry implementation in [`contrib/registry/kubernetes/registry.go`](https://github.com/go-kratos/kratos/blob/main/contrib/registry/kubernetes/registry.go) patches the running pod with the `kratos-service-protocols` annotation and standardized labels. This metadata tells Istio and Linkerd which ports serve HTTP versus gRPC traffic, enabling proper protocol selection and telemetry collection.

### Can I use Linkerd instead of Istio with Kratos?

Yes. Both service meshes consume the same Kubernetes metadata and OpenTelemetry/Prometheus standards that Kratos produces. Use `linkerd inject` on your deployments instead of Istio's injection labels, while keeping the same Kratos application code and registry configuration.

### Should Kratos handle TLS when running inside a service mesh?

Typically no. When running in a mesh, configure Kratos servers to use plain text (HTTP) or server-only TLS if required by your security policy. The mesh's sidecar proxy (Envoy or Linkerd-proxy) automatically upgrades connections to mutual TLS (mTLS) between services, handling certificate management and encryption at the infrastructure layer.