Kratos: Go Cloud-Native Microservices Framework
Build cloud-native microservices with Kratos - a lightweight Go framework with Protobuf APIs, HTTP/gRPC transport, and middleware.
- Step 1
Verify Go version requirements
Kratos v3 requires Go 1.25 or later. Check your Go version first:
go version⚠ Heads up: Kratos v3 requires Go 1.25+. If using an older version, upgrade Go before proceeding. - Step 2
Install Protocol Buffers compiler
Kratos uses Protobuf for API-first development. Install protoc and related tools:
# On macOS: brew install protobuf # On Ubuntu/Debian: sudo apt-get install protobuf-compiler # On Arch Linux: sudo pacman -S protobuf # On Windows (Chocolatey): choco install protoc # Verify installation: protoc --version - Step 3
Install Go Protobuf plugins
Install the Go Protobuf plugins needed for code generation:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/protobuf/cmd/protoc-gen-go-grpc@latest⚠ Heads up: Ensure $GOPATH/bin is in your PATH for the generated commands to be accessible. - Step 4
Install Kratos CLI
The Kratos CLI provides commands for project scaffolding and code generation:
# Install the latest kratos CLI go install github.com/go-kratos/kratos/cmd/kratos/v3@latest # Upgrade the CLI runtime (installs runtime dependencies) kratos upgrade # Verify installation kratos version - Step 5
Create a new Kratos service
Use the Kratos CLI to scaffold a new project. This creates the standard Kratos project layout:
# Create a new Kratos project kratos new helloworld cd helloworld # Install dependencies go mod tidy # Run the service kratos run - Step 6
Explore the generated project structure
Kratos generates a standard project layout following best practices. The structure includes:
# Typical Kratos project structure: helloworld/ ├── api/ # API definitions (Protobuf) │ └── helloworld/ │ └── helloworld.proto ├── cmd/ │ └── helloworld/ # Service entry point │ └── main.go ├── conf/ │ ├── app.yaml # Service configuration │ └── log.yaml # Logging configuration ├── internal/ # Internal business logic │ └── service/ │ └── helloworld/ │ ├── helloworld.go │ └── helloworld_test.go ├── go.mod ├── go.sum └── README.md # View the project structure tree -L 3 - Step 7
Define your service API in Protobuf
Create an API definition using Protobuf. Start by understanding the API directory structure and helloworld.proto:
syntax = "proto3"; package kratos.api.helloworld.v1; import "google/protobuf/timestamp.proto"; option go_package = "github.com/helloworld/api/helloworld/v1;helloworldv1"; service GreeterService { rpc SayHello (SayHelloRequest) returns (SayHelloResponse); } message SayHelloRequest { string name = 1; } message SayHelloResponse { string message = 1; } - Step 8
Add a new Protobuf API file
Use the kratos proto command to add new API files within your service:
# Add a new proto definition kratos proto add api/helloworld/helloworld.proto # This creates a new proto file template in the api/ directory - Step 9
Generate gRPC client stub
Generate Go gRPC client code from your Protobuf definition. This creates client-side code for service-to-service communication:
# Generate client code kratos proto client api/helloworld/helloworld.proto # This command generates: # - Go types from the .proto file # - gRPC client interfaces # - Places generated files in the appropriate directory - Step 10
Generate gRPC server code
Generate Go server code from your Protobuf definition. This creates interfaces and type definitions your service must implement:
# Generate server code (targets internal/service directory) kratos proto server api/helloworld/helloworld.proto -t internal/service # Run all code generation go generate ./... - Step 11
Implement the service handler
Implement your business logic in the service layer. Here's an example Greeter service implementation:
package helloworld import ( "context" "fmt" helloworldv1 "github.com/helloworld/api/helloworld/v1" ) // GreeterServiceImpl implements the Greeter service type GreeterServiceImpl struct { helloworldv1.UnimplementedGreeterServiceServer } // SayHello implements helloworldv1.GreeterServiceServer type SayHelloRequest struct { Name string `json:"name"` } func (s *GreeterServiceImpl) SayHello( ctx context.Context, req *helloworldv1.SayHelloRequest, ) (*helloworldv1.SayHelloResponse, error) { return &helloworldv1.SayHelloResponse{ Message: fmt.Sprintf("Hello %s!", req.GetName()), }, nil } - Step 12
Register HTTP transport
Configure the HTTP transport layer to expose your service. Kratos provides a unified transport abstraction:
package helloworld import ( "context" "github.com/go-kratos/kratos/v3/log" "github.com/go-kratos/kratos/v3/transport/http" "github.com/helloworld/api/helloworld/v1" ) // WithUnaryInterceptor adds HTTP middleware func NewHTTPServer(c *Config) http.Server { srv := http.NewServer( http.Address(c.Server.Host+":8000"), http.Timeout(c.Server.Timeout), ) v1.RegisterGreeterServiceHTTPServer(srv, &GreeterServiceImpl{}) return srv } // Config structure for HTTP server configuration type Config struct { Server struct { Host string Timeout string } } - Step 13
Register gRPC transport
Configure the gRPC transport layer. Kratos supports both HTTP and gRPC transports simultaneously:
package helloworld import ( "context" "github.com/go-kratos/kratos/v3/log" "github.com/go-kratos/kratos/v3/transport/grpc" "github.com/helloworld/api/helloworld/v1" ) // WithUnaryInterceptor adds gRPC middleware func NewGRPCServer(c *Config) grpc.Server { srv := grpc.NewServer( grpc.Address(c.Server.Host+":9000"), grpc.Timeout(c.Server.Timeout), ) v1.RegisterGreeterServiceServer(srv, &GreeterServiceImpl{}) return srv } // Config structure for gRPC server configuration type Config struct { Server struct { Host string Timeout string } } - Step 14
Create service entry point (main.go)
The main.go file initializes configuration, creates transports, and starts the application. Here's a complete example:
package main import ( "flag" "log" "os" "github.com/go-kratos/kratos/v3" "github.com/go-kratos/kratos/v3/config" "github.com/go-kratos/kratos/v3/config/file" "github.com/go-kratos/kratos/v3/transport/grpc" "github.com/go-kratos/kratos/v3/transport/http" "github.com/helloworld/internal/conf" "github.com/helloworld/internal/service/helloworld" ) func run() error { var confPath string flag.StringVar(&confPath, "conf", "./conf/app.yaml", "config path") flag.Parse() // Load configuration c := config.New(config.WithSource( file.NewWithNamespace(file.WithPath(confPath)), )) if err := c.Load(); err != nil { return err } // Get config from loaded configuration var bc conf.Button if err := c.Scan(&bc); err != nil { return err } // Create transports httpSrv := http.NewServer( http.Address(":8000"), http.Middleware(log.Logger()), ) grpcSrv := grpc.NewServer( grpc.Address(":9000"), grpc.Middleware(log.Logger()), ) // Create Kratos application app := kratos.New( kratos.Name("helloworld"), kratos.Version("v1.0.0"), kratos.Server( httpSrv, grpcSrv, ), kratos.Logger(c.Get("log").MustValue("kratos").AsAny()), ) defer app.Shutdown() log.Info("Start Kratos...") if err := app.Run(); err != nil { return err } return nil } func main() { if err := run(); err != nil { log.Fatal(err) os.Exit(-1) } } - Step 15
Configure service settings
Kratos uses YAML configuration files. Edit conf/app.yaml to configure your service:
# app.yaml - main application configuration button: grpc: host: 0.0.0.0 port: 9000 http: host: 0.0.0.0 port: 8000 log: level: info outputs: - stdout encoding: - json # Optional: Add registry configuration registry: etcd: endpoint: - 127.0.0.1:2379 # Optional: Add metrics configuration metrics: enable: true - Step 16
Add middleware components
Kratos provides composable middleware for cross-cutting concerns. Add recovery, logging, authentication, etc.:
import ( "github.com/go-kratos/kratos/v3/middleware/logging" "github.com/go-kratos/kratos/v3/middleware/recovery" "github.com/go-kratos/kratos/v3/middleware/tracing" "github.com/go-kratos/kratos/v3/middleware/selector" ) // Add middleware to HTTP transport httpSrv := http.NewServer( http.Address(":8000"), http.Middleware( // Recovery middleware for panic handling recovery.Recovery(), // Logging middleware logging.New(logging.WithLogger(log.Default)), // Tracing middleware (requires OpenTelemetry setup) tracing.Trace(), ), ) // Add middleware to gRPC transport grpcSrv := grpc.NewServer( grpc.Address(":9000"), grpc.Middleware( recovery.Recovery(), logging.New(logging.WithLogger(log.Default)), ), ) // Use selector middleware for specific endpoints selector.Match( selector.WithContextValue("path", "/admin/*"), logging.New(logging.WithLogger(log.Default)), ).Server() - Step 17
Use Kratos configuration
Kratos provides configuration management with file-based sources or external configuration stores:
import ( "github.com/go-kratos/kratos/v3/config" "github.com/go-kratos/kratos/v3/config/file" // External config sources (from contrib): // "github.com/go-kratos/kratos/contrib/config/etcd/v2" // "github.com/go-kratos/kratos/contrib/config/kubernetes/v2" // "github.com/go-kratos/kratos/contrib/config/apollo/v2" ) // File-based configuration c := config.New( config.WithSource( file.NewWithNamespace( file.WithPath("conf"), ), ), ) // Load configuration if err := c.Load(); err != nil { panic(err) } // Watch for configuration changes c.OnChanged("button", func(key string, value config.Value) { log.Infof("Config changed: %s", key) }) // Scan configuration into struct type ButtonConfig struct { Grpc struct { Host string Port int } } var bc ButtonConfig if err := c.Scan(&bc); err != nil { panic(err) } - Step 18
Set up service discovery
Kratos supports multiple service discovery backends through the contrib ecosystem. Here's how to configure etcd:
import ( "github.com/go-kratos/kratos/v3/registry" "github.com/go-kratos/kratos/contrib/registry/etcd/v2" // contrib package ) // etcd service registry reg, err := etcd.New( etcd.Address("127.0.0.1:2379"), ) if err != nil { panic(err) } // Create application with registry app := kratos.New( kratos.Name("helloworld"), kratos.Version("v1.0.0"), kratos.Registry(reg), kratos.Server(httpSrv, grpcSrv), ) // Register service instance if err := app.Register(); err != nil { panic(err) } // Other supported registries: // - consul: github.com/go-kratos/kratos/contrib/registry/consul/v2 // - kubernetes: github.com/go-kratos/kratos/contrib/registry/kubernetes/v2 // - nacos: github.com/go-kratos/kratos/contrib/registry/nacos/v2 // - zookeeper: github.com/go-kratos/kratos/contrib/registry/zookeeper/v2 // - redis: github.com/go-kratos/kratos/contrib/registry/redis/v2 // - moka: github.com/go-kratos/kratos/contrib/registry/moka/v2 - Step 19
Implement service client for internal communication
Use generated clients to communicate between services within your microservices architecture:
import ( "context" "github.com/go-kratos/kratos/v3/transport/http" helloworldv1 "github.com/helloworld/api/helloworld/v1" ) // Create HTTP client httpClient, err := http.NewClient( http.WithTransport( http.NewTransport( http.BaseURL("http://other-service:8000"), ), ), ) if err != nil { panic(err) } // Create gRPC client import ( "github.com/go-kratos/kratos/v3/transport/grpc" ) grpcClient, err := grpc.NewClient( grpc.WithTransport( grpc.Transport( grpc.BaseAddr("other-service:9000"), ), ), ) if err != nil { panic(err) } // Use the client ctx := context.Background() resp, err := helloworldv1.NewGreeterServiceClient(httpClient).SayHello( ctx, &helloworldv1.SayHelloRequest{Name: "World"}, ) if err != nil { panic(err) } log.Printf("Response: %s", resp.GetMessage()) - Step 20
Add custom health checks
Implement health check endpoints for container orchestration and load balancers:
import ( "github.com/go-kratos/kratos/v3/middleware" ) // Simple health check middleware func HealthCheck() middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (interface{}, error) { if reqPath, ok := middleware.RequestPath(ctx).Get("path"); ok { if reqPath == "/health" || reqPath == "/ready" || reqPath == "/live" { return map[string]string{"status": "OK"}, nil } } return handler(ctx, req) } } } // Add to HTTP server httpSrv := http.NewServer( http.Address(":8000"), http.Middleware( HealthCheck(), ), ) - Step 21
Use request validation
Add request/response validation middleware to ensure data integrity:
import ( "github.com/go-kratos/kratos/v3/middleware/validation" ) // Add validation middleware httpSrv := http.NewServer( http.Address(":8000"), http.Middleware( validation.Validator(), ), ) // Validate request in service method func (s *GreeterServiceImpl) SayHello( ctx context.Context, req *helloworldv1.SayHelloRequest, ) (*helloworldv1.SayHelloResponse, error) { if req.GetName() == "" { return nil, kratoserrors.New( kratoserrors.CodeInvalidArgument, "name is required", "name is required", ) } return &helloworldv1.SayHelloResponse{ Message: fmt.Sprintf("Hello %s!", req.GetName()), }, nil } - Step 22
Implement graceful shutdown
Kratos handles graceful shutdown automatically. You can customize shutdown behavior:
import ( "context" "os" "os/signal" "syscall" "time" "github.com/go-kratos/kratos/v3" ) func run() error { // Create application app := kratos.New(...) defer app.Shutdown() // Setup shutdown handler quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT) go func() { <-quit log.Info("Received shutdown signal") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := app.Shutdown(ctx); err != nil { log.Fatalf("failed to shutdown cleanly: %v", err) } os.Exit(0) }() // Run the application if err := app.Run(); err != nil { return err } return nil } func main() { if err := run(); err != nil { log.Fatal(err) os.Exit(-1) } } - Step 23
Create Dockerfile for containerized deployment
Containerize your Kratos service for deployment in Kubernetes or other container orchestration platforms:
# Build stage FROM golang:1.25-alpine AS builder WORKDIR /build # Install protoc and plugins RUN apk add --no-cache protobuf protoc RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest RUN go install google.golang.org/protobuf/cmd/protoc-gen-go-grpc@latest # Copy go mod files COPY go.mod go.sum ./ RUN go mod download || true # Copy source code COPY . . # Run code generation RUN go generate ./... # Build the application RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o helloworld ./cmd/helloworld/ # Final stage FROM alpine:latest RUN apk --no-cache add ca-certificates tzdata WORKDIR /app # Copy binary and configuration from builder COPY --from=builder /build/helloworld . COPY --from=builder /build/conf ./conf # Expose ports EXPOSE 8000 9000 # Run the application CMD ["./helloworld", "--conf=./conf/app.yaml"] - Step 24
Create Docker Compose setup
Use Docker Compose for local development with all services including etcd registry:
version: '3.8' networks: kratos: driver: bridge services: # etcd for service discovery etcd: image: quay.io/coreos/etcd:v3.5.9 container_name: kratos-etcd environment: - ETCD_LISTEN_CLIENT_URIS=http://0.0.0.0:2379 - ETCD_ADVERTISE_CLIENT_URIS=http://etcd:2379 ports: - 2379:2379 networks: - kratos # Consul for alternative service discovery consul: image: consul:1.16.0 container_name: kratos-consul ports: - 8500:8500 networks: - kratos # Your Kratos service greeter-service: build: context: . dockerfile: Dockerfile container_name: kratos-greeter depends_on: - etcd environment: - REGISTRY_ENDPOINT=etcd:2379 - SERVER_PORT_HTTP=8000 - SERVER_PORT_GRPC=9000 ports: - 8000:8000 - 9000:9000 networks: - kratos # Prometheus for metrics prometheus: image: prom/prometheus:v2.47.0 container_name: kratos-prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - 9090:9090 networks: - kratos - Step 25
Configure Prometheus metrics
Kratos integrates with Prometheus for metrics collection:
import ( "github.com/go-kratos/kratos/contrib/metrics/prometheus/v2" ) // Initialize Prometheus metric tp := prometheus.New( prometheus.Namespace("kratos"), ) httpSrv := http.NewServer( http.Address(":8000"), http.Middleware( tp.Metrics(), ), ) // In your config file // prometheus.yml: global: scrape_interval: 15s scrape_configs: - job_name: 'greeter-service' static_configs: - targets: ['greeter-service:8000'] metrics_path: /metrics - Step 26
Set up OpenTelemetry tracing
Kratos supports OpenTelemetry for distributed tracing through contrib packages:
import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/jaeger" "go.opentelemetry.io/otel/sdk/trace" "github.com/go-kratos/kratos/v3/middleware/tracing" ) // Setup Jaeger tracer exporter, err := jaeger.New( jaeger.WithCollectorEndpoint( jaeger.WithURL("http://localhost:14268/api/traces"), ), jaeger.WithServiceName("greeter-service"), ) if err != nil { panic(err) } // Create tracer provider provider := trace.NewTracerProvider( trace.WithSyncer(exporter), ) otel.SetTracerProvider(provider) // Add tracing middleware httpSrv := http.NewServer( http.Address(":8000"), http.Middleware( tracing.Trace( tracing.WithTracerProvider(provider), ), ), ) - Step 27
Explore Kratos contrib ecosystem
Kratos provides a rich contrib ecosystem for common integrations. Explore available packages:
# Available Kratos contrib packages: # https://github.com/go-kratos-contrib/ # Registries: # - github.com/go-kratos/kratos/contrib/registry/etcd/v2 # - github.com/go-kratos/kratos/contrib/registry/consul/v2 # - github.com/go-kratos/kratos/contrib/registry/kubernetes/v2 # - github.com/go-kratos/kratos/contrib/registry/nacos/v2 # - github.com/go-kratos/kratos/contrib/registry/zookeeper/v2 # - github.com/go-kratos/kratos/contrib/registry/redis/v2 # - github.com/go-kratos/kratos/contrib/registry/moka/v2 # Config Stores: # - github.com/go-kratos/kratos/contrib/config/etcd/v2 # - github.com/go-kratos/kratos/contrib/config/kubernetes/v2 # - github.com/go-kratos/kratos/contrib/config/apollo/v2 # - github.com/go-kratos/kratos/contrib/config/nacos/v2 # - github.com/go-kratos/kratos/contrib/config/polaris/v2 # Middlewares: # - github.com/go-kratos/kratos/contrib/middleware/auth/jwt/v2 # - github.com/go-kratos/kratos/contrib/middleware/selector/v2 # Metrics: # - github.com/go-kratos/kratos/contrib/metrics/prometheus/v2 # - github.com/go-kratos/kratos/contrib/metrics/v2 # Install a contrib package: go get github.com/go-kratos/kratos/contrib/registry/etcd/v2 - Step 28
Test your Kratos service
Kratos follows Go testing conventions. Create unit tests and integration tests:
package helloworld import ( "context" "testing" "github.com/go-kratos/kratos/v3/test" helloworldv1 "github.com/helloworld/api/helloworld/v1" ) func TestGreeterService_SayHello(t *testing.T) { tests := []struct { name string req *helloworldv1.SayHelloRequest wantErr bool }{ { name: "valid request", req: &helloworldv1.SayHelloRequest{Name: "World"}, }, { name: "empty name", req: &helloworldv1.SayHelloRequest{Name: ""}, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { svc := &GreeterServiceImpl{} _, err := svc.SayHello(context.Background(), tt.req) if (err != nil) != tt.wantErr { t.Errorf("SayHello() error = %v, wantErr %v", err, tt.wantErr) } }) } } // Run tests go test -v ./... - Step 29
Run linting and code quality checks
Maintain code quality with linting tools recommended by Kratos:
# Install golangci-lint go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest # Run linter golangci-lint run # Use Makefile targets (if provided) make lint make test make run # Example Makefile includes: default: run all: run test lint test: go test -v -cover ./... lint: golangci-lint run run: kratos run clean: rm -f bin/* - Step 30
Deploy to Kubernetes
Deploy your Kratos service to Kubernetes using standard YAML manifests or Helm charts:
# k8s/service.yaml apiVersion: v1 kind: Service metadata: name: greeter-service spec: type: ClusterIP ports: - port: 8000 targetPort: 8000 protocol: TCP - port: 9000 targetPort: 9000 protocol: TCP selector: app: greeter-service --- apiVersion: apps/v1 kind: Deployment metadata: name: greeter-service spec: replicas: 3 selector: matchLabels: app: greeter-service template: metadata: labels: app: greeter-service spec: containers: - name: greeter image: your-registry/greeter-service:latest ports: - containerPort: 8000 - containerPort: 9000 env: - name: REGISTRY_ENDPOINT value: "etcd:2379" resources: limits: cpu: 500m memory: 256Mi requests: cpu: 100m memory: 128Mi livenessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8000 initialDelaySeconds: 5 periodSeconds: 5 - Step 31
Explore further resources
Continue learning with official documentation, examples, and community resources:
# Official Kratos resources: # Documentation: https://go-kratos.dev/docs # Examples: https://github.com/go-kratos/examples # Project Layout: https://github.com/go-kratos/kratos-layout # Contrib Packages: https://github.com/go-kratos-contrib # Discord Chat: https://discord.gg/BWzJsUJ # Clone examples repo for reference implementations git clone https://github.com/go-kratos/examples.git cd examples
Feature requests
Sign in to suggest features or vote on existing ones.
No feature requests yet.
Discussion
Sign in to join the discussion.
No comments yet.