Set up comprehensive distributed tracing in your Istio service mesh using both Jaeger and Zipkin backends. Configure telemetry collection, trace sampling, and monitoring dashboards for full microservices observability.
Prerequisites
- Kubernetes cluster with kubectl access
- Istio service mesh installed
- At least 8GB RAM available
- Storage class for persistent volumes
What this solves
Distributed tracing tracks requests as they flow through multiple microservices, helping you identify bottlenecks, debug errors, and understand service dependencies. This tutorial configures Istio's telemetry system with both Jaeger and Zipkin to collect, store, and visualize traces from your service mesh.
Prerequisites
You need a Kubernetes cluster with Istio service mesh already installed. This builds on our Istio installation guide to add comprehensive tracing capabilities.
Step-by-step configuration
Install Jaeger tracing backend
Deploy Jaeger using the operator for production-grade distributed tracing with Elasticsearch storage.
kubectl create namespace observability
kubectl apply -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.51.0/jaeger-operator.yaml -n observability
Configure Jaeger with persistent storage
Create a Jaeger instance with Elasticsearch backend for long-term trace storage and high availability.
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: jaeger-production
namespace: istio-system
spec:
strategy: production
storage:
type: elasticsearch
options:
es:
server-urls: http://elasticsearch.observability.svc.cluster.local:9200
index-prefix: jaeger
esIndexCleaner:
enabled: true
numberOfDays: 7
schedule: "55 23 *"
query:
replicas: 2
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
collector:
replicas: 2
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 200m
memory: 256Mi
kubectl apply -f jaeger-production.yaml
Deploy Elasticsearch for Jaeger storage
Set up Elasticsearch cluster to store Jaeger traces with proper resource allocation and persistence.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
namespace: observability
spec:
serviceName: elasticsearch
replicas: 3
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
ports:
- containerPort: 9200
name: http
- containerPort: 9300
name: transport
env:
- name: discovery.type
value: zen
- name: cluster.name
value: jaeger-cluster
- name: network.host
value: "0.0.0.0"
- name: xpack.security.enabled
value: "false"
- name: ES_JAVA_OPTS
value: "-Xms2g -Xmx2g"
resources:
limits:
cpu: 2
memory: 4Gi
requests:
cpu: 500m
memory: 2Gi
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: observability
spec:
selector:
app: elasticsearch
ports:
- port: 9200
targetPort: 9200
kubectl apply -f elasticsearch-jaeger.yaml
Install Zipkin tracing backend
Deploy Zipkin as an alternative tracing backend with in-memory storage for development and testing.
apiVersion: apps/v1
kind: Deployment
metadata:
name: zipkin
namespace: istio-system
labels:
app: zipkin
spec:
replicas: 2
selector:
matchLabels:
app: zipkin
template:
metadata:
labels:
app: zipkin
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: zipkin
image: openzipkin/zipkin:2.24
ports:
- containerPort: 9411
env:
- name: STORAGE_TYPE
value: elasticsearch
- name: ES_HOSTS
value: http://elasticsearch.observability.svc.cluster.local:9200
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 200m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: zipkin
namespace: istio-system
labels:
app: zipkin
spec:
type: ClusterIP
ports:
- port: 9411
targetPort: 9411
selector:
app: zipkin
kubectl apply -f zipkin-deployment.yaml
Configure Istio telemetry for distributed tracing
Set up Istio's telemetry system to collect traces and send them to both Jaeger and Zipkin backends.
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: tracing-config
spec:
values:
pilot:
traceSampling: 1.0
global:
meshConfig:
defaultConfig:
tracing:
sampling: 100.0
max_path_tag_length: 256
extensionProviders:
- name: jaeger
envoyOtelAls:
service: jaeger-collector.istio-system.svc.cluster.local
port: 14268
- name: zipkin
zipkin:
service: zipkin.istio-system.svc.cluster.local
port: 9411
meshConfig:
defaultProviders:
tracing:
- jaeger
- zipkin
istioctl install -f istio-tracing-config.yaml --skip-confirmation
Configure trace sampling policies
Set up intelligent sampling to balance trace coverage with storage costs and performance impact.
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: tracing-config
namespace: istio-system
spec:
tracing:
- providers:
- name: jaeger
- providers:
- name: zipkin
- randomSamplingPercentage: 1.0
- customTags:
http.method:
header:
name: ":method"
http.status_code:
header:
name: ":status"
user.id:
header:
name: "x-user-id"
---
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: high-traffic-sampling
namespace: production
spec:
tracing:
- randomSamplingPercentage: 0.1
- providers:
- name: jaeger
kubectl apply -f telemetry-v2.yaml
Enable tracing for application namespaces
Configure specific namespaces to send traces with appropriate sampling rates for different environments.
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: app-tracing
namespace: default
spec:
tracing:
- providers:
- name: jaeger
- name: zipkin
- randomSamplingPercentage: 10.0
- customTags:
app.version:
literal:
value: "v1.2.3"
environment:
literal:
value: "staging"
---
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
istio-injection: enabled
tracing.istio.io/sampling: "0.1"
---
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
istio-injection: enabled
tracing.istio.io/sampling: "5.0"
kubectl apply -f namespace-tracing.yaml
Configure Jaeger access and security
Set up secure access to Jaeger UI with authentication and network policies.
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: jaeger-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https-jaeger
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: jaeger-tls-secret
hosts:
- jaeger.example.com
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: jaeger-vs
namespace: istio-system
spec:
hosts:
- jaeger.example.com
gateways:
- jaeger-gateway
http:
- match:
- uri:
prefix: "/"
route:
- destination:
host: jaeger-query.istio-system.svc.cluster.local
port:
number: 16686
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: jaeger-access
namespace: istio-system
spec:
selector:
matchLabels:
app: jaeger
rules:
- from:
- source:
principals: ["cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"]
- to:
- operation:
methods: ["GET", "POST"]
kubectl apply -f jaeger-gateway.yaml
Configure Zipkin access
Set up access to Zipkin UI for alternative trace analysis and debugging workflows.
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: zipkin-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https-zipkin
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: zipkin-tls-secret
hosts:
- zipkin.example.com
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: zipkin-vs
namespace: istio-system
spec:
hosts:
- zipkin.example.com
gateways:
- zipkin-gateway
http:
- match:
- uri:
prefix: "/"
route:
- destination:
host: zipkin.istio-system.svc.cluster.local
port:
number: 9411
kubectl apply -f zipkin-gateway.yaml
Set up Grafana dashboards for trace metrics
Configure Grafana to display tracing metrics and service topology from both Jaeger and Zipkin data sources.
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-datasources
namespace: istio-system
data:
datasources.yaml: |
apiVersion: 1
datasources:
- name: Jaeger
type: jaeger
url: http://jaeger-query.istio-system.svc.cluster.local:16686
access: proxy
isDefault: false
editable: true
- name: Zipkin
type: zipkin
url: http://zipkin.istio-system.svc.cluster.local:9411
access: proxy
isDefault: false
editable: true
- name: Prometheus
type: prometheus
url: http://prometheus.istio-system.svc.cluster.local:9090
access: proxy
isDefault: true
editable: true
kubectl apply -f grafana-tracing-datasource.yaml
kubectl rollout restart deployment/grafana -n istio-system
Deploy sample application for testing
Deploy a multi-service application to generate traces and test your distributed tracing setup.
apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: productpage
version: v1
template:
metadata:
labels:
app: productpage
version: v1
spec:
containers:
- name: productpage
image: docker.io/istio/examples-bookinfo-productpage-v1:1.18.0
ports:
- containerPort: 9080
env:
- name: JAEGER_AGENT_HOST
value: "jaeger-agent.istio-system.svc.cluster.local"
- name: JAEGER_AGENT_PORT
value: "6831"
- name: JAEGER_SAMPLER_TYPE
value: "const"
- name: JAEGER_SAMPLER_PARAM
value: "1"
---
apiVersion: v1
kind: Service
metadata:
name: productpage
namespace: default
spec:
selector:
app: productpage
ports:
- port: 9080
targetPort: 9080
kubectl apply -f bookinfo-tracing.yaml
Configure advanced trace analysis
Set up trace correlation with logs
Configure log correlation to link traces with application logs for comprehensive debugging.
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: log-correlation
namespace: istio-system
spec:
accessLogging:
- providers:
- name: otel
tracing:
- providers:
- name: jaeger
- customTags:
trace_id:
operation: INSERT
header:
name: "x-trace-id"
span_id:
operation: INSERT
header:
name: "x-span-id"
kubectl apply -f log-correlation.yaml
Configure performance monitoring
Set up alerts for trace latency, error rates, and service dependencies using our existing Istio monitoring setup.
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: tracing-alerts
namespace: istio-system
spec:
groups:
- name: istio-tracing
rules:
- alert: HighTraceLatency
expr: histogram_quantile(0.99, sum(rate(istio_request_duration_milliseconds_bucket{reporter="destination"}[5m])) by (le, destination_service_name)) > 1000
for: 5m
labels:
severity: warning
annotations:
summary: "High trace latency detected"
description: "Service {{ $labels.destination_service_name }} has 99th percentile latency > 1s"
- alert: TraceErrorRate
expr: sum(rate(istio_requests_total{reporter="destination",response_code!~"2.."}[5m])) by (destination_service_name) / sum(rate(istio_requests_total{reporter="destination"}[5m])) by (destination_service_name) > 0.1
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate in traces"
description: "Service {{ $labels.destination_service_name }} has error rate > 10%"
kubectl apply -f trace-alerts.yaml
Verify your setup
Check that all tracing components are running and collecting traces properly.
# Check Jaeger pods
kubectl get pods -n istio-system -l app=jaeger
Check Zipkin deployment
kubectl get pods -n istio-system -l app=zipkin
Check Elasticsearch storage
kubectl get pods -n observability -l app=elasticsearch
Verify telemetry configuration
kubectl get telemetry -A
Test trace collection
kubectl exec -n default deployment/productpage-v1 -- curl -s http://productpage.default.svc.cluster.local:9080/productpage
Check Jaeger UI access
kubectl port-forward -n istio-system svc/jaeger-query 16686:16686
Visit http://localhost:16686
Check Zipkin UI access
kubectl port-forward -n istio-system svc/zipkin 9411:9411
Visit http://localhost:9411
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| No traces appearing | Sampling rate too low | Increase randomSamplingPercentage in Telemetry config |
| Jaeger UI not accessible | Service not exposed correctly | Check Gateway and VirtualService configuration |
| High storage usage | No trace retention policy | Configure esIndexCleaner in Jaeger spec |
| Missing trace data | Istio proxy not injected | Label namespace with istio-injection: enabled |
| Elasticsearch connection failed | Network policy blocking access | Allow traffic between namespaces: kubectl label namespace istio-system name=istio-system |
| Traces not correlated | Missing trace headers | Ensure applications propagate x-trace-id headers |
Next steps
- Configure advanced OpenTelemetry sampling strategies for high-traffic environments
- Set up Istio security policies to secure your traced services
- Configure Istio traffic management for canary deployments with tracing
- Set up multi-datacenter Jaeger replication for global observability
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Script configuration
SCRIPT_NAME="$(basename "$0")"
ELASTICSEARCH_NAMESPACE="${ELASTICSEARCH_NAMESPACE:-observability}"
ISTIO_NAMESPACE="${ISTIO_NAMESPACE:-istio-system}"
JAEGER_OPERATOR_VERSION="${JAEGER_OPERATOR_VERSION:-v1.51.0}"
ELASTICSEARCH_STORAGE="${ELASTICSEARCH_STORAGE:-100Gi}"
ELASTICSEARCH_REPLICAS="${ELASTICSEARCH_REPLICAS:-3}"
usage() {
echo "Usage: $SCRIPT_NAME [OPTIONS]"
echo "Configure Istio distributed tracing with Jaeger and Zipkin"
echo ""
echo "Options:"
echo " -n, --namespace NAMESPACE Elasticsearch namespace (default: observability)"
echo " -s, --storage SIZE Elasticsearch storage size (default: 100Gi)"
echo " -r, --replicas COUNT Elasticsearch replicas (default: 3)"
echo " -h, --help Show this help message"
echo ""
echo "Environment variables:"
echo " ELASTICSEARCH_NAMESPACE Override elasticsearch namespace"
echo " ISTIO_NAMESPACE Override istio namespace (default: istio-system)"
echo " ELASTICSEARCH_STORAGE Override storage size"
echo " ELASTICSEARCH_REPLICAS Override replica count"
}
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
cleanup() {
if [[ $? -ne 0 ]]; then
log_error "Installation failed. Cleaning up..."
kubectl delete namespace "$ELASTICSEARCH_NAMESPACE" --ignore-not-found=true 2>/dev/null || true
kubectl delete -f https://github.com/jaegertracing/jaeger-operator/releases/download/$JAEGER_OPERATOR_VERSION/jaeger-operator.yaml -n "$ELASTICSEARCH_NAMESPACE" --ignore-not-found=true 2>/dev/null || true
fi
}
trap cleanup ERR
check_prerequisites() {
log_info "[1/8] Checking prerequisites..."
if [[ $EUID -eq 0 ]]; then
log_error "Do not run this script as root. Use a user with kubectl access."
exit 1
fi
command -v kubectl >/dev/null 2>&1 || { log_error "kubectl is required but not installed"; exit 1; }
command -v curl >/dev/null 2>&1 || { log_error "curl is required but not installed"; exit 1; }
# Check kubectl cluster access
kubectl cluster-info >/dev/null 2>&1 || { log_error "Cannot connect to Kubernetes cluster"; exit 1; }
# Check if Istio is installed
kubectl get namespace "$ISTIO_NAMESPACE" >/dev/null 2>&1 || {
log_error "Istio namespace '$ISTIO_NAMESPACE' not found. Install Istio first."
exit 1
}
kubectl get deployment istiod -n "$ISTIO_NAMESPACE" >/dev/null 2>&1 || {
log_error "Istio control plane not found. Install Istio first."
exit 1
}
}
detect_distro() {
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
;;
*)
log_error "Unsupported distro: $ID"
exit 1
;;
esac
else
log_error "Cannot detect Linux distribution"
exit 1
fi
log_info "Detected distribution: $ID"
}
create_namespaces() {
log_info "[2/8] Creating namespaces..."
kubectl create namespace "$ELASTICSEARCH_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
log_info "Created/verified namespace: $ELASTICSEARCH_NAMESPACE"
}
deploy_elasticsearch() {
log_info "[3/8] Deploying Elasticsearch cluster..."
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
namespace: $ELASTICSEARCH_NAMESPACE
spec:
serviceName: elasticsearch
replicas: $ELASTICSEARCH_REPLICAS
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
ports:
- containerPort: 9200
name: http
- containerPort: 9300
name: transport
env:
- name: discovery.type
value: single-node
- name: cluster.name
value: jaeger-cluster
- name: network.host
value: "0.0.0.0"
- name: xpack.security.enabled
value: "false"
- name: ES_JAVA_OPTS
value: "-Xms2g -Xmx2g"
resources:
limits:
cpu: 2
memory: 4Gi
requests:
cpu: 500m
memory: 2Gi
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: $ELASTICSEARCH_STORAGE
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: $ELASTICSEARCH_NAMESPACE
spec:
selector:
app: elasticsearch
ports:
- port: 9200
targetPort: 9200
name: http
- port: 9300
targetPort: 9300
name: transport
EOF
log_info "Waiting for Elasticsearch to be ready..."
kubectl wait --for=condition=ready pod -l app=elasticsearch -n "$ELASTICSEARCH_NAMESPACE" --timeout=300s
}
install_jaeger_operator() {
log_info "[4/8] Installing Jaeger operator..."
kubectl apply -f "https://github.com/jaegertracing/jaeger-operator/releases/download/$JAEGER_OPERATOR_VERSION/jaeger-operator.yaml" -n "$ELASTICSEARCH_NAMESPACE"
log_info "Waiting for Jaeger operator to be ready..."
kubectl wait --for=condition=available deployment/jaeger-operator -n "$ELASTICSEARCH_NAMESPACE" --timeout=300s
}
configure_jaeger_production() {
log_info "[5/8] Configuring Jaeger production instance..."
cat <<EOF | kubectl apply -f -
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: jaeger-production
namespace: $ISTIO_NAMESPACE
spec:
strategy: production
storage:
type: elasticsearch
options:
es:
server-urls: http://elasticsearch.$ELASTICSEARCH_NAMESPACE.svc.cluster.local:9200
index-prefix: jaeger
esIndexCleaner:
enabled: true
numberOfDays: 7
schedule: "55 23 * * *"
query:
replicas: 2
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
collector:
replicas: 2
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 200m
memory: 256Mi
EOF
log_info "Waiting for Jaeger components to be ready..."
kubectl wait --for=condition=available deployment -l app.kubernetes.io/instance=jaeger-production -n "$ISTIO_NAMESPACE" --timeout=300s
}
deploy_zipkin() {
log_info "[6/8] Deploying Zipkin..."
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: zipkin
namespace: $ISTIO_NAMESPACE
labels:
app: zipkin
spec:
replicas: 2
selector:
matchLabels:
app: zipkin
template:
metadata:
labels:
app: zipkin
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: zipkin
image: openzipkin/zipkin:2.24
ports:
- containerPort: 9411
env:
- name: STORAGE_TYPE
value: elasticsearch
- name: ES_HOSTS
value: http://elasticsearch.$ELASTICSEARCH_NAMESPACE.svc.cluster.local:9200
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
---
apiVersion: v1
kind: Service
metadata:
name: zipkin
namespace: $ISTIO_NAMESPACE
labels:
app: zipkin
spec:
selector:
app: zipkin
ports:
- port: 9411
targetPort: 9411
name: http
EOF
kubectl wait --for=condition=available deployment/zipkin -n "$ISTIO_NAMESPACE" --timeout=300s
}
configure_istio_telemetry() {
log_info "[7/8] Configuring Istio telemetry..."
cat <<EOF | kubectl apply -f -
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: tracing-config
namespace: $ISTIO_NAMESPACE
spec:
meshConfig:
defaultConfig:
proxyStatsMatcher:
inclusionRegexps:
- ".*circuit_breakers.*"
- ".*upstream_rq_retry.*"
- ".*_cx_.*"
tracing:
sampling: 100.0
zipkin:
address: zipkin.$ISTIO_NAMESPACE.svc.cluster.local:9411
extensionProviders:
- name: jaeger
envoyOtelAls:
service: jaeger-production-collector.$ISTIO_NAMESPACE.svc.cluster.local
port: 14250
- name: zipkin
zipkin:
service: zipkin.$ISTIO_NAMESPACE.svc.cluster.local
port: 9411
EOF
}
verify_installation() {
log_info "[8/8] Verifying installation..."
# Check Elasticsearch
if kubectl get pods -l app=elasticsearch -n "$ELASTICSEARCH_NAMESPACE" | grep -q Running; then
log_info "✓ Elasticsearch is running"
else
log_error "✗ Elasticsearch is not running properly"
return 1
fi
# Check Jaeger
if kubectl get jaeger jaeger-production -n "$ISTIO_NAMESPACE" >/dev/null 2>&1; then
log_info "✓ Jaeger is configured"
else
log_error "✗ Jaeger configuration failed"
return 1
fi
# Check Zipkin
if kubectl get deployment zipkin -n "$ISTIO_NAMESPACE" >/dev/null 2>&1; then
log_info "✓ Zipkin is deployed"
else
log_error "✗ Zipkin deployment failed"
return 1
fi
log_info "Installation completed successfully!"
log_info ""
log_info "Access URLs (use kubectl port-forward):"
log_info " Jaeger UI: kubectl port-forward svc/jaeger-production-query -n $ISTIO_NAMESPACE 16686:16686"
log_info " Zipkin UI: kubectl port-forward svc/zipkin -n $ISTIO_NAMESPACE 9411:9411"
log_info " Elasticsearch: kubectl port-forward svc/elasticsearch -n $ELASTICSEARCH_NAMESPACE 9200:9200"
}
main() {
while [[ $# -gt 0 ]]; do
case $1 in
-n|--namespace)
ELASTICSEARCH_NAMESPACE="$2"
shift 2
;;
-s|--storage)
ELASTICSEARCH_STORAGE="$2"
shift 2
;;
-r|--replicas)
ELASTICSEARCH_REPLICAS="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
log_error "Unknown option: $1"
usage
exit 1
;;
esac
done
detect_distro
check_prerequisites
create_namespaces
deploy_elasticsearch
install_jaeger_operator
configure_jaeger_production
deploy_zipkin
configure_istio_telemetry
verify_installation
}
main "$@"
Review the script before running. Execute with: bash install.sh