diff --git a/cmd/kops/create_cluster.go b/cmd/kops/create_cluster.go index 749e5355e7..13b3384aee 100644 --- a/cmd/kops/create_cluster.go +++ b/cmd/kops/create_cluster.go @@ -240,7 +240,7 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command { cmd.Flags().StringVar(&options.Image, "image", options.Image, "Image to use for all instances.") - cmd.Flags().StringVar(&options.Networking, "networking", "kubenet", "Networking mode to use. kubenet (default), classic, external, kopeio-vxlan (or kopeio), weave, flannel, calico, canal.") + cmd.Flags().StringVar(&options.Networking, "networking", "kubenet", "Networking mode to use. kubenet (default), classic, external, kopeio-vxlan (or kopeio), weave, flannel, calico, canal, kube-router.") cmd.Flags().StringVar(&options.DNSZone, "dns-zone", options.DNSZone, "DNS hosted zone to use (defaults to longest matching zone)") cmd.Flags().StringVar(&options.OutDir, "out", options.OutDir, "Path to write any local output") @@ -671,6 +671,8 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e cluster.Spec.Networking.Calico = &api.CalicoNetworkingSpec{} case "canal": cluster.Spec.Networking.Canal = &api.CanalNetworkingSpec{} + case "kube-router": + cluster.Spec.Networking.Kuberouter = &api.KuberouterNetworkingSpec{} default: return fmt.Errorf("unknown networking mode %q", c.Networking) } @@ -708,7 +710,7 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e case api.TopologyPrivate: if !supportsPrivateTopology(cluster.Spec.Networking) { - return fmt.Errorf("Invalid networking option %s. Currently only '--networking kopeio-vxlan (or kopeio)', '--networking weave', '--networking flannel', '--networking calico', '--networking canal' are supported for private topologies", c.Networking) + return fmt.Errorf("Invalid networking option %s. Currently only '--networking kopeio-vxlan (or kopeio)', '--networking weave', '--networking flannel', '--networking calico', '--networking canal', '--networking kube-router' are supported for private topologies", c.Networking) } cluster.Spec.Topology = &api.TopologySpec{ Masters: api.TopologyPrivate, @@ -934,7 +936,7 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e func supportsPrivateTopology(n *api.NetworkingSpec) bool { - if n.CNI != nil || n.Kopeio != nil || n.Weave != nil || n.Flannel != nil || n.Calico != nil || n.Canal != nil { + if n.CNI != nil || n.Kopeio != nil || n.Weave != nil || n.Flannel != nil || n.Calico != nil || n.Canal != nil || n.Kuberouter != nil { return true } return false diff --git a/docs/cli/kops_create_cluster.md b/docs/cli/kops_create_cluster.md index 2fb47182a8..bdc67d33fa 100644 --- a/docs/cli/kops_create_cluster.md +++ b/docs/cli/kops_create_cluster.md @@ -78,7 +78,7 @@ kops create cluster --master-zones stringSlice Zones in which to run masters (must be an odd number) --model string Models to apply (separate multiple models with commas) (default "config,proto,cloudup") --network-cidr string Set to override the default network CIDR - --networking string Networking mode to use. kubenet (default), classic, external, kopeio-vxlan (or kopeio), weave, flannel, calico, canal. (default "kubenet") + --networking string Networking mode to use. kubenet (default), classic, external, kopeio-vxlan (or kopeio), weave, flannel, calico, canal, kube-router. (default "kubenet") --node-count int32 Set the number of nodes --node-security-groups stringSlice Add precreated additional security groups to nodes. --node-size string Set instance size for nodes diff --git a/docs/networking.md b/docs/networking.md index ab47d4627d..bb9949613e 100644 --- a/docs/networking.md +++ b/docs/networking.md @@ -35,6 +35,7 @@ Several different providers are currently built into kops: 3. [flannel](https://github.com/coreos/flannel) 4. [Calico](http://docs.projectcalico.org/v2.0/getting-started/kubernetes/installation/hosted/) 5. [Canal (Flannel + Calico)](https://github.com/projectcalico/canal) +6. [kube-router](https://github.com/cloudnativelabs/kube-router) The manifests for the providers are included with kops, and you simply use `--networking provider-name`. Replace the provider name with the names listed above with you `kops cluster create`. For instance @@ -232,6 +233,33 @@ For support with Flannel you can submit an issue on Github: - [Flannel](https://github.com/coreos/flannel/issues) +### Kube-router example for CNI, IPVS based service proxy and Network Policy enforcer + +[Kube-router](https://github.com/cloudnativelabs/kube-router) is project that provides one cohesive soltion that provides CNI networking for pods, an IPVS based network service proxy and iptables based network policy enforcement. + +#### Installing kube-router on a new Cluster + +The following command sets up a cluster with Kube-router as the CNI, service proxy and networking policy provider + +``` +$ kops create cluster \ + --node-count 2 \ + --zones us-west-2a \ + --master-zones us-west-2a \ + --dns-zone aws.cloudnativelabs.net \ + --node-size t2.medium \ + --master-size t2.medium \ + --networking kube-router \ + --yes \ + --name myclustername.mydns.io +``` + +Currently kube-router supports 1.6 and above. Please note that kube-router will also provide service proxy, so kube-proxy will not be deployed in to the cluster. Kube-router used node routing stack for cross node pod-to-pod connectivity with out any encapsulation. In the case of AWS, EC2 instances have source/destination checks enabled by default. So please ensure to turn off source-destination checks on the AWS EC2 instances by running below command. + +``` +aws ec2 modify-instance-attribute --instance-id --no-source-dest-check +``` + ### Validating CNI Installation You will notice that `kube-dns` fails to start properly until you deploy your CNI provider. diff --git a/nodeup/pkg/model/kuberouter.go b/nodeup/pkg/model/kuberouter.go new file mode 100644 index 0000000000..50872b8526 --- /dev/null +++ b/nodeup/pkg/model/kuberouter.go @@ -0,0 +1,49 @@ +/* +Copyright 2017 The Kubernetes 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 model + +import ( + "k8s.io/kops/upup/pkg/fi" + "k8s.io/kops/upup/pkg/fi/nodeup/nodetasks" +) + +// KubeProxyBuilder installs kube-proxy +type KubeRouterBuilder struct { + *NodeupModelContext +} + +var _ fi.ModelBuilder = &KubeRouterBuilder{} + +func (b *KubeRouterBuilder) Build(c *fi.ModelBuilderContext) error { + + // Add kubeconfig + { + kubeconfig, err := b.buildPKIKubeconfig("kube-router") + if err != nil { + return err + } + t := &nodetasks.File{ + Path: "/var/lib/kube-router/kubeconfig", + Contents: fi.NewStringResource(kubeconfig), + Type: nodetasks.FileType_File, + Mode: s("0400"), + } + c.AddTask(t) + } + + return nil +} diff --git a/nodeup/pkg/model/network.go b/nodeup/pkg/model/network.go index 49cccde06b..95311e0513 100644 --- a/nodeup/pkg/model/network.go +++ b/nodeup/pkg/model/network.go @@ -40,7 +40,7 @@ func (b *NetworkBuilder) Build(c *fi.ModelBuilderContext) error { } else if networking.External != nil { // external is based on kubenet assetNames = append(assetNames, "bridge", "host-local", "loopback") - } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil { assetNames = append(assetNames, "bridge", "host-local", "loopback", "ptp") // Do we need tuning? diff --git a/pkg/apis/kops/cluster.go b/pkg/apis/kops/cluster.go index eea7a2199b..b5f6bc7a5f 100644 --- a/pkg/apis/kops/cluster.go +++ b/pkg/apis/kops/cluster.go @@ -382,6 +382,8 @@ func (c *Cluster) FillDefaults() error { // OK } else if c.Spec.Networking.Canal != nil { // OK + } else if c.Spec.Networking.Kuberouter != nil { + // OK } else { // No networking model selected; choose Kubenet c.Spec.Networking.Kubenet = &KubenetNetworkingSpec{} diff --git a/pkg/apis/kops/networking.go b/pkg/apis/kops/networking.go index 4792dc568d..bc7bb1fb57 100644 --- a/pkg/apis/kops/networking.go +++ b/pkg/apis/kops/networking.go @@ -18,15 +18,16 @@ package kops // NetworkingSpec allows selection and configuration of a networking plugin type NetworkingSpec struct { - Classic *ClassicNetworkingSpec `json:"classic,omitempty"` - Kubenet *KubenetNetworkingSpec `json:"kubenet,omitempty"` - External *ExternalNetworkingSpec `json:"external,omitempty"` - CNI *CNINetworkingSpec `json:"cni,omitempty"` - Kopeio *KopeioNetworkingSpec `json:"kopeio,omitempty"` - Weave *WeaveNetworkingSpec `json:"weave,omitempty"` - Flannel *FlannelNetworkingSpec `json:"flannel,omitempty"` - Calico *CalicoNetworkingSpec `json:"calico,omitempty"` - Canal *CanalNetworkingSpec `json:"canal,omitempty"` + Classic *ClassicNetworkingSpec `json:"classic,omitempty"` + Kubenet *KubenetNetworkingSpec `json:"kubenet,omitempty"` + External *ExternalNetworkingSpec `json:"external,omitempty"` + CNI *CNINetworkingSpec `json:"cni,omitempty"` + Kopeio *KopeioNetworkingSpec `json:"kopeio,omitempty"` + Weave *WeaveNetworkingSpec `json:"weave,omitempty"` + Flannel *FlannelNetworkingSpec `json:"flannel,omitempty"` + Calico *CalicoNetworkingSpec `json:"calico,omitempty"` + Canal *CanalNetworkingSpec `json:"canal,omitempty"` + Kuberouter *KuberouterNetworkingSpec `json:"kuberouter,omitempty"` } // ClassicNetworkingSpec is the specification of classic networking mode, integrated into kubernetes @@ -69,3 +70,7 @@ type CalicoNetworkingSpec struct { // Canal declares that we want Canal networking type CanalNetworkingSpec struct { } + +// Kuberouter declares that we want Kube-router networking +type KuberouterNetworkingSpec struct { +} diff --git a/pkg/apis/kops/v1alpha1/networking.go b/pkg/apis/kops/v1alpha1/networking.go index b43ebf5364..1c93d52883 100644 --- a/pkg/apis/kops/v1alpha1/networking.go +++ b/pkg/apis/kops/v1alpha1/networking.go @@ -18,15 +18,16 @@ package v1alpha1 // NetworkingSpec allows selection and configuration of a networking plugin type NetworkingSpec struct { - Classic *ClassicNetworkingSpec `json:"classic,omitempty"` - Kubenet *KubenetNetworkingSpec `json:"kubenet,omitempty"` - External *ExternalNetworkingSpec `json:"external,omitempty"` - CNI *CNINetworkingSpec `json:"cni,omitempty"` - Kopeio *KopeioNetworkingSpec `json:"kopeio,omitempty"` - Weave *WeaveNetworkingSpec `json:"weave,omitempty"` - Flannel *FlannelNetworkingSpec `json:"flannel,omitempty"` - Calico *CalicoNetworkingSpec `json:"calico,omitempty"` - Canal *CanalNetworkingSpec `json:"canal,omitempty"` + Classic *ClassicNetworkingSpec `json:"classic,omitempty"` + Kubenet *KubenetNetworkingSpec `json:"kubenet,omitempty"` + External *ExternalNetworkingSpec `json:"external,omitempty"` + CNI *CNINetworkingSpec `json:"cni,omitempty"` + Kopeio *KopeioNetworkingSpec `json:"kopeio,omitempty"` + Weave *WeaveNetworkingSpec `json:"weave,omitempty"` + Flannel *FlannelNetworkingSpec `json:"flannel,omitempty"` + Calico *CalicoNetworkingSpec `json:"calico,omitempty"` + Canal *CanalNetworkingSpec `json:"canal,omitempty"` + Kuberouter *KuberouterNetworkingSpec `json:"kuberouter,omitempty"` } // ClassicNetworkingSpec is the specification of classic networking mode, integrated into kubernetes @@ -69,3 +70,7 @@ type CalicoNetworkingSpec struct { // Canal declares that we want Canal networking type CanalNetworkingSpec struct { } + +// Kuberouter declares that we want Canal networking +type KuberouterNetworkingSpec struct { +} diff --git a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go index e8cdb3a3de..0c7c1cc6cc 100644 --- a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go @@ -103,6 +103,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kops_KubeletConfigSpec_To_v1alpha1_KubeletConfigSpec, Convert_v1alpha1_KubenetNetworkingSpec_To_kops_KubenetNetworkingSpec, Convert_kops_KubenetNetworkingSpec_To_v1alpha1_KubenetNetworkingSpec, + Convert_v1alpha1_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec, + Convert_kops_KuberouterNetworkingSpec_To_v1alpha1_KuberouterNetworkingSpec, Convert_v1alpha1_LeaderElectionConfiguration_To_kops_LeaderElectionConfiguration, Convert_kops_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration, Convert_v1alpha1_LoadBalancerAccessSpec_To_kops_LoadBalancerAccessSpec, @@ -1534,6 +1536,22 @@ func Convert_kops_KubenetNetworkingSpec_To_v1alpha1_KubenetNetworkingSpec(in *ko return autoConvert_kops_KubenetNetworkingSpec_To_v1alpha1_KubenetNetworkingSpec(in, out, s) } +func autoConvert_v1alpha1_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(in *KuberouterNetworkingSpec, out *kops.KuberouterNetworkingSpec, s conversion.Scope) error { + return nil +} + +func Convert_v1alpha1_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(in *KuberouterNetworkingSpec, out *kops.KuberouterNetworkingSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(in, out, s) +} + +func autoConvert_kops_KuberouterNetworkingSpec_To_v1alpha1_KuberouterNetworkingSpec(in *kops.KuberouterNetworkingSpec, out *KuberouterNetworkingSpec, s conversion.Scope) error { + return nil +} + +func Convert_kops_KuberouterNetworkingSpec_To_v1alpha1_KuberouterNetworkingSpec(in *kops.KuberouterNetworkingSpec, out *KuberouterNetworkingSpec, s conversion.Scope) error { + return autoConvert_kops_KuberouterNetworkingSpec_To_v1alpha1_KuberouterNetworkingSpec(in, out, s) +} + func autoConvert_v1alpha1_LeaderElectionConfiguration_To_kops_LeaderElectionConfiguration(in *LeaderElectionConfiguration, out *kops.LeaderElectionConfiguration, s conversion.Scope) error { out.LeaderElect = in.LeaderElect return nil @@ -1654,6 +1672,15 @@ func autoConvert_v1alpha1_NetworkingSpec_To_kops_NetworkingSpec(in *NetworkingSp } else { out.Canal = nil } + if in.Kuberouter != nil { + in, out := &in.Kuberouter, &out.Kuberouter + *out = new(kops.KuberouterNetworkingSpec) + if err := Convert_v1alpha1_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Kuberouter = nil + } return nil } @@ -1743,6 +1770,15 @@ func autoConvert_kops_NetworkingSpec_To_v1alpha1_NetworkingSpec(in *kops.Network } else { out.Canal = nil } + if in.Kuberouter != nil { + in, out := &in.Kuberouter, &out.Kuberouter + *out = new(KuberouterNetworkingSpec) + if err := Convert_kops_KuberouterNetworkingSpec_To_v1alpha1_KuberouterNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Kuberouter = nil + } return nil } diff --git a/pkg/apis/kops/v1alpha2/networking.go b/pkg/apis/kops/v1alpha2/networking.go index 335a5ff32c..832b39a1d1 100644 --- a/pkg/apis/kops/v1alpha2/networking.go +++ b/pkg/apis/kops/v1alpha2/networking.go @@ -18,15 +18,16 @@ package v1alpha2 // NetworkingSpec allows selection and configuration of a networking plugin type NetworkingSpec struct { - Classic *ClassicNetworkingSpec `json:"classic,omitempty"` - Kubenet *KubenetNetworkingSpec `json:"kubenet,omitempty"` - External *ExternalNetworkingSpec `json:"external,omitempty"` - CNI *CNINetworkingSpec `json:"cni,omitempty"` - Kopeio *KopeioNetworkingSpec `json:"kopeio,omitempty"` - Weave *WeaveNetworkingSpec `json:"weave,omitempty"` - Flannel *FlannelNetworkingSpec `json:"flannel,omitempty"` - Calico *CalicoNetworkingSpec `json:"calico,omitempty"` - Canal *CanalNetworkingSpec `json:"canal,omitempty"` + Classic *ClassicNetworkingSpec `json:"classic,omitempty"` + Kubenet *KubenetNetworkingSpec `json:"kubenet,omitempty"` + External *ExternalNetworkingSpec `json:"external,omitempty"` + CNI *CNINetworkingSpec `json:"cni,omitempty"` + Kopeio *KopeioNetworkingSpec `json:"kopeio,omitempty"` + Weave *WeaveNetworkingSpec `json:"weave,omitempty"` + Flannel *FlannelNetworkingSpec `json:"flannel,omitempty"` + Calico *CalicoNetworkingSpec `json:"calico,omitempty"` + Canal *CanalNetworkingSpec `json:"canal,omitempty"` + Kuberouter *KuberouterNetworkingSpec `json:"kuberouter,omitempty"` } // ClassicNetworkingSpec is the specification of classic networking mode, integrated into kubernetes @@ -69,3 +70,7 @@ type CalicoNetworkingSpec struct { // Canal declares that we want Canal networking type CanalNetworkingSpec struct { } + +// Kuberouter declares that we want Canal networking +type KuberouterNetworkingSpec struct { +} diff --git a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go index 3680ecf806..2c0773f331 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go @@ -107,6 +107,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kops_KubeletConfigSpec_To_v1alpha2_KubeletConfigSpec, Convert_v1alpha2_KubenetNetworkingSpec_To_kops_KubenetNetworkingSpec, Convert_kops_KubenetNetworkingSpec_To_v1alpha2_KubenetNetworkingSpec, + Convert_v1alpha2_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec, + Convert_kops_KuberouterNetworkingSpec_To_v1alpha2_KuberouterNetworkingSpec, Convert_v1alpha2_LeaderElectionConfiguration_To_kops_LeaderElectionConfiguration, Convert_kops_LeaderElectionConfiguration_To_v1alpha2_LeaderElectionConfiguration, Convert_v1alpha2_LoadBalancerAccessSpec_To_kops_LoadBalancerAccessSpec, @@ -1474,6 +1476,7 @@ func autoConvert_kops_KubeProxyConfig_To_v1alpha2_KubeProxyConfig(in *kops.KubeP out.CPURequest = in.CPURequest out.LogLevel = in.LogLevel out.ClusterCIDR = in.ClusterCIDR + // WARNING: in.HostnameOverride requires manual conversion: does not exist in peer-type out.Master = in.Master return nil } @@ -1632,6 +1635,22 @@ func Convert_kops_KubenetNetworkingSpec_To_v1alpha2_KubenetNetworkingSpec(in *ko return autoConvert_kops_KubenetNetworkingSpec_To_v1alpha2_KubenetNetworkingSpec(in, out, s) } +func autoConvert_v1alpha2_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(in *KuberouterNetworkingSpec, out *kops.KuberouterNetworkingSpec, s conversion.Scope) error { + return nil +} + +func Convert_v1alpha2_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(in *KuberouterNetworkingSpec, out *kops.KuberouterNetworkingSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(in, out, s) +} + +func autoConvert_kops_KuberouterNetworkingSpec_To_v1alpha2_KuberouterNetworkingSpec(in *kops.KuberouterNetworkingSpec, out *KuberouterNetworkingSpec, s conversion.Scope) error { + return nil +} + +func Convert_kops_KuberouterNetworkingSpec_To_v1alpha2_KuberouterNetworkingSpec(in *kops.KuberouterNetworkingSpec, out *KuberouterNetworkingSpec, s conversion.Scope) error { + return autoConvert_kops_KuberouterNetworkingSpec_To_v1alpha2_KuberouterNetworkingSpec(in, out, s) +} + func autoConvert_v1alpha2_LeaderElectionConfiguration_To_kops_LeaderElectionConfiguration(in *LeaderElectionConfiguration, out *kops.LeaderElectionConfiguration, s conversion.Scope) error { out.LeaderElect = in.LeaderElect return nil @@ -1752,6 +1771,15 @@ func autoConvert_v1alpha2_NetworkingSpec_To_kops_NetworkingSpec(in *NetworkingSp } else { out.Canal = nil } + if in.Kuberouter != nil { + in, out := &in.Kuberouter, &out.Kuberouter + *out = new(kops.KuberouterNetworkingSpec) + if err := Convert_v1alpha2_KuberouterNetworkingSpec_To_kops_KuberouterNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Kuberouter = nil + } return nil } @@ -1841,6 +1869,15 @@ func autoConvert_kops_NetworkingSpec_To_v1alpha2_NetworkingSpec(in *kops.Network } else { out.Canal = nil } + if in.Kuberouter != nil { + in, out := &in.Kuberouter, &out.Kuberouter + *out = new(KuberouterNetworkingSpec) + if err := Convert_kops_KuberouterNetworkingSpec_To_v1alpha2_KuberouterNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Kuberouter = nil + } return nil } diff --git a/pkg/model/components/context.go b/pkg/model/components/context.go index b0bb075abc..ebb6a9e91e 100644 --- a/pkg/model/components/context.go +++ b/pkg/model/components/context.go @@ -72,7 +72,7 @@ func UsesKubenet(clusterSpec *kops.ClusterSpec) (bool, error) { } else if networking.External != nil { // external is based on kubenet return true, nil - } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil { return false, nil } else if networking.Kopeio != nil { // Kopeio is based on kubenet / external diff --git a/pkg/model/components/kubecontrollermanager.go b/pkg/model/components/kubecontrollermanager.go index 9242ae5b4e..c9d22fcb4b 100644 --- a/pkg/model/components/kubecontrollermanager.go +++ b/pkg/model/components/kubecontrollermanager.go @@ -139,7 +139,7 @@ func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error kcm.ConfigureCloudRoutes = fi.Bool(true) } else if networking.External != nil { kcm.ConfigureCloudRoutes = fi.Bool(false) - } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil { kcm.ConfigureCloudRoutes = fi.Bool(false) } else if networking.Kopeio != nil { // Kopeio is based on kubenet / external diff --git a/pkg/model/components/networking.go b/pkg/model/components/networking.go index bb819b85a3..f9eba56fba 100644 --- a/pkg/model/components/networking.go +++ b/pkg/model/components/networking.go @@ -47,7 +47,7 @@ func (b *NetworkingOptionsBuilder) BuildOptions(o interface{}) error { if networking == nil { return fmt.Errorf("networking not set") } - if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil { + if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil { options.Kubelet.NetworkPluginName = "cni" if k8sVersion.Major == 1 && k8sVersion.Minor <= 4 { diff --git a/pkg/model/pki.go b/pkg/model/pki.go index e6a5778b9b..c7da399bf0 100644 --- a/pkg/model/pki.go +++ b/pkg/model/pki.go @@ -60,6 +60,16 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error { c.AddTask(t) } + if b.KopsModelContext.Cluster.Spec.Networking.Kuberouter != nil { + // Keypair used by the kube-router + t := &fitasks.Keypair{ + Name: fi.String("kube-router"), + Subject: "cn=" + "system:kube-router", + Type: "client", + } + c.AddTask(t) + } + { // Keypair used by the kube-controller-manager t := &fitasks.Keypair{ diff --git a/upup/models/cloudup/resources/addons/networking.kuberouter/k8s-1.6.yaml.template b/upup/models/cloudup/resources/addons/networking.kuberouter/k8s-1.6.yaml.template new file mode 100644 index 0000000000..c44a74a56d --- /dev/null +++ b/upup/models/cloudup/resources/addons/networking.kuberouter/k8s-1.6.yaml.template @@ -0,0 +1,156 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: kube-router-cfg + namespace: kube-system + labels: + tier: node + k8s-app: kube-router +data: + cni-conf.json: | + { + "name":"kubernetes", + "type":"bridge", + "bridge":"kube-bridge", + "isDefaultGateway":true, + "ipam": { + "type":"host-local" + } + } +--- +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + labels: + k8s-app: kube-router + tier: node + name: kube-router + namespace: kube-system +spec: + template: + metadata: + labels: + k8s-app: kube-router + tier: node + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + pod.beta.kubernetes.io/init-containers: '[ + { + "name": "install-cni", + "image": "busybox", + "command": [ "/bin/sh", "-c", "set -e -x; if [ ! -f /etc/cni/net.d/10-kuberouter.conf ]; then TMP=/etc/cni/net.d/.tmp-kuberouter-cfg; cp /etc/kube-router/cni-conf.json ${TMP}; mv ${TMP} /etc/cni/net.d/10-kuberouter.conf; fi" ], + "volumeMounts": [ + { + "name": "cni", + "mountPath": "/etc/cni/net.d" + }, + { + "name": "kube-router-cfg", + "mountPath": "/etc/kube-router" + } + ], + "volumes": { + "name": "cni", + "hostPath": { + "path": "/etc/cni/net.d" + } + } + } + ]' + spec: + containers: + - name: kube-router + image: cloudnativelabs/kube-router + imagePullPolicy: Always + args: + - --run-router=true + - --run-firewall=true + - --run-service-proxy=true + - --kubeconfig=/var/lib/kube-router/kubeconfig + - --cluster-cidr={{ .NonMasqueradeCIDR }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + resources: + requests: + cpu: 250m + memory: 250Mi + securityContext: + privileged: true + volumeMounts: + - name: lib-modules + mountPath: /lib/modules + readOnly: true + - name: cni + mountPath: /etc/cni/net.d + - name: kubeconfig + mountPath: /var/lib/kube-router/kubeconfig + readOnly: true + hostNetwork: true + serviceAccountName: kube-router + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + volumes: + - hostPath: + path: /lib/modules + name: lib-modules + - hostPath: + path: /etc/cni/net.d + name: cni + - name: kubeconfig + hostPath: + path: /var/lib/kube-router/kubeconfig + - name: kube-router-cfg + configMap: + name: kube-router-cfg +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-router + namespace: kube-system +--- +# Kube-router roles +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: kube-router + namespace: kube-system +rules: + - apiGroups: [""] + resources: + - namespaces + - pod + - service + - node + - endpoints + verbs: + - get + - list + - watch + - apiGroups: ["extensions"] + resources: + - networkpolicies + verbs: + - get + - list + - watch +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: kube-router +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kube-router +subjects: +- kind: ServiceAccount + name: kube-router + namespace: kube-system diff --git a/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go b/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go index 49fe23e691..880382469e 100644 --- a/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go +++ b/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go @@ -421,5 +421,26 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri } } + if b.cluster.Spec.Networking.Kuberouter != nil { + key := "networking.kuberouter" + + version := "0.1.0" + + { + location := key + "/k8s-1.6.yaml" + id := "k8s-1.6" + + addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{ + Name: fi.String(key), + Version: fi.String(version), + Selector: networkingSelector, + Manifest: fi.String(location), + KubernetesVersion: ">=1.6.0", + Id: id, + }) + manifests[key+"-"+id] = "addons/" + location + } + } + return addons, manifests, nil } diff --git a/upup/pkg/fi/cloudup/networking.go b/upup/pkg/fi/cloudup/networking.go index 213c56055c..d956bc903a 100644 --- a/upup/pkg/fi/cloudup/networking.go +++ b/upup/pkg/fi/cloudup/networking.go @@ -68,6 +68,11 @@ func usesCNI(c *api.Cluster) bool { return true } + if networkConfig.Kuberouter != nil { + // Kuberouter uses CNI + return true + } + if networkConfig.CNI != nil { // CNI definitely uses CNI! return true diff --git a/upup/pkg/fi/cloudup/tagbuilder.go b/upup/pkg/fi/cloudup/tagbuilder.go index 1bc7fa768a..d06cab59df 100644 --- a/upup/pkg/fi/cloudup/tagbuilder.go +++ b/upup/pkg/fi/cloudup/tagbuilder.go @@ -45,7 +45,7 @@ func buildCloudupTags(cluster *api.Cluster) (sets.String, error) { } else if networking.External != nil { // external is based on kubenet tags.Insert("_networking_kubenet", "_networking_external") - } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil { tags.Insert("_networking_cni") } else if networking.Kopeio != nil { // TODO combine with the External @@ -113,7 +113,7 @@ func buildNodeupTags(role api.InstanceGroupRole, cluster *api.Cluster, clusterTa return nil, fmt.Errorf("Networking is not set, and should not be nil here") } - if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil { + if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil { // external is based on cni, weave, flannel, calico, etc tags.Insert("_networking_cni") } diff --git a/upup/pkg/fi/nodeup/command.go b/upup/pkg/fi/nodeup/command.go index c1fe1e8b9a..ddf89b5015 100644 --- a/upup/pkg/fi/nodeup/command.go +++ b/upup/pkg/fi/nodeup/command.go @@ -231,7 +231,11 @@ func (c *NodeUpCommand) Run(out io.Writer) error { loader.Builders = append(loader.Builders, &model.KubeAPIServerBuilder{NodeupModelContext: modelContext}) loader.Builders = append(loader.Builders, &model.KubeControllerManagerBuilder{NodeupModelContext: modelContext}) loader.Builders = append(loader.Builders, &model.KubeSchedulerBuilder{NodeupModelContext: modelContext}) - loader.Builders = append(loader.Builders, &model.KubeProxyBuilder{NodeupModelContext: modelContext}) + if c.cluster.Spec.Networking.Kuberouter == nil { + loader.Builders = append(loader.Builders, &model.KubeProxyBuilder{NodeupModelContext: modelContext}) + } else { + loader.Builders = append(loader.Builders, &model.KubeRouterBuilder{NodeupModelContext: modelContext}) + } loader.Builders = append(loader.Builders, &model.HookBuilder{NodeupModelContext: modelContext}) tf.populate(loader.TemplateFunctions)