diff --git a/src/content/core/divert.mdx b/src/content/core/divert.mdx
index ab4c4cbb2..e065936f0 100644
--- a/src/content/core/divert.mdx
+++ b/src/content/core/divert.mdx
@@ -20,6 +20,203 @@ Divert transforms how teams develop microservices by making selective service de
- **Reduce infrastructure costs**: Share expensive resources like databases and message queues across your team
- **Test against real services**: No more mocks or stubs for services you're not modifying
+## Getting Started with Divert
+
+This section provides a complete end-to-end guide for setting up and using Divert in your organization. Follow these steps in order for a successful implementation.
+
+### Step 1: Prerequisites Check
+
+Before enabling Divert, ensure you have:
+
+**For Administrators:**
+- Okteto self-hosted installation (version 1.31+)
+- Cluster admin access via `kubectl`
+- Helm 3.x installed
+- Decision on driver: nginx (default) or istio (if Istio already installed)
+
+**For Developers:**
+- Access to an Okteto instance with Divert enabled
+- Okteto CLI installed ([installation guide](../get-started/install-okteto-cli.mdx))
+- Git repository with your application's `okteto.yaml` manifest
+
+**Application Requirements:**
+- Microservice architecture with multiple services
+- Services that can propagate HTTP headers to downstream calls
+- A stable, complete deployment that can serve as the shared environment
+
+### Step 2: Set Up Shared Environment
+
+Create a shared namespace containing your complete application stack:
+
+```bash
+# Option 1: Deploy using Okteto CLI
+okteto deploy --namespace staging
+
+# Option 2: Use kubectl/helm directly
+kubectl create namespace staging
+helm install myapp ./chart --namespace staging
+```
+
+**Key considerations:**
+- Choose a memorable namespace name (e.g., `staging`, `shared`, `baseline`)
+- Deploy all services, databases, and dependencies
+- Ensure all services are healthy and accessible
+- This environment should be stable and updated regularly
+
+See [Setting Up Shared Environments](#setting-up-shared-environments) for detailed configuration options.
+
+### Step 3: Choose and Configure Driver
+
+**Option A: nginx Driver (Recommended)**
+
+The nginx driver is enabled by default. Install Linkerd for service-to-service routing:
+
+```bash
+# 1. Install Linkerd (Administrators only)
+curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
+linkerd install --crds | kubectl apply -f -
+linkerd install | kubectl apply -f -
+linkerd check
+
+# 2. Enable Linkerd in Okteto namespaces
+# Add to Okteto Helm values:
+namespace:
+ annotations:
+ linkerd.io/inject: enabled
+```
+
+**Option B: istio Driver (If Istio Already Installed)**
+
+Configure Okteto to use Istio:
+
+```yaml
+# Okteto Helm values
+okteto-nginx:
+ enabled: false
+
+virtualServices:
+ enabled: true
+
+namespace:
+ labels:
+ istio-injection: enabled
+```
+
+See [Self-Hosted Configuration](../self-hosted/install/divert/index.mdx) for complete admin setup.
+
+### Step 4: Configure Your Application
+
+Update your `okteto.yaml` to enable Divert:
+
+```yaml
+build:
+ frontend:
+ context: ./frontend
+
+deploy:
+ commands:
+ # Deploy only the service(s) you're modifying
+ - helm upgrade --install frontend ./charts/frontend
+ --set image=${OKTETO_BUILD_FRONTEND_IMAGE}
+
+ # Enable Divert and point to shared environment
+ divert:
+ driver: nginx # or 'istio' if using Istio
+ namespace: ${OKTETO_SHARED_NAMESPACE:-staging}
+```
+
+**Key configuration:**
+- `divert.namespace`: Points to your shared environment
+- `divert.driver`: Matches your cluster configuration (nginx or istio)
+- `deploy.commands`: Only deploy services you're actively changing
+
+### Step 5: Implement Header Propagation
+
+Update your application code to propagate the `baggage` header:
+
+**Example (Node.js/Express):**
+```javascript
+app.use((req, res, next) => {
+ req.baggage = req.headers['baggage'];
+ next();
+});
+
+// In your service calls
+fetch('http://api-service/endpoint', {
+ headers: { 'baggage': req.baggage }
+});
+```
+
+See [Using Divert](../development/using-divert.mdx#header-propagation) for language-specific examples.
+
+### Step 6: Deploy Your First Diverted Environment
+
+Deploy your personal development environment:
+
+```bash
+# Deploy with Divert enabled
+okteto deploy
+
+# Okteto will:
+# 1. Deploy only your modified service(s)
+# 2. Create an ingress with header injection
+# 3. Provide a unique URL for your environment
+```
+
+You'll receive a URL like: `https://frontend-alice-myapp.okteto.example.com`
+
+### Step 7: Verify Divert is Working
+
+Test that traffic routing works correctly:
+
+**1. Check your deployed service:**
+```bash
+okteto namespace alice-myapp
+kubectl get pods
+# Should show only your modified service(s), not the full stack
+```
+
+**2. Verify sidecar injection (nginx driver):**
+```bash
+kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+# Should show 'linkerd-proxy' alongside your application container
+```
+
+**3. Test routing with the baggage header:**
+```bash
+# Test your endpoint
+curl https://frontend-alice-myapp.okteto.example.com
+
+# Test the shared environment
+curl https://frontend-staging-myapp.okteto.example.com
+
+# Verify different responses (yours vs. shared)
+```
+
+**4. Check service-to-service routing:**
+```bash
+# Exec into your pod and test downstream services
+kubectl exec -it deployment/frontend -- curl http://api-service/health
+# Should successfully reach the shared service
+```
+
+### Step 8: Develop and Iterate
+
+With Divert working, you can now:
+
+1. **Make changes** to your service locally
+2. **Deploy updates** with `okteto deploy`
+3. **Test immediately** using your personal URL
+4. **Share with teammates** - they can access your URL to review
+5. **Work in parallel** - other developers can work on different services
+
+### Next Steps
+
+- **[How Divert Works](#how-divert-works)** - Deep dive into architecture and routing
+- **[Divert Tutorial](/docs/tutorials/divert)** - Hands-on walkthrough with sample app
+- **[Using Divert](../development/using-divert.mdx)** - Implementation patterns and best practices
+- **[Troubleshooting](#troubleshooting)** - Common issues and solutions
+
## How Divert Works
Divert creates lightweight development environments containing only your modified services, then intelligently routes traffic between your services and shared infrastructure based on HTTP headers.
@@ -36,7 +233,7 @@ Divert creates lightweight development environments containing only your modifie
### Traffic Routing Mechanism
-Divert uses the W3C Trace Context standard `baggage` header for routing decisions:
+Divert uses the [W3C Trace Context standard `baggage` header](https://www.w3.org/TR/baggage/) for routing decisions:
```
baggage: okteto-divert=alice-feature
@@ -56,17 +253,17 @@ Consider a Movies application with multiple microservices. Alice is working on t
graph TB
User[User Request]
Frontend["Frontend (React)
Alice's personal version"]
- Catalog[Catalog Service]
API[API Gateway]
+ Catalog[Catalog Service]
Rent[Rent Service]
MongoDB[(MongoDB)]
PostgreSQL[(PostgreSQL)]
Kafka[(Kafka)]
User --> Frontend
- Frontend --> Catalog
Frontend --> API
- Frontend --> Rent
+ API --> Catalog
+ API --> Rent
Catalog --> MongoDB
API --> PostgreSQL
Rent --> Kafka
@@ -76,7 +273,7 @@ graph TB
classDef infrastructure fill:#f5f5f5,stroke:#ccc,color:#000
class Frontend personal
- class Catalog,API,Rent shared
+ class API,Catalog,Rent shared
class MongoDB,PostgreSQL,Kafka infrastructure
```
@@ -87,13 +284,141 @@ graph TB
Alice doesn't need to deploy or manage the catalog service, rent service, API gateway, MongoDB, PostgreSQL, or Kafka. Divert handles all the routing transparently.
+## Setting Up Shared Environments
+
+For Divert to work effectively, you need a shared namespace containing a complete, stable deployment of your application. This serves as the "baseline" environment that all developers' diverted namespaces will fall back to.
+
+### Shared Namespace Recommendations
+
+**Creating the Shared Namespace:**
+
+You have two primary options for creating shared namespaces:
+
+1. **Global Preview Namespace** (Recommended for most teams)
+ - Created via Okteto's preview environment system
+ - Automatically managed by Okteto
+ - Good for teams with CI/CD pipelines
+ - Requires: Configure preview automation in your repository
+
+2. **Regular Namespace**
+ - Standard Okteto namespace deployed manually or via CI
+ - More control over deployment timing
+ - Good for stable staging/demo environments
+ - Requires: Manual deployment management
+
+:::info Access Requirements
+All developers need **read access** to the shared namespace services for Divert routing to work. Configure namespace permissions to ensure team members can access shared resources without deployment permissions.
+:::
+
+### Infrastructure Configuration Options
+
+When setting up your shared environment, you can configure databases and message queues in two ways:
+
+#### Option 1: Shared Infrastructure (Most Common)
+
+Databases and queues remain in the shared namespace, accessed by all developers:
+
+```yaml
+# In shared namespace (e.g., staging)
+deploy:
+ commands:
+ - helm upgrade --install postgresql bitnami/postgresql
+ - helm upgrade --install kafka bitnami/kafka
+ - helm upgrade --install frontend chart/ --set image=${FRONTEND_IMAGE}
+ - helm upgrade --install api chart/ --set image=${API_IMAGE}
+```
+
+**Benefits:**
+- Shared test data across all developers
+- Lower resource usage per developer
+- Simpler configuration
+- Best for stable database schemas
+
+**Use when:**
+- Database schemas are stable
+- Test data can be shared
+- You want minimal resource overhead
+
+#### Option 2: Isolated Databases (Per Developer)
+
+Each developer deploys their own database instances in their personal namespace:
+
+```yaml
+# In developer namespace (e.g., alice-feature)
+dependencies:
+ postgresql:
+ repository: https://github.com/okteto/postgresql
+ wait: true
+
+deploy:
+ commands:
+ # Deploy local database
+ - helm upgrade --install postgresql bitnami/postgresql
+ # Deploy only services you're modifying
+ - helm upgrade --install api chart/ --set image=${OKTETO_BUILD_API_IMAGE}
+ divert:
+ namespace: staging
+```
+
+**Benefits:**
+- Full control over test data
+- Can modify schemas without affecting others
+- Great for testing migrations
+- Can use [volume snapshots](use-volume-snapshots.mdx) for fast database cloning
+
+**Use when:**
+- Testing database migrations
+- Need isolated test data
+- Schema changes are frequent
+- Working with sensitive data
+
+:::tip Hybrid Approach
+You can mix both patterns: share stable databases (e.g., user accounts) while running isolated databases for services under active development (e.g., new feature schemas).
+:::
+
+### Linkerd Configuration for Shared Namespaces
+
+When using the nginx driver, **Linkerd must be installed and configured** in both your shared namespace and developer namespaces for service-to-service routing to work.
+
+**Key Requirements:**
+- Linkerd sidecar injection must be enabled in the shared namespace
+- All services in the shared namespace need Linkerd sidecars
+- Developer namespaces automatically inherit Linkerd configuration
+
+See the [Linkerd Installation Guide](../self-hosted/install/divert/linkerd-installation.mdx) for detailed setup instructions.
+
+### Verifying Your Shared Environment
+
+Before developers start using Divert, verify your shared namespace is correctly configured:
+
+1. **Check all services are running:**
+ ```bash
+ kubectl get pods -n staging
+ ```
+
+2. **Verify Linkerd sidecars (nginx driver only):**
+ ```bash
+ kubectl get pods -n staging -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+ ```
+ Each pod should show both application and `linkerd-proxy` containers
+
+3. **Test service connectivity:**
+ ```bash
+ kubectl exec -n staging deployment/frontend -- curl http://api-service/health
+ ```
+
+4. **Confirm ingress is accessible:**
+ ```bash
+ curl https://staging-yourapp.okteto.example.com
+ ```
+
## Divert Drivers
Okteto supports two implementations of Divert to accommodate different infrastructure setups:
| Driver | Use Case | Requirements |
|--------|----------|--------------|
-| **nginx** (default) | Standard Okteto installations | Uses Okteto's built-in nginx ingress with optional Linkerd for service mesh |
+| **nginx** (default) | Standard Okteto installations | Uses Okteto's built-in nginx ingress. **Requires Linkerd** for service-to-service routing |
| **istio** | Environments with existing Istio service mesh | Requires Istio installation (non-default Okteto configuration) |
Both drivers provide the same developer experience and use the same `okteto.yaml` configuration. The difference is in the underlying routing technology.
@@ -107,7 +432,7 @@ Both drivers now use the same baggage header format: `baggage: okteto-divert= -o jsonpath='{.metadata.annotations}'
+```
+
+Should include: `linkerd.io/inject: enabled`
+
+**Verify Linkerd sidecars are running:**
+```bash
+kubectl get pods -n -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+```
+
+Each pod should show both your application container and `linkerd-proxy`.
+
+**Force sidecar injection:**
+```bash
+# Restart all deployments to trigger injection
+kubectl rollout restart deployment -n
+```
+
+### Ingress Controller Issues
+
+**Check nginx ingress controller status (nginx driver):**
+```bash
+kubectl get pods -n okteto
+# Should see okteto-nginx pods in Running state
+```
+
+**Verify ingress rules are created:**
+```bash
+kubectl get ingress -n
+# Should show ingress for your service with divert annotations
+```
+
+**Check ingress logs for errors:**
+```bash
+kubectl logs -n okteto deployment/okteto-nginx -f
+```
+
+### Linkerd Deployment Verification
+
+**Check Linkerd control plane (nginx driver):**
+```bash
+# Using Linkerd CLI
+linkerd check
+
+# Or using kubectl
+kubectl get deployments -n linkerd
+# Should show: linkerd-destination, linkerd-identity, linkerd-proxy-injector
+```
+
+**Verify Linkerd is routing traffic:**
+```bash
+# Watch traffic flow
+linkerd viz tap deployment/ --namespace
+```
+
+**Check ServiceProfiles (if configured):**
+```bash
+kubectl get serviceprofiles -n
+```
+
+### Header Propagation Problems
+
+**Test header is being injected at ingress:**
+```bash
+curl -v https://your-app.okteto.example.com 2>&1 | grep -i baggage
+# Should see: baggage: okteto-divert=
+```
+
+**Verify header format:**
+```bash
+# Correct format
+baggage: okteto-divert=alice-feature
+
+# Incorrect formats (won't work)
+baggage.okteto-divert=alice-feature
+okteto-divert: alice-feature
+```
+
+**Check application code propagates headers:**
+- Review service code to ensure `baggage` header is forwarded in all HTTP/gRPC calls
+- Add logging to verify header presence at each service boundary
+- Use distributed tracing to follow header through the call chain
+
+**Test service-to-service routing:**
+```bash
+# Exec into your pod and test with header
+kubectl exec -it deployment/your-service -- \
+ curl -H "baggage: okteto-divert=your-namespace" \
+ http://downstream-service/api/endpoint
+```
+
+### Traffic Not Being Diverted
+
+**Verify divert configuration in okteto.yaml:**
+```yaml
+deploy:
+ divert:
+ namespace: staging # Must match your shared namespace exactly
+ driver: nginx # Must match cluster configuration
+```
+
+**Check namespace exists and is healthy:**
+```bash
+kubectl get namespaces | grep staging
+kubectl get pods -n staging
+# All pods should be Running
+```
+
+**Test DNS resolution:**
+```bash
+kubectl exec -it deployment/your-service -- \
+ nslookup api-service.staging.svc.cluster.local
+# Should resolve to service IP
+```
+
+**Verify network policies allow traffic:**
+```bash
+kubectl get networkpolicies -n staging
+kubectl get networkpolicies -n
+# Ensure policies allow cross-namespace communication
+```
+
+### Services Not Discovered
+
+**Check service names and DNS:**
+```bash
+# Services should be accessible at
+..svc.cluster.local
+
+# Test resolution
+kubectl exec -it deployment/your-service -- \
+ nslookup api-service.staging.svc.cluster.local
+```
+
+**Verify shared environment services are running:**
+```bash
+kubectl get services -n staging
+kubectl get endpoints -n staging
+# Endpoints should show pod IPs
+```
+
+### Common Configuration Mistakes
+
+1. **Wrong namespace in divert config**: Namespace name must exactly match the shared environment
+2. **Missing Linkerd on shared namespace**: Both personal and shared namespaces need Linkerd sidecars
+3. **Forgot to propagate headers**: Application code must forward the `baggage` header
+4. **Driver mismatch**: Manifest specifies `istio` but cluster uses `nginx` (or vice versa)
+5. **Network policies blocking traffic**: Ensure cross-namespace communication is allowed
+
+### Getting Help
+
+If issues persist after trying these steps:
+
+1. **Check Okteto logs:**
+ ```bash
+ kubectl logs -n okteto deployment/okteto-api
+ ```
+
+2. **Review pod events:**
+ ```bash
+ kubectl describe pod -n
+ ```
+
+3. **Enable debug logging:** Add to your `okteto.yaml`:
+ ```yaml
+ deploy:
+ divert:
+ namespace: staging
+ debug: true # Enables verbose routing logs
+ ```
+
+4. **Consult documentation:**
+ - [Using Divert](../development/using-divert.mdx#troubleshooting) - Developer troubleshooting
+ - [Linkerd Installation](../self-hosted/install/divert/linkerd-installation.mdx#troubleshooting) - Admin troubleshooting
+ - [Configure Divert](../self-hosted/install/divert/index.mdx#troubleshooting) - Driver configuration issues
+
## Next Steps
- **[Using Divert](../development/using-divert.mdx)** - Implementation details, manifest configuration, and code patterns
diff --git a/src/content/development/using-divert.mdx b/src/content/development/using-divert.mdx
index 3f4f92c6e..f94801e51 100644
--- a/src/content/development/using-divert.mdx
+++ b/src/content/development/using-divert.mdx
@@ -365,23 +365,181 @@ Others can access your diverted environment using:
## Troubleshooting
+This section covers common issues developers encounter when using Divert. For admin-level troubleshooting, see [Configure Divert](../self-hosted/install/divert/index.mdx#troubleshooting).
+
+### Verify Sidecar Injection (nginx driver)
+
+**Check if Linkerd sidecar is running:**
+```bash
+kubectl get pods -n -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+```
+
+Should show both your application container and `linkerd-proxy`.
+
+**If sidecar is missing:**
+```bash
+# Check namespace annotation
+kubectl get namespace -o jsonpath='{.metadata.annotations}'
+
+# Restart deployment to trigger injection
+kubectl rollout restart deployment/ -n
+```
+
+### Check Ingress Controller
+
+**Verify ingress is created:**
+```bash
+kubectl get ingress -n
+```
+
+Should show your service ingress with divert annotations.
+
+**Check ingress controller logs:**
+```bash
+kubectl logs -n okteto deployment/okteto-nginx -f | grep
+```
+
+### Verify Linkerd Deployment (nginx driver)
+
+**Check Linkerd control plane:**
+```bash
+# Quick health check
+linkerd check
+
+# Or manually verify deployments
+kubectl get deployments -n linkerd
+```
+
+**Watch traffic flow:**
+```bash
+linkerd viz tap deployment/ --namespace
+```
+
+### Header Propagation Issues
+
+**Test header at ingress:**
+```bash
+curl -v https://your-app.okteto.example.com 2>&1 | grep -i baggage
+# Should see: baggage: okteto-divert=
+```
+
+**Verify header format:**
+```bash
+# ✅ Correct
+baggage: okteto-divert=alice-feature
+
+# ❌ Incorrect
+baggage.okteto-divert=alice-feature
+okteto-divert: alice-feature
+```
+
+**Check application code:**
+- Ensure all services propagate the `baggage` header to downstream calls
+- Add logging at service boundaries: `console.log('Baggage header:', req.headers['baggage'])`
+- Verify header exists in: HTTP clients, gRPC calls, message queue producers
+
+**Test service-to-service routing:**
+```bash
+kubectl exec -it deployment/ -n -- \
+ curl -H "baggage: okteto-divert=" \
+ http://api-service/endpoint
+```
+
### Traffic Not Being Diverted
1. **Check header format**: Ensure you're using `baggage: okteto-divert=` (not `baggage.okteto-divert`)
2. **Verify header propagation**: All services in the call chain must forward the baggage header
3. **Check namespace name**: The namespace in the header must match your Okteto namespace exactly
+4. **Verify divert config**: In your `okteto.yaml`:
+ ```yaml
+ deploy:
+ divert:
+ namespace: staging # Must match shared environment
+ driver: nginx # Must match cluster config
+ ```
### Services Not Discovered
1. **Verify shared namespace**: Ensure the shared namespace is running and healthy
-2. **Check service names**: Service discovery uses Kubernetes DNS (`..svc.cluster.local`)
+ ```bash
+ kubectl get pods -n staging
+ # All pods should be Running
+ ```
+
+2. **Check service names**: Service discovery uses Kubernetes DNS
+ ```bash
+ # Services are accessible at:
+ ..svc.cluster.local
+
+ # Test DNS resolution:
+ kubectl exec -it deployment/ -- \
+ nslookup api-service.staging.svc.cluster.local
+ ```
+
3. **Review divert config**: Ensure `divert.namespace` points to the correct shared environment
+4. **Check network policies**:
+ ```bash
+ kubectl get networkpolicies -n staging
+ kubectl get networkpolicies -n
+ # Ensure cross-namespace communication is allowed
+ ```
+
### Database Connection Issues
1. **Check connection strings**: Ensure they resolve to the correct database (shared vs. local)
+ ```bash
+ # For shared database:
+ postgresql.staging.svc.cluster.local
+
+ # For local database:
+ postgresql..svc.cluster.local
+ ```
+
2. **Verify network policies**: Ensure cross-namespace communication is allowed
+ ```bash
+ # Test connectivity
+ kubectl exec -it deployment/ -n -- \
+ nc -zv postgresql.staging.svc.cluster.local 5432
+ ```
+
3. **Test connectivity**: Use `kubectl exec` to test database connectivity from your pod
+ ```bash
+ kubectl exec -it deployment/ -n -- \
+ psql -h postgresql.staging.svc.cluster.local -U user -d database
+ ```
+
+### Quick Diagnostic Checklist
+
+Run through this checklist when troubleshooting:
+
+- [ ] Linkerd sidecars are running in your pods (nginx driver)
+- [ ] Ingress is created with correct annotations
+- [ ] Shared namespace exists and all services are Running
+- [ ] Header format is correct: `baggage: okteto-divert=`
+- [ ] Application code propagates headers to all downstream calls
+- [ ] DNS resolves shared services: `.staging.svc.cluster.local`
+- [ ] Network policies allow cross-namespace traffic
+- [ ] `divert.namespace` in okteto.yaml matches shared environment
+
+### Getting Additional Help
+
+If issues persist:
+
+1. **Check pod logs**:
+ ```bash
+ kubectl logs deployment/ -n
+ ```
+
+2. **Review pod events**:
+ ```bash
+ kubectl describe pod -n
+ ```
+
+3. **Consult related documentation**:
+ - [Divert Core Concepts](../core/divert.mdx#troubleshooting) - Architecture and setup troubleshooting
+ - [Configure Divert](../self-hosted/install/divert/index.mdx#troubleshooting) - Admin configuration issues
+ - [Linkerd Installation](../self-hosted/install/divert/linkerd-installation.mdx#troubleshooting) - Service mesh issues
## Best Practices
diff --git a/src/content/self-hosted/install/divert/index.mdx b/src/content/self-hosted/install/divert/index.mdx
index f8929fcb7..e35886de5 100644
--- a/src/content/self-hosted/install/divert/index.mdx
+++ b/src/content/self-hosted/install/divert/index.mdx
@@ -18,9 +18,9 @@ Okteto supports two drivers for Divert routing:
:::info Important Distinction
**Istio and Linkerd serve different purposes:**
- **Istio** is a **divert driver** - an alternative to the nginx driver for environments already using Istio
-- **Linkerd** is an **optional enhancement** for the **nginx driver** - it adds service mesh capabilities to nginx-based routing
+- **Linkerd** is **required for the nginx driver** - it provides service mesh capabilities for service-to-service routing
- You **cannot** use both Istio driver and Linkerd together
-- Choose one: nginx driver (with optional Linkerd) **OR** istio driver
+- Choose one: nginx driver (requires Linkerd) **OR** istio driver
:::
## nginx Driver (Default)
@@ -30,24 +30,29 @@ The nginx driver is enabled by default in Okteto installations. It uses the `okt
### Requirements
- Standard Okteto installation (no additional configuration needed)
-- Optional: [Linkerd service mesh](linkerd-installation.mdx) for enhanced service-to-service routing
+- **Required**: [Linkerd service mesh](linkerd-installation.mdx) for service-to-service routing
### How It Works
1. When a developer deploys with `divert` configuration, Okteto creates ingress rules that inject the baggage header
2. Requests through the developer's endpoint automatically include `baggage: okteto-divert=`
3. The nginx ingress controller routes requests to the appropriate namespace based on this header
-4. For service-to-service communication, applications must propagate the baggage header
+4. Linkerd's service mesh handles service-to-service routing based on the propagated baggage header
+5. Applications must propagate the baggage header for routing to work across service boundaries
-### Linkerd Integration (Optional)
+### Linkerd Integration (Required)
-For enhanced service mesh capabilities with the nginx driver, you can install Linkerd. This provides:
+For service-to-service routing with the nginx driver, Linkerd must be installed. Linkerd provides:
-- Header-based routing at the service mesh level
+- Header-based routing at the service mesh level for inter-service communication
- Automatic mTLS between services
- Advanced traffic management and observability
- Improved reliability with retries and circuit breaking
+:::warning Required Component
+While ingress-level routing works without Linkerd, **service-to-service routing requires Linkerd** to be installed. Without Linkerd, only external ingress traffic can be diverted, not internal service-to-service calls.
+:::
+
See [Linkerd Installation](linkerd-installation.mdx) for setup instructions.
## istio Driver
@@ -172,24 +177,246 @@ For complete network policy configuration options, see the [Helm Configuration r
## Troubleshooting
+This section covers admin-level troubleshooting for Divert configuration. For developer troubleshooting, see [Using Divert](../../../development/using-divert.mdx#troubleshooting).
+
+### Verify Sidecar Injection
+
+**Check namespace annotation (nginx driver with Linkerd):**
+```bash
+kubectl get namespace -o jsonpath='{.metadata.annotations}'
+```
+
+Should include: `linkerd.io/inject: enabled`
+
+**Check Istio sidecar injection (istio driver):**
+```bash
+kubectl get namespace -o jsonpath='{.metadata.labels}'
+```
+
+Should include: `istio-injection: enabled`
+
+**Verify sidecars are running:**
+```bash
+# For Linkerd
+kubectl get pods -n -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+
+# Should show linkerd-proxy or istio-proxy alongside application containers
+```
+
+### Check Ingress Controller Status
+
+**Verify ingress controller is running (nginx driver):**
+```bash
+kubectl get deployments -n okteto
+# Should see okteto-nginx deployment in Ready state
+
+kubectl get pods -n okteto -l app=okteto-nginx
+# All pods should be Running
+```
+
+**Check ingress controller logs:**
+```bash
+kubectl logs -n okteto deployment/okteto-nginx -f
+```
+
+**For Istio driver, check Istio ingress gateway:**
+```bash
+kubectl get pods -n istio-system -l app=istio-ingressgateway
+kubectl logs -n istio-system deployment/istio-ingressgateway -f
+```
+
+### Verify Linkerd Deployment (nginx driver)
+
+**Check Linkerd control plane health:**
+```bash
+# Using Linkerd CLI
+linkerd check
+
+# Manual verification
+kubectl get deployments -n linkerd
+# Should show: linkerd-destination, linkerd-identity, linkerd-proxy-injector
+
+kubectl get pods -n linkerd
+# All pods should be Running
+```
+
+**Verify Linkerd viz extension (for monitoring):**
+```bash
+linkerd viz check
+kubectl get deployments -n linkerd-viz
+```
+
+**Check ServiceProfiles (if configured):**
+```bash
+kubectl get serviceprofiles --all-namespaces
+```
+
+### Header Propagation Testing
+
+**Test ingress header injection:**
+```bash
+# Create a test deployment with divert
+curl -v https://test-app-namespace.okteto.example.com 2>&1 | grep -i baggage
+# Should see: baggage: okteto-divert=
+```
+
+**Verify header format:**
+```bash
+# Correct format
+baggage: okteto-divert=alice-feature
+
+# Incorrect formats
+baggage.okteto-divert=alice-feature # Wrong separator
+okteto-divert: alice-feature # Wrong header name
+```
+
+**Test service-to-service routing:**
+```bash
+# Deploy test pods in two namespaces
+kubectl run test-client -n dev --image=curlimages/curl --command -- sleep 3600
+kubectl run test-server -n staging --image=hashicorp/http-echo --command -- /http-echo -listen=:5678 -text="shared"
+
+# Test routing with header
+kubectl exec -it test-client -n dev -- \
+ curl -H "baggage: okteto-divert=dev" \
+ http://test-server.staging.svc.cluster.local:5678
+```
+
### Divert Not Working
1. **Check driver configuration**: Ensure the correct driver is installed and configured
+ ```bash
+ # For nginx driver
+ kubectl get deployment okteto-nginx -n okteto
+
+ # For istio driver
+ kubectl get deployment istiod -n istio-system
+ ```
+
2. **Verify header propagation**: Test with `curl -H "baggage: okteto-divert="` to confirm routing works
+
3. **Check namespace labels**: For Istio, verify `istio-injection: enabled` label exists
+ ```bash
+ kubectl get namespace -o yaml | grep -A 5 labels
+ ```
+
4. **Review ingress configuration**: Ensure ingress rules are being created correctly
+ ```bash
+ kubectl get ingress --all-namespaces
+ kubectl describe ingress -n
+ ```
+
+5. **Check Okteto configuration**:
+ ```bash
+ kubectl get configmap okteto-config -n okteto -o yaml
+ # Verify driver settings
+ ```
### VirtualServices Not Appearing (Istio)
1. Verify `virtualServices.enabled: true` in Helm values
+ ```bash
+ helm get values okteto -n okteto
+ ```
+
2. Check that Istio CRDs are installed
+ ```bash
+ kubectl get crd | grep istio
+ ```
+
3. Ensure the VirtualService is in a namespace managed by Okteto
+ ```bash
+ kubectl get virtualservices --all-namespaces
+ ```
+
+4. Check Okteto API logs for VirtualService creation:
+ ```bash
+ kubectl logs -n okteto deployment/okteto-api | grep -i virtualservice
+ ```
### Cross-Namespace Communication Failing
1. Check network policies allow the traffic (see [Network Policies section](#network-policies))
+ ```bash
+ kubectl get networkpolicies --all-namespaces
+ kubectl describe networkpolicy -n
+ ```
+
2. Verify DNS resolution works across namespaces
+ ```bash
+ kubectl run dns-test --image=busybox --rm -it -- \
+ nslookup service-name.namespace.svc.cluster.local
+ ```
+
3. Test direct pod-to-pod communication to isolate the issue
+ ```bash
+ # Get pod IPs
+ kubectl get pods -n namespace-a -o wide
+ kubectl get pods -n namespace-b -o wide
+
+ # Test connectivity
+ kubectl exec -it pod-in-namespace-a -- nc -zv 8080
+ ```
+
+4. Check if service mesh is blocking traffic:
+ ```bash
+ # For Linkerd
+ linkerd viz tap deployment/ -n
+
+ # For Istio
+ istioctl proxy-status
+ ```
+
+### Common Configuration Issues
+
+1. **Linkerd not installed**: Required for nginx driver
+ ```bash
+ linkerd version
+ # Should show both client and server versions
+ ```
+
+2. **Wrong driver in okteto.yaml**: Manifest specifies different driver than cluster
+ ```bash
+ # Check what user specified
+ cat okteto.yaml | grep -A 2 divert
+
+ # Check cluster configuration
+ kubectl get configmap okteto-config -n okteto -o yaml
+ ```
+
+3. **Network policies too restrictive**: Blocking cross-namespace traffic
+ ```bash
+ # Temporarily disable to test
+ kubectl delete networkpolicy -n
+ ```
+
+4. **Istio and Linkerd both installed**: Cannot use both together
+ ```bash
+ kubectl get namespaces -o custom-columns=NAME:.metadata.name,ISTIO:.metadata.labels.istio-injection,LINKERD:.metadata.annotations.linkerd\\.io/inject
+ ```
+
+### Getting Help
+
+For persistent issues:
+
+1. **Collect diagnostic information**:
+ ```bash
+ kubectl logs -n okteto deployment/okteto-api > okteto-api.log
+ kubectl logs -n okteto deployment/okteto-nginx > okteto-nginx.log
+ linkerd check > linkerd-check.log # If using nginx driver
+ kubectl get all --all-namespaces > cluster-state.txt
+ ```
+
+2. **Enable debug logging** in Okteto Helm values:
+ ```yaml
+ api:
+ logLevel: debug
+ ```
+
+3. **Consult related documentation**:
+ - [Linkerd Installation](linkerd-installation.mdx#troubleshooting) - Linkerd-specific issues
+ - [Using Divert](../../../development/using-divert.mdx#troubleshooting) - Developer-side troubleshooting
+ - [Divert Core Concepts](../../../core/divert.mdx#troubleshooting) - Architecture and flow troubleshooting
## Next Steps
diff --git a/src/content/self-hosted/install/divert/linkerd-installation.mdx b/src/content/self-hosted/install/divert/linkerd-installation.mdx
index e937ef50e..5e9db90be 100644
--- a/src/content/self-hosted/install/divert/linkerd-installation.mdx
+++ b/src/content/self-hosted/install/divert/linkerd-installation.mdx
@@ -1,6 +1,6 @@
---
title: Linkerd Installation for Divert
-description: Install Linkerd to enhance Divert routing capabilities with the nginx driver
+description: Install Linkerd to enable Divert service-to-service routing with the nginx driver
sidebar_label: Linkerd Installation
---
@@ -8,14 +8,14 @@ sidebar_label: Linkerd Installation
This guide is for **Okteto administrators** setting up Linkerd in the cluster. Developers do not need to install anything - once Linkerd is configured in the cluster, Divert works transparently for all developers.
:::
-This guide covers installing Linkerd to enhance Divert's routing capabilities when using the nginx driver. Linkerd provides service mesh functionality that enables more sophisticated traffic routing based on HTTP headers.
+This guide covers installing Linkerd to enable Divert's service-to-service routing when using the nginx driver. Linkerd provides the service mesh functionality that enables traffic routing based on HTTP headers between services.
:::warning For nginx Driver Only
Linkerd is **only** for use with the **nginx driver**. If you're using the istio driver, do not install Linkerd - Istio already provides service mesh capabilities. See [Configure Divert](index.mdx) for the distinction between drivers.
:::
-:::info
-Linkerd is **optional** for the nginx driver. The basic Divert functionality works without it, but Linkerd enables enhanced service-to-service routing within the mesh.
+:::warning Required for nginx Driver
+Linkerd is **required** for service-to-service routing with the nginx driver. While Divert can route ingress traffic without Linkerd, service-to-service communication within the cluster requires Linkerd's service mesh capabilities.
:::
## Prerequisites
diff --git a/versioned_docs/version-1.40/core/divert.mdx b/versioned_docs/version-1.40/core/divert.mdx
index ab4c4cbb2..e065936f0 100644
--- a/versioned_docs/version-1.40/core/divert.mdx
+++ b/versioned_docs/version-1.40/core/divert.mdx
@@ -20,6 +20,203 @@ Divert transforms how teams develop microservices by making selective service de
- **Reduce infrastructure costs**: Share expensive resources like databases and message queues across your team
- **Test against real services**: No more mocks or stubs for services you're not modifying
+## Getting Started with Divert
+
+This section provides a complete end-to-end guide for setting up and using Divert in your organization. Follow these steps in order for a successful implementation.
+
+### Step 1: Prerequisites Check
+
+Before enabling Divert, ensure you have:
+
+**For Administrators:**
+- Okteto self-hosted installation (version 1.31+)
+- Cluster admin access via `kubectl`
+- Helm 3.x installed
+- Decision on driver: nginx (default) or istio (if Istio already installed)
+
+**For Developers:**
+- Access to an Okteto instance with Divert enabled
+- Okteto CLI installed ([installation guide](../get-started/install-okteto-cli.mdx))
+- Git repository with your application's `okteto.yaml` manifest
+
+**Application Requirements:**
+- Microservice architecture with multiple services
+- Services that can propagate HTTP headers to downstream calls
+- A stable, complete deployment that can serve as the shared environment
+
+### Step 2: Set Up Shared Environment
+
+Create a shared namespace containing your complete application stack:
+
+```bash
+# Option 1: Deploy using Okteto CLI
+okteto deploy --namespace staging
+
+# Option 2: Use kubectl/helm directly
+kubectl create namespace staging
+helm install myapp ./chart --namespace staging
+```
+
+**Key considerations:**
+- Choose a memorable namespace name (e.g., `staging`, `shared`, `baseline`)
+- Deploy all services, databases, and dependencies
+- Ensure all services are healthy and accessible
+- This environment should be stable and updated regularly
+
+See [Setting Up Shared Environments](#setting-up-shared-environments) for detailed configuration options.
+
+### Step 3: Choose and Configure Driver
+
+**Option A: nginx Driver (Recommended)**
+
+The nginx driver is enabled by default. Install Linkerd for service-to-service routing:
+
+```bash
+# 1. Install Linkerd (Administrators only)
+curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
+linkerd install --crds | kubectl apply -f -
+linkerd install | kubectl apply -f -
+linkerd check
+
+# 2. Enable Linkerd in Okteto namespaces
+# Add to Okteto Helm values:
+namespace:
+ annotations:
+ linkerd.io/inject: enabled
+```
+
+**Option B: istio Driver (If Istio Already Installed)**
+
+Configure Okteto to use Istio:
+
+```yaml
+# Okteto Helm values
+okteto-nginx:
+ enabled: false
+
+virtualServices:
+ enabled: true
+
+namespace:
+ labels:
+ istio-injection: enabled
+```
+
+See [Self-Hosted Configuration](../self-hosted/install/divert/index.mdx) for complete admin setup.
+
+### Step 4: Configure Your Application
+
+Update your `okteto.yaml` to enable Divert:
+
+```yaml
+build:
+ frontend:
+ context: ./frontend
+
+deploy:
+ commands:
+ # Deploy only the service(s) you're modifying
+ - helm upgrade --install frontend ./charts/frontend
+ --set image=${OKTETO_BUILD_FRONTEND_IMAGE}
+
+ # Enable Divert and point to shared environment
+ divert:
+ driver: nginx # or 'istio' if using Istio
+ namespace: ${OKTETO_SHARED_NAMESPACE:-staging}
+```
+
+**Key configuration:**
+- `divert.namespace`: Points to your shared environment
+- `divert.driver`: Matches your cluster configuration (nginx or istio)
+- `deploy.commands`: Only deploy services you're actively changing
+
+### Step 5: Implement Header Propagation
+
+Update your application code to propagate the `baggage` header:
+
+**Example (Node.js/Express):**
+```javascript
+app.use((req, res, next) => {
+ req.baggage = req.headers['baggage'];
+ next();
+});
+
+// In your service calls
+fetch('http://api-service/endpoint', {
+ headers: { 'baggage': req.baggage }
+});
+```
+
+See [Using Divert](../development/using-divert.mdx#header-propagation) for language-specific examples.
+
+### Step 6: Deploy Your First Diverted Environment
+
+Deploy your personal development environment:
+
+```bash
+# Deploy with Divert enabled
+okteto deploy
+
+# Okteto will:
+# 1. Deploy only your modified service(s)
+# 2. Create an ingress with header injection
+# 3. Provide a unique URL for your environment
+```
+
+You'll receive a URL like: `https://frontend-alice-myapp.okteto.example.com`
+
+### Step 7: Verify Divert is Working
+
+Test that traffic routing works correctly:
+
+**1. Check your deployed service:**
+```bash
+okteto namespace alice-myapp
+kubectl get pods
+# Should show only your modified service(s), not the full stack
+```
+
+**2. Verify sidecar injection (nginx driver):**
+```bash
+kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+# Should show 'linkerd-proxy' alongside your application container
+```
+
+**3. Test routing with the baggage header:**
+```bash
+# Test your endpoint
+curl https://frontend-alice-myapp.okteto.example.com
+
+# Test the shared environment
+curl https://frontend-staging-myapp.okteto.example.com
+
+# Verify different responses (yours vs. shared)
+```
+
+**4. Check service-to-service routing:**
+```bash
+# Exec into your pod and test downstream services
+kubectl exec -it deployment/frontend -- curl http://api-service/health
+# Should successfully reach the shared service
+```
+
+### Step 8: Develop and Iterate
+
+With Divert working, you can now:
+
+1. **Make changes** to your service locally
+2. **Deploy updates** with `okteto deploy`
+3. **Test immediately** using your personal URL
+4. **Share with teammates** - they can access your URL to review
+5. **Work in parallel** - other developers can work on different services
+
+### Next Steps
+
+- **[How Divert Works](#how-divert-works)** - Deep dive into architecture and routing
+- **[Divert Tutorial](/docs/tutorials/divert)** - Hands-on walkthrough with sample app
+- **[Using Divert](../development/using-divert.mdx)** - Implementation patterns and best practices
+- **[Troubleshooting](#troubleshooting)** - Common issues and solutions
+
## How Divert Works
Divert creates lightweight development environments containing only your modified services, then intelligently routes traffic between your services and shared infrastructure based on HTTP headers.
@@ -36,7 +233,7 @@ Divert creates lightweight development environments containing only your modifie
### Traffic Routing Mechanism
-Divert uses the W3C Trace Context standard `baggage` header for routing decisions:
+Divert uses the [W3C Trace Context standard `baggage` header](https://www.w3.org/TR/baggage/) for routing decisions:
```
baggage: okteto-divert=alice-feature
@@ -56,17 +253,17 @@ Consider a Movies application with multiple microservices. Alice is working on t
graph TB
User[User Request]
Frontend["Frontend (React)
Alice's personal version"]
- Catalog[Catalog Service]
API[API Gateway]
+ Catalog[Catalog Service]
Rent[Rent Service]
MongoDB[(MongoDB)]
PostgreSQL[(PostgreSQL)]
Kafka[(Kafka)]
User --> Frontend
- Frontend --> Catalog
Frontend --> API
- Frontend --> Rent
+ API --> Catalog
+ API --> Rent
Catalog --> MongoDB
API --> PostgreSQL
Rent --> Kafka
@@ -76,7 +273,7 @@ graph TB
classDef infrastructure fill:#f5f5f5,stroke:#ccc,color:#000
class Frontend personal
- class Catalog,API,Rent shared
+ class API,Catalog,Rent shared
class MongoDB,PostgreSQL,Kafka infrastructure
```
@@ -87,13 +284,141 @@ graph TB
Alice doesn't need to deploy or manage the catalog service, rent service, API gateway, MongoDB, PostgreSQL, or Kafka. Divert handles all the routing transparently.
+## Setting Up Shared Environments
+
+For Divert to work effectively, you need a shared namespace containing a complete, stable deployment of your application. This serves as the "baseline" environment that all developers' diverted namespaces will fall back to.
+
+### Shared Namespace Recommendations
+
+**Creating the Shared Namespace:**
+
+You have two primary options for creating shared namespaces:
+
+1. **Global Preview Namespace** (Recommended for most teams)
+ - Created via Okteto's preview environment system
+ - Automatically managed by Okteto
+ - Good for teams with CI/CD pipelines
+ - Requires: Configure preview automation in your repository
+
+2. **Regular Namespace**
+ - Standard Okteto namespace deployed manually or via CI
+ - More control over deployment timing
+ - Good for stable staging/demo environments
+ - Requires: Manual deployment management
+
+:::info Access Requirements
+All developers need **read access** to the shared namespace services for Divert routing to work. Configure namespace permissions to ensure team members can access shared resources without deployment permissions.
+:::
+
+### Infrastructure Configuration Options
+
+When setting up your shared environment, you can configure databases and message queues in two ways:
+
+#### Option 1: Shared Infrastructure (Most Common)
+
+Databases and queues remain in the shared namespace, accessed by all developers:
+
+```yaml
+# In shared namespace (e.g., staging)
+deploy:
+ commands:
+ - helm upgrade --install postgresql bitnami/postgresql
+ - helm upgrade --install kafka bitnami/kafka
+ - helm upgrade --install frontend chart/ --set image=${FRONTEND_IMAGE}
+ - helm upgrade --install api chart/ --set image=${API_IMAGE}
+```
+
+**Benefits:**
+- Shared test data across all developers
+- Lower resource usage per developer
+- Simpler configuration
+- Best for stable database schemas
+
+**Use when:**
+- Database schemas are stable
+- Test data can be shared
+- You want minimal resource overhead
+
+#### Option 2: Isolated Databases (Per Developer)
+
+Each developer deploys their own database instances in their personal namespace:
+
+```yaml
+# In developer namespace (e.g., alice-feature)
+dependencies:
+ postgresql:
+ repository: https://github.com/okteto/postgresql
+ wait: true
+
+deploy:
+ commands:
+ # Deploy local database
+ - helm upgrade --install postgresql bitnami/postgresql
+ # Deploy only services you're modifying
+ - helm upgrade --install api chart/ --set image=${OKTETO_BUILD_API_IMAGE}
+ divert:
+ namespace: staging
+```
+
+**Benefits:**
+- Full control over test data
+- Can modify schemas without affecting others
+- Great for testing migrations
+- Can use [volume snapshots](use-volume-snapshots.mdx) for fast database cloning
+
+**Use when:**
+- Testing database migrations
+- Need isolated test data
+- Schema changes are frequent
+- Working with sensitive data
+
+:::tip Hybrid Approach
+You can mix both patterns: share stable databases (e.g., user accounts) while running isolated databases for services under active development (e.g., new feature schemas).
+:::
+
+### Linkerd Configuration for Shared Namespaces
+
+When using the nginx driver, **Linkerd must be installed and configured** in both your shared namespace and developer namespaces for service-to-service routing to work.
+
+**Key Requirements:**
+- Linkerd sidecar injection must be enabled in the shared namespace
+- All services in the shared namespace need Linkerd sidecars
+- Developer namespaces automatically inherit Linkerd configuration
+
+See the [Linkerd Installation Guide](../self-hosted/install/divert/linkerd-installation.mdx) for detailed setup instructions.
+
+### Verifying Your Shared Environment
+
+Before developers start using Divert, verify your shared namespace is correctly configured:
+
+1. **Check all services are running:**
+ ```bash
+ kubectl get pods -n staging
+ ```
+
+2. **Verify Linkerd sidecars (nginx driver only):**
+ ```bash
+ kubectl get pods -n staging -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+ ```
+ Each pod should show both application and `linkerd-proxy` containers
+
+3. **Test service connectivity:**
+ ```bash
+ kubectl exec -n staging deployment/frontend -- curl http://api-service/health
+ ```
+
+4. **Confirm ingress is accessible:**
+ ```bash
+ curl https://staging-yourapp.okteto.example.com
+ ```
+
## Divert Drivers
Okteto supports two implementations of Divert to accommodate different infrastructure setups:
| Driver | Use Case | Requirements |
|--------|----------|--------------|
-| **nginx** (default) | Standard Okteto installations | Uses Okteto's built-in nginx ingress with optional Linkerd for service mesh |
+| **nginx** (default) | Standard Okteto installations | Uses Okteto's built-in nginx ingress. **Requires Linkerd** for service-to-service routing |
| **istio** | Environments with existing Istio service mesh | Requires Istio installation (non-default Okteto configuration) |
Both drivers provide the same developer experience and use the same `okteto.yaml` configuration. The difference is in the underlying routing technology.
@@ -107,7 +432,7 @@ Both drivers now use the same baggage header format: `baggage: okteto-divert= -o jsonpath='{.metadata.annotations}'
+```
+
+Should include: `linkerd.io/inject: enabled`
+
+**Verify Linkerd sidecars are running:**
+```bash
+kubectl get pods -n -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+```
+
+Each pod should show both your application container and `linkerd-proxy`.
+
+**Force sidecar injection:**
+```bash
+# Restart all deployments to trigger injection
+kubectl rollout restart deployment -n
+```
+
+### Ingress Controller Issues
+
+**Check nginx ingress controller status (nginx driver):**
+```bash
+kubectl get pods -n okteto
+# Should see okteto-nginx pods in Running state
+```
+
+**Verify ingress rules are created:**
+```bash
+kubectl get ingress -n
+# Should show ingress for your service with divert annotations
+```
+
+**Check ingress logs for errors:**
+```bash
+kubectl logs -n okteto deployment/okteto-nginx -f
+```
+
+### Linkerd Deployment Verification
+
+**Check Linkerd control plane (nginx driver):**
+```bash
+# Using Linkerd CLI
+linkerd check
+
+# Or using kubectl
+kubectl get deployments -n linkerd
+# Should show: linkerd-destination, linkerd-identity, linkerd-proxy-injector
+```
+
+**Verify Linkerd is routing traffic:**
+```bash
+# Watch traffic flow
+linkerd viz tap deployment/ --namespace
+```
+
+**Check ServiceProfiles (if configured):**
+```bash
+kubectl get serviceprofiles -n
+```
+
+### Header Propagation Problems
+
+**Test header is being injected at ingress:**
+```bash
+curl -v https://your-app.okteto.example.com 2>&1 | grep -i baggage
+# Should see: baggage: okteto-divert=
+```
+
+**Verify header format:**
+```bash
+# Correct format
+baggage: okteto-divert=alice-feature
+
+# Incorrect formats (won't work)
+baggage.okteto-divert=alice-feature
+okteto-divert: alice-feature
+```
+
+**Check application code propagates headers:**
+- Review service code to ensure `baggage` header is forwarded in all HTTP/gRPC calls
+- Add logging to verify header presence at each service boundary
+- Use distributed tracing to follow header through the call chain
+
+**Test service-to-service routing:**
+```bash
+# Exec into your pod and test with header
+kubectl exec -it deployment/your-service -- \
+ curl -H "baggage: okteto-divert=your-namespace" \
+ http://downstream-service/api/endpoint
+```
+
+### Traffic Not Being Diverted
+
+**Verify divert configuration in okteto.yaml:**
+```yaml
+deploy:
+ divert:
+ namespace: staging # Must match your shared namespace exactly
+ driver: nginx # Must match cluster configuration
+```
+
+**Check namespace exists and is healthy:**
+```bash
+kubectl get namespaces | grep staging
+kubectl get pods -n staging
+# All pods should be Running
+```
+
+**Test DNS resolution:**
+```bash
+kubectl exec -it deployment/your-service -- \
+ nslookup api-service.staging.svc.cluster.local
+# Should resolve to service IP
+```
+
+**Verify network policies allow traffic:**
+```bash
+kubectl get networkpolicies -n staging
+kubectl get networkpolicies -n
+# Ensure policies allow cross-namespace communication
+```
+
+### Services Not Discovered
+
+**Check service names and DNS:**
+```bash
+# Services should be accessible at
+..svc.cluster.local
+
+# Test resolution
+kubectl exec -it deployment/your-service -- \
+ nslookup api-service.staging.svc.cluster.local
+```
+
+**Verify shared environment services are running:**
+```bash
+kubectl get services -n staging
+kubectl get endpoints -n staging
+# Endpoints should show pod IPs
+```
+
+### Common Configuration Mistakes
+
+1. **Wrong namespace in divert config**: Namespace name must exactly match the shared environment
+2. **Missing Linkerd on shared namespace**: Both personal and shared namespaces need Linkerd sidecars
+3. **Forgot to propagate headers**: Application code must forward the `baggage` header
+4. **Driver mismatch**: Manifest specifies `istio` but cluster uses `nginx` (or vice versa)
+5. **Network policies blocking traffic**: Ensure cross-namespace communication is allowed
+
+### Getting Help
+
+If issues persist after trying these steps:
+
+1. **Check Okteto logs:**
+ ```bash
+ kubectl logs -n okteto deployment/okteto-api
+ ```
+
+2. **Review pod events:**
+ ```bash
+ kubectl describe pod -n
+ ```
+
+3. **Enable debug logging:** Add to your `okteto.yaml`:
+ ```yaml
+ deploy:
+ divert:
+ namespace: staging
+ debug: true # Enables verbose routing logs
+ ```
+
+4. **Consult documentation:**
+ - [Using Divert](../development/using-divert.mdx#troubleshooting) - Developer troubleshooting
+ - [Linkerd Installation](../self-hosted/install/divert/linkerd-installation.mdx#troubleshooting) - Admin troubleshooting
+ - [Configure Divert](../self-hosted/install/divert/index.mdx#troubleshooting) - Driver configuration issues
+
## Next Steps
- **[Using Divert](../development/using-divert.mdx)** - Implementation details, manifest configuration, and code patterns
diff --git a/versioned_docs/version-1.40/development/using-divert.mdx b/versioned_docs/version-1.40/development/using-divert.mdx
index 3f4f92c6e..f94801e51 100644
--- a/versioned_docs/version-1.40/development/using-divert.mdx
+++ b/versioned_docs/version-1.40/development/using-divert.mdx
@@ -365,23 +365,181 @@ Others can access your diverted environment using:
## Troubleshooting
+This section covers common issues developers encounter when using Divert. For admin-level troubleshooting, see [Configure Divert](../self-hosted/install/divert/index.mdx#troubleshooting).
+
+### Verify Sidecar Injection (nginx driver)
+
+**Check if Linkerd sidecar is running:**
+```bash
+kubectl get pods -n -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+```
+
+Should show both your application container and `linkerd-proxy`.
+
+**If sidecar is missing:**
+```bash
+# Check namespace annotation
+kubectl get namespace -o jsonpath='{.metadata.annotations}'
+
+# Restart deployment to trigger injection
+kubectl rollout restart deployment/ -n
+```
+
+### Check Ingress Controller
+
+**Verify ingress is created:**
+```bash
+kubectl get ingress -n
+```
+
+Should show your service ingress with divert annotations.
+
+**Check ingress controller logs:**
+```bash
+kubectl logs -n okteto deployment/okteto-nginx -f | grep
+```
+
+### Verify Linkerd Deployment (nginx driver)
+
+**Check Linkerd control plane:**
+```bash
+# Quick health check
+linkerd check
+
+# Or manually verify deployments
+kubectl get deployments -n linkerd
+```
+
+**Watch traffic flow:**
+```bash
+linkerd viz tap deployment/ --namespace
+```
+
+### Header Propagation Issues
+
+**Test header at ingress:**
+```bash
+curl -v https://your-app.okteto.example.com 2>&1 | grep -i baggage
+# Should see: baggage: okteto-divert=
+```
+
+**Verify header format:**
+```bash
+# ✅ Correct
+baggage: okteto-divert=alice-feature
+
+# ❌ Incorrect
+baggage.okteto-divert=alice-feature
+okteto-divert: alice-feature
+```
+
+**Check application code:**
+- Ensure all services propagate the `baggage` header to downstream calls
+- Add logging at service boundaries: `console.log('Baggage header:', req.headers['baggage'])`
+- Verify header exists in: HTTP clients, gRPC calls, message queue producers
+
+**Test service-to-service routing:**
+```bash
+kubectl exec -it deployment/ -n -- \
+ curl -H "baggage: okteto-divert=" \
+ http://api-service/endpoint
+```
+
### Traffic Not Being Diverted
1. **Check header format**: Ensure you're using `baggage: okteto-divert=` (not `baggage.okteto-divert`)
2. **Verify header propagation**: All services in the call chain must forward the baggage header
3. **Check namespace name**: The namespace in the header must match your Okteto namespace exactly
+4. **Verify divert config**: In your `okteto.yaml`:
+ ```yaml
+ deploy:
+ divert:
+ namespace: staging # Must match shared environment
+ driver: nginx # Must match cluster config
+ ```
### Services Not Discovered
1. **Verify shared namespace**: Ensure the shared namespace is running and healthy
-2. **Check service names**: Service discovery uses Kubernetes DNS (`..svc.cluster.local`)
+ ```bash
+ kubectl get pods -n staging
+ # All pods should be Running
+ ```
+
+2. **Check service names**: Service discovery uses Kubernetes DNS
+ ```bash
+ # Services are accessible at:
+ ..svc.cluster.local
+
+ # Test DNS resolution:
+ kubectl exec -it deployment/ -- \
+ nslookup api-service.staging.svc.cluster.local
+ ```
+
3. **Review divert config**: Ensure `divert.namespace` points to the correct shared environment
+4. **Check network policies**:
+ ```bash
+ kubectl get networkpolicies -n staging
+ kubectl get networkpolicies -n
+ # Ensure cross-namespace communication is allowed
+ ```
+
### Database Connection Issues
1. **Check connection strings**: Ensure they resolve to the correct database (shared vs. local)
+ ```bash
+ # For shared database:
+ postgresql.staging.svc.cluster.local
+
+ # For local database:
+ postgresql..svc.cluster.local
+ ```
+
2. **Verify network policies**: Ensure cross-namespace communication is allowed
+ ```bash
+ # Test connectivity
+ kubectl exec -it deployment/ -n -- \
+ nc -zv postgresql.staging.svc.cluster.local 5432
+ ```
+
3. **Test connectivity**: Use `kubectl exec` to test database connectivity from your pod
+ ```bash
+ kubectl exec -it deployment/ -n -- \
+ psql -h postgresql.staging.svc.cluster.local -U user -d database
+ ```
+
+### Quick Diagnostic Checklist
+
+Run through this checklist when troubleshooting:
+
+- [ ] Linkerd sidecars are running in your pods (nginx driver)
+- [ ] Ingress is created with correct annotations
+- [ ] Shared namespace exists and all services are Running
+- [ ] Header format is correct: `baggage: okteto-divert=`
+- [ ] Application code propagates headers to all downstream calls
+- [ ] DNS resolves shared services: `.staging.svc.cluster.local`
+- [ ] Network policies allow cross-namespace traffic
+- [ ] `divert.namespace` in okteto.yaml matches shared environment
+
+### Getting Additional Help
+
+If issues persist:
+
+1. **Check pod logs**:
+ ```bash
+ kubectl logs deployment/ -n
+ ```
+
+2. **Review pod events**:
+ ```bash
+ kubectl describe pod -n
+ ```
+
+3. **Consult related documentation**:
+ - [Divert Core Concepts](../core/divert.mdx#troubleshooting) - Architecture and setup troubleshooting
+ - [Configure Divert](../self-hosted/install/divert/index.mdx#troubleshooting) - Admin configuration issues
+ - [Linkerd Installation](../self-hosted/install/divert/linkerd-installation.mdx#troubleshooting) - Service mesh issues
## Best Practices
diff --git a/versioned_docs/version-1.40/self-hosted/install/divert/index.mdx b/versioned_docs/version-1.40/self-hosted/install/divert/index.mdx
index f8929fcb7..e35886de5 100644
--- a/versioned_docs/version-1.40/self-hosted/install/divert/index.mdx
+++ b/versioned_docs/version-1.40/self-hosted/install/divert/index.mdx
@@ -18,9 +18,9 @@ Okteto supports two drivers for Divert routing:
:::info Important Distinction
**Istio and Linkerd serve different purposes:**
- **Istio** is a **divert driver** - an alternative to the nginx driver for environments already using Istio
-- **Linkerd** is an **optional enhancement** for the **nginx driver** - it adds service mesh capabilities to nginx-based routing
+- **Linkerd** is **required for the nginx driver** - it provides service mesh capabilities for service-to-service routing
- You **cannot** use both Istio driver and Linkerd together
-- Choose one: nginx driver (with optional Linkerd) **OR** istio driver
+- Choose one: nginx driver (requires Linkerd) **OR** istio driver
:::
## nginx Driver (Default)
@@ -30,24 +30,29 @@ The nginx driver is enabled by default in Okteto installations. It uses the `okt
### Requirements
- Standard Okteto installation (no additional configuration needed)
-- Optional: [Linkerd service mesh](linkerd-installation.mdx) for enhanced service-to-service routing
+- **Required**: [Linkerd service mesh](linkerd-installation.mdx) for service-to-service routing
### How It Works
1. When a developer deploys with `divert` configuration, Okteto creates ingress rules that inject the baggage header
2. Requests through the developer's endpoint automatically include `baggage: okteto-divert=`
3. The nginx ingress controller routes requests to the appropriate namespace based on this header
-4. For service-to-service communication, applications must propagate the baggage header
+4. Linkerd's service mesh handles service-to-service routing based on the propagated baggage header
+5. Applications must propagate the baggage header for routing to work across service boundaries
-### Linkerd Integration (Optional)
+### Linkerd Integration (Required)
-For enhanced service mesh capabilities with the nginx driver, you can install Linkerd. This provides:
+For service-to-service routing with the nginx driver, Linkerd must be installed. Linkerd provides:
-- Header-based routing at the service mesh level
+- Header-based routing at the service mesh level for inter-service communication
- Automatic mTLS between services
- Advanced traffic management and observability
- Improved reliability with retries and circuit breaking
+:::warning Required Component
+While ingress-level routing works without Linkerd, **service-to-service routing requires Linkerd** to be installed. Without Linkerd, only external ingress traffic can be diverted, not internal service-to-service calls.
+:::
+
See [Linkerd Installation](linkerd-installation.mdx) for setup instructions.
## istio Driver
@@ -172,24 +177,246 @@ For complete network policy configuration options, see the [Helm Configuration r
## Troubleshooting
+This section covers admin-level troubleshooting for Divert configuration. For developer troubleshooting, see [Using Divert](../../../development/using-divert.mdx#troubleshooting).
+
+### Verify Sidecar Injection
+
+**Check namespace annotation (nginx driver with Linkerd):**
+```bash
+kubectl get namespace -o jsonpath='{.metadata.annotations}'
+```
+
+Should include: `linkerd.io/inject: enabled`
+
+**Check Istio sidecar injection (istio driver):**
+```bash
+kubectl get namespace -o jsonpath='{.metadata.labels}'
+```
+
+Should include: `istio-injection: enabled`
+
+**Verify sidecars are running:**
+```bash
+# For Linkerd
+kubectl get pods -n -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].name}{"\n"}{end}'
+
+# Should show linkerd-proxy or istio-proxy alongside application containers
+```
+
+### Check Ingress Controller Status
+
+**Verify ingress controller is running (nginx driver):**
+```bash
+kubectl get deployments -n okteto
+# Should see okteto-nginx deployment in Ready state
+
+kubectl get pods -n okteto -l app=okteto-nginx
+# All pods should be Running
+```
+
+**Check ingress controller logs:**
+```bash
+kubectl logs -n okteto deployment/okteto-nginx -f
+```
+
+**For Istio driver, check Istio ingress gateway:**
+```bash
+kubectl get pods -n istio-system -l app=istio-ingressgateway
+kubectl logs -n istio-system deployment/istio-ingressgateway -f
+```
+
+### Verify Linkerd Deployment (nginx driver)
+
+**Check Linkerd control plane health:**
+```bash
+# Using Linkerd CLI
+linkerd check
+
+# Manual verification
+kubectl get deployments -n linkerd
+# Should show: linkerd-destination, linkerd-identity, linkerd-proxy-injector
+
+kubectl get pods -n linkerd
+# All pods should be Running
+```
+
+**Verify Linkerd viz extension (for monitoring):**
+```bash
+linkerd viz check
+kubectl get deployments -n linkerd-viz
+```
+
+**Check ServiceProfiles (if configured):**
+```bash
+kubectl get serviceprofiles --all-namespaces
+```
+
+### Header Propagation Testing
+
+**Test ingress header injection:**
+```bash
+# Create a test deployment with divert
+curl -v https://test-app-namespace.okteto.example.com 2>&1 | grep -i baggage
+# Should see: baggage: okteto-divert=
+```
+
+**Verify header format:**
+```bash
+# Correct format
+baggage: okteto-divert=alice-feature
+
+# Incorrect formats
+baggage.okteto-divert=alice-feature # Wrong separator
+okteto-divert: alice-feature # Wrong header name
+```
+
+**Test service-to-service routing:**
+```bash
+# Deploy test pods in two namespaces
+kubectl run test-client -n dev --image=curlimages/curl --command -- sleep 3600
+kubectl run test-server -n staging --image=hashicorp/http-echo --command -- /http-echo -listen=:5678 -text="shared"
+
+# Test routing with header
+kubectl exec -it test-client -n dev -- \
+ curl -H "baggage: okteto-divert=dev" \
+ http://test-server.staging.svc.cluster.local:5678
+```
+
### Divert Not Working
1. **Check driver configuration**: Ensure the correct driver is installed and configured
+ ```bash
+ # For nginx driver
+ kubectl get deployment okteto-nginx -n okteto
+
+ # For istio driver
+ kubectl get deployment istiod -n istio-system
+ ```
+
2. **Verify header propagation**: Test with `curl -H "baggage: okteto-divert="` to confirm routing works
+
3. **Check namespace labels**: For Istio, verify `istio-injection: enabled` label exists
+ ```bash
+ kubectl get namespace -o yaml | grep -A 5 labels
+ ```
+
4. **Review ingress configuration**: Ensure ingress rules are being created correctly
+ ```bash
+ kubectl get ingress --all-namespaces
+ kubectl describe ingress -n
+ ```
+
+5. **Check Okteto configuration**:
+ ```bash
+ kubectl get configmap okteto-config -n okteto -o yaml
+ # Verify driver settings
+ ```
### VirtualServices Not Appearing (Istio)
1. Verify `virtualServices.enabled: true` in Helm values
+ ```bash
+ helm get values okteto -n okteto
+ ```
+
2. Check that Istio CRDs are installed
+ ```bash
+ kubectl get crd | grep istio
+ ```
+
3. Ensure the VirtualService is in a namespace managed by Okteto
+ ```bash
+ kubectl get virtualservices --all-namespaces
+ ```
+
+4. Check Okteto API logs for VirtualService creation:
+ ```bash
+ kubectl logs -n okteto deployment/okteto-api | grep -i virtualservice
+ ```
### Cross-Namespace Communication Failing
1. Check network policies allow the traffic (see [Network Policies section](#network-policies))
+ ```bash
+ kubectl get networkpolicies --all-namespaces
+ kubectl describe networkpolicy -n
+ ```
+
2. Verify DNS resolution works across namespaces
+ ```bash
+ kubectl run dns-test --image=busybox --rm -it -- \
+ nslookup service-name.namespace.svc.cluster.local
+ ```
+
3. Test direct pod-to-pod communication to isolate the issue
+ ```bash
+ # Get pod IPs
+ kubectl get pods -n namespace-a -o wide
+ kubectl get pods -n namespace-b -o wide
+
+ # Test connectivity
+ kubectl exec -it pod-in-namespace-a -- nc -zv 8080
+ ```
+
+4. Check if service mesh is blocking traffic:
+ ```bash
+ # For Linkerd
+ linkerd viz tap deployment/ -n
+
+ # For Istio
+ istioctl proxy-status
+ ```
+
+### Common Configuration Issues
+
+1. **Linkerd not installed**: Required for nginx driver
+ ```bash
+ linkerd version
+ # Should show both client and server versions
+ ```
+
+2. **Wrong driver in okteto.yaml**: Manifest specifies different driver than cluster
+ ```bash
+ # Check what user specified
+ cat okteto.yaml | grep -A 2 divert
+
+ # Check cluster configuration
+ kubectl get configmap okteto-config -n okteto -o yaml
+ ```
+
+3. **Network policies too restrictive**: Blocking cross-namespace traffic
+ ```bash
+ # Temporarily disable to test
+ kubectl delete networkpolicy -n
+ ```
+
+4. **Istio and Linkerd both installed**: Cannot use both together
+ ```bash
+ kubectl get namespaces -o custom-columns=NAME:.metadata.name,ISTIO:.metadata.labels.istio-injection,LINKERD:.metadata.annotations.linkerd\\.io/inject
+ ```
+
+### Getting Help
+
+For persistent issues:
+
+1. **Collect diagnostic information**:
+ ```bash
+ kubectl logs -n okteto deployment/okteto-api > okteto-api.log
+ kubectl logs -n okteto deployment/okteto-nginx > okteto-nginx.log
+ linkerd check > linkerd-check.log # If using nginx driver
+ kubectl get all --all-namespaces > cluster-state.txt
+ ```
+
+2. **Enable debug logging** in Okteto Helm values:
+ ```yaml
+ api:
+ logLevel: debug
+ ```
+
+3. **Consult related documentation**:
+ - [Linkerd Installation](linkerd-installation.mdx#troubleshooting) - Linkerd-specific issues
+ - [Using Divert](../../../development/using-divert.mdx#troubleshooting) - Developer-side troubleshooting
+ - [Divert Core Concepts](../../../core/divert.mdx#troubleshooting) - Architecture and flow troubleshooting
## Next Steps
diff --git a/versioned_docs/version-1.40/self-hosted/install/divert/linkerd-installation.mdx b/versioned_docs/version-1.40/self-hosted/install/divert/linkerd-installation.mdx
index e937ef50e..5e9db90be 100644
--- a/versioned_docs/version-1.40/self-hosted/install/divert/linkerd-installation.mdx
+++ b/versioned_docs/version-1.40/self-hosted/install/divert/linkerd-installation.mdx
@@ -1,6 +1,6 @@
---
title: Linkerd Installation for Divert
-description: Install Linkerd to enhance Divert routing capabilities with the nginx driver
+description: Install Linkerd to enable Divert service-to-service routing with the nginx driver
sidebar_label: Linkerd Installation
---
@@ -8,14 +8,14 @@ sidebar_label: Linkerd Installation
This guide is for **Okteto administrators** setting up Linkerd in the cluster. Developers do not need to install anything - once Linkerd is configured in the cluster, Divert works transparently for all developers.
:::
-This guide covers installing Linkerd to enhance Divert's routing capabilities when using the nginx driver. Linkerd provides service mesh functionality that enables more sophisticated traffic routing based on HTTP headers.
+This guide covers installing Linkerd to enable Divert's service-to-service routing when using the nginx driver. Linkerd provides the service mesh functionality that enables traffic routing based on HTTP headers between services.
:::warning For nginx Driver Only
Linkerd is **only** for use with the **nginx driver**. If you're using the istio driver, do not install Linkerd - Istio already provides service mesh capabilities. See [Configure Divert](index.mdx) for the distinction between drivers.
:::
-:::info
-Linkerd is **optional** for the nginx driver. The basic Divert functionality works without it, but Linkerd enables enhanced service-to-service routing within the mesh.
+:::warning Required for nginx Driver
+Linkerd is **required** for service-to-service routing with the nginx driver. While Divert can route ingress traffic without Linkerd, service-to-service communication within the cluster requires Linkerd's service mesh capabilities.
:::
## Prerequisites