diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..9576c5422 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +config +./**/build/** +./idea +./gradle diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..8b85a859c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,95 @@ +FROM alpine:3.9 as consul + +# This is the release of Consul to pull in. +ENV CONSUL_VERSION=1.7.4 + +# This is the location of the releases. +ENV HASHICORP_RELEASES=https://releases.hashicorp.com + +# Set up certificates, base tools, and Consul. +# libc6-compat is needed to symlink the shared libraries for ARM builds +RUN set -eux && \ + apk add --no-cache ca-certificates curl dumb-init gnupg libcap openssl su-exec iputils jq libc6-compat && \ + gpg --keyserver keyserver.ubuntu.com --recv-keys 91A6E7F85D05C65630BEF18951852D87348FFC4C && \ + mkdir -p /tmp/build && \ + cd /tmp/build && \ + apkArch="$(apk --print-arch)" && \ + case "${apkArch}" in \ + aarch64) consulArch='arm64' ;; \ + armhf) consulArch='armhfv6' ;; \ + x86) consulArch='386' ;; \ + x86_64) consulArch='amd64' ;; \ + *) echo >&2 "error: unsupported architecture: ${apkArch} (see ${HASHICORP_RELEASES}/consul/${CONSUL_VERSION}/)" && exit 1 ;; \ + esac && \ + wget ${HASHICORP_RELEASES}/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_${consulArch}.zip && \ + wget ${HASHICORP_RELEASES}/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_SHA256SUMS && \ + wget ${HASHICORP_RELEASES}/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_SHA256SUMS.sig && \ + gpg --batch --verify consul_${CONSUL_VERSION}_SHA256SUMS.sig consul_${CONSUL_VERSION}_SHA256SUMS && \ + grep consul_${CONSUL_VERSION}_linux_${consulArch}.zip consul_${CONSUL_VERSION}_SHA256SUMS | sha256sum -c && \ + unzip -d /bin consul_${CONSUL_VERSION}_linux_${consulArch}.zip && \ + cd /tmp && \ + rm -rf /tmp/build && \ + gpgconf --kill all && \ + apk del gnupg openssl && \ + rm -rf /root/.gnupg && \ +# tiny smoke test to ensure the binary we downloaded runs + consul version + +# The /consul/data dir is used by Consul to store state. The agent will be started +# with /consul/config as the configuration directory so you can add additional +# config files in that location. +RUN mkdir -p /consul/data && \ + mkdir -p /consul/config + +# set up nsswitch.conf for Go's "netgo" implementation which is used by Consul, +# otherwise DNS supercedes the container's hosts file, which we don't want. +RUN test -e /etc/nsswitch.conf || echo 'hosts: files dns' > /etc/nsswitch.conf + +# Expose the consul data directory as a volume since there's mutable state in there. +VOLUME /consul/data + +# Server RPC is used for communication between Consul clients and servers for internal +# request forwarding. +EXPOSE 8300 + +# Serf LAN and WAN (WAN is used only by Consul servers) are used for gossip between +# Consul agents. LAN is within the datacenter and WAN is between just the Consul +# servers in all datacenters. +EXPOSE 8301 8301/udp 8302 8302/udp + +# HTTP and DNS (both TCP and UDP) are the primary interfaces that applications +# use to interact with Consul. +EXPOSE 8500 8600 8600/udp + +# Consul doesn't need root privileges so we run it as the consul user from the +# entry point script. The entry point script also uses dumb-init as the top-level +# process to reap any zombie processes created by Consul sub-processes. + +FROM gradle:5.6.2-jdk11 AS build +COPY --chown=gradle:gradle settings.gradle build.gradle /home/gradle/src/ +COPY --chown=gradle:gradle envoy-control-core/ /home/gradle/src/envoy-control-core/ +COPY --chown=gradle:gradle envoy-control-runner/ /home/gradle/src/envoy-control-runner/ +COPY --chown=gradle:gradle envoy-control-services/ /home/gradle/src/envoy-control-services/ +COPY --chown=gradle:gradle envoy-control-source-consul/ /home/gradle/src/envoy-control-source-consul/ +WORKDIR /home/gradle/src +RUN gradle :envoy-control-runner:assemble --parallel --no-daemon + +FROM envoyproxy/envoy-alpine-dev:6c2137468c25d167dbbe4719b0ecaf343bfb4233 as envoy +COPY heroku/envoy1.yaml /etc/envoy1.yaml +COPY heroku/envoy2.yaml /etc/envoy2.yaml +COPY heroku/envoy-front-proxy.yaml /etc/envoy-front-proxy.yaml +COPY --from=consul /bin/consul /bin/consul + +RUN apk --no-cache add openjdk11 curl --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community +RUN mkdir /tmp/envoy-control-dist /tmp/envoy-control /bin/envoy-control /etc/envoy-control +COPY --from=build /home/gradle/src/envoy-control-runner/build/distributions/ /tmp/envoy-control-dist +COPY ./envoy-control-runner/src/main/resources/application.yaml /etc/envoy-control/ +COPY heroku/register-echo1.json /etc/envoy-control/ +COPY heroku/register-echo2.json /etc/envoy-control/ +RUN tar -xf /tmp/envoy-control-dist/envoy-control-runner*.tar -C /tmp/envoy-control +RUN mv /tmp/envoy-control/envoy-control-runner*/ /bin/envoy-control/envoy-control-runner +# APP_PORT: 8080 +# XDS_PORT: 50000 + +COPY heroku/run-envoy.sh /run-envoy.sh +CMD ["sh", "/run-envoy.sh"] diff --git a/app.json b/app.json new file mode 100644 index 000000000..d845b8e33 --- /dev/null +++ b/app.json @@ -0,0 +1,8 @@ +{ + "addons": [ + { + "plan": "papertrail:choklad" + } + ], + "stack": "container" +} diff --git a/heroku.yml b/heroku.yml new file mode 100644 index 000000000..f629ab176 --- /dev/null +++ b/heroku.yml @@ -0,0 +1,7 @@ +setup: + addons: + - plan: 'papertrail:choklad' + as: PAPERTRAIL +build: + docker: + web: Dockerfile diff --git a/heroku/envoy-front-proxy.yaml b/heroku/envoy-front-proxy.yaml new file mode 100644 index 000000000..4b82e0994 --- /dev/null +++ b/heroku/envoy-front-proxy.yaml @@ -0,0 +1,173 @@ +admin: + access_log_path: /dev/stdout + address: + socket_address: + address: 0.0.0.0 + port_value: 10001 +static_resources: + clusters: + - name: this_admin + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: this_admin + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10001 + - name: envoy1 + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: envoy1 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10010 + - name: envoy1-egress + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: envoy1-egress + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10011 + - name: envoy1-direct + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: envoy1-direct + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10013 + + - name: envoy2 + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: envoy2 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10020 + - name: envoy2-egress + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: envoy2-egress + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10021 + - name: envoy2-direct + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: envoy2-direct + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10023 + + - name: ec1 + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: ec1 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8080 + - name: consul1 + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: consul1 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8500 + listeners: + - name: ingress + address: + socket_address: + address: 0.0.0.0 + port_value: {{.IngressListenerPort}} + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager + use_remote_address: true + stat_prefix: ingress_http + codec_type: AUTO + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: { prefix: "/ec1/"} + route: + cluster: ec1 + prefix_rewrite: "/" + - match: { prefix: "/envoy1/ingress/"} + route: + cluster: envoy1 + prefix_rewrite: "/" + - match: { prefix: "/envoy1/egress/"} + route: + cluster: envoy1-egress + prefix_rewrite: "/" + - match: { prefix: "/envoy1/direct/"} + route: + cluster: envoy1-direct + prefix_rewrite: "/" + - match: { prefix: "/consul/ui"} + route: + cluster: consul1 + prefix_rewrite: "/consul/ui" + - match: { prefix: "/v1/"} + route: + cluster: consul1 + prefix_rewrite: "/v1/" + - match: { prefix: "/status/envoy/"} + route: + cluster: this_admin + prefix_rewrite: "/" + - match: { path: "/" } + direct_response: + status: 200 + body: + inline_string: '

