惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
TaoSecurity Blog
TaoSecurity Blog
T
Threat Research - Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tenable Blog
C
Cybersecurity and Infrastructure Security Agency CISA
GbyAI
GbyAI
Microsoft Security Blog
Microsoft Security Blog
N
Netflix TechBlog - Medium
AWS News Blog
AWS News Blog
Security Latest
Security Latest
L
LINUX DO - 热门话题
Blog — PlanetScale
Blog — PlanetScale
T
Threatpost
Stack Overflow Blog
Stack Overflow Blog
Vercel News
Vercel News
S
Securelist
I
Intezer
D
Darknet – Hacking Tools, Hacker News & Cyber Security
H
Heimdal Security Blog
T
The Exploit Database - CXSecurity.com
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Hacker News
The Hacker News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
H
Hackread – Cybersecurity News, Data Breaches, AI and More
U
Unit 42
The Register - Security
The Register - Security
NISL@THU
NISL@THU
S
Schneier on Security
M
MIT News - Artificial intelligence
The Last Watchdog
The Last Watchdog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
Know Your Adversary
Know Your Adversary
罗磊的独立博客
MongoDB | Blog
MongoDB | Blog
美团技术团队
W
WeLiveSecurity
P
Privacy International News Feed
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
小众软件
小众软件
博客园 - 【当耐特】
P
Proofpoint News Feed
P
Privacy & Cybersecurity Law Blog
T
Tor Project blog

Learn Cloud Native

Agentgateway rate limiting for agents | Learn Cloud Native Local development with coding agents on Kubernetes using Signadot | Learn Cloud Native cuenv: one typed file for your whole project | Learn Cloud Native Preflight: AI Code Review Before You Push Anatomy of AI Agents Accessing Google Drive from Next.js Deploying to Fly.io using Dagger and Github Top Cloud-Native & Kubernetes Certifications [2026 Guide] Rapid microservices development with Signadot How to prepare for Istio certified associate exam (ICA) Global Rate Limiting in Istio with Envoy Rate Limit Service My Journey with Istio: From Incubation to Graduation Cilium Network Policy Tutorial: Secure Kubernetes Step by Step Kubernetes Networking: How kube-proxy and iptables Work Istio ServiceEntry: DNS vs. STATIC Resolution & Endpoints Explained Apply an Istio DestinationRule Globally (Mesh-Wide) Istio Rate Limiting: Configure a Local Rate Limiter in Envoy Portainer Tutorial: A Web UI for Kubernetes & Containers Traefik Proxy 2.x and TLS 101 Kubernetes CLI (kubectl) tips you didn't know about Setting up SSL certificates with Istio Gateway ArgoCD Best Practices You Should Know 在 OCI Ampere A1 计算实例上运行 AI Running AI On OCI Ampere A1 Instance How to Deploy Traefik Proxy Using Flux and GitOps Principles Firebase Emulators with Next.js: Local Setup Guide Running Hugo on free Ampere VM (Oracle Cloud Infrastructure) How to use kwatch to detect crashes in Kubernetes clusters Continuous profiling in Kubernetes using Pyroscope Monitoring containers with cAdvisor Creating a Kubernetes cluster in Google Cloud (LAB) Your first Kubernetes Pod and ReplicaSet (LABS) Container Lifecycle Hooks Maybe Convert Wasm Extension Config? GetIstio - CLI, training, and community Attach multiple VirtualServices to Istio Gateway Kubernetes Volumes Explained: Keep Data Beyond the Pod Send a Slack message when Docker images are updated Kubernetes Network Policy Ambassador Container Pattern Start Kubernetes Release Sidecar Container Pattern Kubernetes Init Containers Deploying multiple Istio Ingress Gateways Branch by Abstraction Pattern The Strangler Pattern Kubernetes Development Environment with Skaffold Securing Kubernetes Ingress with Ambassador and Let's Encrypt All About the Ingress Resource How to quarantine Kubernetes pods? Getting started with Kubernetes Horizontal partitioning in MongoDB Docker image tagging scheme Six things to keep in mind when working with Dockerfiles Beginners guide to Docker Beginners guide to gateways and proxies Deploy and Operate Multiple Istio Meshes in one Kubernetes Cluster Managing service meshes with Meshery Circuit Breaking in Istio Explained Build and push your Docker images using Github Actions Kubernetes and Istio service mesh workshop materials Build Netlify-like deployment for React app using Kubernetes pods Six exciting enhancements in Istio 1.4.0 Fallacies of Distributed Systems CAP Theorem Explained Master the Kubernetes CLI (kubectl) - Cheatsheet Minikube Basics and How to Get Started with Kubernetes 5 Tips to Be More Productive with Kubernetes What are sticky sessions and how to configure them with Istio? Debugging Kubernetes applications using Istio Kubernetes Ingress and Istio Gateway Resource Zero Downtime Releases using Kubernetes and Istio Traffic Mirroring with Istio Service Mesh Expose a Kubernetes service on your own custom domain
How to expose custom ports on Istio ingress gateway
Peter Jausovec · 2022-08-01 · via Learn Cloud Native

