Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NET-10190 & NET-10191 - allow consul dataplane to be run as a DNS proxy without Envoy or XDS #571

Merged
merged 15 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changelog/571.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
```release-note:feature
Added the ability to set the `-mode` flag. Options available are `sidecar` and `dns-proxy`. The system defaults to `sidecar`.
When set to `sidecar`:
- DNS Server, xDS Server, and Envoy are enabled.
- The system validates that `-consul-dns-bind-addr` and equivalent environment variable must be set to the loopback address.
When set to `dns-proxy`:
- Only DNS Server is enabled. xDS Server and Envoy are disabled.
- `consul-dns-bind-addr` and equivalent environment variable can be set to other values besides the loopback address.
```
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ docker-run: docker ## run the image of $(TAG)

.PHONY: dev-docker
dev-docker: docker ## build docker image and tag the image to local
echo '$(ARCH)'
docker tag '$(PRODUCT_NAME):$(VERSION)' '$(PRODUCT_NAME):local'

##@ Testing
Expand Down
3 changes: 3 additions & 0 deletions cmd/consul-dataplane/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type FlagOpts struct {
}

type DataplaneConfigFlags struct {
Mode *string `json:"mode,omitempty"`
Consul ConsulFlags `json:"consul,omitempty"`
Service ServiceFlags `json:"service,omitempty"`
Proxy ProxyFlags `json:"proxy,omitempty"`
Expand Down Expand Up @@ -209,6 +210,7 @@ func (f *FlagOpts) buildConfigFromFile() (DataplaneConfigFlags, error) {
func buildDefaultConsulDPFlags() (DataplaneConfigFlags, error) {
data := `
{
"mode": "sidecar",
"consul": {
"grpcPort": 8502,
"serverWatchDisabled": false,
Expand Down Expand Up @@ -316,6 +318,7 @@ func constructRuntimeConfig(cfg DataplaneConfigFlags, extraArgs []string) (*cons
InsecureSkipVerify: boolVal(cfg.Consul.TLS.InsecureSkipVerify),
},
},
Mode: consuldp.ModeType(stringVal(cfg.Mode)),
Proxy: &proxyCfg,
Logging: &consuldp.LoggingConfig{
Name: DefaultLogName,
Expand Down
10 changes: 10 additions & 0 deletions cmd/consul-dataplane/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeSidecar,
Consul: &consuldp.ConsulConfig{
Addresses: stringVal(flagOpts.dataplaneConfig.Consul.Addresses),
GRPCPort: intVal(flagOpts.dataplaneConfig.Consul.GRPCPort),
Expand Down Expand Up @@ -111,6 +112,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeSidecar,
Consul: &consuldp.ConsulConfig{
Addresses: stringVal(flagOpts.dataplaneConfig.Consul.Addresses),
GRPCPort: intVal(flagOpts.dataplaneConfig.Consul.GRPCPort),
Expand Down Expand Up @@ -189,6 +191,7 @@ func TestConfigGeneration(t *testing.T) {
if err != nil {
return nil, err
}
opts.dataplaneConfig.Mode = strReference("dns-proxy")
opts.dataplaneConfig.Consul.Credentials.Login.BearerTokenPath = strReference("/consul/bearertokenpath/")
opts.dataplaneConfig.Consul.Credentials.Login.Datacenter = strReference("dc100")
opts.dataplaneConfig.Consul.Credentials.Login.Meta = map[string]string{
Expand All @@ -206,6 +209,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeDNSProxy,
Consul: &consuldp.ConsulConfig{
Addresses: stringVal(flagOpts.dataplaneConfig.Consul.Addresses),
GRPCPort: intVal(flagOpts.dataplaneConfig.Consul.GRPCPort),
Expand Down Expand Up @@ -310,6 +314,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeSidecar,
Consul: &consuldp.ConsulConfig{
Addresses: stringVal(flagOpts.dataplaneConfig.Consul.Addresses),
GRPCPort: intVal(flagOpts.dataplaneConfig.Consul.GRPCPort),
Expand Down Expand Up @@ -408,6 +413,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeSidecar,
Consul: &consuldp.ConsulConfig{
Addresses: stringVal(flagOpts.dataplaneConfig.Consul.Addresses),
GRPCPort: intVal(flagOpts.dataplaneConfig.Consul.GRPCPort),
Expand Down Expand Up @@ -521,6 +527,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeSidecar,
Consul: &consuldp.ConsulConfig{
Addresses: "consul_server.dc1",
GRPCPort: 8502,
Expand Down Expand Up @@ -627,6 +634,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeSidecar,
Consul: &consuldp.ConsulConfig{
Addresses: stringVal(flagOpts.dataplaneConfig.Consul.Addresses),
GRPCPort: intVal(flagOpts.dataplaneConfig.Consul.GRPCPort),
Expand Down Expand Up @@ -706,6 +714,7 @@ func TestConfigGeneration(t *testing.T) {
desc: "test whether CLI flag values override the file values with proxy flags",
flagOpts: func() (*FlagOpts, error) {
opts, err := generateFlagOptsWithProxyFlags()
opts.dataplaneConfig.Mode = strReference("dns-proxy")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -754,6 +763,7 @@ func TestConfigGeneration(t *testing.T) {
},
makeExpectedCfg: func(flagOpts *FlagOpts) *consuldp.Config {
return &consuldp.Config{
Mode: consuldp.ModeTypeDNSProxy,
Consul: &consuldp.ConsulConfig{
Addresses: stringVal(flagOpts.dataplaneConfig.Consul.Addresses),
GRPCPort: intVal(flagOpts.dataplaneConfig.Consul.GRPCPort),
Expand Down
8 changes: 6 additions & 2 deletions cmd/consul-dataplane/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func init() {
flagOpts = &FlagOpts{}
flags.BoolVar(&flagOpts.printVersion, "version", false, "Prints the current version of consul-dataplane.")

StringVar(flags, &flagOpts.dataplaneConfig.Mode, "mode", "DP_MODE", "dataplane mode. Value can be:\n"+
"1. sidecar - used when running as a sidecar to Consul services with xDS Server, Envoy, and DNS Server running; OR\n"+
"2. dns-proxy - used when running as a standalone application where DNS Server runs, but Envoy and xDS Server are enabled.\n")

StringVar(flags, &flagOpts.dataplaneConfig.Consul.Addresses, "addresses", "DP_CONSUL_ADDRESSES", "Consul server gRPC addresses. Value can be:\n"+
"1. A DNS name that resolves to server addresses or the DNS name of a load balancer in front of the Consul servers; OR\n"+
"2. An executable command in the format, 'exec=<executable with optional args>'. The executable\n"+
Expand Down Expand Up @@ -107,8 +111,8 @@ func init() {
StringVar(flags, &flagOpts.dataplaneConfig.Consul.TLS.ServerName, "tls-server-name", "DP_TLS_SERVER_NAME", "The hostname to expect in the server certificate's subject. This is required if -addresses is not a DNS name.")
BoolVar(flags, &flagOpts.dataplaneConfig.Consul.TLS.InsecureSkipVerify, "tls-insecure-skip-verify", "DP_TLS_INSECURE_SKIP_VERIFY", "Do not verify the server's certificate. Useful for testing, but not recommended for production.")

StringVar(flags, &flagOpts.dataplaneConfig.DNSServer.BindAddr, "consul-dns-bind-addr", "DP_CONSUL_DNS_BIND_ADDR", "The address that will be bound to the consul dns proxy.")
IntVar(flags, &flagOpts.dataplaneConfig.DNSServer.BindPort, "consul-dns-bind-port", "DP_CONSUL_DNS_BIND_PORT", "The port the consul dns proxy will listen on. By default -1 disables the dns proxy")
StringVar(flags, &flagOpts.dataplaneConfig.DNSServer.BindAddr, "consul-dns-bind-addr", "DP_CONSUL_DNS_BIND_ADDR", "The address that will be bound to the consul dns listener.")
IntVar(flags, &flagOpts.dataplaneConfig.DNSServer.BindPort, "consul-dns-bind-port", "DP_CONSUL_DNS_BIND_PORT", "The port the consul dns listener will listen on. By default -1 disables the dns listener.")

// Default is false because it will generally be configured appropriately by Helm
// configuration or pod annotation.
Expand Down
13 changes: 13 additions & 0 deletions pkg/consuldp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ const (
CredentialsTypeLogin CredentialsType = "login"
)

// CredentialsType identifies the type of credentials provided.
type ModeType string

const (
// ModeTypeSidecar indicates that consul-dataplane is running in sidecar
// mode where DNS Server, xDS Server, and Envoy are all enabled.
ModeTypeSidecar ModeType = "sidecar"
// ModeTypeDNSProxy indicates that consul-dataplane is running in DNS Proxy
// mode where DNS Server is running but xDSServer and Envoy are disabled.
ModeTypeDNSProxy ModeType = "dns-proxy"
)

// StaticCredentialsConfig contains the static ACL token that will be used to
// authenticate requests and streams to the Consul servers.
type StaticCredentialsConfig struct {
Expand Down Expand Up @@ -316,6 +328,7 @@ type XDSServer struct {
// Config is the configuration used by consul-dataplane, consolidated
// from various sources - CLI flags, env vars, config file settings.
type Config struct {
Mode ModeType
DNSServer *DNSServerConfig
Consul *ConsulConfig
Proxy *ProxyConfig
Expand Down
46 changes: 30 additions & 16 deletions pkg/consuldp/consul_dataplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,24 +79,24 @@ func validateConfig(cfg *Config) error {
return errors.New("consul addresses not specified")
case cfg.Consul.GRPCPort == 0:
return errors.New("consul server gRPC port not specified")
case cfg.Proxy == nil:
case cfg.Mode == ModeTypeSidecar && cfg.Proxy == nil:
return errors.New("proxy details not specified")
case cfg.Proxy.ProxyID == "":
case cfg.Mode == ModeTypeSidecar && cfg.Proxy.ProxyID == "":
return errors.New("proxy ID not specified")
case cfg.Envoy == nil:
case cfg.Mode == ModeTypeSidecar && cfg.Envoy == nil:
return errors.New("envoy settings not specified")
case cfg.Envoy.AdminBindAddress == "":
case cfg.Mode == ModeTypeSidecar && cfg.Envoy.AdminBindAddress == "":
return errors.New("envoy admin bind address not specified")
case cfg.Envoy.AdminBindPort == 0:
case cfg.Mode == ModeTypeSidecar && cfg.Envoy.AdminBindPort == 0:
return errors.New("envoy admin bind port not specified")
case cfg.Logging == nil:
return errors.New("logging settings not specified")
case cfg.XDSServer.BindAddress == "":
case cfg.Mode == ModeTypeSidecar && cfg.XDSServer.BindAddress == "":
return errors.New("envoy xDS bind address not specified")
case !strings.HasPrefix(cfg.XDSServer.BindAddress, "unix://") && !net.ParseIP(cfg.XDSServer.BindAddress).IsLoopback():
case cfg.Mode == ModeTypeSidecar && !strings.HasPrefix(cfg.XDSServer.BindAddress, "unix://") && !net.ParseIP(cfg.XDSServer.BindAddress).IsLoopback():
return errors.New("non-local xDS bind address not allowed")
case cfg.DNSServer.Port != -1 && !net.ParseIP(cfg.DNSServer.BindAddr).IsLoopback():
return errors.New("non-local DNS proxy bind address not allowed")
case cfg.Mode == ModeTypeSidecar && cfg.DNSServer.Port != -1 && !net.ParseIP(cfg.DNSServer.BindAddr).IsLoopback():
return errors.New("non-local DNS proxy bind address not allowed when running as a sidecar")
}

creds := cfg.Consul.Credentials
Expand Down Expand Up @@ -129,6 +129,7 @@ func validateConfig(cfg *Config) error {
func (cdp *ConsulDataplane) Run(ctx context.Context) error {
ctx = hclog.WithContext(ctx, cdp.logger)
cdp.logger.Info("started consul-dataplane process")
cdp.logger.Info(fmt.Sprintf("consul-dataplane mode: %s", cdp.cfg.Mode))

// At startup we need to cache metrics until we have information from the bootstrap envoy config
// that the consumer wants metrics enabled. Until then we will set our own light weight metrics
Expand Down Expand Up @@ -178,6 +179,24 @@ func (cdp *ConsulDataplane) Run(ctx context.Context) error {
cdp.aclToken = state.Token
cdp.dpServiceClient = pbdataplane.NewDataplaneServiceClient(state.GRPCConn)

doneCh := make(chan error)
// start up DNS server
if err = cdp.startDNSProxy(ctx); err != nil {
cdp.logger.Error("failed to start the dns proxy", "error", err)
return err
}

// if running as DNS PRoxy, xDS Server and Envoy are disabled, so
// return before configuring them.
if cdp.cfg.Mode == ModeTypeDNSProxy {
go func() {
<-ctx.Done()
doneCh <- nil
}()
return <-doneCh
}

cdp.logger.Info("configuring xDS and Envoy")
err = cdp.setupXDSServer()
if err != nil {
return err
Expand All @@ -191,11 +210,7 @@ func (cdp *ConsulDataplane) Run(ctx context.Context) error {
}
cdp.logger.Debug("generated envoy bootstrap config", "config", string(cfg))

if err = cdp.startDNSProxy(ctx); err != nil {
cdp.logger.Error("failed to start the dns proxy", "error", err)
return err
}

cdp.logger.Info("configuring envoy and xDS")
proxy, err := envoy.NewProxy(cdp.envoyProxyConfig(cfg))
if err != nil {
cdp.logger.Error("failed to create new proxy", "error", err)
Expand All @@ -218,7 +233,6 @@ func (cdp *ConsulDataplane) Run(ctx context.Context) error {
return err
}

doneCh := make(chan error)
go func() {
select {
case <-ctx.Done():
Expand Down Expand Up @@ -266,7 +280,7 @@ func (cdp *ConsulDataplane) startDNSProxy(ctx context.Context) error {
Token: cdp.aclToken,
})
if err == dns.ErrServerDisabled {
cdp.logger.Info("dns proxy disabled: configure the Consul DNS port to enable")
cdp.logger.Info("dns server disabled: configure the Consul DNS port to enable")
return nil
} else if err != nil {
return fmt.Errorf("failed to create dns server: %w", err)
Expand Down
Loading
Loading