Welcome to mesh on heroku

\n

this is front proxy view, see apps

envoy1
' + http_filters: + - name: envoy.filters.http.router \ No newline at end of file diff --git a/heroku/envoy1.yaml b/heroku/envoy1.yaml new file mode 100644 index 000000000..bdf40d11b --- /dev/null +++ b/heroku/envoy1.yaml @@ -0,0 +1,97 @@ +admin: + access_log_path: /dev/stdout + address: + socket_address: + address: 0.0.0.0 + port_value: 10012 +dynamic_resources: + lds_config: {ads: {}} + cds_config: {ads: {}} + ads_config: + api_type: GRPC + grpc_services: + envoy_grpc: + cluster_name: envoy-control-xds +node: + cluster: test-cluster + id: test-id + metadata: + service_name: "echo1" + ads: true + ingress_host: "0.0.0.0" + ingress_port: 10010 + egress_host: "0.0.0.0" + egress_port: 10011 + use_remote_address: true + access_log_enabled: false + add_upstream_external_address_header: true + resources_dir: "/etc/envoy/extra" + proxy_settings: + incoming: + endpoints: + - pathPrefix: "/" + clients: ["echo2"] + outgoing: + dependencies: + - service: "consul" + - service: "echo1" + - service: "echo2" +static_resources: + listeners: + - name: ingress_direct_response + address: + socket_address: + address: 0.0.0.0 + port_value: 10013 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager + use_remote_address: true + stat_prefix: ingress_http + codec_type: AUTO + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: { prefix: "/status/envoy/"} + route: + cluster: this_admin + prefix_rewrite: "/" + - match: { path: "/" } + direct_response: + status: 200 + body: + inline_string: "Hello from echo1" + http_filters: + - name: envoy.filters.http.router + clusters: + - name: local_service + connect_timeout: 1s + hosts: + - socket_address: + address: 127.0.0.1 + port_value: 10013 + http2_protocol_options: {} + - name: envoy-control-xds + connect_timeout: 1s + hosts: + - socket_address: + address: 127.0.0.1 + port_value: 50000 + http2_protocol_options: {} + - name: this_admin + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: this_admin + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10012 diff --git a/heroku/envoy2.yaml b/heroku/envoy2.yaml new file mode 100644 index 000000000..e445348bb --- /dev/null +++ b/heroku/envoy2.yaml @@ -0,0 +1,97 @@ +admin: + access_log_path: /dev/stdout + address: + socket_address: + address: 0.0.0.0 + port_value: 10022 +dynamic_resources: + lds_config: {ads: {}} + cds_config: {ads: {}} + ads_config: + api_type: GRPC + grpc_services: + envoy_grpc: + cluster_name: envoy-control-xds +node: + cluster: test-cluster + id: test-id + metadata: + service_name: "echo2" + ads: true + ingress_host: "0.0.0.0" + ingress_port: 10020 + egress_host: "0.0.0.0" + egress_port: 10021 + use_remote_address: true + access_log_enabled: false + add_upstream_external_address_header: true + resources_dir: "/etc/envoy/extra" + proxy_settings: + incoming: + endpoints: + - pathPrefix: "/" + clients: ["echo1"] + outgoing: + dependencies: + - service: "consul" + - service: "echo1" + - service: "echo2" +static_resources: + listeners: + - name: ingress_direct_response + address: + socket_address: + address: 0.0.0.0 + port_value: 10023 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager + use_remote_address: true + stat_prefix: ingress_http + codec_type: AUTO + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: { prefix: "/status/envoy/"} + route: + cluster: this_admin + prefix_rewrite: "/" + - match: { path: "/" } + direct_response: + status: 200 + body: + inline_string: "Hello from echo2" + http_filters: + - name: envoy.filters.http.router + clusters: + - name: local_service + connect_timeout: 1s + hosts: + - socket_address: + address: 127.0.0.1 + port_value: 10023 + http2_protocol_options: {} + - name: envoy-control-xds + connect_timeout: 1s + hosts: + - socket_address: + address: 127.0.0.1 + port_value: 50000 + http2_protocol_options: {} + - name: this_admin + type: STATIC + connect_timeout: 1s + load_assignment: + cluster_name: this_admin + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10022 diff --git a/heroku/register-echo1.json b/heroku/register-echo1.json new file mode 100644 index 000000000..bcb3292c5 --- /dev/null +++ b/heroku/register-echo1.json @@ -0,0 +1,15 @@ +{ + "ID":"echo1", + "Name":"echo1", + "Tags":[ + "primary" + ], + "Address":"127.0.0.1", + "Port":10010, + "Check":{ + "DeregisterCriticalServiceAfter":"90m", + "http":"http://127.0.0.1:10010", + "Interval":"10s" + } +} + diff --git a/heroku/register-echo2.json b/heroku/register-echo2.json new file mode 100644 index 000000000..426855d3d --- /dev/null +++ b/heroku/register-echo2.json @@ -0,0 +1,15 @@ +{ + "ID":"echo2", + "Name":"echo2", + "Tags":[ + "primary" + ], + "Address":"127.0.0.1", + "Port":10020, + "Check":{ + "DeregisterCriticalServiceAfter":"90m", + "http":"http://127.0.0.1:10020", + "Interval":"10s" + } +} + diff --git a/heroku/run-envoy.sh b/heroku/run-envoy.sh new file mode 100755 index 000000000..6687ece1f --- /dev/null +++ b/heroku/run-envoy.sh @@ -0,0 +1,24 @@ +#!/usr/bin/dumb-init /bin/sh +set -e + +# start EC +START_ARGUMENTS="" +CONFIG_FILE=/etc/envoy-control/application.yaml +if [ -f "$CONFIG_FILE" ]; then + START_ARGUMENTS="--spring.config.location=file:$CONFIG_FILE " +fi +if [ ! -z "${ENVOY_CONTROL_PROPERTIES}" ]; then + START_ARGUMENTS="$START_ARGUMENTS $ENVOY_CONTROL_PROPERTIES" +fi +echo "Launching Envoy-control with $START_ARGUMENTS" +/bin/envoy-control/envoy-control-runner/bin/envoy-control-runner $START_ARGUMENTS & + +# start envoys +sed -i "s/{{.IngressListenerPort}}/${PORT:-10000}/g" /etc/envoy-front-proxy.yaml +sh -c 'sleep 20; /usr/local/bin/envoy --base-id 1 -c /etc/envoy1.yaml' & +sh -c 'sleep 20; /usr/local/bin/envoy --base-id 2 -c /etc/envoy2.yaml' & +/usr/local/bin/envoy -c /etc/envoy-front-proxy.yaml & + +sh -c 'sleep 25; curl -X PUT -s localhost:8500/v1/agent/service/register -T /etc/envoy-control/register-echo1.json' & + +consul agent -server -ui -ui-content-path "/consul/ui" -dev -client 0.0.0.0