Skip to content

Conversation

@AryanParashar24
Copy link
Contributor

@AryanParashar24 AryanParashar24 commented Sep 16, 2025

Description

Doc created for the Service-Entry section in traffic-management section of kgateway docs which will be handling with single.

It is a part of LFX Mentorship sep-nov 2025 with Issue: #399

Change Type

/kind documentation

Changelog

This pull request adds comprehensive documentation for using Istio Service Entries with K-Gateway, enabling integration of external services into the service mesh. The new guide explains key concepts, provides architectural diagrams, and includes step-by-step YAML examples and verification instructions for multiple Service Entry use cases.

Key additions and improvements:

Documentation & Conceptual Overview

  • Introduced a new guide, service-entry.md, detailing how to extend K-Gateway's service mesh to external services using Istio Service Entries, including a high-level explanation and a mermaid sequence diagram to illustrate traffic flow and integration scenarios.

Practical Examples & Use Cases

  • Provided four detailed usage scenarios with YAML manifests and verification steps:
    • Static Endpoints: For fixed external IPs.
    • DNS Resolution: For dynamic, DNS-based external services.
    • Workload Selector: For routing to in-mesh workloads by label.
    • Workload Entry: For hybrid-cloud integration of non-Kubernetes workloads (e.g., VMs).

Verification & Troubleshooting

  • Included practical verification commands and expected outputs for each scenario, helping users test and validate their configurations in real environments.

Consistent Ingress Example

  • Demonstrated the use of a common Gateway and HTTPRoute configuration for all scenarios, emphasizing separation of ingress logic from backend discovery.

```
You will see an output as:
```
Name: se.example.com
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this example there are a couple steps missing:

  1. Setting up an example app
  2. Injecting the sidecar/enabling ambient mode

For static IPs here's an example: https://istio.io/latest/blog/2018/egress-tcp/#mesh-external-service-entry-for-an-external-mysql-instance

I would actually drop the static resolution example and just reference the docs. Then keep the DNS and WorkloadEntry examples, and add an example kgateway TrafficPolicy.

namespace: gwtest
spec:
hosts:
- se.example.com
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a functioning example hostname here for egress, like this:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: github-https
spec:
  hosts:
  - github.com
  ports:
  - number: 443
    name: https
    protocol: HTTPS

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've mentioned it at the last, as a separate Egress Traffic manager to handle outbound traffic. Let me know if it should be changed.

@AryanParashar24
Copy link
Contributor Author

I've made some changes to the file. Please let me know if anything else needs to be updated.

targetRef:
kind: HTTPRoute
name: route-to-upstream
http:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timeouts are a little more tricky to validate. If you're already using httpbin I would use a header manipulation example, transformation, or rbac example here instead.

namespace: gwtest
spec:
hosts:
- se.example.com
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I mentioned before, we want to make this example functional so we might want to use a real external host name here instead. Currently se.example.com wouldn't resolve to anything. Let's use the external httpbin website to keep it consistent:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-httpbin
spec:
  hosts:
  - httpbin.org
  location: MESH_EXTERNAL
  ports:
  - name: http
    number: 80
    protocol: HTTP
  resolution: DNS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Peter had a great blog from a couple years ago on basic SE examples: https://www.learncloudnative.com/blog/2023-02-10-servicentry-feature There's also this useful doc on the Istio page: https://istio.io/latest/docs/tasks/traffic-management/egress/egress-control/

We basically want something similar to the egress control flow, but with a kgateway Gateway and TrafficPolicy applied.

@npolshakova
Copy link
Contributor

I've made some changes to the file. Please let me know if anything else needs to be updated.

Left some more comments. Let's also update the PR description to be consistent in style. Remember using AI tools is totally fine, but you want to make sure that 1) the configuration actually works, 2) the style is consistent with the other docs.

Copy link
Contributor

@npolshakova npolshakova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good progress! To get some more practice with technical docs and Istio, I would run through this guide https://istio.io/latest/docs/tasks/traffic-management/egress/egress-gateway/ and then try the same guide with a kgateway Gateway.

@AryanParashar24
Copy link
Contributor Author

  • I've Added Header Manipulation to HTTPRoute and have edited Verification steps, so that they can run successfully for all types of ServiceEntries types.
  • For Egress ServiceEntries , I'll try to run code again and will add a verification step with a real external Host.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be deleted in favor of istio/service-entry.md?

hosts:
- se.example.com
ports:
- number: 80
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this port is incorrect. If you try validating this SE, you'll see:

