diff --git a/cmd/cloud-controller-manager/app/options/options.go b/cmd/cloud-controller-manager/app/options/options.go index 0f5a3e79689..2d57294ec88 100644 --- a/cmd/cloud-controller-manager/app/options/options.go +++ b/cmd/cloud-controller-manager/app/options/options.go @@ -71,6 +71,8 @@ func (s *CloudControllerManagerServer) AddFlags(fs *pflag.FlagSet) { fs.Var(componentconfig.IPVar{Val: &s.Address}, "address", "The IP address to serve on (set to 0.0.0.0 for all interfaces)") fs.StringVar(&s.CloudProvider, "cloud-provider", s.CloudProvider, "The provider of cloud services. Cannot be empty.") fs.StringVar(&s.CloudConfigFile, "cloud-config", s.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.") + fs.BoolVar(&s.AllowUntaggedCloud, "allow-untagged-cloud", false, "Allow the cluster to run without the cluster-id on cloud instances. This is a legacy mode of operation and a cluster-id will be required in the future.") + fs.MarkDeprecated("allow-untagged-cloud", "This flag is deprecated and will be removed in a future release. A cluster-id will be required on cloud instances") fs.DurationVar(&s.MinResyncPeriod.Duration, "min-resync-period", s.MinResyncPeriod.Duration, "The resync period in reflectors will be random between MinResyncPeriod and 2*MinResyncPeriod") fs.DurationVar(&s.NodeMonitorPeriod.Duration, "node-monitor-period", s.NodeMonitorPeriod.Duration, "The period for syncing NodeStatus in NodeController.") diff --git a/cmd/cloud-controller-manager/controller-manager.go b/cmd/cloud-controller-manager/controller-manager.go index 28f906e528e..49f793294b5 100644 --- a/cmd/cloud-controller-manager/controller-manager.go +++ b/cmd/cloud-controller-manager/controller-manager.go @@ -61,6 +61,14 @@ func main() { glog.Fatalf("Cloud provider could not be initialized: %v", err) } + if cloud.HasClusterID() == false { + if s.AllowUntaggedCloud == true { + glog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues") + } else { + glog.Fatalf("no ClusterID Found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option") + } + } + if err := app.Run(s, cloud); err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index bf6539edd9d..2c5e2518fc0 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -411,6 +411,14 @@ func CreateControllerContext(s *options.CMServer, rootClientBuilder, clientBuild if cloud != nil { // Initialize the cloud provider with a reference to the clientBuilder cloud.Initialize(rootClientBuilder) + + if cloud.HasClusterID() == false { + if s.AllowUntaggedCloud == true { + glog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues") + } else { + return ControllerContext{}, fmt.Errorf("no ClusterID Found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option") + } + } } ctx := ControllerContext{ diff --git a/cmd/kube-controller-manager/app/options/options.go b/cmd/kube-controller-manager/app/options/options.go index f7754b381d2..5b834261fa7 100644 --- a/cmd/kube-controller-manager/app/options/options.go +++ b/cmd/kube-controller-manager/app/options/options.go @@ -134,6 +134,8 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet, allControllers []string, disabled fs.BoolVar(&s.UseServiceAccountCredentials, "use-service-account-credentials", s.UseServiceAccountCredentials, "If true, use individual service account credentials for each controller.") fs.StringVar(&s.CloudProvider, "cloud-provider", s.CloudProvider, "The provider for cloud services. Empty string for no provider.") fs.StringVar(&s.CloudConfigFile, "cloud-config", s.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.") + fs.BoolVar(&s.AllowUntaggedCloud, "allow-untagged-cloud", false, "Allow the cluster to run without the cluster-id on cloud instances. This is a legacy mode of operation and a cluster-id will be required in the future.") + fs.MarkDeprecated("allow-untagged-cloud", "This flag is deprecated and will be removed in a future release. A cluster-id will be required on cloud instances") fs.Int32Var(&s.ConcurrentEndpointSyncs, "concurrent-endpoint-syncs", s.ConcurrentEndpointSyncs, "The number of endpoint syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load") fs.Int32Var(&s.ConcurrentServiceSyncs, "concurrent-service-syncs", s.ConcurrentServiceSyncs, "The number of services that are allowed to sync concurrently. Larger number = more responsive service management, but more CPU (and network) load") fs.Int32Var(&s.ConcurrentRCSyncs, "concurrent_rc_syncs", s.ConcurrentRCSyncs, "The number of replication controllers that are allowed to sync concurrently. Larger number = more responsive replica management, but more CPU (and network) load") diff --git a/pkg/apis/componentconfig/types.go b/pkg/apis/componentconfig/types.go index 2c0a7b2fe4f..4e4d5e1c1e6 100644 --- a/pkg/apis/componentconfig/types.go +++ b/pkg/apis/componentconfig/types.go @@ -669,6 +669,8 @@ type KubeControllerManagerConfiguration struct { CloudProvider string // cloudConfigFile is the path to the cloud provider configuration file. CloudConfigFile string + // run with untagged cloud instances + AllowUntaggedCloud bool // concurrentEndpointSyncs is the number of endpoint syncing operations // that will be done concurrently. Larger number = faster endpoint updating, // but more CPU (and network) load. diff --git a/pkg/cloudprovider/cloud.go b/pkg/cloudprovider/cloud.go index 409d39a7d13..5c4651f7d3a 100644 --- a/pkg/cloudprovider/cloud.go +++ b/pkg/cloudprovider/cloud.go @@ -45,6 +45,8 @@ type Interface interface { ProviderName() string // ScrubDNS provides an opportunity for cloud-provider-specific code to process DNS settings for pods. ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) + // HasClusterID returns true if a ClusterID is required and set + HasClusterID() bool } // Clusters is an abstract, pluggable interface for clusters of containers. diff --git a/pkg/cloudprovider/providers/aws/aws.go b/pkg/cloudprovider/providers/aws/aws.go index ebd56a36086..704c5e9966e 100644 --- a/pkg/cloudprovider/providers/aws/aws.go +++ b/pkg/cloudprovider/providers/aws/aws.go @@ -971,6 +971,11 @@ func (c *Cloud) Routes() (cloudprovider.Routes, bool) { return c, true } +// HasClusterID returns true if the cluster has a clusterID +func (c *Cloud) HasClusterID() bool { + return len(c.tagging.clusterID()) > 0 +} + // NodeAddresses is an implementation of Instances.NodeAddresses. func (c *Cloud) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) { if c.selfAWSInstance.nodeName == name || len(name) == 0 { diff --git a/pkg/cloudprovider/providers/aws/tags.go b/pkg/cloudprovider/providers/aws/tags.go index 3d051850574..bb63fce2bfd 100644 --- a/pkg/cloudprovider/providers/aws/tags.go +++ b/pkg/cloudprovider/providers/aws/tags.go @@ -276,3 +276,7 @@ func (t *awsTagging) buildTags(lifecycle ResourceLifecycle, additionalTags map[s return tags } + +func (t *awsTagging) clusterID() string { + return t.ClusterID +} diff --git a/pkg/cloudprovider/providers/azure/azure.go b/pkg/cloudprovider/providers/azure/azure.go index 33c90b38360..be0e2df4464 100644 --- a/pkg/cloudprovider/providers/azure/azure.go +++ b/pkg/cloudprovider/providers/azure/azure.go @@ -391,6 +391,11 @@ func (az *Cloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []stri return nameservers, searches } +// HasClusterID returns true if the cluster has a clusterID +func (az *Cloud) HasClusterID() bool { + return true +} + // ProviderName returns the cloud provider ID. func (az *Cloud) ProviderName() string { return CloudProviderName diff --git a/pkg/cloudprovider/providers/cloudstack/cloudstack.go b/pkg/cloudprovider/providers/cloudstack/cloudstack.go index f8e2b3ffb6f..1b86d8243ab 100644 --- a/pkg/cloudprovider/providers/cloudstack/cloudstack.go +++ b/pkg/cloudprovider/providers/cloudstack/cloudstack.go @@ -120,6 +120,11 @@ func (cs *CSCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []st return nameservers, searches } +// HasClusterID returns true if the cluster has a clusterID +func (cs *CSCloud) HasClusterID() bool { + return true +} + // GetZone returns the Zone containing the region that the program is running in. func (cs *CSCloud) GetZone() (cloudprovider.Zone, error) { glog.V(2).Infof("Current zone is %v", cs.zone) diff --git a/pkg/cloudprovider/providers/fake/fake.go b/pkg/cloudprovider/providers/fake/fake.go index 77022e2cb8c..05c10c146cc 100644 --- a/pkg/cloudprovider/providers/fake/fake.go +++ b/pkg/cloudprovider/providers/fake/fake.go @@ -111,6 +111,11 @@ func (f *FakeCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []s return nameservers, searches } +// HasClusterID returns true if the cluster has a clusterID +func (f *FakeCloud) HasClusterID() bool { + return true +} + // LoadBalancer returns a fake implementation of LoadBalancer. // Actually it just returns f itself. func (f *FakeCloud) LoadBalancer() (cloudprovider.LoadBalancer, bool) { diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index a6d5dccaedb..a4dd5eab159 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -469,6 +469,11 @@ func (gce *GCECloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut [] return nameservers, srchOut } +// HasClusterID returns true if the cluster has a clusterID +func (gce *GCECloud) HasClusterID() bool { + return true +} + // GCECloud implements cloudprovider.Interface. var _ cloudprovider.Interface = (*GCECloud)(nil) diff --git a/pkg/cloudprovider/providers/openstack/openstack.go b/pkg/cloudprovider/providers/openstack/openstack.go index 15993f6f910..43599ec1b7f 100644 --- a/pkg/cloudprovider/providers/openstack/openstack.go +++ b/pkg/cloudprovider/providers/openstack/openstack.go @@ -458,6 +458,11 @@ func (os *OpenStack) ScrubDNS(nameServers, searches []string) ([]string, []strin return nameServers, searches } +// HasClusterID returns true if the cluster has a clusterID +func (os *OpenStack) HasClusterID() bool { + return true +} + func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) { glog.V(4).Info("openstack.LoadBalancer() called") diff --git a/pkg/cloudprovider/providers/ovirt/ovirt.go b/pkg/cloudprovider/providers/ovirt/ovirt.go index 73275262919..fe71113ed0a 100644 --- a/pkg/cloudprovider/providers/ovirt/ovirt.go +++ b/pkg/cloudprovider/providers/ovirt/ovirt.go @@ -134,6 +134,11 @@ func (v *OVirtCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut [] return nameservers, searches } +// HasClusterID returns true if the cluster has a clusterID +func (v *OVirtCloud) HasClusterID() bool { + return true +} + // LoadBalancer returns an implementation of LoadBalancer for oVirt cloud func (v *OVirtCloud) LoadBalancer() (cloudprovider.LoadBalancer, bool) { return nil, false diff --git a/pkg/cloudprovider/providers/photon/photon.go b/pkg/cloudprovider/providers/photon/photon.go index 8ef0b1dcfcc..87ecc1b160e 100644 --- a/pkg/cloudprovider/providers/photon/photon.go +++ b/pkg/cloudprovider/providers/photon/photon.go @@ -539,6 +539,11 @@ func (pc *PCCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []st return nameservers, searches } +// HasClusterID returns true if the cluster has a clusterID +func (pc *PCCloud) HasClusterID() bool { + return true +} + // Attaches given virtual disk volume to the compute running kubelet. func (pc *PCCloud) AttachDisk(pdID string, nodeName k8stypes.NodeName) error { photonClient, err := getPhotonClient(pc) diff --git a/pkg/cloudprovider/providers/rackspace/rackspace.go b/pkg/cloudprovider/providers/rackspace/rackspace.go index 0e04d9407c4..b087bfa4cea 100644 --- a/pkg/cloudprovider/providers/rackspace/rackspace.go +++ b/pkg/cloudprovider/providers/rackspace/rackspace.go @@ -529,6 +529,11 @@ func (os *Rackspace) ScrubDNS(nameservers, searches []string) (nsOut, srchOut [] return nameservers, searches } +// HasClusterID returns true if the cluster has a clusterID +func (os *Rackspace) HasClusterID() bool { + return true +} + func (os *Rackspace) LoadBalancer() (cloudprovider.LoadBalancer, bool) { return nil, false } diff --git a/pkg/cloudprovider/providers/vsphere/vsphere.go b/pkg/cloudprovider/providers/vsphere/vsphere.go index b1409ea3b28..60086d52297 100644 --- a/pkg/cloudprovider/providers/vsphere/vsphere.go +++ b/pkg/cloudprovider/providers/vsphere/vsphere.go @@ -747,3 +747,8 @@ func (vs *VSphere) DeleteVolume(vmDiskPath string) error { vclib.RecordvSphereMetric(vclib.OperationDeleteVolume, requestTime, err) return err } + +// HasClusterID returns true if the cluster has a clusterID +func (vs *VSphere) HasClusterID() bool { + return true +}