This guide demonstrates a client within the service mesh accessing destinations external to the mesh using OSM’s Egress policy API.
Prerequisites
- Kubernetes cluster running Kubernetes v1.20.0 or greater.
- Have OSM installed.
- Have
kubectlavailable to interact with the API server. - Have
osmCLI available for managing the service mesh.
Demo
Enable egress policy if not enabled:
export osm_namespace=osm-system # Replace osm-system with the namespace where OSM is installedkubectl patch meshconfig osm-mesh-config -n "$osm_namespace" -p '{"spec":{"featureFlags":{"enableEgressPolicy":true}}}' --type=merge
Deploy the
curlclient into thecurlnamespace after enrolling its namespace to the mesh.# Create the curl namespacekubectl create namespace curl# Add the namespace to the meshosm namespace add curl# Deploy curl client in the curl namespacekubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.1/manifests/samples/curl/curl.yaml -n curl
Confirm the
curlclient pod is up and running.$ kubectl get pods -n curlNAME READY STATUS RESTARTS AGEcurl-54ccc6954c-9rlvp 2/2 Running 0 20s
HTTP Egress
Confirm the
curlclient is unable make the HTTP requesthttp://httpbin.org:80/getto thehttpbin.orgwebsite on port80.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/getcommand terminated with exit code 7
Apply an Egress policy to allow the
curlclient’s ServiceAccount to access thehttpbin.orgwebsite on port80serving thehttpprotocol.kubectl apply -f - <<EOFkind: EgressapiVersion: policy.openservicemesh.io/v1alpha1metadata:name: httpbin-80namespace: curlspec:sources:- kind: ServiceAccountname: curlnamespace: curlhosts:- httpbin.orgports:- number: 80protocol: httpEOF
Confirm the
curlclient is able to make successful HTTP requests tohttp://httpbin.org:80/get.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/getHTTP/1.1 200 OKdate: Thu, 13 May 2021 21:49:35 GMTcontent-type: application/jsoncontent-length: 335server: envoyaccess-control-allow-origin: *access-control-allow-credentials: truex-envoy-upstream-service-time: 168
Confirm the
curlclient can no longer make successful HTTP requests tohttp://httpbin.org:80/getwhen the above policy is removed.kubectl delete egress httpbin-80 -n curl
$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/getcommand terminated with exit code 7
HTTPS Egress
Since HTTPS traffic is encrypted with TLS, OSM routes HTTPS based traffic by proxying it to its original destination as a TCP stream. The Server Name Indication (SNI) indicated by the HTTPS client application in the TLS handshake is matched against hosts specified in the Egress policy.
Confirm the
curlclient is unable make the HTTPS requesthttps://httpbin.org:443/getto thehttpbin.orgwebsite on port443.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI https://httpbin.org:443/getcommand terminated with exit code 7
Apply an Egress policy to allow the
curlclient’s ServiceAccount to access thehttpbin.orgwebsite on port443serving thehttpsprotocol.kubectl apply -f - <<EOFkind: EgressapiVersion: policy.openservicemesh.io/v1alpha1metadata:name: httpbin-443namespace: curlspec:sources:- kind: ServiceAccountname: curlnamespace: curlhosts:- httpbin.orgports:- number: 443protocol: httpsEOF
Confirm the
curlclient is able to make successful HTTPS requests tohttps://httpbin.org:443/get.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI https://httpbin.org:443/getHTTP/2 200date: Thu, 13 May 2021 22:09:36 GMTcontent-type: application/jsoncontent-length: 260server: gunicorn/19.9.0access-control-allow-origin: *access-control-allow-credentials: true
Confirm the
curlclient can no longer make successful HTTPS requests tohttps://httpbin.org:443/getwhen the above policy is removed.kubectl delete egress httpbin-443 -n curl
$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI https://httpbin.org:443/getcommand terminated with exit code 7
TCP Egress
TCP based Egress traffic is matched against the destination port and IP address ranges specified in an egress policy. If an IP address range is not specified, traffic will be matched only based on the destination port.
Confirm the
curlclient is unable make the HTTPS requesthttps://openservicemesh.io:443to theopenservicemesh.iowebsite on port443. Since HTTPS uses TCP as the underlying transport protocol, TCP based routing should implicitly enable access to any HTTP(s) host on the specified port.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI https://openservicemesh.io:443command terminated with exit code 7
Apply an Egress policy to allow the
curlclient’s ServiceAccount to access the any destination on port443serving thetcpprotocol.kubectl apply -f - <<EOFkind: EgressapiVersion: policy.openservicemesh.io/v1alpha1metadata:name: tcp-443namespace: curlspec:sources:- kind: ServiceAccountname: curlnamespace: curlports:- number: 443protocol: tcpEOF
Note: For
server-firstprotocols such asMySQL,PostgreSQL, etc., where the server initiates the first bytes of data between the client and server, the protocol must be set totcp-server-firstto indicate to OSM to not perform protocol detection on the port. Protocol detection relies on inspecting the initial bytes of a connection, which is incompatible withserver-firstprotocols. When the port’s protocol is set totcp-server-first, protocol detection is skipped for that port number. It is also important to note thatserver-firstport numbers must not be used for other application ports that require protocol detection to performed, which means the port numbers used forserver-firstprotocols must not be used with other protocols such asHTTPandTCPthat require protocol detection to be performed.Confirm the
curlclient is able to make successful HTTPS requests tohttps://openservicemesh.io:443.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI https://openservicemesh.io:443HTTP/2 200cache-control: public, max-age=0, must-revalidatecontent-length: 0content-type: text/html; charset=UTF-8date: Thu, 13 May 2021 22:35:07 GMTetag: "353ebaaf9573718bd1df6b817a472e47-ssl"strict-transport-security: max-age=31536000age: 0server: Netlifyx-nf-request-id: 35a4f2dc-5356-45dc-9208-63e6fa162e0f-3350874
Confirm the
curlclient can no longer make successful HTTPS requests tohttps://openservicemesh.io:443when the above policy is removed.kubectl delete egress tcp-443 -n curl
$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI https://openservicemesh.io:443command terminated with exit code 7
HTTP Egress with SMI route matches
HTTP Egress policies can specify SMI HTTPRouteGroup matches for fine grained traffic control based on HTTP methods, headers and paths.
Confirm the
curlclient is unable make HTTP requests tohttp://httpbin.org:80/getandhttp://httpbin.org:80/status/200to thehttpbin.orgwebsite on port80.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/getcommand terminated with exit code 7$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/status/200command terminated with exit code 7
Apply an SMI HTTPRouteGroup resource to allow access to the HTTP path
/getand an Egress policy to access thehttpbin.orgon website port80that matches on the SMI HTTPRouteGroup.kubectl apply -f - <<EOFapiVersion: specs.smi-spec.io/v1alpha4kind: HTTPRouteGroupmetadata:name: egress-http-routenamespace: curlspec:matches:- name: getpathRegex: /get---kind: EgressapiVersion: policy.openservicemesh.io/v1alpha1metadata:name: httpbin-80namespace: curlspec:sources:- kind: ServiceAccountname: curlnamespace: curlhosts:- httpbin.orgports:- number: 80protocol: httpmatches:- apiGroup: specs.smi-spec.io/v1alpha4kind: HTTPRouteGroupname: egress-http-routeEOF
Confirm the
curlclient is able to make successful HTTP requests tohttp://httpbin.org:80/get.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/getHTTP/1.1 200 OKdate: Thu, 13 May 2021 21:49:35 GMTcontent-type: application/jsoncontent-length: 335server: envoyaccess-control-allow-origin: *access-control-allow-credentials: truex-envoy-upstream-service-time: 168
Confirm the
curlclient is unable to make successful HTTP requests tohttp://httpbin.org:80/status/200.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/status/200HTTP/1.1 404 Not Founddate: Fri, 14 May 2021 17:08:48 GMTserver: envoytransfer-encoding: chunked
Update the matching SMI HTTPRouteGroup resource to allow requests to HTTP paths matching the regex
/status.*.kubectl apply -f - <<EOFapiVersion: specs.smi-spec.io/v1alpha4kind: HTTPRouteGroupmetadata:name: egress-http-routenamespace: curlspec:matches:- name: getpathRegex: /get- name: statuspathRegex: /status.*EOF
Confirm the
curlclient can now make successful HTTP requests tohttp://httpbin.org:80/status/200.$ kubectl exec $(kubectl get pod -n curl -l app=curl -o jsonpath='{.items..metadata.name}') -n curl -c curl -- curl -sI http://httpbin.org:80/status/200HTTP/1.1 200 OKdate: Fri, 14 May 2021 17:10:48 GMTcontent-type: text/html; charset=utf-8content-length: 0server: envoyaccess-control-allow-origin: *access-control-allow-credentials: truex-envoy-upstream-service-time: 188
