Getting Started with Istio (Part 7): Ingress and Egress Gateways

2023年7月9日 26点热度 0人点赞 0条评论
内容目录

此教程已加入 Istio 系列:https://istio.whuanle.cn

5. Egress and Ingress Gateways

Istio can manage ingress and egress traffic in a cluster. When clients access applications within the cluster, Istio can implement load balancing, circuit breaking, and other features for traffic that passes through the istio-ingressgateway.

However, if an application within the cluster wants to access google.com, can we set up load balancing for all internal requests to google.com? The answer is yes. Istio provides the istio-egressgateway to achieve this functionality. When containers in a Pod need to access external networks, they will be intercepted by Envoy, which can easily analyze these requests and influence the behavior of the requests through various means.

In this chapter, we will briefly discuss istio-ingressgateway and istio-egressgateway.

istio-ingressgateway

The ingress gateway refers to the traffic flowing into the cluster via istio-ingressgateway, which requires the creation of a Gateway to bind the traffic.

Regarding istio-ingressgateway, you should be familiar with it from previous chapters.

The istio-ingressgateway consists of Pod and Service. The istio-ingressgateway itself is a gateway application, which you can think of as similar to Nginx, Apisix, or Kong. You can find concepts similar to istio-ingressgateway among various gateway applications.

image-20230526194223740

image-20230526194154234

As an application, it needs to expose some ports; istio-ingressgateway will only be effective when traffic passes through these ports. To expose ports in Kubernetes, istio-ingressgateway also has a Service object.

image-20230526194139225

With istio-ingressgateway, we can monitor certain domain names or IP addresses through Istio Gateway and expose internal services of the cluster.

The concept of Gateway shares many similarities with Nginx.

For example, in terms of configuration, both Gateway and Nginx monitor particular ingress traffic as shown below:

Nginx:

server {
    listen      80;
    server_name example.org www.example.org;
    #...
}

Gateway:

  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - example.org
    - www.example.org

These configurations specify which traffic the Gateway and Nginx will monitor.

Subsequently, when the specified ingress traffic is detected, it needs to be forwarded to applications within the cluster.

Nginx can set this directly in the same configuration file:

server {
    listen      80;
    server_name example.org www.example.org;
    #...
}

location /some/path/ {
    proxy_pass http://bookinfo:9080/;
}

While the Gateway needs to use VirtualService to specify where the traffic should be forwarded and can further filter based on the ingress address.

spec:
  hosts:
  - "www.example.org"
  gateways:
  # Bind to Gateway
  - mygateway
  http:
    route:
    - destination:
        host: bookinfo
        port:
          number: 9080

To summarize, Istio's approach is to have the Gateway monitor ingress traffic, define the traffic entry strategy through VirtualService, and point to the Service. The DestinationRule then defines the strategy for traffic flowing to the Pods.

Deploying Services

Here, we will use the httpbin service as an example to explain how to configure external access to the httpbin service step-by-step.

First, deploy an httpbin service, which is quite simple and includes a Service and a Deployment.

httpbin.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80
kubectl -n bookinfo apply -f httpbin.yaml

Configure Gateway

Next, create a Gateway that specifies which ingress traffic to listen for.

httpbin_gw.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.s1.whuanle.cn"
    - "*"

This step helps everyone understand the Gateway more intuitively through the domain name. You can modify httpbin.s1.whuanle.cn to your own domain.

Then, on your computer, open C:\Windows\System32\drivers\etc\hosts and add a record to point the IP to your server.

image-20230515193213923

kubectl -n bookinfo apply -f httpbin_gw.yaml

Now, we have configured istio-ingressgateway to monitor the address httpbin.s1.whuanle.cn. If anyone accesses httpbin.s1.whuanle.cn, the traffic will flow into httpbin-gateway.

image-20230515190518804

Next, we will configure the service address for the Gateway and specify the allowed suffix for external access.

Configure VirtualService:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - match: 
    - uri:
        prefix: /status
    - uri:
        prefix: /delay 
    route:
    - destination:
        port:
          number: 8000
        host: httpbin

When both Gateway and VirtualService only have one port, port binding is not necessary.

kubectl -n bookinfo apply -f httpbin_vs.yaml

Find the port exposed by istio-ingressgateway.

kubectl get svc istio-ingressgateway  -n istio-system

1683287785674

httpbin is an HTTP testing program, and we can retrieve the corresponding HTTP request status using /status/{status_code}.

For example:

image-20230505200437890

image-20230505200444999

image-20230515193314909image-20230515193301641

If we do not want this service to be accessible externally, we can first remove /status.

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

At this point, you will not be able to access the status path; however, you can still access the /delay path.

The /delay path of httpbin is used to test the delay of HTTP request responses, and /delay/{seconds} specifies how long the server will wait before returning a response.