The question (paraphrased) goes like this:

Note

I'd like to expose two ports on the ingress gateway (e.g. 5000 and 3000) and use any host (e.g. "*"). Can I do this?

Practically, here's what we want to happen. When a request is sent to GATEWAY_IP:3000 the response comes from one service within the cluster and when the request is sent to GATEWAY_IP:5000 the response will come from another service. The host stays the same (* in this case, but it could be any other hostname). The difference is in the port numbers.

Is it possible to do this?

The answer is YES and here are the high-level steps:

  1. Install Istio and expose additional ports through the ingress gateway service.
  2. Configure the Gateway resource to tell the Envoy proxy to listen to those ports.
  3. Create the VirtualService resource to route traffic to the services.
  4. Deploy the sample workload (httpbin).

Let's get started.

Install Istio & expose additional ports

We need to modify how the Istio ingress gateway gets installed to expose the additional ports. By default, the ingress gateway exposes ports 80, 443, and a couple of other ports (15021 for health checks, 15012 for xDS, etc.).

Another option is to create a separate ingress gateway that only exposes the additional ports.

Here's an example IstioOperator resource that exposes the two additional ports called http-custom-1 and http-custom-2:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio-with-extra-ports
spec:
  profile: default
  components:
    ingressGateways:
      - namespace: istio-system
        name: istio-ingressgateway
        enabled: true
        k8s:
          service:
            ports:
              - port: 15021
                targetPort: 15021
                name: status-port
                protocol: TCP
              - port: 80
                targetPort: 8080
                name: http2
                protocol: TCP
              - port: 443
                targetPort: 8443
                name: https
                protocol: TCP
              - port: 15012
                targetPort: 15012
                name: tcp-istiod
                protocol: TCP
              - port: 15443
                targetPort: 15443
                name: tls
                protocol: TCP
              - port: 3000
                targetPort: 3000
                name: http-custom-1
                protocol: TCP
              - port: 5000
                targetPort: 5000
                name: http-custom-2
                protocol: TCP

Once you deploy this (e.g. istioctl install -f istio-with-extra-ports.yaml) and list the services in the istio-system namespace, you'll notice the extra two ports listed:

$ kubectl get svc  -n istio-system
NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)                                                                                                    AGE
istio-ingressgateway   LoadBalancer   10.96.8.13    [GATEWAY_IP]   15021:32415/TCP,80:31070/TCP,443:31578/TCP,15012:31223/TCP,15443:30192/TCP,3000:32333/TCP,5000:31199/TCP   10m
istiod                 ClusterIP      10.96.4.186   <none>         15010/TCP,15012/TCP,443/TCP,15014/TCP

This allows us to send requests to GATEWAY_IP:3000 and GATEWAY_IP:5000.

Configure the Gateway resource to listen on those ports

We can now create the Gateway resource that tells the ingress gateway (Envoy) to listen on port 3000 and port 5000.

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: my-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 3000
        name: http
        protocol: HTTP
      hosts:
        - '*'
    - port:
        number: 5000
        name: http-second
        protocol: HTTP
      hosts:
        - '*'

Behind the scenes, this creates two listeners on the ingress gateway - http.3000 and http.5000:

$ istioctl proxy-config listener istio-ingressgateway-9f6bc6bd7-szd5k -n istio-system
ADDRESS PORT  MATCH DESTINATION
0.0.0.0 3000  ALL   Route: http.3000
0.0.0.0 5000  ALL   Route: http.5000
0.0.0.0 15021 ALL   Inline Route: /healthz/ready*
0.0.0.0 15090 ALL   Inline Route: /stats/prometheus*

In the next step, we need to configure the VirtualService resource. If we check the configured routes on the ingress gateway, you'll notice that the 404 in the VIRTUAL SERVICE column:

$ istioctl proxy-config routes  istio-ingressgateway-9f6bc6bd7-szd5k -n istio-system
NAME          DOMAINS     MATCH                  VIRTUAL SERVICE
http.5000     *           /*                     404
http.3000     *           /*                     404
              *           /stats/prometheus*
              *           /healthz/ready*

Create a VirtualService to define routes

We need the VirtualService resource to tell Envoys where to route the traffic. As a best practice, you'd probably create two separate VirtualService resources, but for brevity, I'll create only one.

In the end, it doesn't matter as Istio merges the resources, resulting in the same Envoy configuration.

Here's what the YAML could look like:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: my-virtualservice
spec:
  hosts:
    - '*'
  gateways:
    - my-gateway
  http:
    - match:
        - port: 3000
      route:
        - destination:
            host: httpbin-one.default.svc.cluster.local
            port:
              number: 3000
    - match:
        - port: 5000
      route:
        - destination:
            host: httpbin-two.default.svc.cluster.local
            port:
              number: 5000

We're specifying the host as *, which will match the host specified in the gateway. Next, we're attaching the my-gateway gateway to the VirtualService. When traffic hits the ingress gateway from any host, it will match to this VirtualService (because of the * in the hosts field on both resources). In a more typical scenario, you'd configure one or more hosts in the Gateway resource (e.g., mydomain.com) and then have hostname defined in the VirtualService where you configure the destination you want to expose to the world.

These two settings are insufficient as we need a way to differentiate or tell Istio where the traffic should go when it's received on port 3000 vs. port 5000. To do that, the match statement supports the port value and allows us to match on the port. We have the two match sections, and inside those, we have the route section where we specify the actual destination: httpbin-one for traffic on port 3000 and httpbin-two for traffic on port 5000.

To complete the example, we need two workloads - we'll use two deployments of httpbin:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin-one
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin-one
  labels:
    app: httpbin-one
    service: httpbin-one
spec:
  ports:
    - name: http
      port: 3000
      targetPort: 80
  selector:
    app: httpbin-one
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-one
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin-one
      version: v1
  template:
    metadata:
      labels:
        app: httpbin-one
        version: v1
    spec:
      serviceAccountName: httpbin-one
      containers:
        - image: docker.io/kennethreitz/httpbin
          imagePullPolicy: IfNotPresent
          name: httpbin-one
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin-two
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin-two
  labels:
    app: httpbin-two
    service: httpbin-two
spec:
  ports:
    - name: http
      port: 5000
      targetPort: 80
  selector:
    app: httpbin-two
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-two
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin-two
      version: v1
  template:
    metadata:
      labels:
        app: httpbin-two
        version: v1
    spec:
      serviceAccountName: httpbin-two
      containers:
        - image: docker.io/kennethreitz/httpbin
          imagePullPolicy: IfNotPresent
          name: httpbin-two
          ports:
            - containerPort: 80

For simplicity sake, both deployments (and other resources) are in the same namespace (default):

$ kubectl get po
NAME                           READY   STATUS    RESTARTS   AGE
httpbin-one-5bb7696978-4jmpz   2/2     Running   0          14m
httpbin-two-56947cd774-j7hth   2/2     Running   0          14m

We can use the proxy-config command in the Istio CLI to see what the Envoy configuration looks like. Starting with the listeners (this should be the same as before):

$ istioctl proxy-config listener  istio-ingressgateway-6668f9548d-mrtp5 -n istio-system
ADDRESS PORT  MATCH DESTINATION
0.0.0.0 3000  ALL   Route: http.3000
0.0.0.0 5000  ALL   Route: http.5000
0.0.0.0 15021 ALL   Inline Route: /healthz/ready*
0.0.0.0 15090 ALL   Inline Route: /stats/prometheus*

The listeners on ports 3000 and 5000 correspond to the two servers we defined in the Gateway resource. You'll also notice two different routes are in the configuration - http.3000 and http.5000.

We can also see the routes using the routes sub-command:

$ istioctl proxy-config routes istio-ingressgateway-6668f9548d-mrtp5 -n istio-system
NAME          DOMAINS     MATCH                  VIRTUAL SERVICE
http.3000     *           /*                     my-virtualservice.default
http.5000     *           /*                     my-virtualservice.default
              *           /stats/prometheus*
              *           /healthz/ready*

This time the two routes map to the VirtualService we deployed. Also, note the domains (*) - this corresponds to the hosts setting in the Gateway resource.

By the way, the name of the VirtualService used to generate the Envoy configuration gets stored in the filter metadata. Here's a snippet from the configuration:

...
"metadata": {
  "filter_metadata": {
    "istio": {
      "config": "/apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/my-virtualservice"
    }
  }
}
...

This is how Istio CLI knows which VirtualService to put in the above output.

If we list the clusters and filter by port number, we'll see which Kubernetes services the two ports are mapped to:

$ istioctl proxy-config clusters istio-ingressgateway-9f6bc6bd7-szd5k -n istio-system --port 3000
SERVICE FQDN                                            PORT     SUBSET     DIRECTION     TYPE     DESTINATION RULE
httpbin-one.default.svc.cluster.local                   3000     -          outbound      EDS
istio-ingressgateway.istio-system.svc.cluster.local     3000     -          outbound      EDS

$ istioctl proxy-config clusters istio-ingressgateway-9f6bc6bd7-szd5k -n istio-system --port 5000
SERVICE FQDN                                            PORT     SUBSET     DIRECTION     TYPE     DESTINATION RULE
httpbin-two.default.svc.cluster.local                   5000     -          outbound      EDS
istio-ingressgateway.istio-system.svc.cluster.local     5000     -          outbound      EDS

Finally, we can send the requests to GATEWAY_IP:3000 and GATEWAY_IP:5000 to verify we get back the response from the correct services:

$ curl GATEWAY_IP:3000/headers
{
  "headers": {
    "Accept": "*/*",
    "Host": "GATEWAY_IP:3000",
    "User-Agent": "curl/7.74.0",
    "X-B3-Parentspanid": "5af6344416c73bcc",
    "X-B3-Sampled": "1",
    "X-B3-Spanid": "fc079d9bc28baee1",
    "X-B3-Traceid": "954cffe5dda361e85af6344416c73bcc",
    "X-Envoy-Attempt-Count": "1",
    "X-Envoy-Internal": "true",
    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin-one;Hash=b957e7eef3880984bbf97b7443f5f4afdced8d1082dc56bd21b25ae2949b6a88;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"
  }
}

$ curl GATEWAY_IP:5000/headers
{
  "headers": {
    "Accept": "*/*",
    "Host": "GATEWAY_IP:5000",
    "User-Agent": "curl/7.74.0",
    "X-B3-Parentspanid": "d9469dcbeed22f99",
    "X-B3-Sampled": "1",
    "X-B3-Spanid": "0f2d699ec78b914d",
    "X-B3-Traceid": "c58aa2e193746bd1d9469dcbeed22f99",
    "X-Envoy-Attempt-Count": "1",
    "X-Envoy-Internal": "true",
    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin-two;Hash=b957e7eef3880984bbf97b7443f5f4afdced8d1082dc56bd21b25ae2949b6a88;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"
  }
}

Notice the SPIFFE URI in the X-Forwarded-Client-Cert is different in each request. One uses the httpbin-one service account, and the second one uses httpbin-two service account, proving the requests came from correct services.

Conclusion

This article explained how to expose custom ports on the Istio ingress gateway Kubernetes service. Additionally, we crafted a VirtualService configuration that matches the incoming ports and routes the traffic to appropriate backend services.