❯ curl -s -H "Host: se.example.com" localhost:8080/ -v * Host localhost:8080 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:8080... * Connected to localhost (::1) port 8080 * using HTTP/1.x > GET / HTTP/1.1 > Host: se.example.com > User-Agent: curl/8.13.0 > Accept: */* > * Request completely sent off < HTTP/1.1 503 Service Unavailable < content-length: 91 < content-type: text/plain < date: Tue, 14 Oct 2025 12:53:35 GMT < server: envoy

You want the ServiceEntry port to match what the service exposes because you're selecting the k8s service here. The actual Kubernetes Service (httpbin) exposes ports 8000 and 9000:

❯ kubectl get svc -n httpbin httpbin
NAME      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
httpbin   ClusterIP   10.96.151.225   <none>        8000/TCP,9000/TCP   11m

So Envoy is attempting to connect to 10.96.151.225:80 (where nothing is listening), hence it's timing out with the 503. This fix is to change this to match the svc port.

hosts:
- se.example.com
ports:
- number: 80
Copy link
Contributor

@npolshakova npolshakova Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here as https://github.com/kgateway-dev/kgateway.dev/pull/393/files#r2429070323

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: example-se
  namespace: gwtest
spec:
  hosts:
  - se.example.com
  location: MESH_INTERNAL
  resolution: STATIC
  ports:
  - number: 8000           # Gateway layer sees this port
    name: http
    protocol: HTTP       
  endpoints:
  - address: 10.96.151.225 
    ports:
      http: 8000
EOF

Now, define the `ServiceEntry`. This `ServiceEntry` leverages a `workloadSelector` that matches the `app: httpbin` label. Istio will automatically discover and include any `httpbin` pods within the `httpbin` namespace that possess this label as part of this service's endpoints.

```yaml
kubectl apply -f - <<EOF
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is actually a little trickier because the httpbin app is in the httpbin namespace. You will need to update the HTTPRoute and add a ReferenceGrant to get it working like this:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: example-se
  namespace: httpbin   # same namespace as pods
spec:
  hosts:
    - se.example.com
  location: MESH_INTERNAL
  resolution: STATIC
  workloadSelector:
    labels:
      app: httpbin
  ports:
    - number: 8080
      name: http-8080
      protocol: HTTP
  exportTo:
    - "*"       # visible across namespaces
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-gwtest-to-se
  namespace: httpbin
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: gwtest
  to:
    - group: networking.istio.io
      kind: ServiceEntry
      name: example-se
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
  name: route-to-upstream
  namespace: gwtest
spec:
  hostnames:
  - se.example.com
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: http-gw-for-test
  rules:
  - backendRefs:
    - group: networking.istio.io
      kind: ServiceEntry
      name: example-se
      namespace: httpbin
      port: 8080
      weight: 1
    filters:
    - requestHeaderModifier:
        add:
        - name: App
          value: ServiceEntry
        remove:
        - X-Remove
        set:
        - name: User-Agent
          value: custom
      type: RequestHeaderModifier
    matches:
    - path:
        type: PathPrefix
        value: /
EOF

location: MESH_INTERNAL
workloadSelector:
labels:
app: reviews-workloadentry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This switches to using reviews, let's keep the httpbin example.

`**ServiceEntry:**` Utilizes a `workloadSelector` that matches the labels defined in the `WorkloadEntry`. This instructs Istio to automatically discover and use these `WorkloadEntry` instances as its endpoints, effectively bridging your Kubernetes-native mesh with external infrastructure.

```yaml
kubectl apply -f - <<EOF
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can change this example to use the external httpbin docker container running in the kind network:

docker run -d --name httpbin --network kind -p 8081:8080 kennethreitz/httpbin

Then inspect to find the IP:

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' httpbin

Then apply an example WorkloadEntry that selects the external non-k8s docker workload:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: route-to-httpbin
  namespace: gwtest
spec:
  parentRefs:
    - name: http-gw-for-test
  hostnames:
    - se.example.com
  rules:
    - backendRefs:
        - name: httpbin-se
          port: 80
          kind: ServiceEntry
          group: networking.istio.io
---
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: httpbin-se
  namespace: gwtest
spec:
  hosts:
    - se.example.com
  location: MESH_INTERNAL
  resolution: STATIC
  workloadSelector:
    labels:
      app: httpbin
  ports:
    - number: 80
      name: http-80
      protocol: HTTP
---
apiVersion: networking.istio.io/v1
kind: WorkloadEntry
metadata:
  name: httpbin-we-1
  namespace: gwtest
  labels:
    app: httpbin
spec:
  address: 172.18.0.3     # reuse docker container IP
  ports:
    http: 80
EOF

Then the validation is the same as the other steps:

curl -H "Host: se.example.com" localhost:8080/headers -v

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: github-https
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example looks incorrect. There is a mismatch between the SE name and host. Also the validation steps will not work for this with the current HTTPRoute.

resolution: DNS
EOF
```
---
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are the TrafficPolicy examples in this version of the doc? See the previous comment: https://github.com/kgateway-dev/kgateway.dev/pull/393/files#r2360202490

Comment on lines +76 to +86
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: App
value: ServiceEntry
set:
- name: User-Agent
value: custom
remove:
- X-Remove
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of these filters, let's add a kgateway-specific policy example

Co-authored-by: Nina Polshakova <[email protected]>
Signed-off-by: Aryan Parashar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants