Merge pull request #1911 from justinsb/more_options_to_code

Move more options to code
This commit is contained in:
Eric Hole 2017-02-16 23:09:35 -05:00 committed by GitHub
commit 0ce094a956
26 changed files with 341 additions and 184 deletions

View File

@ -33,29 +33,29 @@ type KubeAPIServerOptionsBuilder struct {
var _ loader.OptionsBuilder = &KubeAPIServerOptionsBuilder{}
func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
options := o.(*kops.ClusterSpec)
if options.KubeAPIServer == nil {
options.KubeAPIServer = &kops.KubeAPIServerConfig{}
clusterSpec := o.(*kops.ClusterSpec)
if clusterSpec.KubeAPIServer == nil {
clusterSpec.KubeAPIServer = &kops.KubeAPIServerConfig{}
}
if options.KubeAPIServer.APIServerCount == nil {
count := b.buildAPIServerCount()
if clusterSpec.KubeAPIServer.APIServerCount == nil {
count := b.buildAPIServerCount(clusterSpec)
if count == 0 {
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
options.KubeAPIServer.StorageBackend = fi.String("etcd2")
clusterSpec.KubeAPIServer.StorageBackend = fi.String("etcd2")
}
k8sVersion, err := b.Context.KubernetesVersion()
k8sVersion, err := KubernetesVersion(clusterSpec)
if err != nil {
return err
}
if options.KubeAPIServer.KubeletPreferredAddressTypes == nil {
if clusterSpec.KubeAPIServer.KubeletPreferredAddressTypes == nil {
if k8sVersion.GTE(semver.MustParse("1.5.0")) {
// Default precedence
//options.KubeAPIServer.KubeletPreferredAddressTypes = []string {
@ -66,7 +66,7 @@ func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
//}
// We prioritize the internal IP above the hostname
options.KubeAPIServer.KubeletPreferredAddressTypes = []string{
clusterSpec.KubeAPIServer.KubeletPreferredAddressTypes = []string{
string(api.NodeInternalIP),
string(api.NodeHostName),
string(api.NodeExternalIP),
@ -78,7 +78,7 @@ func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
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
// We should do something like this:
@ -103,7 +103,7 @@ func (b *KubeAPIServerOptionsBuilder) buildAPIServerCount() int {
// the flag won't exist
counts := make(map[string]int)
for _, etcdCluster := range b.Context.Cluster.Spec.EtcdClusters {
for _, etcdCluster := range clusterSpec.EtcdClusters {
counts[etcdCluster.Name] = len(etcdCluster.Members)
}

View File

@ -17,20 +17,22 @@ limitations under the License.
package components
import (
"encoding/binary"
"fmt"
"github.com/blang/semver"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/util"
"math/big"
"net"
)
// OptionsContext is the context object for options builders
type OptionsContext struct {
Cluster *kops.Cluster
}
// KubernetesVersion parses the semver version of kubernetes, from the cluster spec
func (c *OptionsContext) KubernetesVersion() (*semver.Version, error) {
kubernetesVersion := c.Cluster.Spec.KubernetesVersion
func KubernetesVersion(clusterSpec *kops.ClusterSpec) (*semver.Version, error) {
kubernetesVersion := clusterSpec.KubernetesVersion
if kubernetesVersion == "" {
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
func (c *OptionsContext) UsesKubenet() (bool, error) {
networking := c.Cluster.Spec.Networking
func UsesKubenet(clusterSpec *kops.ClusterSpec) (bool, error) {
networking := clusterSpec.Networking
if networking == nil || networking.Classic != nil {
return false, nil
} else if networking.Kubenet != nil {
@ -63,3 +65,35 @@ func (c *OptionsContext) UsesKubenet() (bool, error) {
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)
}

View File

@ -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
}

View File

@ -31,19 +31,19 @@ type DockerOptionsBuilder struct {
var _ loader.OptionsBuilder = &DockerOptionsBuilder{}
func (b *DockerOptionsBuilder) BuildOptions(o interface{}) error {
options := o.(*kops.ClusterSpec)
if options.Docker == nil {
options.Docker = &kops.DockerConfig{}
clusterSpec := o.(*kops.ClusterSpec)
if clusterSpec.Docker == nil {
clusterSpec.Docker = &kops.DockerConfig{}
}
if fi.StringValue(options.Docker.Version) == "" {
if options.KubernetesVersion == "" {
if fi.StringValue(clusterSpec.Docker.Version) == "" {
if clusterSpec.KubernetesVersion == "" {
return fmt.Errorf("KubernetesVersion is required")
}
sv, err := b.Context.KubernetesVersion()
sv, err := KubernetesVersion(clusterSpec)
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 := ""
@ -54,10 +54,10 @@ func (b *DockerOptionsBuilder) BuildOptions(o interface{}) error {
}
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

View File

@ -41,10 +41,10 @@ var _ loader.OptionsBuilder = &KubeControllerManagerOptionsBuilder{}
// BuildOptions generates the configurations used to create kubernetes controller manager manifest
func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error {
options := o.(*kops.ClusterSpec)
clusterSpec := o.(*kops.ClusterSpec)
if options.KubeControllerManager == nil {
options.KubeControllerManager = &kops.KubeControllerManagerConfig{}
if clusterSpec.KubeControllerManager == nil {
clusterSpec.KubeControllerManager = &kops.KubeControllerManagerConfig{}
}
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)
}
kubernetesVersion, err := b.Context.KubernetesVersion()
kubernetesVersion, err := KubernetesVersion(clusterSpec)
if err != nil {
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)
// If not set ... or set to 0s ... which is stupid
if options.KubeControllerManager.AttachDetachReconcileSyncPeriod == nil ||
options.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration.String() == "0s" {
if clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod == nil ||
clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration.String() == "0s" {
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
} else if options.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration < defaultAttachDetachReconcileSyncPeriod &&
options.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration > time.Second {
} else if clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration < defaultAttachDetachReconcileSyncPeriod &&
clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration > time.Second {
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
// 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")
}
} else {
glog.V(4).Infof("not setting AttachDetachReconcileSyncPeriod, k8s version is too low")
options.KubeControllerManager.AttachDetachReconcileSyncPeriod = nil
clusterSpec.KubeControllerManager.AttachDetachReconcileSyncPeriod = nil
}
return nil

View File

@ -47,9 +47,7 @@ func Test_Build_KCM_Builder_Lower_Version(t *testing.T) {
c := buildCluster()
kcm := &KubeControllerManagerOptionsBuilder{
Context: &OptionsContext{
Cluster: c,
},
Context: &OptionsContext{},
}
spec := c.Spec
@ -76,9 +74,7 @@ func Test_Build_KCM_Builder_High_Enough_Version(t *testing.T) {
c.Spec.KubernetesVersion = v
kcm := &KubeControllerManagerOptionsBuilder{
Context: &OptionsContext{
Cluster: c,
},
Context: &OptionsContext{},
}
spec := c.Spec
@ -101,9 +97,7 @@ func Test_Build_KCM_Builder_Change_Duration(t *testing.T) {
c.Spec.KubernetesVersion = "v1.5.2"
kcm := &KubeControllerManagerOptionsBuilder{
Context: &OptionsContext{
Cluster: c,
},
Context: &OptionsContext{},
}
spec := c.Spec

View File

@ -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
}

View File

@ -31,47 +31,70 @@ type KubeletOptionsBuilder struct {
var _ loader.OptionsBuilder = &KubeletOptionsBuilder{}
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 {
return err
}
if options.Kubelet == nil {
options.Kubelet = &kops.KubeletConfigSpec{}
if clusterSpec.Kubelet == nil {
clusterSpec.Kubelet = &kops.KubeletConfigSpec{}
}
if options.MasterKubelet == nil {
options.MasterKubelet = &kops.KubeletConfigSpec{}
if clusterSpec.MasterKubelet == nil {
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
// so that hostNetwork pods can come up
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)
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)
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) {
options.MasterKubelet.ReconcileCIDR = fi.Bool(false)
if fi.BoolValue(clusterSpec.IsolateMasters) {
clusterSpec.MasterKubelet.ReconcileCIDR = fi.Bool(false)
}
usesKubenet, err := b.Context.UsesKubenet()
usesKubenet, err := UsesKubenet(clusterSpec)
if err != nil {
return err
}
if usesKubenet {
options.Kubelet.ReconcileCIDR = fi.Bool(true)
clusterSpec.Kubelet.ReconcileCIDR = fi.Bool(true)
}
}
if kubernetesVersion.Major == 1 && kubernetesVersion.Minor >= 4 {
// For pod eviction in low memory or empty disk situations
if options.Kubelet.EvictionHard == nil {
if clusterSpec.Kubelet.EvictionHard == nil {
evictionHard := []string{
// TODO: Some people recommend 250Mi, but this would hurt small machines
"memory.available<100Mi",
@ -83,15 +106,48 @@ func (b *KubeletOptionsBuilder) BuildOptions(o interface{}) error {
"imagefs.available<10%",
"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
// In newer versions of kubernetes, most of that functionality has been removed though
if fi.BoolValue(b.Context.Cluster.Spec.IsolateMasters) {
options.MasterKubelet.EnableDebuggingHandlers = fi.Bool(false)
options.MasterKubelet.HairpinMode = "none"
if fi.BoolValue(clusterSpec.IsolateMasters) {
clusterSpec.MasterKubelet.EnableDebuggingHandlers = fi.Bool(false)
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

View File

@ -31,7 +31,9 @@ type NetworkingOptionsBuilder struct {
var _ loader.OptionsBuilder = &NetworkingOptionsBuilder{}
func (b *NetworkingOptionsBuilder) BuildOptions(o interface{}) error {
k8sVersion, err := b.Context.KubernetesVersion()
clusterSpec := o.(*kops.ClusterSpec)
k8sVersion, err := KubernetesVersion(clusterSpec)
if err != nil {
return err
}
@ -41,7 +43,7 @@ func (b *NetworkingOptionsBuilder) BuildOptions(o interface{}) error {
options.Kubelet = &kops.KubeletConfigSpec{}
}
networking := b.Context.Cluster.Spec.Networking
networking := clusterSpec.Networking
if networking == nil {
return fmt.Errorf("networking not set")
}

View File

@ -25,11 +25,14 @@ import (
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/pkg/model/components"
"net"
)
type KopsModelContext struct {
Cluster *kops.Cluster
Region string
Cluster *kops.Cluster
InstanceGroups []*kops.InstanceGroup
SSHPublicKeys [][]byte
@ -223,3 +226,7 @@ func VersionGTE(version semver.Version, major uint64, minor uint64) bool {
}
return false
}
func (c *KopsModelContext) WellKnownServiceIP(id int) (net.IP, error) {
return components.WellKnownServiceIP(&c.Cluster.Spec, id)
}

86
pkg/model/pki.go Normal file
View File

@ -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
}

View File

@ -1,3 +0,0 @@
keypair/kubecfg:
subject: cn=kubecfg
type: client

View File

@ -1,3 +0,0 @@
keypair/kubelet:
subject: cn=kubelet
type: client

View File

@ -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 }}"

View File

@ -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

View File

@ -1,5 +0,0 @@
Kubelet:
CloudProvider: aws
CgroupRoot: docker
# Use the hostname from the AWS metadata service
HostnameOverride: "@aws"

View File

@ -1,7 +0,0 @@
Kubelet:
CloudProvider: gce
HairpinMode: promiscuous-bridge
RuntimeCgroups: /docker-daemon
KubeletCgroups: /kubelet
SystemCgroups: /system
CgroupRoot: /

View File

@ -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

View File

@ -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

View File

@ -1,2 +0,0 @@
Kubelet:
NetworkPluginName: kubenet

View File

@ -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

View File

@ -1,6 +0,0 @@
Multizone: true
ClusterDNSDomain: cluster.local
KubeUser: admin

View File

@ -378,6 +378,7 @@ func (c *ApplyClusterCmd) Run() error {
&model.ExternalAccessModelBuilder{KopsModelContext: modelContext},
&model.FirewallModelBuilder{KopsModelContext: modelContext},
&model.IAMModelBuilder{KopsModelContext: modelContext},
&model.PKIModelBuilder{KopsModelContext: modelContext},
&model.MasterVolumeBuilder{KopsModelContext: modelContext},
&model.NetworkModelBuilder{KopsModelContext: modelContext},
&model.SSHKeyModelBuilder{KopsModelContext: modelContext},

View File

@ -254,17 +254,19 @@ func (c *populateClusterSpec) run() error {
tf.AddTo(templateFunctions)
optionsContext := &components.OptionsContext{
Cluster: cluster,
}
optionsContext := &components.OptionsContext{}
var fileModels []string
var codeModels []loader.OptionsBuilder
for _, m := range c.Models {
switch m {
case "config":
// Note: DefaultOptionsBuilder comes first
codeModels = append(codeModels, &components.DefaultsOptionsBuilder{Context: optionsContext})
codeModels = append(codeModels, &components.KubeAPIServerOptionsBuilder{Context: optionsContext})
codeModels = append(codeModels, &components.DockerOptionsBuilder{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.KubeControllerManagerOptionsBuilder{Context: optionsContext})
fileModels = append(fileModels, m)

View File

@ -29,15 +29,12 @@ package cloudup
import (
"encoding/base64"
"encoding/binary"
"fmt"
"github.com/golang/glog"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/model"
"k8s.io/kops/util/pkg/vfs"
"k8s.io/kubernetes/pkg/util/sets"
"math/big"
"net"
"strings"
"text/template"
)
@ -52,38 +49,6 @@ type TemplateFunctions struct {
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
// If we are trying to get a new function implemented it MUST
// be defined here.
@ -96,8 +61,6 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap) {
// Network topology definitions
dest["GetELBName32"] = tf.modelContext.GetELBName32
dest["WellKnownServiceIP"] = tf.WellKnownServiceIP
dest["Base64Encode"] = func(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s))
}

View File

@ -41,6 +41,7 @@ type Keypair struct {
}
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
func (e *Keypair) CheckExisting(c *fi.Context) bool {