Send Requests Using Istio Egress Gateway in SAP BTP, Kyma Runtime
- How to configure the Istio egress Gateway to allow outbound traffic
- How to send an HTTPS request to an external website
Prerequisites
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.
- Step 1
- Enable the egress Gateway in the Istio custom resource:
Shell/BashCopy
kubectl 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 EOF -
Enable additional sidecar logs to see the egress Gateway being used in requests:
Shell/BashCopykubectl apply -f - <<EOF apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-default namespace: istio-system spec: accessLogging: - providers: - name: envoy EOF
- Enable the egress Gateway in the Istio custom resource:
- Step 2
-
Export the name of the namespace in which you want to create a sample Deployment:
Shell/BashCopyexport NAMESPACE={service-namespace} -
Create a new namespace for the sample application:
Shell/BashCopykubectl create ns $NAMESPACE kubectl label namespace $NAMESPACE istio-injection=enabled --overwrite - Apply the
curlDeployment to send the requests:Shell/BashCopykubectl 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 EOF -
Export the name of the
curlPod:Shell/BashCopyexport SOURCE_POD=$(kubectl get pod -n "$NAMESPACE" -l app=curl -o jsonpath={.items..metadata.name})
-
- Step 3
- Define a ServiceEntry which adds the kyma-project.io hostname to the mesh:
Shell/BashCopy
kubectl 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
- Define a ServiceEntry which adds the kyma-project.io hostname to the mesh:
- Step 4
- Create an egress Gateway:
Shell/BashCopy
kubectl 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 EOF - Create a DestinationRule:
Shell/BashCopy
kubectl 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 EOF -
Create a VirtualService:
Shell/BashCopykubectl 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
- Create an egress Gateway:
- Step 5
To test your configutation, send an HTTPS request to the
kyma-project.iowebsite and check the Istio egress Gateway’s logs.-
Send an HTTPS request to the Kyma project website:
Shell/BashCopykubectl 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/BashCopyHTTP/2 200 accept-ranges: bytes age: 203 ... -
Check the logs of the Istio egress Gateway:
Shell/BashCopykubectl logs -l istio=egressgateway -n istio-systemIf successful, the logs contain the request made by the egress Gateway:
Shell/BashCopy{"requested_server_name":"kyma-project.io","upstream_cluster":"outbound|443||kyma-project.io",[...]}
-
- Step 6
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/BashCopyexport 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/BashCopykubectl 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 EOF - Send an HTTPS request to the Kyma project website:
Shell/BashCopy
kubectl 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/BashCopyHTTP/2 200 accept-ranges: bytes age: 203 ... -
Send an HTTPS request to an external website:
Shell/BashCopykubectl 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/BashCopycurl: (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.
-