Send Requests Using Istio Egress Gateway in SAP BTP, Kyma Runtime
Configure and use the Istio egress Gateway to allow outbound traffic from your Kyma runtime cluster to specific external destinations.
Overview
You will learn
- How to configure the Istio egress Gateway to allow outbound traffic
- How to send an HTTPS request to an external website
Prerequisites
Steps
Intro
Learn how to configure and use the Istio egress Gateway to allow outbound traffic from your Kyma runtime cluster to specific external destinations. Test your configuration by sending an HTTPS request to an external website using a sample Deployment.
Enable the egress Gateway in the Istio custom resource:
Shell/Bashkubectl apply -f - <<EOF apiVersion: operator.kyma-project.io/v1alpha2 kind: Istio metadata: name: default namespace: kyma-system labels: app.kubernetes.io/name: default spec: components: egressGateway: enabled: true EOFEnable additional sidecar logs to see the egress Gateway being used in requests:
Shell/Bashkubectl apply -f - <<EOF apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-default namespace: istio-system spec: accessLogging: - providers: - name: envoy EOF
Export the name of the namespace in which you want to create a sample Deployment:
Shell/Bashexport NAMESPACE={service-namespace}Create a new namespace for the sample application:
Shell/Bashkubectl create ns $NAMESPACE kubectl label namespace $NAMESPACE istio-injection=enabled --overwriteApply the
curlDeployment to send the requests:Shell/Bashkubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: curl namespace: ${NAMESPACE} --- apiVersion: v1 kind: Service metadata: name: curl namespace: ${NAMESPACE} labels: app: curl service: curl spec: ports: - port: 80 name: http selector: app: curl --- apiVersion: apps/v1 kind: Deployment metadata: name: curl namespace: ${NAMESPACE} spec: replicas: 1 selector: matchLabels: app: curl template: metadata: labels: app: curl spec: terminationGracePeriodSeconds: 0 serviceAccountName: curl containers: - name: curl image: curlimages/curl command: ["/bin/sleep", "infinity"] imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /etc/curl/tls name: secret-volume volumes: - name: secret-volume secret: secretName: curl-secret optional: true EOFExport the name of the
curlPod:Shell/Bashexport SOURCE_POD=$(kubectl get pod -n "$NAMESPACE" -l app=curl -o jsonpath={.items..metadata.name})
Define a ServiceEntry which adds the kyma-project.io hostname to the mesh:
Shell/Bashkubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: ServiceEntry metadata: name: kyma-project namespace: $NAMESPACE spec: hosts: - kyma-project.io ports: - number: 443 name: tls protocol: TLS resolution: DNS EOF
Create an egress Gateway:
Shell/Bashkubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: Gateway metadata: name: istio-egressgateway namespace: ${NAMESPACE} spec: selector: istio: egressgateway servers: - port: number: 443 name: tls protocol: TLS hosts: - kyma-project.io tls: mode: PASSTHROUGH EOFCreate a DestinationRule:
Shell/Bashkubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: egressgateway-for-kyma-project namespace: ${NAMESPACE} spec: host: istio-egressgateway.istio-system.svc.cluster.local subsets: - name: kyma-project EOFCreate a VirtualService:
Shell/Bashkubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: direct-kyma-project-through-egress-gateway namespace: ${NAMESPACE} spec: hosts: - kyma-project.io gateways: - mesh - istio-egressgateway tls: - match: - gateways: - mesh port: 443 sniHosts: - kyma-project.io route: - destination: host: istio-egressgateway.istio-system.svc.cluster.local subset: kyma-project port: number: 443 - match: - gateways: - istio-egressgateway port: 443 sniHosts: - kyma-project.io route: - destination: host: kyma-project.io port: number: 443 weight: 100 EOF
To test your configutation, send an HTTPS request to the kyma-project.io website and check the Istio egress Gateway’s logs.
Send an HTTPS request to the Kyma project website:
Shell/Bashkubectl exec -n "$NAMESPACE" "$SOURCE_POD" -c curl -- curl -sSL -o /dev/null -D - https://kyma-project.ioIf successful, you get a response from the website similar to this one:
Shell/BashHTTP/2 200 accept-ranges: bytes age: 203 ...Check the logs of the Istio egress Gateway:
Shell/Bashkubectl logs -l istio=egressgateway -n istio-systemIf successful, the logs contain the request made by the egress Gateway:
Shell/Bash{"requested_server_name":"kyma-project.io","upstream_cluster":"outbound|443||kyma-project.io",[...]}
By default, Istio cannot securely enforce that egress traffic is routed through the Istio egress Gateway. It only enables the flow through sidecar proxies.
However, you can use Kubernetes NetworkPolicies to restrict namespace traffic, so it only passes through the Istio egress Gateway. NetworkPolicies are the Kubernetes method for enforcing traffic rules within a namespace.
Support for NetworkPolicies depends on the Kubernetes CNI plugin used in the cluster. By default, SAP BTP, Kyma runtime uses the CNI configuration provided and managed by Gardener, which supports NetworkPolicies. However, if youโve made any changes, make sure to check the relevant documentation.
In Gardener-based clusters, such as SAP BTP, Kyma runtime, the Network Policy restricting DNS traffic may not work as expected. It is due to the local DNS service used in discovery working outside the CNI. In such cases, define the IP CIDR of the
kube-dnsservice in the NetworkPolicy’s ipBlock section to allow proper DNS resolution.
Fetch the IP address of the
kube-dnsService:Shell/Bashexport KUBE_DNS_ADDRESS=$(kubectl get svc -n kube-system kube-dns -o jsonpath='{.spec.clusterIP}')Create a NetworkPolicy with the fetched IP address in the ipBlock section. The NetworkPolicy allows only egress traffic to the Istio egress Gateway, blocking all other egress traffic.
Shell/Bashkubectl apply -f - <<EOF apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: network-policy-allow-egress-traffic namespace: ${NAMESPACE} spec: egress: - ports: - port: 53 protocol: UDP to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system - ipBlock: cidr: ${KUBE_DNS_ADDRESS}/32 - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: istio-system podSelector: {} policyTypes: - Egress EOFSend an HTTPS request to the Kyma project website:
Shell/Bashkubectl exec -n "$NAMESPACE" "$SOURCE_POD" -c curl -- curl -sSL -o /dev/null -D - https://kyma-project.ioIf successful, you get a response from the website similar to this one:
Shell/BashHTTP/2 200 accept-ranges: bytes age: 203 ...Send an HTTPS request to an external website:
Shell/Bashkubectl exec -n "$NAMESPACE" "$SOURCE_POD" -c curl -- curl -sSL -o /dev/null -D - https://www.google.comThe request should fail with an error message similar to this one:
Shell/Bashcurl: (35) Recv failure: Connection reset by peer command terminated with exit code 35You have successfully secured the egress traffic in your namespace using Istio egress Gateway and Kubernetes NetworkPolicies.
Resources
Discussion
Share feedback on this tutorial or join the conversation in SAP Community.