From 94e83573b29e85d52e191c052ac8c4c4e617f8ab Mon Sep 17 00:00:00 2001 From: Taras Yatsurak Date: Mon, 27 Sep 2021 17:01:23 +0300 Subject: [PATCH] Renaming from petshop to petstore, added initial dynamic Envoy configuration --- LICENSE | 2 +- README.md | 4 +- .../Dockerfile-control-plane | 12 ++ examples/petstore-dynamic-config/README.md | 23 +++ .../docker-compose.yaml | 42 +++++ examples/petstore-dynamic-config/envoy.yaml | 42 +++++ examples/petstore-dynamic-config/resource.go | 175 ++++++++++++++++++ .../README.md | 6 +- .../docker-compose.yml | 10 +- .../envoy.yaml} | 0 .../petshop-openapi-short-with-kusk.yaml | 0 11 files changed, 305 insertions(+), 11 deletions(-) create mode 100644 examples/petstore-dynamic-config/Dockerfile-control-plane create mode 100644 examples/petstore-dynamic-config/README.md create mode 100644 examples/petstore-dynamic-config/docker-compose.yaml create mode 100644 examples/petstore-dynamic-config/envoy.yaml create mode 100644 examples/petstore-dynamic-config/resource.go rename examples/{petshop => petstore-static-config}/README.md (67%) rename examples/{petshop => petstore-static-config}/docker-compose.yml (76%) rename examples/{petshop/envoy-proxy.yaml => petstore-static-config/envoy.yaml} (100%) rename examples/{petshop => petstore-static-config}/petshop-openapi-short-with-kusk.yaml (100%) diff --git a/LICENSE b/LICENSE index 7d3c644be..4c691a5ba 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 kubeshop +Copyright (c) 2021 Kubeshop Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6a2cec333..17467045d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# kusk-ingress -Kusk-ingress is the Kubernetes Ingress Controller, based on Envoy and using OpenAPI specification as the source of configuration +# kusk-gateway +Kusk-gateway is the API Gateway, based on Envoy and using OpenAPI specification as the source of configuration diff --git a/examples/petstore-dynamic-config/Dockerfile-control-plane b/examples/petstore-dynamic-config/Dockerfile-control-plane new file mode 100644 index 000000000..cc676ae24 --- /dev/null +++ b/examples/petstore-dynamic-config/Dockerfile-control-plane @@ -0,0 +1,12 @@ +FROM golang + +RUN apt-get update \ + && apt-get install --no-install-recommends -y netcat \ + && apt-get autoremove -y \ + && apt-get clean \ + && rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/* + +RUN git clone https://github.com/envoyproxy/go-control-plane && cd go-control-plane && git checkout b4adc3bb5fe5288bff01cd452dad418ef98c676e +ADD ./resource.go /go/go-control-plane/internal/example/resource.go +RUN cd go-control-plane && make bin/example +WORKDIR /go/go-control-plane diff --git a/examples/petstore-dynamic-config/README.md b/examples/petstore-dynamic-config/README.md new file mode 100644 index 000000000..c325b1dde --- /dev/null +++ b/examples/petstore-dynamic-config/README.md @@ -0,0 +1,23 @@ +# Testing Envoy with Dynamic configuration + +This directory provides local testing configuration with Envoy as frontend proxy and petstore application as a backend. + +The example completely maps "/" in Envoy to petstore, i.e. http://127.0.0.1:8080 will proxy to Petstore without changes. + +The configuration is done with go-control-plane container using hardcoded values in resource.go. + +To run: + +```shell +docker-compose up +``` + +Envoy frontend will be available on *localhost:8080* while backend could be reached on http://172.21.0.3:8080 . + +To test: + +```shell +curl -v -X GET 'http://localhost:8080/pets_prefix/api/v3/pet/1' -H 'accept: application/json' +``` + +Envoy management interface is available on http://172.21.0.2:19000. diff --git a/examples/petstore-dynamic-config/docker-compose.yaml b/examples/petstore-dynamic-config/docker-compose.yaml new file mode 100644 index 000000000..5042f54d5 --- /dev/null +++ b/examples/petstore-dynamic-config/docker-compose.yaml @@ -0,0 +1,42 @@ +version: "3.7" +services: + + front-envoy: + container_name: front-envoy + image: envoyproxy/envoy-dev:latest + networks: + kusk-gateway: + ipv4_address: "172.21.0.2" + volumes: + - ./envoy.yaml:/etc/envoy/envoy.yaml + ports: + - "8080:8080" + depends_on: + - petstore + - go-control-plane + petstore: + container_name: petstore + image: swaggerapi/petstore3:unstable + networks: + kusk-gateway: + ipv4_address: "172.21.0.3" + go-control-plane: + container_name: go-control-plane + build: + context: . + dockerfile: Dockerfile-control-plane + command: bin/example -debug + healthcheck: + test: nc -zv localhost 18000 + networks: + kusk-gateway: + ipv4_address: "172.21.0.4" + + +networks: + kusk-gateway: + name: "kusk-gateway" + ipam: + driver: default + config: + - subnet: 172.21.0.0/24 diff --git a/examples/petstore-dynamic-config/envoy.yaml b/examples/petstore-dynamic-config/envoy.yaml new file mode 100644 index 000000000..aafd75065 --- /dev/null +++ b/examples/petstore-dynamic-config/envoy.yaml @@ -0,0 +1,42 @@ +node: + cluster: test-cluster + id: test-id + +dynamic_resources: + ads_config: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + cds_config: + resource_api_version: V3 + ads: {} + lds_config: + resource_api_version: V3 + ads: {} + +static_resources: + clusters: + - type: STRICT_DNS + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + name: xds_cluster + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: go-control-plane + port_value: 18000 + +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 19000 diff --git a/examples/petstore-dynamic-config/resource.go b/examples/petstore-dynamic-config/resource.go new file mode 100644 index 000000000..983c34791 --- /dev/null +++ b/examples/petstore-dynamic-config/resource.go @@ -0,0 +1,175 @@ +// Copyright 2020 Envoyproxy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package example + +import ( + "time" + + "github.com/golang/protobuf/ptypes" + + cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" + core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + endpoint "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" + listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" + route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + "github.com/envoyproxy/go-control-plane/pkg/cache/types" + "github.com/envoyproxy/go-control-plane/pkg/cache/v3" + "github.com/envoyproxy/go-control-plane/pkg/resource/v3" + "github.com/envoyproxy/go-control-plane/pkg/wellknown" +) + +const ( + ClusterName = "example_proxy_cluster" + RouteName = "local_route" + ListenerName = "listener_0" + ListenerPort = 8080 + UpstreamHost = "petstore" + UpstreamPort = 8080 +) + +func makeCluster(clusterName string) *cluster.Cluster { + return &cluster.Cluster{ + Name: clusterName, + ConnectTimeout: ptypes.DurationProto(5 * time.Second), + ClusterDiscoveryType: &cluster.Cluster_Type{Type: cluster.Cluster_LOGICAL_DNS}, + LbPolicy: cluster.Cluster_ROUND_ROBIN, + LoadAssignment: makeEndpoint(clusterName), + DnsLookupFamily: cluster.Cluster_V4_ONLY, + } +} + +func makeEndpoint(clusterName string) *endpoint.ClusterLoadAssignment { + return &endpoint.ClusterLoadAssignment{ + ClusterName: clusterName, + Endpoints: []*endpoint.LocalityLbEndpoints{{ + LbEndpoints: []*endpoint.LbEndpoint{{ + HostIdentifier: &endpoint.LbEndpoint_Endpoint{ + Endpoint: &endpoint.Endpoint{ + Address: &core.Address{ + Address: &core.Address_SocketAddress{ + SocketAddress: &core.SocketAddress{ + Protocol: core.SocketAddress_TCP, + Address: UpstreamHost, + PortSpecifier: &core.SocketAddress_PortValue{ + PortValue: UpstreamPort, + }, + }, + }, + }, + }, + }, + }}, + }}, + } +} + +func makeRoute(routeName string, clusterName string) *route.RouteConfiguration { + return &route.RouteConfiguration{ + Name: routeName, + VirtualHosts: []*route.VirtualHost{{ + Name: "local_service", + Domains: []string{"*"}, + Routes: []*route.Route{{ + Match: &route.RouteMatch{ + PathSpecifier: &route.RouteMatch_Prefix{ + Prefix: "/", + }, + }, + Action: &route.Route_Route{ + Route: &route.RouteAction{ + ClusterSpecifier: &route.RouteAction_Cluster{ + Cluster: clusterName, + }, + }, + }, + }}, + }}, + } +} + +func makeHTTPListener(listenerName string, route string) *listener.Listener { + // HTTP filter configuration + manager := &hcm.HttpConnectionManager{ + CodecType: hcm.HttpConnectionManager_AUTO, + StatPrefix: "http", + RouteSpecifier: &hcm.HttpConnectionManager_Rds{ + Rds: &hcm.Rds{ + ConfigSource: makeConfigSource(), + RouteConfigName: route, + }, + }, + HttpFilters: []*hcm.HttpFilter{{ + Name: wellknown.Router, + }}, + } + pbst, err := ptypes.MarshalAny(manager) + if err != nil { + panic(err) + } + + return &listener.Listener{ + Name: listenerName, + Address: &core.Address{ + Address: &core.Address_SocketAddress{ + SocketAddress: &core.SocketAddress{ + Protocol: core.SocketAddress_TCP, + Address: "0.0.0.0", + PortSpecifier: &core.SocketAddress_PortValue{ + PortValue: ListenerPort, + }, + }, + }, + }, + FilterChains: []*listener.FilterChain{{ + Filters: []*listener.Filter{{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &listener.Filter_TypedConfig{ + TypedConfig: pbst, + }, + }}, + }}, + } +} + +func makeConfigSource() *core.ConfigSource { + source := &core.ConfigSource{} + source.ResourceApiVersion = resource.DefaultAPIVersion + source.ConfigSourceSpecifier = &core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &core.ApiConfigSource{ + TransportApiVersion: resource.DefaultAPIVersion, + ApiType: core.ApiConfigSource_GRPC, + SetNodeOnFirstMessageOnly: true, + GrpcServices: []*core.GrpcService{{ + TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "xds_cluster"}, + }, + }}, + }, + } + return source +} + +func GenerateSnapshot() cache.Snapshot { + return cache.NewSnapshot( + "1", + []types.Resource{}, // endpoints + []types.Resource{makeCluster(ClusterName)}, + []types.Resource{makeRoute(RouteName, ClusterName)}, + []types.Resource{makeHTTPListener(ListenerName, RouteName)}, + []types.Resource{}, // runtimes + []types.Resource{}, // secrets + []types.Resource{}, // extensions configs + ) +} diff --git a/examples/petshop/README.md b/examples/petstore-static-config/README.md similarity index 67% rename from examples/petshop/README.md rename to examples/petstore-static-config/README.md index 20ffdea3d..b3612ba7e 100644 --- a/examples/petshop/README.md +++ b/examples/petstore-static-config/README.md @@ -1,8 +1,8 @@ # Testing Envoy as Ingress -This directory provides local testing configuration with Envoy as frontend proxy and petshop application as a backend. +This directory provides local testing configuration with Envoy as frontend proxy and petstore application as a backend. -Envoy configuration is done accordingly to cut-off Petshop OpenAPI file with *x-kusk* extension configuration. +Envoy configuration is done accordingly to cut-off Petstore OpenAPI file with *x-kusk* extension configuration. To run: @@ -16,4 +16,4 @@ To test: ```shell curl -v -X GET 'http://localhost:8080/pets_prefix/api/v3/pet/1' -H 'accept: application/json' -``` \ No newline at end of file +``` diff --git a/examples/petshop/docker-compose.yml b/examples/petstore-static-config/docker-compose.yml similarity index 76% rename from examples/petshop/docker-compose.yml rename to examples/petstore-static-config/docker-compose.yml index 430926c4c..e4894f377 100644 --- a/examples/petshop/docker-compose.yml +++ b/examples/petstore-static-config/docker-compose.yml @@ -5,10 +5,10 @@ services: container_name: front-envoy image: envoyproxy/envoy-dev:latest networks: - kusk-ingress: + kusk-gateway: ipv4_address: "172.21.0.2" volumes: - - ./envoy-proxy.yaml:/etc/envoy/envoy.yaml + - ./envoy.yaml:/etc/envoy/envoy.yaml ports: - "8080:8080" @@ -16,13 +16,13 @@ services: container_name: petstore image: swaggerapi/petstore3:unstable networks: - kusk-ingress: + kusk-gateway: ipv4_address: "172.21.0.3" networks: - kusk-ingress: - name: "kusk-ingress" + kusk-gateway: + name: "kusk-gateway" ipam: driver: default config: diff --git a/examples/petshop/envoy-proxy.yaml b/examples/petstore-static-config/envoy.yaml similarity index 100% rename from examples/petshop/envoy-proxy.yaml rename to examples/petstore-static-config/envoy.yaml diff --git a/examples/petshop/petshop-openapi-short-with-kusk.yaml b/examples/petstore-static-config/petshop-openapi-short-with-kusk.yaml similarity index 100% rename from examples/petshop/petshop-openapi-short-with-kusk.yaml rename to examples/petstore-static-config/petshop-openapi-short-with-kusk.yaml