mirror of https://github.com/kubernetes/kops.git
Merge pull request #1911 from justinsb/more_options_to_code
Move more options to code
This commit is contained in:
commit
0ce094a956
|
@ -33,29 +33,29 @@ type KubeAPIServerOptionsBuilder struct {
|
||||||
var _ loader.OptionsBuilder = &KubeAPIServerOptionsBuilder{}
|
var _ loader.OptionsBuilder = &KubeAPIServerOptionsBuilder{}
|
||||||
|
|
||||||
func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
|
func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
options := o.(*kops.ClusterSpec)
|
clusterSpec := o.(*kops.ClusterSpec)
|
||||||
if options.KubeAPIServer == nil {
|
if clusterSpec.KubeAPIServer == nil {
|
||||||
options.KubeAPIServer = &kops.KubeAPIServerConfig{}
|
clusterSpec.KubeAPIServer = &kops.KubeAPIServerConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.KubeAPIServer.APIServerCount == nil {
|
if clusterSpec.KubeAPIServer.APIServerCount == nil {
|
||||||
count := b.buildAPIServerCount()
|
count := b.buildAPIServerCount(clusterSpec)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return fmt.Errorf("no instance groups found")
|
return fmt.Errorf("no instance groups found")
|
||||||
}
|
}
|
||||||
options.KubeAPIServer.APIServerCount = fi.Int32(int32(count))
|
clusterSpec.KubeAPIServer.APIServerCount = fi.Int32(int32(count))
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.KubeAPIServer.StorageBackend == nil {
|
if clusterSpec.KubeAPIServer.StorageBackend == nil {
|
||||||
// For the moment, we continue to use etcd2
|
// For the moment, we continue to use etcd2
|
||||||
options.KubeAPIServer.StorageBackend = fi.String("etcd2")
|
clusterSpec.KubeAPIServer.StorageBackend = fi.String("etcd2")
|
||||||
}
|
}
|
||||||
|
|
||||||
k8sVersion, err := b.Context.KubernetesVersion()
|
k8sVersion, err := KubernetesVersion(clusterSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if options.KubeAPIServer.KubeletPreferredAddressTypes == nil {
|
if clusterSpec.KubeAPIServer.KubeletPreferredAddressTypes == nil {
|
||||||
if k8sVersion.GTE(semver.MustParse("1.5.0")) {
|
if k8sVersion.GTE(semver.MustParse("1.5.0")) {
|
||||||
// Default precedence
|
// Default precedence
|
||||||
//options.KubeAPIServer.KubeletPreferredAddressTypes = []string {
|
//options.KubeAPIServer.KubeletPreferredAddressTypes = []string {
|
||||||
|
@ -66,7 +66,7 @@ func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// We prioritize the internal IP above the hostname
|
// We prioritize the internal IP above the hostname
|
||||||
options.KubeAPIServer.KubeletPreferredAddressTypes = []string{
|
clusterSpec.KubeAPIServer.KubeletPreferredAddressTypes = []string{
|
||||||
string(api.NodeInternalIP),
|
string(api.NodeInternalIP),
|
||||||
string(api.NodeHostName),
|
string(api.NodeHostName),
|
||||||
string(api.NodeExternalIP),
|
string(api.NodeExternalIP),
|
||||||
|
@ -78,7 +78,7 @@ func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *KubeAPIServerOptionsBuilder) buildAPIServerCount() int {
|
func (b *KubeAPIServerOptionsBuilder) buildAPIServerCount(clusterSpec *kops.ClusterSpec) int {
|
||||||
// The --apiserver-count flag is (generally agreed) to be something we need to get rid of in k8s
|
// The --apiserver-count flag is (generally agreed) to be something we need to get rid of in k8s
|
||||||
|
|
||||||
// We should do something like this:
|
// We should do something like this:
|
||||||
|
@ -103,7 +103,7 @@ func (b *KubeAPIServerOptionsBuilder) buildAPIServerCount() int {
|
||||||
// the flag won't exist
|
// the flag won't exist
|
||||||
|
|
||||||
counts := make(map[string]int)
|
counts := make(map[string]int)
|
||||||
for _, etcdCluster := range b.Context.Cluster.Spec.EtcdClusters {
|
for _, etcdCluster := range clusterSpec.EtcdClusters {
|
||||||
counts[etcdCluster.Name] = len(etcdCluster.Members)
|
counts[etcdCluster.Name] = len(etcdCluster.Members)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,20 +17,22 @@ limitations under the License.
|
||||||
package components
|
package components
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/blang/semver"
|
"github.com/blang/semver"
|
||||||
"k8s.io/kops/pkg/apis/kops"
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
"k8s.io/kops/pkg/apis/kops/util"
|
"k8s.io/kops/pkg/apis/kops/util"
|
||||||
|
"math/big"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OptionsContext is the context object for options builders
|
// OptionsContext is the context object for options builders
|
||||||
type OptionsContext struct {
|
type OptionsContext struct {
|
||||||
Cluster *kops.Cluster
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// KubernetesVersion parses the semver version of kubernetes, from the cluster spec
|
// KubernetesVersion parses the semver version of kubernetes, from the cluster spec
|
||||||
func (c *OptionsContext) KubernetesVersion() (*semver.Version, error) {
|
func KubernetesVersion(clusterSpec *kops.ClusterSpec) (*semver.Version, error) {
|
||||||
kubernetesVersion := c.Cluster.Spec.KubernetesVersion
|
kubernetesVersion := clusterSpec.KubernetesVersion
|
||||||
|
|
||||||
if kubernetesVersion == "" {
|
if kubernetesVersion == "" {
|
||||||
return nil, fmt.Errorf("KubernetesVersion is required")
|
return nil, fmt.Errorf("KubernetesVersion is required")
|
||||||
|
@ -45,8 +47,8 @@ func (c *OptionsContext) KubernetesVersion() (*semver.Version, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UsesKubenet returns true if our networking is derived from kubenet
|
// UsesKubenet returns true if our networking is derived from kubenet
|
||||||
func (c *OptionsContext) UsesKubenet() (bool, error) {
|
func UsesKubenet(clusterSpec *kops.ClusterSpec) (bool, error) {
|
||||||
networking := c.Cluster.Spec.Networking
|
networking := clusterSpec.Networking
|
||||||
if networking == nil || networking.Classic != nil {
|
if networking == nil || networking.Classic != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
} else if networking.Kubenet != nil {
|
} else if networking.Kubenet != nil {
|
||||||
|
@ -63,3 +65,35 @@ func (c *OptionsContext) UsesKubenet() (bool, error) {
|
||||||
return false, fmt.Errorf("No networking mode set")
|
return false, fmt.Errorf("No networking mode set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WellKnownServiceIP(clusterSpec *kops.ClusterSpec, id int) (net.IP, error) {
|
||||||
|
_, cidr, err := net.ParseCIDR(clusterSpec.ServiceClusterIPRange)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing ServiceClusterIPRange %q: %v", clusterSpec.ServiceClusterIPRange, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ip4 := cidr.IP.To4()
|
||||||
|
if ip4 != nil {
|
||||||
|
n := binary.BigEndian.Uint32(ip4)
|
||||||
|
n += uint32(id)
|
||||||
|
serviceIP := make(net.IP, len(ip4))
|
||||||
|
binary.BigEndian.PutUint32(serviceIP, n)
|
||||||
|
return serviceIP, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ip6 := cidr.IP.To16()
|
||||||
|
if ip6 != nil {
|
||||||
|
baseIPInt := big.NewInt(0)
|
||||||
|
baseIPInt.SetBytes(ip6)
|
||||||
|
serviceIPInt := big.NewInt(0)
|
||||||
|
serviceIPInt.Add(big.NewInt(int64(id)), baseIPInt)
|
||||||
|
serviceIP := make(net.IP, len(ip6))
|
||||||
|
serviceIPBytes := serviceIPInt.Bytes()
|
||||||
|
for i := range serviceIPBytes {
|
||||||
|
serviceIP[len(serviceIP)-len(serviceIPBytes)+i] = serviceIPBytes[i]
|
||||||
|
}
|
||||||
|
return serviceIP, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("Unexpected IP address type for ServiceClusterIPRange: %s", clusterSpec.ServiceClusterIPRange)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 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 components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
|
"k8s.io/kops/upup/pkg/fi/loader"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultsOptionsBuilder adds default options. This should come first!
|
||||||
|
type DefaultsOptionsBuilder struct {
|
||||||
|
Context *OptionsContext
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ loader.OptionsBuilder = &DefaultsOptionsBuilder{}
|
||||||
|
|
||||||
|
func (b *DefaultsOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
|
options := o.(*kops.ClusterSpec)
|
||||||
|
|
||||||
|
if options.ClusterDNSDomain == "" {
|
||||||
|
options.ClusterDNSDomain = "cluster.local"
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -31,19 +31,19 @@ type DockerOptionsBuilder struct {
|
||||||
var _ loader.OptionsBuilder = &DockerOptionsBuilder{}
|
var _ loader.OptionsBuilder = &DockerOptionsBuilder{}
|
||||||
|
|
||||||
func (b *DockerOptionsBuilder) BuildOptions(o interface{}) error {
|
func (b *DockerOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
options := o.(*kops.ClusterSpec)
|
clusterSpec := o.(*kops.ClusterSpec)
|
||||||
if options.Docker == nil {
|
if clusterSpec.Docker == nil {
|
||||||
options.Docker = &kops.DockerConfig{}
|
clusterSpec.Docker = &kops.DockerConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.StringValue(options.Docker.Version) == "" {
|
if fi.StringValue(clusterSpec.Docker.Version) == "" {
|
||||||
if options.KubernetesVersion == "" {
|
if clusterSpec.KubernetesVersion == "" {
|
||||||
return fmt.Errorf("KubernetesVersion is required")
|
return fmt.Errorf("KubernetesVersion is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
sv, err := b.Context.KubernetesVersion()
|
sv, err := KubernetesVersion(clusterSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to determine kubernetes version from %q", options.KubernetesVersion)
|
return fmt.Errorf("unable to determine kubernetes version from %q", clusterSpec.KubernetesVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
dockerVersion := ""
|
dockerVersion := ""
|
||||||
|
@ -54,10 +54,10 @@ func (b *DockerOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if dockerVersion == "" {
|
if dockerVersion == "" {
|
||||||
return fmt.Errorf("unknown version of kubernetes %q (cannot infer docker version)", options.KubernetesVersion)
|
return fmt.Errorf("unknown version of kubernetes %q (cannot infer docker version)", clusterSpec.KubernetesVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
options.Docker.Version = &dockerVersion
|
clusterSpec.Docker.Version = &dockerVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -41,10 +41,10 @@ var _ loader.OptionsBuilder = &KubeControllerManagerOptionsBuilder{}
|
||||||
// BuildOptions generates the configurations used to create kubernetes controller manager manifest
|
// BuildOptions generates the configurations used to create kubernetes controller manager manifest
|
||||||
func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error {
|
func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
|
|
||||||
options := o.(*kops.ClusterSpec)
|
clusterSpec := o.(*kops.ClusterSpec)
|
||||||
|
|
||||||
if options.KubeControllerManager == nil {
|
if clusterSpec.KubeControllerManager == nil {
|
||||||
options.KubeControllerManager = &kops.KubeControllerManagerConfig{}
|
clusterSpec.KubeControllerManager = &kops.KubeControllerManagerConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
k8sv148, err := util.ParseKubernetesVersion("v1.4.8")
|
k8sv148, err := util.ParseKubernetesVersion("v1.4.8")
|
||||||
|
@ -63,7 +63,7 @@ func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error
|
||||||
return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
|
return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kubernetesVersion, err := b.Context.KubernetesVersion()
|
kubernetesVersion, err := KubernetesVersion(clusterSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
|
return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
|
||||||
}
|
}
|
||||||
|
@ -78,27 +78,27 @@ func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error
|
||||||
|
|
||||||
glog.V(4).Infof("Kubernetes version %q supports AttachDetachReconcileSyncPeriod; will configure", kubernetesVersion)
|
glog.V(4).Infof("Kubernetes version %q supports AttachDetachReconcileSyncPeriod; will configure", kubernetesVersion)
|
||||||
// If not set ... or set to 0s ... which is stupid
|
// If not set ... or set to 0s ... which is stupid
|
||||||
if options.KubeControllerManager.AttachDetachReconcileSyncPeriod == nil ||
|
if clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod == nil ||
|
||||||
options.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration.String() == "0s" {
|
clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration.String() == "0s" {
|
||||||
|
|
||||||
glog.V(8).Infof("AttachDetachReconcileSyncPeriod is not set; will set to default %v", defaultAttachDetachReconcileSyncPeriod)
|
glog.V(8).Infof("AttachDetachReconcileSyncPeriod is not set; will set to default %v", defaultAttachDetachReconcileSyncPeriod)
|
||||||
options.KubeControllerManager.AttachDetachReconcileSyncPeriod = &metav1.Duration{Duration: defaultAttachDetachReconcileSyncPeriod}
|
clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod = &metav1.Duration{Duration: defaultAttachDetachReconcileSyncPeriod}
|
||||||
|
|
||||||
// If less than 1 min and greater than 1 sec ... you get a warning
|
// If less than 1 min and greater than 1 sec ... you get a warning
|
||||||
} else if options.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration < defaultAttachDetachReconcileSyncPeriod &&
|
} else if clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration < defaultAttachDetachReconcileSyncPeriod &&
|
||||||
options.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration > time.Second {
|
clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration > time.Second {
|
||||||
|
|
||||||
glog.Infof("KubeControllerManager AttachDetachReconcileSyncPeriod is set lower than recommended: %s", defaultAttachDetachReconcileSyncPeriod)
|
glog.Infof("KubeControllerManager AttachDetachReconcileSyncPeriod is set lower than recommended: %s", defaultAttachDetachReconcileSyncPeriod)
|
||||||
|
|
||||||
// If less than 1sec you get an error. Controller is coded to not allow configuration
|
// If less than 1sec you get an error. Controller is coded to not allow configuration
|
||||||
// less than one second.
|
// less than one second.
|
||||||
} else if options.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration < time.Second {
|
} else if clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration < time.Second {
|
||||||
return fmt.Errorf("AttachDetachReconcileSyncPeriod cannot be set to less than 1 second")
|
return fmt.Errorf("AttachDetachReconcileSyncPeriod cannot be set to less than 1 second")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
glog.V(4).Infof("not setting AttachDetachReconcileSyncPeriod, k8s version is too low")
|
glog.V(4).Infof("not setting AttachDetachReconcileSyncPeriod, k8s version is too low")
|
||||||
options.KubeControllerManager.AttachDetachReconcileSyncPeriod = nil
|
clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -47,9 +47,7 @@ func Test_Build_KCM_Builder_Lower_Version(t *testing.T) {
|
||||||
c := buildCluster()
|
c := buildCluster()
|
||||||
|
|
||||||
kcm := &KubeControllerManagerOptionsBuilder{
|
kcm := &KubeControllerManagerOptionsBuilder{
|
||||||
Context: &OptionsContext{
|
Context: &OptionsContext{},
|
||||||
Cluster: c,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spec := c.Spec
|
spec := c.Spec
|
||||||
|
@ -76,9 +74,7 @@ func Test_Build_KCM_Builder_High_Enough_Version(t *testing.T) {
|
||||||
c.Spec.KubernetesVersion = v
|
c.Spec.KubernetesVersion = v
|
||||||
|
|
||||||
kcm := &KubeControllerManagerOptionsBuilder{
|
kcm := &KubeControllerManagerOptionsBuilder{
|
||||||
Context: &OptionsContext{
|
Context: &OptionsContext{},
|
||||||
Cluster: c,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spec := c.Spec
|
spec := c.Spec
|
||||||
|
@ -101,9 +97,7 @@ func Test_Build_KCM_Builder_Change_Duration(t *testing.T) {
|
||||||
c.Spec.KubernetesVersion = "v1.5.2"
|
c.Spec.KubernetesVersion = "v1.5.2"
|
||||||
|
|
||||||
kcm := &KubeControllerManagerOptionsBuilder{
|
kcm := &KubeControllerManagerOptionsBuilder{
|
||||||
Context: &OptionsContext{
|
Context: &OptionsContext{},
|
||||||
Cluster: c,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spec := c.Spec
|
spec := c.Spec
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 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 components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
|
"k8s.io/kops/upup/pkg/fi/loader"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KubeDnsOptionsBuilder adds options for kube-dns
|
||||||
|
type KubeDnsOptionsBuilder struct {
|
||||||
|
Context *OptionsContext
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ loader.OptionsBuilder = &KubeDnsOptionsBuilder{}
|
||||||
|
|
||||||
|
func (b *KubeDnsOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
|
clusterSpec := o.(*kops.ClusterSpec)
|
||||||
|
|
||||||
|
if clusterSpec.KubeDNS == nil {
|
||||||
|
clusterSpec.KubeDNS = &kops.KubeDNSConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterSpec.KubeDNS.Replicas = 2
|
||||||
|
ip, err := WellKnownServiceIP(clusterSpec, 10)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clusterSpec.KubeDNS.ServerIP = ip.String()
|
||||||
|
clusterSpec.KubeDNS.Domain = clusterSpec.ClusterDNSDomain
|
||||||
|
// TODO: Once we start shipping more images, start using them
|
||||||
|
clusterSpec.KubeDNS.Image = "gcr.io/google_containers/kubedns-amd64:1.3"
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -31,47 +31,70 @@ type KubeletOptionsBuilder struct {
|
||||||
var _ loader.OptionsBuilder = &KubeletOptionsBuilder{}
|
var _ loader.OptionsBuilder = &KubeletOptionsBuilder{}
|
||||||
|
|
||||||
func (b *KubeletOptionsBuilder) BuildOptions(o interface{}) error {
|
func (b *KubeletOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
options := o.(*kops.ClusterSpec)
|
clusterSpec := o.(*kops.ClusterSpec)
|
||||||
|
|
||||||
kubernetesVersion, err := b.Context.KubernetesVersion()
|
kubernetesVersion, err := KubernetesVersion(clusterSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Kubelet == nil {
|
if clusterSpec.Kubelet == nil {
|
||||||
options.Kubelet = &kops.KubeletConfigSpec{}
|
clusterSpec.Kubelet = &kops.KubeletConfigSpec{}
|
||||||
}
|
}
|
||||||
if options.MasterKubelet == nil {
|
if clusterSpec.MasterKubelet == nil {
|
||||||
options.MasterKubelet = &kops.KubeletConfigSpec{}
|
clusterSpec.MasterKubelet = &kops.KubeletConfigSpec{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip, err := WellKnownServiceIP(clusterSpec, 10)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard options
|
||||||
|
clusterSpec.Kubelet.EnableDebuggingHandlers = fi.Bool(true)
|
||||||
|
clusterSpec.Kubelet.PodManifestPath = "/etc/kubernetes/manifests"
|
||||||
|
clusterSpec.Kubelet.AllowPrivileged = fi.Bool(true)
|
||||||
|
clusterSpec.Kubelet.LogLevel = fi.Int32(2)
|
||||||
|
clusterSpec.Kubelet.ClusterDNS = ip.String()
|
||||||
|
clusterSpec.Kubelet.ClusterDomain = clusterSpec.ClusterDNSDomain
|
||||||
|
clusterSpec.Kubelet.BabysitDaemons = fi.Bool(true)
|
||||||
|
clusterSpec.Kubelet.APIServers = "https://" + clusterSpec.MasterInternalName
|
||||||
|
clusterSpec.Kubelet.NonMasqueradeCIDR = clusterSpec.NonMasqueradeCIDR
|
||||||
|
|
||||||
|
clusterSpec.MasterKubelet.RegisterSchedulable = fi.Bool(false)
|
||||||
|
clusterSpec.MasterKubelet.APIServers = "http://127.0.0.1:8080"
|
||||||
|
// Replace the CIDR with a CIDR allocated by KCM (the default, but included for clarity)
|
||||||
|
// We _do_ allow debugging handlers, so we can do logs
|
||||||
|
// This does allow more access than we would like though
|
||||||
|
clusterSpec.MasterKubelet.EnableDebuggingHandlers = fi.Bool(true)
|
||||||
|
|
||||||
// In 1.5 we fixed this, but in 1.4 we need to set the PodCIDR on the master
|
// In 1.5 we fixed this, but in 1.4 we need to set the PodCIDR on the master
|
||||||
// so that hostNetwork pods can come up
|
// so that hostNetwork pods can come up
|
||||||
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor <= 4 {
|
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor <= 4 {
|
||||||
// We bootstrap with a fake CIDR, but then this will be replaced (unless we're running with _isolated_master)
|
// We bootstrap with a fake CIDR, but then this will be replaced (unless we're running with _isolated_master)
|
||||||
options.MasterKubelet.PodCIDR = "10.123.45.0/28"
|
clusterSpec.MasterKubelet.PodCIDR = "10.123.45.0/28"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.5 deprecates the reconcile cidr option (and 1.6 removes it)
|
// 1.5 deprecates the reconcile cidr option (and 1.6 removes it)
|
||||||
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor <= 4 {
|
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor <= 4 {
|
||||||
options.MasterKubelet.ReconcileCIDR = fi.Bool(true)
|
clusterSpec.MasterKubelet.ReconcileCIDR = fi.Bool(true)
|
||||||
|
|
||||||
if fi.BoolValue(b.Context.Cluster.Spec.IsolateMasters) {
|
if fi.BoolValue(clusterSpec.IsolateMasters) {
|
||||||
options.MasterKubelet.ReconcileCIDR = fi.Bool(false)
|
clusterSpec.MasterKubelet.ReconcileCIDR = fi.Bool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
usesKubenet, err := b.Context.UsesKubenet()
|
usesKubenet, err := UsesKubenet(clusterSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if usesKubenet {
|
if usesKubenet {
|
||||||
options.Kubelet.ReconcileCIDR = fi.Bool(true)
|
clusterSpec.Kubelet.ReconcileCIDR = fi.Bool(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor >= 4 {
|
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor >= 4 {
|
||||||
// For pod eviction in low memory or empty disk situations
|
// For pod eviction in low memory or empty disk situations
|
||||||
if options.Kubelet.EvictionHard == nil {
|
if clusterSpec.Kubelet.EvictionHard == nil {
|
||||||
evictionHard := []string{
|
evictionHard := []string{
|
||||||
// TODO: Some people recommend 250Mi, but this would hurt small machines
|
// TODO: Some people recommend 250Mi, but this would hurt small machines
|
||||||
"memory.available<100Mi",
|
"memory.available<100Mi",
|
||||||
|
@ -83,15 +106,48 @@ func (b *KubeletOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
"imagefs.available<10%",
|
"imagefs.available<10%",
|
||||||
"imagefs.inodesFree<5%",
|
"imagefs.inodesFree<5%",
|
||||||
}
|
}
|
||||||
options.Kubelet.EvictionHard = fi.String(strings.Join(evictionHard, ","))
|
clusterSpec.Kubelet.EvictionHard = fi.String(strings.Join(evictionHard, ","))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsolateMasters enables the legacy behaviour, where master pods on a separate network
|
// IsolateMasters enables the legacy behaviour, where master pods on a separate network
|
||||||
// In newer versions of kubernetes, most of that functionality has been removed though
|
// In newer versions of kubernetes, most of that functionality has been removed though
|
||||||
if fi.BoolValue(b.Context.Cluster.Spec.IsolateMasters) {
|
if fi.BoolValue(clusterSpec.IsolateMasters) {
|
||||||
options.MasterKubelet.EnableDebuggingHandlers = fi.Bool(false)
|
clusterSpec.MasterKubelet.EnableDebuggingHandlers = fi.Bool(false)
|
||||||
options.MasterKubelet.HairpinMode = "none"
|
clusterSpec.MasterKubelet.HairpinMode = "none"
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudProvider := fi.CloudProviderID(clusterSpec.CloudProvider)
|
||||||
|
|
||||||
|
if cloudProvider == fi.CloudProviderAWS {
|
||||||
|
clusterSpec.Kubelet.CloudProvider = "aws"
|
||||||
|
clusterSpec.Kubelet.CgroupRoot = "docker"
|
||||||
|
|
||||||
|
// Use the hostname from the AWS metadata service
|
||||||
|
clusterSpec.Kubelet.HostnameOverride = "@aws"
|
||||||
|
}
|
||||||
|
|
||||||
|
if cloudProvider == fi.CloudProviderGCE {
|
||||||
|
clusterSpec.Kubelet.CloudProvider = "gce"
|
||||||
|
clusterSpec.Kubelet.HairpinMode = "promiscuous-bridge"
|
||||||
|
|
||||||
|
clusterSpec.Kubelet.RuntimeCgroups = "/docker-daemon"
|
||||||
|
clusterSpec.Kubelet.KubeletCgroups = "/kubelet"
|
||||||
|
clusterSpec.Kubelet.SystemCgroups = "/system"
|
||||||
|
clusterSpec.Kubelet.CgroupRoot = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
usesKubenet, err := UsesKubenet(clusterSpec)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if usesKubenet {
|
||||||
|
clusterSpec.Kubelet.NetworkPluginName = "kubenet"
|
||||||
|
|
||||||
|
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor >= 4 {
|
||||||
|
// AWS MTU is 9001
|
||||||
|
clusterSpec.Kubelet.NetworkPluginMTU = fi.Int32(9001)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -31,7 +31,9 @@ type NetworkingOptionsBuilder struct {
|
||||||
var _ loader.OptionsBuilder = &NetworkingOptionsBuilder{}
|
var _ loader.OptionsBuilder = &NetworkingOptionsBuilder{}
|
||||||
|
|
||||||
func (b *NetworkingOptionsBuilder) BuildOptions(o interface{}) error {
|
func (b *NetworkingOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
k8sVersion, err := b.Context.KubernetesVersion()
|
clusterSpec := o.(*kops.ClusterSpec)
|
||||||
|
|
||||||
|
k8sVersion, err := KubernetesVersion(clusterSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -41,7 +43,7 @@ func (b *NetworkingOptionsBuilder) BuildOptions(o interface{}) error {
|
||||||
options.Kubelet = &kops.KubeletConfigSpec{}
|
options.Kubelet = &kops.KubeletConfigSpec{}
|
||||||
}
|
}
|
||||||
|
|
||||||
networking := b.Context.Cluster.Spec.Networking
|
networking := clusterSpec.Networking
|
||||||
if networking == nil {
|
if networking == nil {
|
||||||
return fmt.Errorf("networking not set")
|
return fmt.Errorf("networking not set")
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,14 @@ import (
|
||||||
|
|
||||||
"k8s.io/kops/pkg/apis/kops"
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
"k8s.io/kops/pkg/apis/kops/util"
|
"k8s.io/kops/pkg/apis/kops/util"
|
||||||
|
"k8s.io/kops/pkg/model/components"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type KopsModelContext struct {
|
type KopsModelContext struct {
|
||||||
|
Cluster *kops.Cluster
|
||||||
|
|
||||||
Region string
|
Region string
|
||||||
Cluster *kops.Cluster
|
|
||||||
InstanceGroups []*kops.InstanceGroup
|
InstanceGroups []*kops.InstanceGroup
|
||||||
|
|
||||||
SSHPublicKeys [][]byte
|
SSHPublicKeys [][]byte
|
||||||
|
@ -223,3 +226,7 @@ func VersionGTE(version semver.Version, major uint64, minor uint64) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *KopsModelContext) WellKnownServiceIP(id int) (net.IP, error) {
|
||||||
|
return components.WellKnownServiceIP(&c.Cluster.Spec, id)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 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/fitasks"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PKIModelBuilder configures PKI keypairs
|
||||||
|
type PKIModelBuilder struct {
|
||||||
|
*KopsModelContext
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ fi.ModelBuilder = &PKIModelBuilder{}
|
||||||
|
|
||||||
|
func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||||
|
{
|
||||||
|
// Keypair used by the kubelet
|
||||||
|
t := &fitasks.Keypair{
|
||||||
|
Name: fi.String("kubelet"),
|
||||||
|
Subject: "cn=kubelet",
|
||||||
|
Type: "client",
|
||||||
|
}
|
||||||
|
c.AddTask(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Keypair used for admin kubecfg
|
||||||
|
t := &fitasks.Keypair{
|
||||||
|
Name: fi.String("kubecfg"),
|
||||||
|
Subject: "cn=kubecfg",
|
||||||
|
Type: "client",
|
||||||
|
}
|
||||||
|
c.AddTask(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Keypair used for apiserver
|
||||||
|
|
||||||
|
// A few names used from inside the cluster, which all resolve the same based on our default suffixes
|
||||||
|
alternateNames := []string{
|
||||||
|
"kubernetes",
|
||||||
|
"kubernetes.default",
|
||||||
|
"kubernetes.default.svc",
|
||||||
|
"kubernetes.default.svc." + b.Cluster.Spec.ClusterDNSDomain,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Names specified in the cluster spec
|
||||||
|
alternateNames = append(alternateNames, b.Cluster.Spec.MasterPublicName)
|
||||||
|
alternateNames = append(alternateNames, b.Cluster.Spec.MasterInternalName)
|
||||||
|
|
||||||
|
// Referencing it by internal IP should work also
|
||||||
|
{
|
||||||
|
ip, err := b.WellKnownServiceIP(1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
alternateNames = append(alternateNames, ip.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &fitasks.Keypair{
|
||||||
|
Name: fi.String("master"),
|
||||||
|
Subject: "cn=kubernetes-master",
|
||||||
|
Type: "server",
|
||||||
|
AlternateNames: alternateNames,
|
||||||
|
}
|
||||||
|
c.AddTask(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
keypair/kubecfg:
|
|
||||||
subject: cn=kubecfg
|
|
||||||
type: client
|
|
|
@ -1,3 +0,0 @@
|
||||||
keypair/kubelet:
|
|
||||||
subject: cn=kubelet
|
|
||||||
type: client
|
|
|
@ -1,11 +0,0 @@
|
||||||
keypair/master:
|
|
||||||
subject: cn=kubernetes-master
|
|
||||||
type: server
|
|
||||||
alternateNames:
|
|
||||||
- kubernetes
|
|
||||||
- kubernetes.default
|
|
||||||
- kubernetes.default.svc
|
|
||||||
- kubernetes.default.svc.{{ .ClusterDNSDomain }}
|
|
||||||
- "{{ .MasterPublicName }}"
|
|
||||||
- "{{ .MasterInternalName }}"
|
|
||||||
- "{{ WellKnownServiceIP 1 }}"
|
|
|
@ -1,6 +0,0 @@
|
||||||
KubeDNS:
|
|
||||||
Replicas: 2
|
|
||||||
ServerIP: {{ WellKnownServiceIP 10 }}
|
|
||||||
Domain: {{ .ClusterDNSDomain }}
|
|
||||||
# TODO: Once we start shipping more images, start using them
|
|
||||||
Image: gcr.io/google_containers/kubedns-amd64:1.3
|
|
|
@ -1,5 +0,0 @@
|
||||||
Kubelet:
|
|
||||||
CloudProvider: aws
|
|
||||||
CgroupRoot: docker
|
|
||||||
# Use the hostname from the AWS metadata service
|
|
||||||
HostnameOverride: "@aws"
|
|
|
@ -1,7 +0,0 @@
|
||||||
Kubelet:
|
|
||||||
CloudProvider: gce
|
|
||||||
HairpinMode: promiscuous-bridge
|
|
||||||
RuntimeCgroups: /docker-daemon
|
|
||||||
KubeletCgroups: /kubelet
|
|
||||||
SystemCgroups: /system
|
|
||||||
CgroupRoot: /
|
|
|
@ -1,8 +0,0 @@
|
||||||
Kubelet:
|
|
||||||
# AWS MTU is 9001
|
|
||||||
NetworkPluginMTU: 9001
|
|
||||||
|
|
||||||
# TODO: Having to duplicate MasterKubelet & Kubelet feels wrong
|
|
||||||
MasterKubelet:
|
|
||||||
# AWS MTU is 9001
|
|
||||||
NetworkPluginMTU: 9001
|
|
|
@ -1,8 +0,0 @@
|
||||||
Kubelet:
|
|
||||||
# AWS MTU is 9001
|
|
||||||
NetworkPluginMTU: 9001
|
|
||||||
|
|
||||||
# TODO: Having to duplicate MasterKubelet & Kubelet feels wrong
|
|
||||||
MasterKubelet:
|
|
||||||
# AWS MTU is 9001
|
|
||||||
NetworkPluginMTU: 9001
|
|
|
@ -1,2 +0,0 @@
|
||||||
Kubelet:
|
|
||||||
NetworkPluginName: kubenet
|
|
|
@ -1,18 +0,0 @@
|
||||||
Kubelet:
|
|
||||||
EnableDebuggingHandlers: true
|
|
||||||
PodManifestPath: /etc/kubernetes/manifests
|
|
||||||
AllowPrivileged: true
|
|
||||||
LogLevel: 2
|
|
||||||
ClusterDNS: {{ WellKnownServiceIP 10 }}
|
|
||||||
ClusterDomain: {{ .ClusterDNSDomain }}
|
|
||||||
BabysitDaemons: true
|
|
||||||
APIServers: https://{{ .MasterInternalName }}
|
|
||||||
NonMasqueradeCIDR: {{ .NonMasqueradeCIDR }}
|
|
||||||
|
|
||||||
MasterKubelet:
|
|
||||||
RegisterSchedulable: false
|
|
||||||
APIServers: http://127.0.0.1:8080
|
|
||||||
# Replace the CIDR with a CIDR allocated by KCM (the default, but included for clarity)
|
|
||||||
# We _do_ allow debugging handlers, so we can do logs
|
|
||||||
# This does allow more access than we would like though
|
|
||||||
EnableDebuggingHandlers: true
|
|
|
@ -1,6 +0,0 @@
|
||||||
Multizone: true
|
|
||||||
|
|
||||||
ClusterDNSDomain: cluster.local
|
|
||||||
|
|
||||||
KubeUser: admin
|
|
||||||
|
|
|
@ -378,6 +378,7 @@ func (c *ApplyClusterCmd) Run() error {
|
||||||
&model.ExternalAccessModelBuilder{KopsModelContext: modelContext},
|
&model.ExternalAccessModelBuilder{KopsModelContext: modelContext},
|
||||||
&model.FirewallModelBuilder{KopsModelContext: modelContext},
|
&model.FirewallModelBuilder{KopsModelContext: modelContext},
|
||||||
&model.IAMModelBuilder{KopsModelContext: modelContext},
|
&model.IAMModelBuilder{KopsModelContext: modelContext},
|
||||||
|
&model.PKIModelBuilder{KopsModelContext: modelContext},
|
||||||
&model.MasterVolumeBuilder{KopsModelContext: modelContext},
|
&model.MasterVolumeBuilder{KopsModelContext: modelContext},
|
||||||
&model.NetworkModelBuilder{KopsModelContext: modelContext},
|
&model.NetworkModelBuilder{KopsModelContext: modelContext},
|
||||||
&model.SSHKeyModelBuilder{KopsModelContext: modelContext},
|
&model.SSHKeyModelBuilder{KopsModelContext: modelContext},
|
||||||
|
|
|
@ -254,17 +254,19 @@ func (c *populateClusterSpec) run() error {
|
||||||
|
|
||||||
tf.AddTo(templateFunctions)
|
tf.AddTo(templateFunctions)
|
||||||
|
|
||||||
optionsContext := &components.OptionsContext{
|
optionsContext := &components.OptionsContext{}
|
||||||
Cluster: cluster,
|
|
||||||
}
|
|
||||||
var fileModels []string
|
var fileModels []string
|
||||||
var codeModels []loader.OptionsBuilder
|
var codeModels []loader.OptionsBuilder
|
||||||
for _, m := range c.Models {
|
for _, m := range c.Models {
|
||||||
switch m {
|
switch m {
|
||||||
case "config":
|
case "config":
|
||||||
|
// Note: DefaultOptionsBuilder comes first
|
||||||
|
codeModels = append(codeModels, &components.DefaultsOptionsBuilder{Context: optionsContext})
|
||||||
|
|
||||||
codeModels = append(codeModels, &components.KubeAPIServerOptionsBuilder{Context: optionsContext})
|
codeModels = append(codeModels, &components.KubeAPIServerOptionsBuilder{Context: optionsContext})
|
||||||
codeModels = append(codeModels, &components.DockerOptionsBuilder{Context: optionsContext})
|
codeModels = append(codeModels, &components.DockerOptionsBuilder{Context: optionsContext})
|
||||||
codeModels = append(codeModels, &components.NetworkingOptionsBuilder{Context: optionsContext})
|
codeModels = append(codeModels, &components.NetworkingOptionsBuilder{Context: optionsContext})
|
||||||
|
codeModels = append(codeModels, &components.KubeDnsOptionsBuilder{Context: optionsContext})
|
||||||
codeModels = append(codeModels, &components.KubeletOptionsBuilder{Context: optionsContext})
|
codeModels = append(codeModels, &components.KubeletOptionsBuilder{Context: optionsContext})
|
||||||
codeModels = append(codeModels, &components.KubeControllerManagerOptionsBuilder{Context: optionsContext})
|
codeModels = append(codeModels, &components.KubeControllerManagerOptionsBuilder{Context: optionsContext})
|
||||||
fileModels = append(fileModels, m)
|
fileModels = append(fileModels, m)
|
||||||
|
|
|
@ -29,15 +29,12 @@ package cloudup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
api "k8s.io/kops/pkg/apis/kops"
|
api "k8s.io/kops/pkg/apis/kops"
|
||||||
"k8s.io/kops/pkg/model"
|
"k8s.io/kops/pkg/model"
|
||||||
"k8s.io/kops/util/pkg/vfs"
|
"k8s.io/kops/util/pkg/vfs"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
"math/big"
|
|
||||||
"net"
|
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
@ -52,38 +49,6 @@ type TemplateFunctions struct {
|
||||||
modelContext *model.KopsModelContext
|
modelContext *model.KopsModelContext
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tf *TemplateFunctions) WellKnownServiceIP(id int) (net.IP, error) {
|
|
||||||
_, cidr, err := net.ParseCIDR(tf.cluster.Spec.ServiceClusterIPRange)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error parsing ServiceClusterIPRange %q: %v", tf.cluster.Spec.ServiceClusterIPRange, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ip4 := cidr.IP.To4()
|
|
||||||
if ip4 != nil {
|
|
||||||
n := binary.BigEndian.Uint32(ip4)
|
|
||||||
n += uint32(id)
|
|
||||||
serviceIP := make(net.IP, len(ip4))
|
|
||||||
binary.BigEndian.PutUint32(serviceIP, n)
|
|
||||||
return serviceIP, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ip6 := cidr.IP.To16()
|
|
||||||
if ip6 != nil {
|
|
||||||
baseIPInt := big.NewInt(0)
|
|
||||||
baseIPInt.SetBytes(ip6)
|
|
||||||
serviceIPInt := big.NewInt(0)
|
|
||||||
serviceIPInt.Add(big.NewInt(int64(id)), baseIPInt)
|
|
||||||
serviceIP := make(net.IP, len(ip6))
|
|
||||||
serviceIPBytes := serviceIPInt.Bytes()
|
|
||||||
for i := range serviceIPBytes {
|
|
||||||
serviceIP[len(serviceIP)-len(serviceIPBytes)+i] = serviceIPBytes[i]
|
|
||||||
}
|
|
||||||
return serviceIP, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("Unexpected IP address type for ServiceClusterIPRange: %s", tf.cluster.Spec.ServiceClusterIPRange)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will define the available functions we can use in our YAML models
|
// This will define the available functions we can use in our YAML models
|
||||||
// If we are trying to get a new function implemented it MUST
|
// If we are trying to get a new function implemented it MUST
|
||||||
// be defined here.
|
// be defined here.
|
||||||
|
@ -96,8 +61,6 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap) {
|
||||||
// Network topology definitions
|
// Network topology definitions
|
||||||
dest["GetELBName32"] = tf.modelContext.GetELBName32
|
dest["GetELBName32"] = tf.modelContext.GetELBName32
|
||||||
|
|
||||||
dest["WellKnownServiceIP"] = tf.WellKnownServiceIP
|
|
||||||
|
|
||||||
dest["Base64Encode"] = func(s string) string {
|
dest["Base64Encode"] = func(s string) string {
|
||||||
return base64.StdEncoding.EncodeToString([]byte(s))
|
return base64.StdEncoding.EncodeToString([]byte(s))
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ type Keypair struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ fi.HasCheckExisting = &Keypair{}
|
var _ fi.HasCheckExisting = &Keypair{}
|
||||||
|
var _ fi.HasName = &Keypair{}
|
||||||
|
|
||||||
// It's important always to check for the existing key, so we don't regenerate keys e.g. on terraform
|
// It's important always to check for the existing key, so we don't regenerate keys e.g. on terraform
|
||||||
func (e *Keypair) CheckExisting(c *fi.Context) bool {
|
func (e *Keypair) CheckExisting(c *fi.Context) bool {
|
||||||
|
|
Loading…
Reference in New Issue