|
|
@@ -30,7 +30,7 @@ import (
|
|
|
"github.com/oklog/run"
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
|
- flag "github.com/spf13/pflag"
|
|
|
+ "github.com/spf13/cobra"
|
|
|
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
|
|
"k8s.io/client-go/kubernetes"
|
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
|
@@ -78,52 +78,86 @@ var (
|
|
|
}, ", ")
|
|
|
)
|
|
|
|
|
|
-// Main is the principal function for the binary, wrapped only by `main` for convenience.
|
|
|
-func Main() error {
|
|
|
- backend := flag.String("backend", k8s.Backend, fmt.Sprintf("The backend for the mesh. Possible values: %s", availableBackends))
|
|
|
- cleanUpIface := flag.Bool("clean-up-interface", false, "Should Kilo delete its interface when it shuts down?")
|
|
|
- createIface := flag.Bool("create-interface", true, "Should kilo create an interface on startup?")
|
|
|
- cni := flag.Bool("cni", true, "Should Kilo manage the node's CNI configuration?")
|
|
|
- cniPath := flag.String("cni-path", mesh.DefaultCNIPath, "Path to CNI config.")
|
|
|
- compatibility := flag.String("compatibility", "", fmt.Sprintf("Should Kilo run in compatibility mode? Possible values: %s", availableCompatibilities))
|
|
|
- encapsulate := flag.String("encapsulate", string(encapsulation.Always), fmt.Sprintf("When should Kilo encapsulate packets within a location? Possible values: %s", availableEncapsulations))
|
|
|
- granularity := flag.String("mesh-granularity", string(mesh.LogicalGranularity), fmt.Sprintf("The granularity of the network mesh to create. Possible values: %s", availableGranularities))
|
|
|
- kubeconfig := flag.String("kubeconfig", "", "Path to kubeconfig.")
|
|
|
- hostname := flag.String("hostname", "", "Hostname of the node on which this process is running.")
|
|
|
- iface := flag.String("interface", mesh.DefaultKiloInterface, "Name of the Kilo interface to use; if it does not exist, it will be created.")
|
|
|
- listen := flag.String("listen", ":1107", "The address at which to listen for health and metrics.")
|
|
|
- local := flag.Bool("local", true, "Should Kilo manage routes within a location?")
|
|
|
- logLevel := flag.String("log-level", logLevelInfo, fmt.Sprintf("Log level to use. Possible values: %s", availableLogLevels))
|
|
|
- master := flag.String("master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig).")
|
|
|
- mtu := flag.Uint("mtu", wireguard.DefaultMTU, "The MTU of the WireGuard interface created by Kilo.")
|
|
|
- topologyLabel := flag.String("topology-label", k8s.RegionLabelKey, "Kubernetes node label used to group nodes into logical locations.")
|
|
|
- var port uint
|
|
|
- flag.UintVar(&port, "port", mesh.DefaultKiloPort, "The port over which WireGuard peers should communicate.")
|
|
|
- subnet := flag.String("subnet", mesh.DefaultKiloSubnet.String(), "CIDR from which to allocate addresses for WireGuard interfaces.")
|
|
|
- resyncPeriod := flag.Duration("resync-period", 30*time.Second, "How often should the Kilo controllers reconcile?")
|
|
|
- printVersion := flag.Bool("version", false, "Print version and exit")
|
|
|
- flag.Parse()
|
|
|
+var cmd = &cobra.Command{
|
|
|
+ Use: "kg",
|
|
|
+ Short: "kg is the Kilo agent",
|
|
|
+ Long: `kg is the Kilo agent.
|
|
|
+ It runs on every node of a cluster,
|
|
|
+ setting up the public and private keys for the VPN
|
|
|
+ as well as the necessary rules to route packets between locations.`,
|
|
|
+ RunE: runRoot,
|
|
|
+}
|
|
|
+
|
|
|
+var (
|
|
|
+ backend string
|
|
|
+ cleanUpIface bool
|
|
|
+ createIface bool
|
|
|
+ cni bool
|
|
|
+ cniPath string
|
|
|
+ compatibility string
|
|
|
+ encapsulate string
|
|
|
+ granularity string
|
|
|
+ hostname string
|
|
|
+ kubeconfig string
|
|
|
+ iface string
|
|
|
+ listen string
|
|
|
+ local bool
|
|
|
+ logLevel string
|
|
|
+ master string
|
|
|
+ mtu uint
|
|
|
+ topologyLabel string
|
|
|
+ port uint
|
|
|
+ subnet string
|
|
|
+ resyncPeriod time.Duration
|
|
|
+ printVersion bool
|
|
|
+)
|
|
|
+
|
|
|
+func init() {
|
|
|
+ cmd.PersistentFlags().StringVar(&backend, "backend", k8s.Backend, fmt.Sprintf("The backend for the mesh. Possible values: %s", availableBackends))
|
|
|
+ cmd.PersistentFlags().BoolVar(&cleanUpIface, "clean-up-interface", false, "Should Kilo delete its interface when it shuts down?")
|
|
|
+ cmd.PersistentFlags().BoolVar(&createIface, "create-interface", true, "Should kilo create an interface on startup?")
|
|
|
+ cmd.PersistentFlags().BoolVar(&cni, "cni", true, "Should Kilo manage the node's CNI configuration?")
|
|
|
+ cmd.PersistentFlags().StringVar(&cniPath, "cni-path", mesh.DefaultCNIPath, "Path to CNI config.")
|
|
|
+ cmd.PersistentFlags().StringVar(&compatibility, "compatibility", "", fmt.Sprintf("Should Kilo run in compatibility mode? Possible values: %s", availableCompatibilities))
|
|
|
+ cmd.PersistentFlags().StringVar(&encapsulate, "encapsulate", string(encapsulation.Always), fmt.Sprintf("When should Kilo encapsulate packets within a location? Possible values: %s", availableEncapsulations))
|
|
|
+ cmd.PersistentFlags().StringVar(&granularity, "mesh-granularity", string(mesh.LogicalGranularity), fmt.Sprintf("The granularity of the network mesh to create. Possible values: %s", availableGranularities))
|
|
|
+ cmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", "", "Path to kubeconfig.")
|
|
|
+ cmd.PersistentFlags().StringVar(&hostname, "hostname", "", "Hostname of the node on which this process is running.")
|
|
|
+ cmd.PersistentFlags().StringVar(&iface, "interface", mesh.DefaultKiloInterface, "Name of the Kilo interface to use; if it does not exist, it will be created.")
|
|
|
+ cmd.PersistentFlags().StringVar(&listen, "listen", ":1107", "The address at which to listen for health and metrics.")
|
|
|
+ cmd.PersistentFlags().BoolVar(&local, "local", true, "Should Kilo manage routes within a location?")
|
|
|
+ cmd.PersistentFlags().StringVar(&logLevel, "log-level", logLevelInfo, fmt.Sprintf("Log level to use. Possible values: %s", availableLogLevels))
|
|
|
+ cmd.PersistentFlags().StringVar(&master, "master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig).")
|
|
|
+ cmd.PersistentFlags().UintVar(&mtu, "mtu", wireguard.DefaultMTU, "The MTU of the WireGuard interface created by Kilo.")
|
|
|
+ cmd.PersistentFlags().StringVar(&topologyLabel, "topology-label", k8s.RegionLabelKey, "Kubernetes node label used to group nodes into logical locations.")
|
|
|
+ cmd.PersistentFlags().UintVar(&port, "port", mesh.DefaultKiloPort, "The port over which WireGuard peers should communicate.")
|
|
|
+ cmd.PersistentFlags().StringVar(&subnet, "subnet", mesh.DefaultKiloSubnet.String(), "CIDR from which to allocate addresses for WireGuard interfaces.")
|
|
|
+ cmd.PersistentFlags().DurationVar(&resyncPeriod, "resync-period", 30*time.Second, "How often should the Kilo controllers reconcile?")
|
|
|
+ cmd.PersistentFlags().BoolVar(&printVersion, "version", false, "Print version and exit")
|
|
|
+}
|
|
|
|
|
|
- if *printVersion {
|
|
|
+// Main is the principal function for the binary, wrapped only by `main` for convenience.
|
|
|
+func runRoot(_ *cobra.Command, _ []string) error {
|
|
|
+ if printVersion {
|
|
|
fmt.Println(version.Version)
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- _, s, err := net.ParseCIDR(*subnet)
|
|
|
+ _, s, err := net.ParseCIDR(subnet)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to parse %q as CIDR: %v", *subnet, err)
|
|
|
+ return fmt.Errorf("failed to parse %q as CIDR: %v", subnet, err)
|
|
|
}
|
|
|
|
|
|
- if *hostname == "" {
|
|
|
+ if hostname == "" {
|
|
|
var err error
|
|
|
- *hostname, err = os.Hostname()
|
|
|
- if *hostname == "" || err != nil {
|
|
|
+ hostname, err = os.Hostname()
|
|
|
+ if hostname == "" || err != nil {
|
|
|
return errors.New("failed to determine hostname")
|
|
|
}
|
|
|
}
|
|
|
|
|
|
logger := log.NewJSONLogger(log.NewSyncWriter(os.Stdout))
|
|
|
- switch *logLevel {
|
|
|
+ switch logLevel {
|
|
|
case logLevelAll:
|
|
|
logger = level.NewFilter(logger, level.AllowAll())
|
|
|
case logLevelDebug:
|
|
|
@@ -137,52 +171,52 @@ func Main() error {
|
|
|
case logLevelNone:
|
|
|
logger = level.NewFilter(logger, level.AllowNone())
|
|
|
default:
|
|
|
- return fmt.Errorf("log level %v unknown; possible values are: %s", *logLevel, availableLogLevels)
|
|
|
+ return fmt.Errorf("log level %v unknown; possible values are: %s", logLevel, availableLogLevels)
|
|
|
}
|
|
|
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
|
|
|
logger = log.With(logger, "caller", log.DefaultCaller)
|
|
|
|
|
|
- e := encapsulation.Strategy(*encapsulate)
|
|
|
+ e := encapsulation.Strategy(encapsulate)
|
|
|
switch e {
|
|
|
case encapsulation.Never:
|
|
|
case encapsulation.CrossSubnet:
|
|
|
case encapsulation.Always:
|
|
|
default:
|
|
|
- return fmt.Errorf("encapsulation %v unknown; possible values are: %s", *encapsulate, availableEncapsulations)
|
|
|
+ return fmt.Errorf("encapsulation %v unknown; possible values are: %s", encapsulate, availableEncapsulations)
|
|
|
}
|
|
|
|
|
|
var enc encapsulation.Encapsulator
|
|
|
- switch *compatibility {
|
|
|
+ switch compatibility {
|
|
|
case "flannel":
|
|
|
enc = encapsulation.NewFlannel(e)
|
|
|
default:
|
|
|
enc = encapsulation.NewIPIP(e)
|
|
|
}
|
|
|
|
|
|
- gr := mesh.Granularity(*granularity)
|
|
|
+ gr := mesh.Granularity(granularity)
|
|
|
switch gr {
|
|
|
case mesh.LogicalGranularity:
|
|
|
case mesh.FullGranularity:
|
|
|
default:
|
|
|
- return fmt.Errorf("mesh granularity %v unknown; possible values are: %s", *granularity, availableGranularities)
|
|
|
+ return fmt.Errorf("mesh granularity %v unknown; possible values are: %s", granularity, availableGranularities)
|
|
|
}
|
|
|
|
|
|
var b mesh.Backend
|
|
|
- switch *backend {
|
|
|
+ switch backend {
|
|
|
case k8s.Backend:
|
|
|
- config, err := clientcmd.BuildConfigFromFlags(*master, *kubeconfig)
|
|
|
+ config, err := clientcmd.BuildConfigFromFlags(master, kubeconfig)
|
|
|
if err != nil {
|
|
|
return fmt.Errorf("failed to create Kubernetes config: %v", err)
|
|
|
}
|
|
|
c := kubernetes.NewForConfigOrDie(config)
|
|
|
kc := kiloclient.NewForConfigOrDie(config)
|
|
|
ec := apiextensions.NewForConfigOrDie(config)
|
|
|
- b = k8s.New(c, kc, ec, *topologyLabel)
|
|
|
+ b = k8s.New(c, kc, ec, topologyLabel)
|
|
|
default:
|
|
|
- return fmt.Errorf("backend %v unknown; possible values are: %s", *backend, availableBackends)
|
|
|
+ return fmt.Errorf("backend %v unknown; possible values are: %s", backend, availableBackends)
|
|
|
}
|
|
|
|
|
|
- m, err := mesh.New(b, enc, gr, *hostname, uint32(port), s, *local, *cni, *cniPath, *iface, *cleanUpIface, *createIface, *mtu, *resyncPeriod, log.With(logger, "component", "kilo"))
|
|
|
+ m, err := mesh.New(b, enc, gr, hostname, uint32(port), s, local, cni, cniPath, iface, cleanUpIface, createIface, mtu, resyncPeriod, log.With(logger, "component", "kilo"))
|
|
|
if err != nil {
|
|
|
return fmt.Errorf("failed to create Kilo mesh: %v", err)
|
|
|
}
|
|
|
@@ -201,9 +235,9 @@ func Main() error {
|
|
|
mux.HandleFunc("/health", healthHandler)
|
|
|
mux.Handle("/graph", &graphHandler{m, gr, hostname, s})
|
|
|
mux.Handle("/metrics", promhttp.HandlerFor(r, promhttp.HandlerOpts{}))
|
|
|
- l, err := net.Listen("tcp", *listen)
|
|
|
+ l, err := net.Listen("tcp", listen)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to listen on %s: %v", *listen, err)
|
|
|
+ return fmt.Errorf("failed to listen on %s: %v", listen, err)
|
|
|
}
|
|
|
|
|
|
g.Add(func() error {
|
|
|
@@ -253,7 +287,7 @@ func Main() error {
|
|
|
}
|
|
|
|
|
|
func main() {
|
|
|
- if err := Main(); err != nil {
|
|
|
+ if err := cmd.Execute(); err != nil {
|
|
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
|
os.Exit(1)
|
|
|
}
|