> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo 1 Service Entries

> Control external egress in Istio using ServiceEntry and optional egress gateway, including REGISTRY_ONLY setup, VirtualService, Gateway, and DestinationRule examples

This lesson demonstrates how to control external egress traffic in Istio using ServiceEntry resources and (optionally) an Istio egress Gateway. You'll learn how to:

* Install Istio with a demo profile configured to `REGISTRY_ONLY` outbound policy so only hosts registered in Istio are reachable.
* Run a test pod and observe how an Envoy sidecar enforces egress restrictions.
* Create a ServiceEntry to allow `www.wikipedia.org`.
* Configure an egress Gateway, DestinationRule, and VirtualService to force traffic through the egress gateway and understand why the `mesh` gateway entry is required.

Note: Istio routing and egress control apply only to namespaces with sidecar injection enabled.

<Callout icon="lightbulb" color="#1CB2FE">
  Label any namespaces that should be managed by Istio (for example: `kubectl label namespace default istio-injection=enabled`) and recreate pods so the Envoy sidecar can be injected.
</Callout>

***

## Prerequisites

* A Kubernetes cluster (minikube, Kind, or cloud).
* curl and kubectl configured to talk to the cluster.
* istioctl (we use Istio 1.18.2 in examples below).

Refer to the Istio docs for platform-specific setup: [Istio documentation](https://istio.io/latest/docs/).

***

## 1. Install istioctl and prepare a demo profile

Download Istio and add `istioctl` to your PATH:

```bash theme={null}
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.18.2 sh -
cd istio-1.18.2
export PATH=$PWD/bin:$PATH
which istioctl
# /root/istio-1.18.2/bin/istioctl
```

Dump the `demo` profile into a YAML file for editing:

```bash theme={null}
istioctl profile dump demo -o yaml > demo.yaml
vim demo.yaml
```

Find the `meshConfig` section and set the outbound traffic policy to `REGISTRY_ONLY` so the mesh only allows egress to hosts known to Istio (via ServiceEntry):

```yaml theme={null}
meshConfig:
  outboundTrafficPolicy:
    mode: REGISTRY_ONLY
  accessLogFile: /dev/stdout
  defaultConfig:
    proxyMetadata: {}
```

Validate and install the customized profile:

```bash theme={null}
istioctl validate -f demo.yaml
istioctl install -f demo.yaml -y
# ✓ Istio core installed
# ✓ Istiod installed
# ✓ Egress gateways installed
# ✓ Ingress gateways installed
# ✓ Installation complete
```

Verify Istio system pods are running:

```bash theme={null}
kubectl get pods -n istio-system
# NAME                                           READY   STATUS    RESTARTS   AGE
# istio-egressgateway-...                        1/1     Running   0          28s
# istio-ingressgateway-...                       1/1     Running   0          28s
# istiod-...                                     1/1     Running   0          36s
```

***

## 2. Create a test pod and observe default egress behavior

Run a simple test pod with curl installed:

```bash theme={null}
kubectl run test --image=curlimages/curl:8.1.2 --restart=Never --command -- sleep 3600
kubectl exec -ti test -- /bin/sh
```

From inside the pod, curl Wikipedia to verify normal internet access (no sidecar injected yet):

```bash theme={null}
curl --head -L http://www.wikipedia.org
```

Example (truncated) response headers:

```text theme={null}
HTTP/1.1 301 Moved Permanently
location: https://www.wikipedia.org/

HTTP/2 200
content-type: text/html
...
```

At this stage the pod runs without an Envoy sidecar (namespace not labeled), so it reaches the internet normally.

***

## 3. Enable sidecar injection and observe REGISTRY\_ONLY effect

Label the namespace for automatic sidecar injection (using the `default` namespace in this guide), restart the pod, and confirm the sidecar is injected:

```bash theme={null}
kubectl label namespace default istio-injection=enabled
kubectl delete pod test
kubectl run test --image=curlimages/curl:8.1.2 --restart=Never --command -- sleep 3600
kubectl get pods
# test     0/2     PodInitializing
# test     2/2     Running
```

Enter the pod and attempt to curl Wikipedia again:

```bash theme={null}
kubectl exec -ti test -- /bin/sh
curl --head -L http://www.wikipedia.org
```

Because `meshConfig.outboundTrafficPolicy.mode` is `REGISTRY_ONLY` and `www.wikipedia.org` is not yet registered in Istio, Envoy will block the request and return:

```text theme={null}
HTTP/1.1 502 Bad Gateway
date: ...
server: envoy
```

This demonstrates that `REGISTRY_ONLY` prevents egress unless a ServiceEntry (or other Istio configuration) explicitly allows the external host.

<Callout icon="lightbulb" color="#1CB2FE">
  To permit pods in an Istio-enabled namespace to reach external services, add ServiceEntry resources (or configure egress gateways) for those hosts.
</Callout>

***

## 4. Create a ServiceEntry for Wikipedia

Register `www.wikipedia.org` with Istio by creating a ServiceEntry in the `default` namespace. Save this as `serviceentry-wikipedia.yaml`:

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: wikipedia-egress
spec:
  hosts:
  - www.wikipedia.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
```

Apply the ServiceEntry and verify its creation:

```bash theme={null}
kubectl apply -f serviceentry-wikipedia.yaml
kubectl get serviceentries.networking.istio.io
# NAME                HOSTS                     LOCATION    RESOLUTION   AGE
# wikipedia-egress    ["www.wikipedia.org"]     DNS                    14s
```

Retry from the test pod:

```bash theme={null}
kubectl exec -ti test -- /bin/sh
curl --head -L http://www.wikipedia.org
```

Now the request should succeed (HTTP 200 after the redirect). The ServiceEntry allowed egress to that external host.

***

## 5. Route external traffic through an Istio egress gateway

Routing external traffic through an egress gateway centralizes outbound traffic, enabling monitoring, logging, and centralized policy enforcement.

To route traffic through the egress gateway we need:

* A Gateway resource that selects the egress gateway pods.
* A DestinationRule pointing to the egress gateway service (and a subset).
* A VirtualService that (a) routes mesh-originating traffic to the egress gateway and (b) routes traffic from the egress gateway to the external host.

Important: Gateway resources select pods in the same namespace as the Gateway. The built-in egress gateway pods live in `istio-system`, so create the Gateway in `istio-system` to match pods by label.

First confirm the egress gateway pod and labels:

```bash theme={null}
kubectl get pods -n istio-system --show-labels
# ... istio-egressgateway-...  labels include: istio=egressgateway ...
```

Create the Gateway (save as `gateway.yaml`):

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istio-egressgateway
  namespace: istio-system
spec:
  selector:
    istio: egressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - www.wikipedia.org
```

Apply it and verify:

```bash theme={null}
kubectl apply -f gateway.yaml
kubectl get gateways.networking.istio.io -n istio-system
# NAME                  AGE
# istio-egressgateway   12s
```

Create a DestinationRule that points to the egress gateway service (save as `dr.yaml`):

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: egressgateway-for-wikipedia
  namespace: default
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
  - name: wikipedia
```

Apply and confirm:

```bash theme={null}
kubectl apply -f dr.yaml
kubectl get destinationrules.networking.istio.io
# NAME                         HOST                                                AGE
# egressgateway-for-wikipedia  istio-egressgateway.istio-system.svc.cluster.local  7s
```

Create the VirtualService (save as `vs.yaml`). This resource has two important HTTP blocks:

1. A `mesh` gateway match for port 80: routes traffic originating inside the mesh to the egress gateway subset `wikipedia`.
2. An `istio-system/istio-egressgateway` gateway match: routes traffic arriving at the egress gateway to the external host `www.wikipedia.org`.

Note: Because the Gateway is in `istio-system`, reference it in the VirtualService as `istio-system/istio-egressgateway`.

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: wikipedia-egress-gateway
spec:
  hosts:
  - www.wikipedia.org
  gateways:
  - istio-system/istio-egressgateway
  - mesh
  http:
  - match:
    - gateways:
      - mesh
      port: 80
    route:
    - destination:
        host: istio-egressgateway.istio-system.svc.cluster.local
        subset: wikipedia
        port:
          number: 80
      weight: 100
  - match:
    - gateways:
      - istio-system/istio-egressgateway
    port: 80
    route:
    - destination:
        host: www.wikipedia.org
        port:
          number: 80
      weight: 100
```

Apply the VirtualService and verify:

```bash theme={null}
kubectl apply -f vs.yaml
kubectl get virtualservices.networking.istio.io
# NAME                       GATEWAYS                                      HOSTS
# wikipedia-egress-gateway   ["istio-system/istio-egressgateway","mesh"]   ["www.wikipedia.org"]
```

Important explanation: The `mesh` gateway entry is required so that traffic originating from inside the mesh (pod → external host) matches the first HTTP rule and is routed to the egress gateway subset `wikipedia`. When the egress gateway receives the request, the VirtualService matches the `istio-system/istio-egressgateway` gateway rule and forwards the request to `www.wikipedia.org`. If you omit the `mesh` match, internal traffic will bypass the egress gateway and will not be centrally controlled.

<Callout icon="lightbulb" color="#1CB2FE">
  If you omit the `mesh` gateway entry in the VirtualService, traffic from inside the mesh will bypass the egress gateway, removing centralized control and visibility.
</Callout>

***

## 6. Observe traffic through the egress gateway

Tail logs for the egress gateway pod in another terminal:

```bash theme={null}
kubectl logs -f -n istio-system <istio-egressgateway-pod-name>
# Look for entries like:
# "HEAD / HTTP/2" 301 - via_upstream ... "www.wikipedia.org" ...
```

From the test pod, curl Wikipedia again:

```bash theme={null}
kubectl exec -ti test -- /bin/sh
curl --head -L http://www.wikipedia.org
```

You should see normal responses, and the egress gateway logs will show the outbound request. This confirms that mesh traffic was routed to the egress gateway which then forwarded it to the external host.

***

## Quick reference: resources for egress control

| Resource Type   | Purpose                                                                     | Example / Notes                                                          |
| --------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| ServiceEntry    | Register external host(s) with Istio to allow egress under `REGISTRY_ONLY`  | See `serviceentry-wikipedia.yaml` above                                  |
| Gateway         | Selects egress gateway pods (namespace-specific) and exposes ports/hosts    | Create in `istio-system` to select `istio=egressgateway` pods            |
| DestinationRule | Points to the egress gateway service and defines subsets                    | Host should be `istio-egressgateway.istio-system.svc.cluster.local`      |
| VirtualService  | Routes mesh-originating traffic to egress gateway and gateway→external host | Include both `mesh` and `istio-system/istio-egressgateway` in `gateways` |

***

## Additional ServiceEntry examples

Simple external HTTP ServiceEntry:

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-httpbin
  namespace: egress
spec:
  hosts:
  - example.com
  exportTo:
  - "."
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
```

External TLS ServiceEntry for multiple hosts:

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-https
spec:
  hosts:
  - api.dropboxapi.com
  - www.googleapis.com
  - api.facebook.com
  location: MESH_EXTERNAL
  ports:
  - number: 443
    name: https
    protocol: TLS
  resolution: DNS
```

ServiceEntry pointing to fixed IP endpoints (Mongo example):

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-mongocluster
spec:
  hosts:
  - mymongodb.somedomain
  addresses:
  - 192.192.192.192/24
  ports:
  - number: 27018
    name: mongodb
    protocol: MONGO
  location: MESH_INTERNAL
  resolution: STATIC
  endpoints:
  - address: 2.2.2.2
  - address: 3.3.3.3
```

Generic egress Gateway snippet:

```yaml theme={null}
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istio-egressgateway
  namespace: istio-system
spec:
  selector:
    istio: egressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
```

***

## Troubleshooting tips

* If your VirtualService isn’t taking effect, confirm the Gateway exists in the correct namespace and the `gateways` entry in the VirtualService is properly namespace-qualified (`istio-system/istio-egressgateway`).
* If traffic is still blocked after creating a ServiceEntry, ensure the ServiceEntry is in the same namespace as the client pod (or exported appropriately) and that DNS resolution is working as expected.
* Use `kubectl get virtualservices,destinationrules,gateways,serviceentries -A` to verify configuration across namespaces.

***

## Summary

* Setting `meshConfig.outboundTrafficPolicy.mode` to `REGISTRY_ONLY` blocks egress to hosts not registered in Istio.
* Use ServiceEntry to register external hosts so Istio allows egress.
* To centralize and control external traffic, create an egress Gateway, a DestinationRule pointing to the egress gateway service, and a VirtualService that routes mesh-originating traffic to the egress gateway and the gateway to the external host.
* The `mesh` gateway entry in the VirtualService is essential to route traffic originating from inside the mesh through the egress gateway.

Practice creating these resources (ServiceEntry, Gateway, DestinationRule, VirtualService) so you can apply them swiftly in real-world scenarios and assessments.

***

## Links and references

* [Istio Egress Traffic Control](https://istio.io/latest/docs/tasks/traffic-management/egress/)
* [Istio Gateway and VirtualService concepts](https://istio.io/latest/docs/concepts/traffic-management/#gateways)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/istio-certified-associate/module/f3f5ca4b-b8d6-4788-9553-9ed765709933/lesson/5674ec14-32a4-48c3-bb67-a08d54199396" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/istio-certified-associate/module/f3f5ca4b-b8d6-4788-9553-9ed765709933/lesson/0b5f42c9-6182-4747-8253-554ce30147dc" />
</CardGroup>