For example, http://192.168.3.150:32309/delay/5 will respond after 5 seconds.

httpbin has many routing interfaces, and we can configure which paths to allow through VirtualService.

image-20230505201156220

If you need to allow everything, you can use:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
        subset: v1
EOF

Subversion

In Chapter 4, during routing experiments with versions, traffic can be directed to different versions.

kubectl -n bookinfo apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  subsets:
  - name: v1
    labels:
      version: v1
EOF

First, we direct the DestinationRule to a Service:

  host: httpbin

Of course, we can also write it as:

  host: httpbin.bookinfo.svc.cluster.local

Through the host, we can identify the corresponding Kubernetes Service and obtain the list of all Pods from the Service's corresponding Endpoints.

image-20230515194105645

1684151025350

By obtaining all Pods from the Endpoints, we can check the description of each Pod. When a request arrives, a suitable Pod is chosen based on the label selector in the DestinationRule.

  - name: v1
    labels:
      version: v1

1684151265603

istio-egressgateway

istio-egressgateway is also a component in Istio that needs to be installed separately. The command to install istio-egressgateway is:

helm install istio-egressgateway istio/gateway -n istio-system

In a cluster, if application A accesses an address that belongs to other applications within the cluster, Istio can inject various behaviors into these requests to achieve load balancing and circuit breaking. However, if the application within the cluster needs to access an external service, such as aaa.com, how can we implement load balancing and circuit breaking for these requests?

image-20230515195151940

Istio ServiceEntry is a resource that allows external services (i.e., services not in the Istio service mesh) to be incorporated into the Istio service mesh. By adding external services to the mesh, we can use Istio's traffic management and policy functionalities to control interactions with these external services.

Here is an example of a ServiceEntry that adds an external HTTP service www.google.com to the Istio service mesh:

apiVersion: networking.istio.io/v1alpha3  
kind: ServiceEntry  
metadata:  
  name: google
spec:  
  hosts:  
  - www.google.com  
  addresses:  
  - 192.168.1.1  
  ports:  
  - number: 80  
    name: http  
    protocol: HTTP  
  location: MESH_EXTERNAL  
  resolution: DNS  
  endpoints:  
  - address: "www.google.com"  
    ports:  
      http: 80  
    locality: "us-west1/zone1"  
  exportTo:  
  - "*"  

In this example, we create a ServiceEntry resource named httpbin-ext. The specified host is httpbin.org, with a port of 80 and HTTP protocol. Additionally, we set resolution to DNS and location to MESH_EXTERNAL, indicating that the service is outside the mesh.

To apply this ServiceEntry to the cluster, save it to a YAML file (e.g., httpbin-ext.yaml) and run the following command:

kubectl apply -f httpbin-ext.yaml  

Now, when a service within the Istio service mesh accesses www.google.com, it remains under the control of Istio's policies. For example, you can create a VirtualService for this ServiceEntry to apply traffic management rules or create a DestinationRule for configuring load balancing and connection pool settings.

spec: Contains the specific configuration objects of the ServiceEntry.

  • hosts: A list of fully qualified domain names (FQDN) of the external services to be imported. For example: ["httpbin.org"].
  • addresses: (Optional) A list of virtual IP addresses associated with the external services. For example: ["192.168.1.1"].
  • ports: A list describing the ports used by the external service. Each port has the following attributes:
    • number: Port number, for example: 80.
    • name: Name of the port, e.g., http.
    • protocol: The protocol used, e.g., HTTP, TCP, HTTPS, etc.
  • location: The location of the service. Can be MESH_EXTERNAL (indicating the service is outside the mesh) or MESH_INTERNAL (indicating the service is inside the mesh but not part of any known service).
  • resolution: The method used to determine service instance addresses. It can be NONE (default, indicating no address resolution), STATIC (indicating the use of IP addresses from the addresses field), DNS (indicating DNS resolution of the hostname), or MESH_EXTERNAL.
  • endpoints: (Optional) A list of endpoints for the external service. Each endpoint has the following attributes:
    • address: The IP address or hostname of the endpoint.
    • ports: A mapping containing the port name and port number, for example: {"http": 8080}.
    • labels: (Optional) Labels applied to the endpoint.
    • locality: (Optional) Geographic location of the endpoint, e.g., us-west1/zone1.
  • exportTo: (Optional) A list containing namespace names that specify which namespaces can access this ServiceEntry.

. You can use an asterisk (*) to represent all namespaces. The default value is *.

  • subjectAltNames: (optional) A list used to validate the server certificate's Subject Alternative Names (SANs).

Readers can learn more from the official documentation:

https://istio.io/latest/en/docs/tasks/traffic-management/egress/egress-control/

痴者工良

高级程序员劝退师

文章评论