From 79d331e5900c484925944ea44d66a7940c36f453 Mon Sep 17 00:00:00 2001 From: Caleb Gilmour Date: Wed, 23 Aug 2017 06:34:54 +0000 Subject: [PATCH] Add support for Romana as a networking option --- cmd/kops/create_cluster.go | 8 +- docs/cli/kops_create_cluster.md | 2 +- docs/networking.md | 39 ++ nodeup/pkg/model/network.go | 2 +- pkg/apis/kops/cluster.go | 2 + pkg/apis/kops/networking.go | 9 + pkg/apis/kops/v1alpha1/networking.go | 9 + .../kops/v1alpha1/zz_generated.conversion.go | 42 +++ pkg/apis/kops/v1alpha2/networking.go | 9 + .../kops/v1alpha2/zz_generated.conversion.go | 42 +++ pkg/apis/kops/validation/legacy.go | 6 + pkg/model/components/context.go | 2 +- pkg/model/components/kubecontrollermanager.go | 2 +- pkg/model/components/networking.go | 15 +- pkg/model/firewall.go | 14 + .../networking.romana/k8s-1.6.yaml.template | 347 ++++++++++++++++++ .../pkg/fi/cloudup/bootstrapchannelbuilder.go | 21 ++ upup/pkg/fi/cloudup/networking.go | 5 + upup/pkg/fi/cloudup/tagbuilder.go | 4 +- upup/pkg/fi/cloudup/tagbuilder_test.go | 34 ++ 20 files changed, 604 insertions(+), 10 deletions(-) create mode 100644 upup/models/cloudup/resources/addons/networking.romana/k8s-1.6.yaml.template diff --git a/cmd/kops/create_cluster.go b/cmd/kops/create_cluster.go index 4b9f98d048..865b31f78f 100644 --- a/cmd/kops/create_cluster.go +++ b/cmd/kops/create_cluster.go @@ -251,7 +251,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-vxlan (or flannel), flannel-udp, calico, canal, kube-router.") + cmd.Flags().StringVar(&options.Networking, "networking", "kubenet", "Networking mode to use. kubenet (default), classic, external, kopeio-vxlan (or kopeio), weave, flannel-vxlan (or flannel), flannel-udp, calico, canal, kube-router, romana.") 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") @@ -709,6 +709,8 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e cluster.Spec.Networking.Canal = &api.CanalNetworkingSpec{} case "kube-router": cluster.Spec.Networking.Kuberouter = &api.KuberouterNetworkingSpec{} + case "romana": + cluster.Spec.Networking.Romana = &api.RomanaNetworkingSpec{} default: return fmt.Errorf("unknown networking mode %q", c.Networking) } @@ -746,7 +748,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', '--networking kube-router' 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', '--networking romana' are supported for private topologies", c.Networking) } cluster.Spec.Topology = &api.TopologySpec{ Masters: api.TopologyPrivate, @@ -992,7 +994,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 || n.Kuberouter != nil { + if n.CNI != nil || n.Kopeio != nil || n.Weave != nil || n.Flannel != nil || n.Calico != nil || n.Canal != nil || n.Kuberouter != nil || n.Romana != nil { return true } return false diff --git a/docs/cli/kops_create_cluster.md b/docs/cli/kops_create_cluster.md index c05a4f1aa4..7fdfbb704e 100644 --- a/docs/cli/kops_create_cluster.md +++ b/docs/cli/kops_create_cluster.md @@ -82,7 +82,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-vxlan (or flannel), flannel-udp, calico, canal, kube-router. (default "kubenet") + --networking string Networking mode to use. kubenet (default), classic, external, kopeio-vxlan (or kopeio), weave, flannel-vxlan (or flannel), flannel-udp, calico, canal, kube-router, romana. (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 ebaa378556..bf1f3221dc 100644 --- a/docs/networking.md +++ b/docs/networking.md @@ -35,6 +35,7 @@ Several different providers are currently built into kops: * [flannel](https://github.com/coreos/flannel) - use `--networking flannel-vxlan` (recommended) or `--networking flannel-udp` (legacy). `--networking flannel` now selects `flannel-vxlan`. * [kopeio-vxlan](https://github.com/kopeio/networking) * [kube-router](./networking.md#kube-router-example-for-cni-ipvs-based-service-proxy-and-network-policy-enforcer) +* [romana](https://github.com/romana/romana) * [weave](https://github.com/weaveworks/weave-kube) The manifests for the providers are included with kops, and you simply use `--networking provider-name`. @@ -258,6 +259,44 @@ Currently kube-router supports 1.6 and above. Please note that kube-router will No additional configurations are required to be done by user. Kube-router automatically disables source-destination check on all AWS EC2 instances. For the traffic within a subnet there is no overlay or tunneling used. For cross-subnet pod traffic ip-ip tunneling is used implicitly and no configuration is required. +### Romana Example for CNI + +#### Installing Romana on a new Cluster + +The following command sets up a cluster with Romana as the CNI. + +**NOTE** This currently deploys v2.0 Preview 2, and will be updated when the 2.0 release is completed. + +```console +$ export $ZONES=mylistofzones +$ kops create cluster \ + --zones $ZONES \ + --master-zones $ZONES \ + --master-size m4.large \ + --node-size m4.large \ + --networking romana \ + --yes \ + --name myclustername.mydns.io +``` + +Currently Romana supports Kubernetes 1.6 and above. + +#### Getting help with Romana + +For problems with deploying Romana please post an issue to Github: + +- [Romana Issues](https://github.com/romana/romana/issues) + +You can also contact the Romana team on Slack + +- [Romana Slack](https://romana.slack.com) (invite required - email [info@romana.io](mailto:info@romana.io)) + +#### Romana Backend + +Romana uses the cluster's etcd as a backend for storing information about routes, hosts, host-groups and IP allocations. +This does not affect normal etcd operations or require special treatment when upgrading etcd. +The etcd port (4001) is opened between masters and nodes when using this networking option. + ### 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/network.go b/nodeup/pkg/model/network.go index 95311e0513..f2fbec31df 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 || networking.Kuberouter != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != 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 dfaceefa63..c1011810a1 100644 --- a/pkg/apis/kops/cluster.go +++ b/pkg/apis/kops/cluster.go @@ -374,6 +374,8 @@ func (c *Cluster) FillDefaults() error { // OK } else if c.Spec.Networking.Kuberouter != nil { // OK + } else if c.Spec.Networking.Romana != 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 065bdfd3f9..0f14630592 100644 --- a/pkg/apis/kops/networking.go +++ b/pkg/apis/kops/networking.go @@ -28,6 +28,7 @@ type NetworkingSpec struct { Calico *CalicoNetworkingSpec `json:"calico,omitempty"` Canal *CanalNetworkingSpec `json:"canal,omitempty"` Kuberouter *KuberouterNetworkingSpec `json:"kuberouter,omitempty"` + Romana *RomanaNetworkingSpec `json:"romana,omitempty"` } // ClassicNetworkingSpec is the specification of classic networking mode, integrated into kubernetes @@ -80,3 +81,11 @@ type CanalNetworkingSpec struct { // Kuberouter declares that we want Kube-router networking type KuberouterNetworkingSpec struct { } + +// Romana declares that we want Romana networking +type RomanaNetworkingSpec struct { + // DaemonServiceIP is the Kubernetes Service IP for the romana-daemon pod + DaemonServiceIP string `json:"daemonServiceIP,omitempty"` + // EtcdServiceIP is the Kubernetes Service IP for the etcd backend used by Romana + EtcdServiceIP string `json:"etcdServiceIP,omitempty"` +} diff --git a/pkg/apis/kops/v1alpha1/networking.go b/pkg/apis/kops/v1alpha1/networking.go index 745ee844bc..8adcf2cbbc 100644 --- a/pkg/apis/kops/v1alpha1/networking.go +++ b/pkg/apis/kops/v1alpha1/networking.go @@ -28,6 +28,7 @@ type NetworkingSpec struct { Calico *CalicoNetworkingSpec `json:"calico,omitempty"` Canal *CanalNetworkingSpec `json:"canal,omitempty"` Kuberouter *KuberouterNetworkingSpec `json:"kuberouter,omitempty"` + Romana *RomanaNetworkingSpec `json:"romana,omitempty"` } // ClassicNetworkingSpec is the specification of classic networking mode, integrated into kubernetes @@ -80,3 +81,11 @@ type CanalNetworkingSpec struct { // Kuberouter declares that we want Canal networking type KuberouterNetworkingSpec struct { } + +// Romana declares that we want Romana networking +type RomanaNetworkingSpec struct { + // DaemonServiceIP is the Kubernetes Service IP for the romana-daemon pod + DaemonServiceIP string `json:"daemonServiceIP,omitempty"` + // EtcdServiceIP is the Kubernetes Service IP for the etcd backend used by Romana + EtcdServiceIP string `json:"etcdServiceIP,omitempty"` +} diff --git a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go index 764eb609b0..fdda06fb83 100644 --- a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go @@ -129,6 +129,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kops_NetworkingSpec_To_v1alpha1_NetworkingSpec, Convert_v1alpha1_RBACAuthorizationSpec_To_kops_RBACAuthorizationSpec, Convert_kops_RBACAuthorizationSpec_To_v1alpha1_RBACAuthorizationSpec, + Convert_v1alpha1_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec, + Convert_kops_RomanaNetworkingSpec_To_v1alpha1_RomanaNetworkingSpec, Convert_v1alpha1_SSHCredential_To_kops_SSHCredential, Convert_kops_SSHCredential_To_v1alpha1_SSHCredential, Convert_v1alpha1_SSHCredentialList_To_kops_SSHCredentialList, @@ -2230,6 +2232,15 @@ func autoConvert_v1alpha1_NetworkingSpec_To_kops_NetworkingSpec(in *NetworkingSp } else { out.Kuberouter = nil } + if in.Romana != nil { + in, out := &in.Romana, &out.Romana + *out = new(kops.RomanaNetworkingSpec) + if err := Convert_v1alpha1_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Romana = nil + } return nil } @@ -2329,6 +2340,15 @@ func autoConvert_kops_NetworkingSpec_To_v1alpha1_NetworkingSpec(in *kops.Network } else { out.Kuberouter = nil } + if in.Romana != nil { + in, out := &in.Romana, &out.Romana + *out = new(RomanaNetworkingSpec) + if err := Convert_kops_RomanaNetworkingSpec_To_v1alpha1_RomanaNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Romana = nil + } return nil } @@ -2355,6 +2375,28 @@ func Convert_kops_RBACAuthorizationSpec_To_v1alpha1_RBACAuthorizationSpec(in *ko return autoConvert_kops_RBACAuthorizationSpec_To_v1alpha1_RBACAuthorizationSpec(in, out, s) } +func autoConvert_v1alpha1_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(in *RomanaNetworkingSpec, out *kops.RomanaNetworkingSpec, s conversion.Scope) error { + out.DaemonServiceIP = in.DaemonServiceIP + out.EtcdServiceIP = in.EtcdServiceIP + return nil +} + +// Convert_v1alpha1_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec is an autogenerated conversion function. +func Convert_v1alpha1_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(in *RomanaNetworkingSpec, out *kops.RomanaNetworkingSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(in, out, s) +} + +func autoConvert_kops_RomanaNetworkingSpec_To_v1alpha1_RomanaNetworkingSpec(in *kops.RomanaNetworkingSpec, out *RomanaNetworkingSpec, s conversion.Scope) error { + out.DaemonServiceIP = in.DaemonServiceIP + out.EtcdServiceIP = in.EtcdServiceIP + return nil +} + +// Convert_kops_RomanaNetworkingSpec_To_v1alpha1_RomanaNetworkingSpec is an autogenerated conversion function. +func Convert_kops_RomanaNetworkingSpec_To_v1alpha1_RomanaNetworkingSpec(in *kops.RomanaNetworkingSpec, out *RomanaNetworkingSpec, s conversion.Scope) error { + return autoConvert_kops_RomanaNetworkingSpec_To_v1alpha1_RomanaNetworkingSpec(in, out, s) +} + func autoConvert_v1alpha1_SSHCredential_To_kops_SSHCredential(in *SSHCredential, out *kops.SSHCredential, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1alpha1_SSHCredentialSpec_To_kops_SSHCredentialSpec(&in.Spec, &out.Spec, s); err != nil { diff --git a/pkg/apis/kops/v1alpha2/networking.go b/pkg/apis/kops/v1alpha2/networking.go index c80bb70f56..75a291dbd9 100644 --- a/pkg/apis/kops/v1alpha2/networking.go +++ b/pkg/apis/kops/v1alpha2/networking.go @@ -28,6 +28,7 @@ type NetworkingSpec struct { Calico *CalicoNetworkingSpec `json:"calico,omitempty"` Canal *CanalNetworkingSpec `json:"canal,omitempty"` Kuberouter *KuberouterNetworkingSpec `json:"kuberouter,omitempty"` + Romana *RomanaNetworkingSpec `json:"romana,omitempty"` } // ClassicNetworkingSpec is the specification of classic networking mode, integrated into kubernetes @@ -80,3 +81,11 @@ type CanalNetworkingSpec struct { // Kuberouter declares that we want Canal networking type KuberouterNetworkingSpec struct { } + +// Romana declares that we want Romana networking +type RomanaNetworkingSpec struct { + // DaemonServiceIP is the Kubernetes Service IP for the romana-daemon pod + DaemonServiceIP string `json:"daemonServiceIP,omitempty"` + // EtcdServiceIP is the Kubernetes Service IP for the etcd backend used by Romana + EtcdServiceIP string `json:"etcdServiceIP,omitempty"` +} diff --git a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go index 85b481fead..ff1e2f7edb 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go @@ -141,6 +141,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_kops_NetworkingSpec_To_v1alpha2_NetworkingSpec, Convert_v1alpha2_RBACAuthorizationSpec_To_kops_RBACAuthorizationSpec, Convert_kops_RBACAuthorizationSpec_To_v1alpha2_RBACAuthorizationSpec, + Convert_v1alpha2_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec, + Convert_kops_RomanaNetworkingSpec_To_v1alpha2_RomanaNetworkingSpec, Convert_v1alpha2_SSHCredential_To_kops_SSHCredential, Convert_kops_SSHCredential_To_v1alpha2_SSHCredential, Convert_v1alpha2_SSHCredentialList_To_kops_SSHCredentialList, @@ -2489,6 +2491,15 @@ func autoConvert_v1alpha2_NetworkingSpec_To_kops_NetworkingSpec(in *NetworkingSp } else { out.Kuberouter = nil } + if in.Romana != nil { + in, out := &in.Romana, &out.Romana + *out = new(kops.RomanaNetworkingSpec) + if err := Convert_v1alpha2_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Romana = nil + } return nil } @@ -2588,6 +2599,15 @@ func autoConvert_kops_NetworkingSpec_To_v1alpha2_NetworkingSpec(in *kops.Network } else { out.Kuberouter = nil } + if in.Romana != nil { + in, out := &in.Romana, &out.Romana + *out = new(RomanaNetworkingSpec) + if err := Convert_kops_RomanaNetworkingSpec_To_v1alpha2_RomanaNetworkingSpec(*in, *out, s); err != nil { + return err + } + } else { + out.Romana = nil + } return nil } @@ -2614,6 +2634,28 @@ func Convert_kops_RBACAuthorizationSpec_To_v1alpha2_RBACAuthorizationSpec(in *ko return autoConvert_kops_RBACAuthorizationSpec_To_v1alpha2_RBACAuthorizationSpec(in, out, s) } +func autoConvert_v1alpha2_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(in *RomanaNetworkingSpec, out *kops.RomanaNetworkingSpec, s conversion.Scope) error { + out.DaemonServiceIP = in.DaemonServiceIP + out.EtcdServiceIP = in.EtcdServiceIP + return nil +} + +// Convert_v1alpha2_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec is an autogenerated conversion function. +func Convert_v1alpha2_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(in *RomanaNetworkingSpec, out *kops.RomanaNetworkingSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_RomanaNetworkingSpec_To_kops_RomanaNetworkingSpec(in, out, s) +} + +func autoConvert_kops_RomanaNetworkingSpec_To_v1alpha2_RomanaNetworkingSpec(in *kops.RomanaNetworkingSpec, out *RomanaNetworkingSpec, s conversion.Scope) error { + out.DaemonServiceIP = in.DaemonServiceIP + out.EtcdServiceIP = in.EtcdServiceIP + return nil +} + +// Convert_kops_RomanaNetworkingSpec_To_v1alpha2_RomanaNetworkingSpec is an autogenerated conversion function. +func Convert_kops_RomanaNetworkingSpec_To_v1alpha2_RomanaNetworkingSpec(in *kops.RomanaNetworkingSpec, out *RomanaNetworkingSpec, s conversion.Scope) error { + return autoConvert_kops_RomanaNetworkingSpec_To_v1alpha2_RomanaNetworkingSpec(in, out, s) +} + func autoConvert_v1alpha2_SSHCredential_To_kops_SSHCredential(in *SSHCredential, out *kops.SSHCredential, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1alpha2_SSHCredentialSpec_To_kops_SSHCredentialSpec(&in.Spec, &out.Spec, s); err != nil { diff --git a/pkg/apis/kops/validation/legacy.go b/pkg/apis/kops/validation/legacy.go index cf3a3295b2..7f6ed9ef4b 100644 --- a/pkg/apis/kops/validation/legacy.go +++ b/pkg/apis/kops/validation/legacy.go @@ -426,6 +426,12 @@ func ValidateCluster(c *kops.Cluster, strict bool) *field.Error { } } + if kubernetesRelease.LT(semver.MustParse("1.6.0")) { + if c.Spec.Networking != nil && c.Spec.Networking.Romana != nil { + return field.Invalid(fieldSpec.Child("Networking"), "romana", "romana networking is not supported with kubernetes versions 1.5 or lower") + } + } + if errs := newValidateCluster(c); len(errs) != 0 { return errs[0] } diff --git a/pkg/model/components/context.go b/pkg/model/components/context.go index d53f8d9995..6b058cc9e5 100644 --- a/pkg/model/components/context.go +++ b/pkg/model/components/context.go @@ -77,7 +77,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 || networking.Kuberouter != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != 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 94b550703f..965af3ff7a 100644 --- a/pkg/model/components/kubecontrollermanager.go +++ b/pkg/model/components/kubecontrollermanager.go @@ -142,7 +142,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 || networking.Kuberouter != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != 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 f9eba56fba..9564bc3757 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 || networking.Kuberouter != nil { + if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != nil { options.Kubelet.NetworkPluginName = "cni" if k8sVersion.Major == 1 && k8sVersion.Minor <= 4 { @@ -69,5 +69,18 @@ func (b *NetworkingOptionsBuilder) BuildOptions(o interface{}) error { } } + if networking.Romana != nil { + daemonIP, err := WellKnownServiceIP(clusterSpec, 99) + if err != nil { + return err + } + networking.Romana.DaemonServiceIP = daemonIP.String() + etcdIP, err := WellKnownServiceIP(clusterSpec, 88) + if err != nil { + return err + } + networking.Romana.EtcdServiceIP = etcdIP.String() + } + return nil } diff --git a/pkg/model/firewall.go b/pkg/model/firewall.go index a9bfc46cf1..29fd4e1122 100644 --- a/pkg/model/firewall.go +++ b/pkg/model/firewall.go @@ -148,6 +148,13 @@ func (b *FirewallModelBuilder) applyNodeToMasterAllowSpecificPorts(c *fi.ModelBu tcpPorts = append(tcpPorts, 179) protocols = append(protocols, ProtocolIPIP) } + + if b.Cluster.Spec.Networking.Romana != nil { + // Romana needs to access etcd + glog.Warningf("Opening etcd port on masters for access from the nodes, for romana. This is unsafe in untrusted environments.") + tcpPorts = append(tcpPorts, 4001) + tcpPorts = append(tcpPorts, 9600) + } } for _, udpPort := range udpPorts { @@ -212,6 +219,13 @@ func (b *FirewallModelBuilder) applyNodeToMasterBlockSpecificPorts(c *fi.ModelBu protocols = append(protocols, ProtocolIPIP) } + if b.Cluster.Spec.Networking.Romana != nil { + // Romana needs to access etcd + glog.Warningf("Opening etcd port on masters for access from the nodes, for romana. This is unsafe in untrusted environments.") + tcpRanges = []portRange{{From: 1, To: 4001}, {From: 4003, To: 65535}} + protocols = append(protocols, ProtocolIPIP) + } + for _, r := range udpRanges { c.AddTask(&awstasks.SecurityGroupRule{ Name: s(fmt.Sprintf("node-to-master-udp-%d-%d", r.From, r.To)), diff --git a/upup/models/cloudup/resources/addons/networking.romana/k8s-1.6.yaml.template b/upup/models/cloudup/resources/addons/networking.romana/k8s-1.6.yaml.template new file mode 100644 index 0000000000..d54bf857b8 --- /dev/null +++ b/upup/models/cloudup/resources/addons/networking.romana/k8s-1.6.yaml.template @@ -0,0 +1,347 @@ +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: romana-listener +rules: +- apiGroups: + - "*" + resources: + - pods + - namespaces + - nodes + - endpoints + verbs: + - get + - list + - watch +- apiGroups: + - extensions + resources: + - networkpolicies + verbs: + - get + - list + - watch +- apiGroups: + - "*" + resources: + - services + verbs: + - update + - list + - watch +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: romana-listener + namespace: kube-system +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: romana-listener +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: romana-listener +subjects: +- kind: ServiceAccount + name: romana-listener + namespace: kube-system +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: romana-agent +rules: +- apiGroups: + - "*" + resources: + - pods + - nodes + verbs: + - get +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: romana-agent + namespace: kube-system +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: romana-agent +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: romana-agent +subjects: +- kind: ServiceAccount + name: romana-agent + namespace: kube-system +--- +apiVersion: v1 +kind: Service +metadata: + name: romana-etcd + namespace: kube-system +spec: + clusterIP: {{ .Networking.Romana.EtcdServiceIP }} + ports: + - name: etcd + port: 12379 + protocol: TCP + targetPort: 4001 + selector: + k8s-app: etcd-server + sessionAffinity: None + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: romana + namespace: kube-system +spec: + clusterIP: {{ .Networking.Romana.DaemonServiceIP }} + ports: + - name: daemon + port: 9600 + protocol: TCP + targetPort: 9600 + selector: + romana-app: daemon + sessionAffinity: None + type: ClusterIP +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: romana-daemon + namespace: kube-system +spec: + replicas: 1 + template: + metadata: + labels: + romana-app: daemon + spec: + nodeSelector: + node-role.kubernetes.io/master: "" + hostNetwork: true + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + containers: + - name: romana-daemon + image: quay.io/romana/daemon:v2.0-preview.2 + imagePullPolicy: Always + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 10m + memory: 64Mi + args: + - --cloud=aws + - --network-cidr-overrides=romana-network={{ .KubeControllerManager.ClusterCIDR }} +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: romana-listener + namespace: kube-system +spec: + replicas: 1 + template: + metadata: + labels: + romana-app: listener + spec: + nodeSelector: + node-role.kubernetes.io/master: "" + hostNetwork: true + serviceAccountName: romana-listener + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + containers: + - name: romana-listener + image: quay.io/romana/listener:v2.0-preview.2 + imagePullPolicy: Always + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 10m + memory: 64Mi +--- +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: romana-agent + namespace: kube-system +spec: + template: + metadata: + labels: + romana-app: agent + spec: + hostNetwork: true + securityContext: + seLinuxOptions: + type: spc_t + serviceAccountName: romana-agent + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + containers: + - name: romana-agent + image: quay.io/romana/agent:v2.0-preview.2 + imagePullPolicy: Always + resources: + requests: + cpu: 25m + memory: 128Mi + limits: + cpu: 25m + memory: 128Mi + env: + - name: NODENAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + args: + - --service-cluster-ip-range={{ .ServiceClusterIPRange }} + securityContext: + privileged: true + volumeMounts: + - name: host-usr-local-bin + mountPath: /host/usr/local/bin + - name: host-etc-romana + mountPath: /host/etc/romana + - name: host-cni-bin + mountPath: /host/opt/cni/bin + - name: host-cni-net-d + mountPath: /host/etc/cni/net.d + - name: run-path + mountPath: /var/run/romana + volumes: + - name: host-usr-local-bin + hostPath: + path: /usr/local/bin + - name: host-etc-romana + hostPath: + path: /etc/romana + - name: host-cni-bin + hostPath: + path: /opt/cni/bin + - name: host-cni-net-d + hostPath: + path: /etc/cni/net.d + - name: run-path + hostPath: + path: /var/run/romana +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: romana-aws +rules: +- apiGroups: + - "*" + resources: + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: romana-aws + namespace: kube-system +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: romana-aws +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: romana-aws +subjects: +- kind: ServiceAccount + name: romana-aws + namespace: kube-system +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: romana-aws + namespace: kube-system +spec: + replicas: 1 + template: + metadata: + labels: + romana-app: aws + spec: + nodeSelector: + node-role.kubernetes.io/master: "" + hostNetwork: true + serviceAccountName: romana-aws + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + containers: + - name: romana-aws + image: quay.io/romana/aws:v2.0-preview.2 + imagePullPolicy: Always + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 10m + memory: 64Mi +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: romana-vpcrouter + namespace: kube-system +spec: + replicas: 1 + template: + metadata: + labels: + romana-app: vpcrouter + spec: + nodeSelector: + node-role.kubernetes.io/master: "" + hostNetwork: true + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + containers: + - name: romana-vpcrouter + image: quay.io/romana/vpcrouter-romana-plugin + imagePullPolicy: Always + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 50m + memory: 128Mi + args: + - --etcd_use_v2 + - --etcd_addr={{ .Networking.Romana.EtcdServiceIP }} + - --etcd_port=12379 diff --git a/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go b/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go index 01b6f292db..5835973473 100644 --- a/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go +++ b/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go @@ -468,6 +468,27 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri } } + if b.cluster.Spec.Networking.Romana != nil { + key := "networking.romana" + + version := "v2.0-preview.2" + + { + 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 + } + } + authenticationSelector := map[string]string{"role.kubernetes.io/authentication": "1"} if b.cluster.Spec.Authentication != nil && b.cluster.Spec.Authentication.Kopeio != nil { diff --git a/upup/pkg/fi/cloudup/networking.go b/upup/pkg/fi/cloudup/networking.go index d956bc903a..b69340d37b 100644 --- a/upup/pkg/fi/cloudup/networking.go +++ b/upup/pkg/fi/cloudup/networking.go @@ -73,6 +73,11 @@ func usesCNI(c *api.Cluster) bool { return true } + if networkConfig.Romana != nil { + // Romana 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 0b2500dd54..95c0cf66da 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 || networking.Kuberouter != nil { + } else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != nil { tags.Insert("_networking_cni") } else if networking.Kopeio != nil { // TODO combine with the External @@ -117,7 +117,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 || networking.Kuberouter != nil { + if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != nil { // external is based on cni, weave, flannel, calico, etc tags.Insert("_networking_cni") } diff --git a/upup/pkg/fi/cloudup/tagbuilder_test.go b/upup/pkg/fi/cloudup/tagbuilder_test.go index d7604d300f..866cdcac71 100644 --- a/upup/pkg/fi/cloudup/tagbuilder_test.go +++ b/upup/pkg/fi/cloudup/tagbuilder_test.go @@ -198,6 +198,40 @@ func TestBuildTags_CloudProvider_AWS_Canal(t *testing.T) { } } +func TestBuildTags_CloudProvider_AWS_Romana(t *testing.T) { + + c := buildCluster(nil) + networking := &api.NetworkingSpec{Romana: &api.RomanaNetworkingSpec{}} + + c.Spec.Networking = networking + + tags, err := buildCloudupTags(c) + if err != nil { + t.Fatalf("buildCloudupTags error: %v", err) + } + + if !tags.Has("_aws") { + t.Fatal("tag _aws not found") + } + + if !tags.Has("_networking_cni") { + t.Fatal("tag _networking_cni not found") + } + + if tags.Has("_networking_kubenet") { + t.Fatal("tag _networking_kubenet found") + } + + nodeUpTags, err := buildNodeupTags(api.InstanceGroupRoleNode, c, tags) + if err != nil { + t.Fatalf("buildNodeupTags error: %v", err) + } + + if !nodeUpTags.Has("_aws") { + t.Fatal("nodeUpTag _aws not found") + } +} + func TestBuildTags_CloudProvider_AWS(t *testing.T) { c := buildCluster(nil)