pkg/mesh/envoy.go (123 lines of code) (raw):

// Copyright 2021 Google LLC // // 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 // // https://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 mesh import ( "bytes" "errors" "fmt" "io" "log" "os" "os/exec" "strconv" "syscall" "github.com/creack/pty" ) const envoyUID = 1337 const envoyGID = 1337 func (kr *KRun) envoyCommand() *exec.Cmd { // For Istio: // -c etc/istio/proxy/envoy-rev0.json --restart-epoch 0 --drain-time-s 45 --drain-strategy immediate --parent-shutdown-time-s 60 --local-address-ip-version v4 --file-flush-interval-msec 1000 --disable-hot-restart --log-format %Y-%m-%dT%T.%fZ %l envoy %n %v -l warning --component-log-level misc:error --concurrency 2 if kr.TdSidecarEnv == nil { // TODO: add a simplified template, customize from ProxyConfig. // ProxyConfig needs to be loaded return exec.Command("/usr/local/bin/envoy", "--config-path", "etc/istio/proxy/envoy-rev0.json", "--allow-unknown-static-fields", "--restart-epoch", "0", "--drain-time-s", "45", "--drain-strategy", "immediate", "--parent-shutdown-time-s", "60", "--local-address-ip-version", "v4", "--file-flush-interval-msec", "1000", "--disable-hot-restart", "--log-format", "%Y-%m-%dT%T.%fZ %l envoy %n %v -l warning", "--component-log-level", "misc:error", "--concurrency", "2", ) } // For TD: return exec.Command("/usr/local/bin/envoy", "--config-path", fmt.Sprintf("%s/bootstrap.yaml", kr.TdSidecarEnv.PackageDirectory), "--log-level", kr.TdSidecarEnv.LogLevel, // Settings this will make the logs invisible and may run out of mem: // "--log-path", "/var/log/envoy/envoy.log", "--allow-unknown-static-fields", ) } // StartEnvoy does iptables interception, envoy bootstrap preparation and // runs envoy. func (kr *KRun) StartEnvoy() error { if os.Getuid() != 0 { return errors.New("td only supports running as root") } // Prepare envoy bootstrap if err := kr.PrepareTrafficDirectorBootstrap( fmt.Sprintf("%s/bootstrap_template.yaml", kr.TdSidecarEnv.PackageDirectory), fmt.Sprintf("%s/bootstrap.yaml", kr.TdSidecarEnv.PackageDirectory)); err != nil { return err } log.Println("TD bootstrap ready") os.MkdirAll(kr.TdSidecarEnv.LogDirectory, 0666) os.Chown(kr.TdSidecarEnv.LogDirectory, envoyUID, envoyGID) cmd := kr.envoyCommand() cmd.SysProcAttr = &syscall.SysProcAttr{} cmd.SysProcAttr.Credential = &syscall.Credential{ Uid: envoyUID, Gid: envoyGID, } var stdout io.ReadCloser pty, tty, err := pty.Open() if err != nil { log.Println("Error opening pty: ", err) stdout, _ = cmd.StdoutPipe() os.Stdout.Chown(envoyUID, envoyGID) } else { cmd.Stdout = tty if err = tty.Chown(envoyUID, envoyGID); err != nil { log.Println("Error chown: ", err) } stdout = pty } cmd.Stderr = os.Stderr go func() { if err := cmd.Start(); err != nil { log.Println("Failed to start: ", cmd, err) } kr.agentCmd = cmd if stdout != nil { go func() { io.Copy(os.Stdout, stdout) }() } if err := cmd.Wait(); err != nil { log.Println("Wait err: ", err) } kr.Exit(0) }() return nil } func (kr *KRun) iptablesCommand() *exec.Cmd { if err := os.Chmod(fmt.Sprintf("%s/iptables.sh", kr.TdSidecarEnv.PackageDirectory), 0700); err != nil { log.Println(err) } if err := os.Chown(fmt.Sprintf("%s/iptables.sh", kr.TdSidecarEnv.PackageDirectory), 0, 0); err != nil { log.Println(err) } return exec.Command(fmt.Sprintf("%s/iptables.sh", kr.TdSidecarEnv.PackageDirectory), "-x", "169.254.169.254/32", // metadata_server_cidr "-i", kr.TdSidecarEnv.ServiceCidr, "-p", kr.TdSidecarEnv.EnvoyPort, "-u", strconv.Itoa(envoyUID), ) } // StartIPTablesInterception intercepts traffic via iptables script. func (kr *KRun) StartIPTablesInterception() error { cmd := kr.iptablesCommand() so := &bytes.Buffer{} cmd.Dir = "/" cmd.Env = os.Environ() cmd.Env = append(cmd.Env, kr.GetTrafficDirectorIPTablesEnvVars()...) cmd.Stdout = so cmd.Stderr = os.Stderr cmd.SysProcAttr = &syscall.SysProcAttr{} cmd.SysProcAttr.Credential = &syscall.Credential{ Uid: 0, } if err := cmd.Start(); err != nil { log.Println("Error starting iptables", err) return err } if err := cmd.Wait(); err != nil { log.Println("Error starting iptables", err, so.String()) return err } return nil }