diff --git a/ci/do_ci.sh b/ci/do_ci.sh index e832dd61ff31e..e8a55c150e034 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -471,7 +471,7 @@ elif [[ "$CI_TARGET" == "tooling" ]]; then bazel run "${BAZEL_BUILD_OPTIONS[@]}" //tools/testing:all_pytests -- --cov-html /source/generated/tooling "${ENVOY_SRCDIR}" exit 0 elif [[ "$CI_TARGET" == "verify_examples" ]]; then - run_ci_verify "*" wasm-cc + run_ci_verify "*" "wasm-cc|win32-front-proxy" exit 0 elif [[ "$CI_TARGET" == "verify_build_examples" ]]; then run_ci_verify wasm-cc diff --git a/ci/verify_examples.sh b/ci/verify_examples.sh index 8f78d54e1a297..8ec2b0701d3e4 100755 --- a/ci/verify_examples.sh +++ b/ci/verify_examples.sh @@ -29,7 +29,8 @@ trap exit 1 INT run_examples () { local examples example cd "${SRCDIR}/examples" || exit 1 - examples=$(find . -mindepth 1 -maxdepth 1 -type d -name "$TESTFILTER" ! -iname "_*" ! -name "$TESTEXCLUDES" | sort) + + examples=$(find . -mindepth 1 -maxdepth 1 -type d -name "$TESTFILTER" ! -iname "_*" | grep -Ev "$TESTEXCLUDES" | sort) for example in $examples; do pushd "$example" > /dev/null || return 1 ./verify.sh diff --git a/docs/root/start/sandboxes/index.rst b/docs/root/start/sandboxes/index.rst index cadaaaa45bb13..75dcb29c91d2d 100644 --- a/docs/root/start/sandboxes/index.rst +++ b/docs/root/start/sandboxes/index.rst @@ -69,4 +69,5 @@ The following sandboxes are available: udp wasm-cc websocket + win32_front_proxy zipkin_tracing diff --git a/docs/root/start/sandboxes/setup.rst b/docs/root/start/sandboxes/setup.rst index 6f4c6067bbda7..eb1c1193823ba 100644 --- a/docs/root/start/sandboxes/setup.rst +++ b/docs/root/start/sandboxes/setup.rst @@ -37,6 +37,9 @@ The user account running the examples will need to have permission to use Docker Full instructions for installing Docker can be found on the `Docker website `_ +If you want to use the Windows based Envoy images make sure that you +`switch Docker to use Windows containers `_. + .. _start_sandboxes_setup_docker_compose: Install Docker Compose diff --git a/docs/root/start/sandboxes/win32_front_proxy.rst b/docs/root/start/sandboxes/win32_front_proxy.rst new file mode 100644 index 0000000000000..625bc6ce2e551 --- /dev/null +++ b/docs/root/start/sandboxes/win32_front_proxy.rst @@ -0,0 +1,352 @@ +Windows based Front proxy +========================= + +.. sidebar:: Requirements + + .. include:: _include/docker-env-setup-link.rst + +To get a flavor of what Envoy has to offer on Windows, we are releasing a +`docker compose `_ sandbox that deploys a front Envoy and a +couple of services (simple Flask apps) colocated with a running service Envoy. + +The three containers will be deployed inside a virtual network called ``envoymesh``. + +Below you can see a graphic showing the docker compose deployment: + +.. image:: /_static/docker_compose_front_proxy.svg + :width: 100% + +All incoming requests are routed via the front Envoy, which is acting as a reverse proxy sitting on +the edge of the ``envoymesh`` network. Port ``8080``, ``8443``, and ``8001`` are exposed by docker +compose (see :download:`docker-compose.yaml <_include/front-proxy/docker-compose.yaml>`) to handle +``HTTP``, ``HTTPS`` calls to the services and requests to ``/admin`` respectively. + +Moreover, notice that all traffic routed by the front Envoy to the service containers is actually +routed to the service Envoys (routes setup in :download:`front-envoy.yaml <_include/front-proxy/front-envoy.yaml>`). + +In turn the service Envoys route the request to the Flask app via the loopback +address (routes setup in :download:`service-envoy.yaml <_include/front-proxy/service-envoy.yaml>`). This +setup illustrates the advantage of running service Envoys collocated with your services: all +requests are handled by the service Envoy, and efficiently routed to your services. + +Step 1: Start all of our containers +*********************************** + +Change to the ``examples/front-proxy`` directory. + +.. code-block:: console + + PS> $PWD + D:\envoy\examples\win32-front-proxy + PS> docker-compose build --pull + PS> docker-compose up -d + PS> docker-compose ps + Name Command State Ports + ------------------------------------------------------------------------------------------------------------------------------------------------------------ + envoy-front-proxy_front-envoy_1 powershell.exe ./start_env ... Up 10000/tcp, 0.0.0.0:8003->8003/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:8443->8443/tcp + envoy-front-proxy_service1_1 powershell.exe ./start_ser ... Up 10000/tcp + envoy-front-proxy_service2_1 powershell.exe ./start_ser ... Up 10000/tcp + +Step 2: Test Envoy's routing capabilities +***************************************** + +You can now send a request to both services via the ``front-envoy``. + +For ``service1``: + +.. code-block:: console + + PS> curl -v localhost:8080/service/1 + * Trying ::1... + * TCP_NODELAY set + * Trying 127.0.0.1... + * TCP_NODELAY set + * Connected to localhost (127.0.0.1) port 8080 (#0) + > GET /service/1 HTTP/1.1 + > Host: localhost:8080 + > User-Agent: curl/7.55.1 + > Accept: */* + > + < HTTP/1.1 200 OK + < content-type: text/html; charset=utf-8 + < content-length: 92 + < server: envoy + < date: Wed, 05 May 2021 05:55:55 GMT + < x-envoy-upstream-service-time: 18 + < + Hello from behind Envoy (service 1)! hostname: 8a45bba91d83 resolvedhostname: 172.30.97.237 + * Connection #0 to host localhost left intact + +For ``service2``: + +.. code-block:: console + + PS> curl -v localhost:8080/service/2 + * Trying ::1... + * TCP_NODELAY set + * Trying 127.0.0.1... + * TCP_NODELAY set + * Connected to localhost (127.0.0.1) port 8080 (#0) + > GET /service/2 HTTP/1.1 + > Host: localhost:8080 + > User-Agent: curl/7.55.1 + > Accept: */* + > + < HTTP/1.1 200 OK + < content-type: text/html; charset=utf-8 + < content-length: 93 + < server: envoy + < date: Wed, 05 May 2021 05:57:03 GMT + < x-envoy-upstream-service-time: 14 + < + Hello from behind Envoy (service 2)! hostname: 51e28eb3c8b8 resolvedhostname: 172.30.109.113 + * Connection #0 to host localhost left intact + +Notice that each request, while sent to the front Envoy, was correctly routed to the respective +application. + +We can also use ``HTTPS`` to call services behind the front Envoy. For example, calling ``service1``: + +.. code-block:: console + + PS> curl https://localhost:8443/service/1 -k -v + * Trying ::1... + * TCP_NODELAY set + * Trying 127.0.0.1... + * TCP_NODELAY set + * Connected to localhost (127.0.0.1) port 8443 (#0) + * schannel: SSL/TLS connection with localhost port 8443 (step 1/3) + * schannel: disabled server certificate revocation checks + * schannel: verifyhost setting prevents Schannel from comparing the supplied target name with the subject names in server certificates. + * schannel: sending initial handshake data: sending 171 bytes... + * schannel: sent initial handshake data: sent 171 bytes + * schannel: SSL/TLS connection with localhost port 8443 (step 2/3) + * schannel: failed to receive handshake, need more data + * schannel: SSL/TLS connection with localhost port 8443 (step 2/3) + * schannel: encrypted data got 1081 + * schannel: encrypted data buffer: offset 1081 length 4096 + * schannel: sending next handshake data: sending 93 bytes... + * schannel: SSL/TLS connection with localhost port 8443 (step 2/3) + * schannel: encrypted data got 258 + * schannel: encrypted data buffer: offset 258 length 4096 + * schannel: SSL/TLS handshake complete + * schannel: SSL/TLS connection with localhost port 8443 (step 3/3) + * schannel: stored credential handle in session cache + > GET /service/1 HTTP/1.1 + > Host: localhost:8443 + > User-Agent: curl/7.55.1 + > Accept: */* + > + * schannel: client wants to read 102400 bytes + * schannel: encdata_buffer resized 103424 + * schannel: encrypted data buffer: offset 0 length 103424 + * schannel: encrypted data got 286 + * schannel: encrypted data buffer: offset 286 length 103424 + * schannel: decrypted data length: 257 + * schannel: decrypted data added: 257 + * schannel: decrypted data cached: offset 257 length 102400 + * schannel: encrypted data buffer: offset 0 length 103424 + * schannel: decrypted data buffer: offset 257 length 102400 + * schannel: schannel_recv cleanup + * schannel: decrypted data returned 257 + * schannel: decrypted data buffer: offset 0 length 102400 + < HTTP/1.1 200 OK + < content-type: text/html; charset=utf-8 + < content-length: 92 + < server: envoy + < date: Wed, 05 May 2021 05:57:45 GMT + < x-envoy-upstream-service-time: 3 + < + Hello from behind Envoy (service 1)! hostname: 8a45bba91d83 resolvedhostname: 172.30.97.237 + * Connection #0 to host localhost left intact + +Step 3: Test Envoy's load balancing capabilities +************************************************ + +Now let's scale up our ``service1`` nodes to demonstrate the load balancing abilities of Envoy: + +.. code-block:: console + + PS> docker-compose scale service1=3 + Creating and starting example_service1_2 ... done + Creating and starting example_service1_3 ... done + +Now if we send a request to ``service1`` multiple times, the front Envoy will load balance the +requests by doing a round robin of the three ``service1`` machines: + +.. code-block:: console + + PS> curl -v localhost:8080/service/1 + * Trying ::1... + * TCP_NODELAY set + * Trying 127.0.0.1... + * TCP_NODELAY set + * Connected to localhost (127.0.0.1) port 8080 (#0) + > GET /service/1 HTTP/1.1 + > Host: localhost:8080 + > User-Agent: curl/7.55.1 + > Accept: */* + > + < HTTP/1.1 200 OK + < content-type: text/html; charset=utf-8 + < content-length: 93 + < server: envoy + < date: Wed, 05 May 2021 05:58:40 GMT + < x-envoy-upstream-service-time: 22 + < + Hello from behind Envoy (service 1)! hostname: 8d2359ee21a8 resolvedhostname: 172.30.101.143 + * Connection #0 to host localhost left intact + PS> curl -v localhost:8080/service/1 + * Trying ::1... + * TCP_NODELAY set + * Trying 127.0.0.1... + * TCP_NODELAY set + * Connected to localhost (127.0.0.1) port 8080 (#0) + > GET /service/1 HTTP/1.1 + > Host: localhost:8080 + > User-Agent: curl/7.55.1 + > Accept: */* + > + < HTTP/1.1 200 OK + < content-type: text/html; charset=utf-8 + < content-length: 91 + < server: envoy + < date: Wed, 05 May 2021 05:58:43 GMT + < x-envoy-upstream-service-time: 11 + < + Hello from behind Envoy (service 1)! hostname: 41e1141eebf4 resolvedhostname: 172.30.96.11 + * Connection #0 to host localhost left intact + PS> curl -v localhost:8080/service/1 + * Trying ::1... + * TCP_NODELAY set + * Trying 127.0.0.1... + * TCP_NODELAY set + * Connected to localhost (127.0.0.1) port 8080 (#0) + > GET /service/1 HTTP/1.1 + > Host: localhost:8080 + > User-Agent: curl/7.55.1 + > Accept: */* + > + < HTTP/1.1 200 OK + < content-type: text/html; charset=utf-8 + < content-length: 92 + < server: envoy + < date: Wed, 05 May 2021 05:58:44 GMT + < x-envoy-upstream-service-time: 7 + < + Hello from behind Envoy (service 1)! hostname: 8a45bba91d83 resolvedhostname: 172.30.97.237 + * Connection #0 to host localhost left intact + +Step 4: Enter containers and curl services +****************************************** + +In addition of using ``curl`` from your host machine, you can also enter the +containers themselves and ``curl`` from inside them. To enter a container you +can use ``docker-compose exec /bin/bash``. For example we can +enter the ``front-envoy`` container, and ``curl`` for services locally: + +.. code-block:: console + + PS> docker-compose exec front-envoy powershell + PS C:\> (curl -UseBasicParsing http://localhost:8080/service/1).Content + Hello from behind Envoy (service 1)! hostname: 41e1141eebf4 resolvedhostname: 172.30.96.11 + + PS C:\> (curl -UseBasicParsing http://localhost:8080/service/1).Content + Hello from behind Envoy (service 1)! hostname: 8a45bba91d83 resolvedhostname: 172.30.97.237 + + PS C:\> (curl -UseBasicParsing http://localhost:8080/service/1).Content + Hello from behind Envoy (service 1)! hostname: 8d2359ee21a8 resolvedhostname: 172.30.101.143 + + +Step 5: Enter container and curl admin interface +************************************************ + +When Envoy runs it also attaches an ``admin`` to your desired port. + +In the example configs the admin listener is bound to port ``8001``. + +We can ``curl`` it to gain useful information: + +- :ref:`/server_info ` provides information about the Envoy version you are running. +- :ref:`/stats ` provides statistics about the Envoy server. + +In the example we can enter the ``front-envoy`` container to query admin: + +.. code-block:: console + + PS> docker-compose exec front-envoy powershell + PS C:\> (curl http://localhost:8003/server_info -UseBasicParsing).Content + +.. code-block:: json + + { + "version": "093e2ffe046313242144d0431f1bb5cf18d82544/1.15.0-dev/Clean/RELEASE/BoringSSL", + "state": "LIVE", + "hot_restart_version": "11.104", + "command_line_options": { + "base_id": "0", + "use_dynamic_base_id": false, + "base_id_path": "", + "concurrency": 8, + "config_path": "/etc/front-envoy.yaml", + "config_yaml": "", + "allow_unknown_static_fields": false, + "reject_unknown_dynamic_fields": false, + "ignore_unknown_dynamic_fields": false, + "admin_address_path": "", + "local_address_ip_version": "v4", + "log_level": "info", + "component_log_level": "", + "log_format": "[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v", + "log_format_escaped": false, + "log_path": "", + "service_cluster": "front-proxy", + "service_node": "", + "service_zone": "", + "drain_strategy": "Gradual", + "mode": "Serve", + "disable_hot_restart": false, + "enable_mutex_tracing": false, + "restart_epoch": 0, + "cpuset_threads": false, + "disabled_extensions": [], + "bootstrap_version": 0, + "hidden_envoy_deprecated_max_stats": "0", + "hidden_envoy_deprecated_max_obj_name_len": "0", + "file_flush_interval": "10s", + "drain_time": "600s", + "parent_shutdown_time": "900s" + }, + "uptime_current_epoch": "188s", + "uptime_all_epochs": "188s" + } + +.. code-block:: console + + PS C:\> (curl http://localhost:8003/stats -UseBasicParsing).Content + cluster.service1.external.upstream_rq_200: 7 + ... + cluster.service1.membership_change: 2 + cluster.service1.membership_total: 3 + ... + cluster.service1.upstream_cx_http2_total: 3 + ... + cluster.service1.upstream_rq_total: 7 + ... + cluster.service2.external.upstream_rq_200: 2 + ... + cluster.service2.membership_change: 1 + cluster.service2.membership_total: 1 + ... + cluster.service2.upstream_cx_http2_total: 1 + ... + cluster.service2.upstream_rq_total: 2 + ... + +Notice that we can get the number of members of upstream clusters, number of requests fulfilled by +them, information about http ingress, and a plethora of other useful stats. + +.. seealso:: + + :ref:`Envoy admin quick start guide ` + Quick start guide to the Envoy admin interface. diff --git a/examples/win32-front-proxy/Dockerfile-frontenvoy b/examples/win32-front-proxy/Dockerfile-frontenvoy new file mode 100644 index 0000000000000..3a3494f54c0d1 --- /dev/null +++ b/examples/win32-front-proxy/Dockerfile-frontenvoy @@ -0,0 +1,6 @@ +FROM envoyproxy/envoy-windows-dev:latest + +COPY ./front-envoy.yaml './front-envoy.yaml' +COPY ./start_envoy.ps1 ./start_envoy.ps1 +ENTRYPOINT ["powershell.exe", "./start_envoy.ps1"] + diff --git a/examples/win32-front-proxy/Dockerfile-service b/examples/win32-front-proxy/Dockerfile-service new file mode 100644 index 0000000000000..a347d8c3189fc --- /dev/null +++ b/examples/win32-front-proxy/Dockerfile-service @@ -0,0 +1,12 @@ +FROM envoyproxy/envoy-windows-dev:latest + +COPY ./setup_python.ps1 / + +RUN powershell.exe .\\setup_python.ps1 +RUN pip3 install -q Flask==0.11.1 requests==2.18.4 + +RUN powershell mkdir code +ADD ./service.py ./code +ADD ./service-envoy.yaml ./service-envoy.yaml +ADD ./start_service.ps1 ./start_service.ps1 +ENTRYPOINT ["powershell.exe", "./start_service.ps1"] diff --git a/examples/win32-front-proxy/README.md b/examples/win32-front-proxy/README.md new file mode 100644 index 0000000000000..cca1fdaf55f96 --- /dev/null +++ b/examples/win32-front-proxy/README.md @@ -0,0 +1,2 @@ +To learn about this sandbox and for instructions on how to run it please head over +to the [envoy docs](https://www.envoyproxy.io/docs/envoy/latest/start/sandboxes/win32_front_proxy.html) diff --git a/examples/win32-front-proxy/docker-compose.yaml b/examples/win32-front-proxy/docker-compose.yaml new file mode 100644 index 0000000000000..71ea7751d01c4 --- /dev/null +++ b/examples/win32-front-proxy/docker-compose.yaml @@ -0,0 +1,34 @@ +version: "3.7" +services: + + front-envoy: + build: + context: . + dockerfile: Dockerfile-frontenvoy + networks: + - envoymesh + ports: + - "8080:8080" + - "8443:8443" + - "8003:8003" + + service1: + build: + context: . + dockerfile: Dockerfile-service + networks: + - envoymesh + environment: + - SERVICE_NAME=1 + + service2: + build: + context: . + dockerfile: Dockerfile-service + networks: + - envoymesh + environment: + - SERVICE_NAME=2 + +networks: + envoymesh: {} diff --git a/examples/win32-front-proxy/front-envoy.yaml b/examples/win32-front-proxy/front-envoy.yaml new file mode 100644 index 0000000000000..d96a5d31538c3 --- /dev/null +++ b/examples/win32-front-proxy/front-envoy.yaml @@ -0,0 +1,167 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 8080 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: backend + domains: + - "*" + routes: + - match: + prefix: "/service/1" + route: + cluster: service1 + - match: + prefix: "/service/2" + route: + cluster: service2 + http_filters: + - name: envoy.filters.http.router + typed_config: {} + + - address: + socket_address: + address: 0.0.0.0 + port_value: 8443 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: backend + domains: + - "*" + routes: + - match: + prefix: "/service/1" + route: + cluster: service1 + - match: + prefix: "/service/2" + route: + cluster: service2 + http_filters: + - name: envoy.filters.http.router + typed_config: {} + + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificates: + # The following self-signed certificate pair is generated using: + # $ openssl req -x509 -newkey rsa:2048 -keyout a/front-proxy-key.pem -out a/front-proxy-crt.pem -days 3650 -nodes -subj '/CN=front-envoy' + # + # Instead of feeding it as an inline_string, certificate pair can also be fed to Envoy + # via filename. Reference: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/base.proto#config-core-v3-datasource. + # + # Or in a dynamic configuration scenario, certificate pair can be fetched remotely via + # Secret Discovery Service (SDS). Reference: https://www.envoyproxy.io/docs/envoy/latest/configuration/security/secret. + - certificate_chain: + inline_string: | + -----BEGIN CERTIFICATE----- + MIICqDCCAZACCQCquzpHNpqBcDANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtm + cm9udC1lbnZveTAeFw0yMDA3MDgwMTMxNDZaFw0zMDA3MDYwMTMxNDZaMBYxFDAS + BgNVBAMMC2Zyb250LWVudm95MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC + AQEAthnYkqVQBX+Wg7aQWyCCb87hBce1hAFhbRM8Y9dQTqxoMXZiA2n8G089hUou + oQpEdJgitXVS6YMFPFUUWfwcqxYAynLK4X5im26Yfa1eO8La8sZUS+4Bjao1gF5/ + VJxSEo2yZ7fFBo8M4E44ZehIIocipCRS+YZehFs6dmHoq/MGvh2eAHIa+O9xssPt + ofFcQMR8rwBHVbKy484O10tNCouX4yUkyQXqCRy6HRu7kSjOjNKSGtjfG+h5M8bh + 10W7ZrsJ1hWhzBulSaMZaUY3vh5ngpws1JATQVSK1Jm/dmMRciwlTK7KfzgxHlSX + 58ENpS7yPTISkEICcLbXkkKGEQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCmj6Hg + vwOxWz0xu+6fSfRL6PGJUGq6wghCfUvjfwZ7zppDUqU47fk+yqPIOzuGZMdAqi7N + v1DXkeO4A3hnMD22Rlqt25vfogAaZVToBeQxCPd/ALBLFrvLUFYuSlS3zXSBpQqQ + Ny2IKFYsMllz5RSROONHBjaJOn5OwqenJ91MPmTAG7ujXKN6INSBM0PjX9Jy4Xb9 + zT+I85jRDQHnTFce1WICBDCYidTIvJtdSSokGSuy4/xyxAAc/BpZAfOjBQ4G1QRe + 9XwOi790LyNUYFJVyeOvNJwveloWuPLHb9idmY5YABwikUY6QNcXwyHTbRCkPB2I + m+/R4XnmL4cKQ+5Z + -----END CERTIFICATE----- + private_key: + inline_string: | + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2GdiSpVAFf5aD + tpBbIIJvzuEFx7WEAWFtEzxj11BOrGgxdmIDafwbTz2FSi6hCkR0mCK1dVLpgwU8 + VRRZ/ByrFgDKcsrhfmKbbph9rV47wtryxlRL7gGNqjWAXn9UnFISjbJnt8UGjwzg + Tjhl6EgihyKkJFL5hl6EWzp2Yeir8wa+HZ4Achr473Gyw+2h8VxAxHyvAEdVsrLj + zg7XS00Ki5fjJSTJBeoJHLodG7uRKM6M0pIa2N8b6HkzxuHXRbtmuwnWFaHMG6VJ + oxlpRje+HmeCnCzUkBNBVIrUmb92YxFyLCVMrsp/ODEeVJfnwQ2lLvI9MhKQQgJw + tteSQoYRAgMBAAECggEAeDGdEkYNCGQLe8pvg8Z0ccoSGpeTxpqGrNEKhjfi6NrB + NwyVav10iq4FxEmPd3nobzDPkAftfvWc6hKaCT7vyTkPspCMOsQJ39/ixOk+jqFx + lNa1YxyoZ9IV2DIHR1iaj2Z5gB367PZUoGTgstrbafbaNY9IOSyojCIO935ubbcx + DWwL24XAf51ez6sXnI8V5tXmrFlNXhbhJdH8iIxNyM45HrnlUlOk0lCK4gmLJjy9 + 10IS2H2Wh3M5zsTpihH1JvM56oAH1ahrhMXs/rVFXXkg50yD1KV+HQiEbglYKUxO + eMYtfaY9i2CuLwhDnWp3oxP3HfgQQhD09OEN3e0IlQKBgQDZ/3poG9TiMZSjfKqL + xnCABMXGVQsfFWNC8THoW6RRx5Rqi8q08yJrmhCu32YKvccsOljDQJQQJdQO1g09 + e/adJmCnTrqxNtjPkX9txV23Lp6Ak7emjiQ5ICu7iWxrcO3zf7hmKtj7z+av8sjO + mDI7NkX5vnlE74nztBEjp3eC0wKBgQDV2GeJV028RW3b/QyP3Gwmax2+cKLR9PKR + nJnmO5bxAT0nQ3xuJEAqMIss/Rfb/macWc2N/6CWJCRT6a2vgy6xBW+bqG6RdQMB + xEZXFZl+sSKhXPkc5Wjb4lQ14YWyRPrTjMlwez3k4UolIJhJmwl+D7OkMRrOUERO + EtUvc7odCwKBgBi+nhdZKWXveM7B5N3uzXBKmmRz3MpPdC/yDtcwJ8u8msUpTv4R + JxQNrd0bsIqBli0YBmFLYEMg+BwjAee7vXeDFq+HCTv6XMva2RsNryCO4yD3I359 + XfE6DJzB8ZOUgv4Dvluie3TB2Y6ZQV/p+LGt7G13yG4hvofyJYvlg3RPAoGAcjDg + +OH5zLN2eqah8qBN0CYa9/rFt0AJ19+7/smLTJ7QvQq4g0gwS1couplcCEnNGWiK + 72y1n/ckvvplmPeAE19HveMvR9UoCeV5ej86fACy8V/oVpnaaLBvL2aCMjPLjPP9 + DWeCIZp8MV86cvOrGfngf6kJG2qZTueXl4NAuwkCgYEArKkhlZVXjwBoVvtHYmN2 + o+F6cGMlRJTLhNc391WApsgDZfTZSdeJsBsvvzS/Nc0burrufJg0wYioTlpReSy4 + ohhtprnQQAddfjHP7rh2LGt+irFzhdXXQ1ybGaGM9D764KUNCXLuwdly0vzXU4HU + q5sGxGrC1RECGB5Zwx2S2ZY= + -----END PRIVATE KEY----- + + clusters: + - name: service1 + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: service1 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: service1 + port_value: 8000 + - name: service2 + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: service2 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: service2 + port_value: 8000 +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 8001 +layered_runtime: + layers: + - name: static_layer_0 + static_layer: + envoy: + resource_limits: + listener: + example_listener_name: + connection_limit: 10000 diff --git a/examples/win32-front-proxy/service-envoy.yaml b/examples/win32-front-proxy/service-envoy.yaml new file mode 100644 index 0000000000000..b3ea728cc5f60 --- /dev/null +++ b/examples/win32-front-proxy/service-envoy.yaml @@ -0,0 +1,46 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 8000 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: service + domains: + - "*" + routes: + - match: + prefix: "/service" + route: + cluster: local_service + http_filters: + - name: envoy.filters.http.router + typed_config: {} + clusters: + - name: local_service + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: local_service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8080 +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 8081 diff --git a/examples/win32-front-proxy/service.py b/examples/win32-front-proxy/service.py new file mode 100644 index 0000000000000..d08b0a897c9e0 --- /dev/null +++ b/examples/win32-front-proxy/service.py @@ -0,0 +1,31 @@ +from flask import Flask +import os +import requests +import socket +import sys + +app = Flask(__name__) + + +@app.route('/service/') +def hello(service_number): + return ( + 'Hello from behind Envoy (service {})! hostname: {} resolved' + 'hostname: {}\n'.format( + os.environ['SERVICE_NAME'], socket.gethostname(), + socket.gethostbyname(socket.gethostname()))) + + +@app.route('/trace/') +def trace(service_number): + if int(os.environ['SERVICE_NAME']) == 1: + requests.get("http://localhost:9000/trace/2") + return ( + 'Hello from behind Envoy (service {})! hostname: {} resolved' + 'hostname: {}\n'.format( + os.environ['SERVICE_NAME'], socket.gethostname(), + socket.gethostbyname(socket.gethostname()))) + + +if __name__ == "__main__": + app.run(host='127.0.0.1', port=8080, debug=True) diff --git a/examples/win32-front-proxy/setup_python.ps1 b/examples/win32-front-proxy/setup_python.ps1 new file mode 100644 index 0000000000000..0905a4b03062c --- /dev/null +++ b/examples/win32-front-proxy/setup_python.ps1 @@ -0,0 +1,54 @@ +$ErrorActionPreference = "Stop"; + +function DownloadAndCheck +{ + param([string]$to, [string]$url, [string]$sha256) + + Write-Host "Downloading $url to $to..." + (New-Object System.Net.WebClient).DownloadFile($url, $to) + $actual = (Get-FileHash -Path $to -Algorithm SHA256).Hash + if ($actual -ne $sha256) { + Write-Host "Download of $url to $to is invalid, expected sha256: $sha256, but got: $actual"; + exit 1 + } + Write-Host "done." +} + +function AddToPath +{ + param([string] $directory) + + $oldPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path + $newPath = "$oldPath;$directory" + Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath + # Add to local path so subsequent commands have access to the executables they need + $env:PATH += ";$directory" + Write-Host "Added $directory to PATH" +} + +function RunAndCheckError +{ + param([string] $exe, [string[]] $argList, [Parameter(Mandatory=$false)] $isInstaller = $false) + + Write-Host "Running '$exe $argList'..." + if ($isInstaller) { + Write-Host "(running as Windows software installer)" + Start-Process $exe -ArgumentList "$argList" -Wait -NoNewWindow + } else { + &$exe $argList + if ($LASTEXITCODE -ne 0) { + Write-Host "$exe $argList exited with code $LASTEXITCODE" + exit $LASTEXITCODE + } + } + Write-Host "done." +} + +# Python3 (do not install via msys2 or the MS store's flavors, this version follows Win32 semantics) +DownloadAndCheck $env:TEMP\python3-installer.exe ` + https://www.python.org/ftp/python/3.8.5/python-3.8.5-amd64.exe ` + cd427c7b17337d7c13761ca20877d2d8be661bd30415ddc17072a31a65a91b64 +# python installer needs to be run as an installer with Start-Process +RunAndCheckError "$env:TEMP\python3-installer.exe" @("/quiet", "InstallAllUsers=1", "Include_launcher=0", "InstallLauncherAllUsers=0") $true +AddToPath $env:ProgramFiles\Python38 +AddToPath $env:ProgramFiles\Python38\Scripts diff --git a/examples/win32-front-proxy/start_envoy.ps1 b/examples/win32-front-proxy/start_envoy.ps1 new file mode 100644 index 0000000000000..efe1e2592e248 --- /dev/null +++ b/examples/win32-front-proxy/start_envoy.ps1 @@ -0,0 +1 @@ +& 'C:\\Program Files\\envoy\\envoy.exe' --config-path .\front-envoy.yaml --service-cluster front-proxy diff --git a/examples/win32-front-proxy/start_service.ps1 b/examples/win32-front-proxy/start_service.ps1 new file mode 100644 index 0000000000000..0aabb3b0b3deb --- /dev/null +++ b/examples/win32-front-proxy/start_service.ps1 @@ -0,0 +1,4 @@ +Start-Process -FilePath "python" -ArgumentList @("./code/service.py") + +$serviceName = "service$env:ServiceId" +& 'C:\\Program Files\\envoy\\envoy.exe' --config-path .\service-envoy.yaml --service-cluster $serviceName