Merge branch 'master' of https://github.com/kubernetes/kops into feature/extend_PR_398

This commit is contained in:
dima 2017-04-19 12:37:52 +02:00
commit 968cf784a9
961 changed files with 202547 additions and 633 deletions

12
.gitmodules vendored
View File

@ -274,3 +274,15 @@
[submodule "_vendor/github.com/golang/protobuf"]
path = _vendor/github.com/golang/protobuf
url = https://github.com/golang/protobuf
[submodule "_vendor/github.com/vmware/govmomi"]
path = _vendor/github.com/vmware/govmomi
url = https://github.com/vmware/govmomi.git
[submodule "_vendor/github.com/coreos/go-semver"]
path = _vendor/github.com/coreos/go-semver
url = https://github.com/coreos/go-semver.git
[submodule "_vendor/github.com/miekg/coredns"]
path = _vendor/github.com/miekg/coredns
url = https://github.com/miekg/coredns.git
[submodule "_vendor/github.com/miekg/dns"]
path = _vendor/github.com/miekg/dns
url = https://github.com/miekg/dns.git

View File

@ -31,8 +31,8 @@ MAKEDIR:=$(strip $(shell dirname "$(realpath $(lastword $(MAKEFILE_LIST)))"))
# Keep in sync with upup/models/cloudup/resources/addons/dns-controller/
DNS_CONTROLLER_TAG=1.6.0
KOPS_RELEASE_VERSION=1.6.0-alpha.1
KOPS_CI_VERSION=1.6.0-alpha.2
KOPS_RELEASE_VERSION=1.6.0-alpha.2
KOPS_CI_VERSION=1.6.0-alpha.3
GITSHA := $(shell cd ${GOPATH_1ST}/src/k8s.io/kops; git describe --always)
@ -111,7 +111,8 @@ test:
go test k8s.io/kops/protokube/... -args -v=1 -logtostderr
go test k8s.io/kops/dns-controller/pkg/... -args -v=1 -logtostderr
go test k8s.io/kops/cmd/... -args -v=1 -logtostderr
go test k8s.io/kops/tests/... -args -v=1 -logtostderr
go test k8s.io/kops/cmd/... -args -v=1 -logtostderr
go test k8s.io/kops/channels/... -args -v=1 -logtostderr
go test k8s.io/kops/util/... -args -v=1 -logtostderr
crossbuild-nodeup:
@ -174,7 +175,7 @@ gcs-publish-ci: gcs-upload
gsutil -h "Cache-Control:private, max-age=0, no-transform" cp .build/upload/${LATEST_FILE} ${GCS_LOCATION}
gen-cli-docs:
KOPS_STATE_STORE= kops genhelpdocs --out docs/cli
@kops genhelpdocs --out docs/cli
# Will always push a linux-based build up to the server
push: crossbuild-nodeup

1
_vendor/github.com/coreos/go-semver generated Submodule

@ -0,0 +1 @@
Subproject commit 5e3acbb5668c4c3deb4842615c4098eb61fb6b1e

1
_vendor/github.com/miekg/coredns generated Submodule

@ -0,0 +1 @@
Subproject commit 757f49d8ff2687d289468b00835f360614357252

1
_vendor/github.com/miekg/dns generated Submodule

@ -0,0 +1 @@
Subproject commit 25ac7f171497271bc74ad3c6b5e1f86b4bab54fa

1
_vendor/github.com/vmware/govmomi generated Submodule

@ -0,0 +1 @@
Subproject commit 2d7d7b3702fddc23a76ac283c3a3d56bb0375e62

View File

@ -15,6 +15,7 @@ spec:
labels:
k8s-app: cluster-autoscaler
annotations:
# For 1.6, we keep the old tolerations in case of a downgrade to 1.5
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"dedicated", "value":"master"}]'
spec:
containers:
@ -43,4 +44,7 @@ spec:
hostPath:
path: {{SSL_CERT_PATH}}
nodeSelector:
kubernetes.io/role: master
node-role.kubernetes.io/master: ""
tolerations:
- key: "node-role.kubernetes.io/master"
effect: NoSchedule

View File

@ -14,9 +14,7 @@ The project is created by wearemolecule, and maintained at
### Deploy To Cluster
```
# Version 1.2.0
# https://github.com/wearemolecule/route53-kubernetes/tree/v1.2.0
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kops/master/addons/route53-mapper/v1.2.0.yml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kops/master/addons/route53-mapper/v1.3.0.yml
```
**Important:**

View File

@ -7,3 +7,7 @@ spec:
selector:
k8s-addon: route53-mapper.addons.k8s.io
manifest: v1.2.0.yaml
- version: 1.3.0
selector:
k8s-addon: route53-mapper.addons.k8s.io
manifest: v1.3.0.yaml

View File

@ -0,0 +1,26 @@
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: route53-mapper
namespace: kube-system
labels:
app: route53-mapper
k8s-addon: route53-mapper.addons.k8s.io
spec:
replicas: 1
selector:
matchLabels:
app: route53-mapper
template:
metadata:
labels:
app: route53-mapper
annotations:
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"dedicated", "value":"master"}]'
spec:
nodeSelector:
kubernetes.io/role: master
containers:
- image: quay.io/molecule/route53-kubernetes:v1.3.0
name: route53-mapper

View File

@ -18,16 +18,14 @@ package main
import (
"fmt"
"k8s.io/kops/channels/pkg/cmd"
"os"
)
func main() {
Execute()
}
// exitWithError will terminate execution with an error result
// It prints the error to stderr and exits with a non-zero exit code
func exitWithError(err error) {
fmt.Fprintf(os.Stderr, "\n%v\n", err)
os.Exit(1)
f := &cmd.DefaultFactory{}
if err := cmd.Execute(f, os.Stdout); err != nil {
fmt.Fprintf(os.Stderr, "\n%v\n", err)
os.Exit(1)
}
}

View File

@ -47,4 +47,15 @@ type AddonSpec struct {
// Manifest is the URL to the manifest that should be applied
Manifest *string `json:"manifest,omitempty"`
// KubernetesVersion is a semver version range on which this version of the addon can be applied
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
// Id is an optional value which can be used to force a refresh even if the Version matches
// This is useful for when we have two manifests expressing the same addon version for two
// different kubernetes api versions. For example, we might label the 1.5 version "k8s-1.5"
// and the 1.6 version "k8s-1.6". Both would have the same Version, determined by the
// version of the software we are packaging. But we always want to reinstall when we
// switch kubernetes versions.
Id string `json:"id,omitempty"`
}

View File

@ -25,6 +25,7 @@ import (
"net/url"
)
// Addon is a wrapper around a single version of an addon
type Addon struct {
Name string
ChannelName string
@ -32,16 +33,42 @@ type Addon struct {
Spec *api.AddonSpec
}
// AddonUpdate holds data about a proposed update to an addon
type AddonUpdate struct {
Name string
ExistingVersion *ChannelVersion
NewVersion *ChannelVersion
}
// AddonMenu is a collection of addons, with helpers for computing the latest versions
type AddonMenu struct {
Addons map[string]*Addon
}
func NewAddonMenu() *AddonMenu {
return &AddonMenu{
Addons: make(map[string]*Addon),
}
}
func (m *AddonMenu) MergeAddons(o *AddonMenu) {
for k, v := range o.Addons {
existing := m.Addons[k]
if existing == nil {
m.Addons[k] = v
} else {
if existing.ChannelVersion().replaces(v.ChannelVersion()) {
m.Addons[k] = v
}
}
}
}
func (a *Addon) ChannelVersion() *ChannelVersion {
return &ChannelVersion{
Channel: &a.ChannelName,
Version: a.Spec.Version,
Id: a.Spec.Id,
}
}
@ -67,7 +94,7 @@ func (a *Addon) GetRequiredUpdates(k8sClient kubernetes.Interface) (*AddonUpdate
return nil, err
}
if existingVersion != nil && !newVersion.Replaces(existingVersion) {
if existingVersion != nil && !newVersion.replaces(existingVersion) {
return nil, nil
}

View File

@ -18,6 +18,7 @@ package channels
import (
"fmt"
"github.com/blang/semver"
"github.com/golang/glog"
"k8s.io/kops/channels/pkg/api"
"k8s.io/kops/upup/pkg/fi/utils"
@ -58,28 +59,29 @@ func ParseAddons(name string, location *url.URL, data []byte) (*Addons, error) {
return &Addons{ChannelName: name, ChannelLocation: *location, APIObject: apiObject}, nil
}
func (a *Addons) GetCurrent() ([]*Addon, error) {
all, err := a.All()
func (a *Addons) GetCurrent(kubernetesVersion semver.Version) (*AddonMenu, error) {
all, err := a.wrapInAddons()
if err != nil {
return nil, err
}
specs := make(map[string]*Addon)
menu := NewAddonMenu()
for _, addon := range all {
if !addon.matches(kubernetesVersion) {
continue
}
name := addon.Name
existing := specs[name]
if existing == nil || addon.ChannelVersion().Replaces(existing.ChannelVersion()) {
specs[name] = addon
existing := menu.Addons[name]
if existing == nil || addon.ChannelVersion().replaces(existing.ChannelVersion()) {
menu.Addons[name] = addon
}
}
var addons []*Addon
for _, addon := range specs {
addons = append(addons, addon)
}
return addons, nil
return menu, nil
}
func (a *Addons) All() ([]*Addon, error) {
func (a *Addons) wrapInAddons() ([]*Addon, error) {
var addons []*Addon
for _, s := range a.APIObject.Spec.Addons {
name := a.APIObject.ObjectMeta.Name
@ -98,3 +100,19 @@ func (a *Addons) All() ([]*Addon, error) {
}
return addons, nil
}
func (s *Addon) matches(kubernetesVersion semver.Version) bool {
if s.Spec.KubernetesVersion != "" {
versionRange, err := semver.ParseRange(s.Spec.KubernetesVersion)
if err != nil {
glog.Warningf("unable to parse KubernetesVersion %q; skipping", s.Spec.KubernetesVersion)
return false
}
if !versionRange(kubernetesVersion) {
glog.V(4).Infof("Skipping version range %q that does not match current version %s", s.Spec.KubernetesVersion, kubernetesVersion)
return false
}
}
return true
}

View File

@ -0,0 +1,154 @@
/*
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 channels
import (
"github.com/blang/semver"
"k8s.io/kops/channels/pkg/api"
"testing"
)
func Test_Filtering(t *testing.T) {
grid := []struct {
Input api.AddonSpec
KubernetesVersion string
Expected bool
}{
{
Input: api.AddonSpec{
KubernetesVersion: ">=1.6.0",
},
KubernetesVersion: "1.6.0",
Expected: true,
},
{
Input: api.AddonSpec{
KubernetesVersion: "<1.6.0",
},
KubernetesVersion: "1.6.0",
Expected: false,
},
{
Input: api.AddonSpec{
KubernetesVersion: ">=1.6.0",
},
KubernetesVersion: "1.5.9",
Expected: false,
},
{
Input: api.AddonSpec{
KubernetesVersion: ">=1.4.0 <1.6.0",
},
KubernetesVersion: "1.5.9",
Expected: true,
},
{
Input: api.AddonSpec{
KubernetesVersion: ">=1.4.0 <1.6.0",
},
KubernetesVersion: "1.6.0",
Expected: false,
},
}
for _, g := range grid {
k8sVersion := semver.MustParse(g.KubernetesVersion)
addon := &Addon{
Spec: &g.Input,
}
actual := addon.matches(k8sVersion)
if actual != g.Expected {
t.Errorf("unexpected result from %v, %s. got %v", g.Input.KubernetesVersion, g.KubernetesVersion, actual)
}
}
}
func Test_Replacement(t *testing.T) {
grid := []struct {
Old *ChannelVersion
New *ChannelVersion
Replaces bool
}{
// With no id, update iff newer semver
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: ""},
New: &ChannelVersion{Version: s("1.0.0"), Id: ""},
Replaces: false,
},
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: ""},
New: &ChannelVersion{Version: s("1.0.1"), Id: ""},
Replaces: true,
},
{
Old: &ChannelVersion{Version: s("1.0.1"), Id: ""},
New: &ChannelVersion{Version: s("1.0.0"), Id: ""},
Replaces: false,
},
{
Old: &ChannelVersion{Version: s("1.1.0"), Id: ""},
New: &ChannelVersion{Version: s("1.1.1"), Id: ""},
Replaces: true,
},
{
Old: &ChannelVersion{Version: s("1.1.1"), Id: ""},
New: &ChannelVersion{Version: s("1.1.0"), Id: ""},
Replaces: false,
},
// With id, update if different id and same version, otherwise follow semver
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: "a"},
New: &ChannelVersion{Version: s("1.0.0"), Id: "a"},
Replaces: false,
},
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: "a"},
New: &ChannelVersion{Version: s("1.0.0"), Id: "b"},
Replaces: true,
},
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: "b"},
New: &ChannelVersion{Version: s("1.0.0"), Id: "a"},
Replaces: true,
},
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: "a"},
New: &ChannelVersion{Version: s("1.0.1"), Id: "a"},
Replaces: true,
},
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: "a"},
New: &ChannelVersion{Version: s("1.0.1"), Id: "a"},
Replaces: true,
},
{
Old: &ChannelVersion{Version: s("1.0.0"), Id: "a"},
New: &ChannelVersion{Version: s("1.0.1"), Id: "a"},
Replaces: true,
},
}
for _, g := range grid {
actual := g.New.replaces(g.Old)
if actual != g.Replaces {
t.Errorf("unexpected result from %v -> %v, expect %t. actual %v", g.Old, g.New, g.Replaces, actual)
}
}
}
func s(v string) *string {
return &v
}

View File

@ -38,6 +38,7 @@ type Channel struct {
type ChannelVersion struct {
Version *string `json:"version,omitempty"`
Channel *string `json:"channel,omitempty"`
Id string `json:"id,omitempty"`
}
func stringValue(s *string) string {
@ -48,7 +49,11 @@ func stringValue(s *string) string {
}
func (c *ChannelVersion) String() string {
return "Version=" + stringValue(c.Version) + " Channel=" + stringValue(c.Channel)
s := "Version=" + stringValue(c.Version) + " Channel=" + stringValue(c.Channel)
if c.Id != "" {
s += " Id=" + c.Id
}
return s
}
func ParseChannelVersion(s string) (*ChannelVersion, error) {
@ -91,7 +96,7 @@ func (c *Channel) AnnotationName() string {
return AnnotationPrefix + c.Name
}
func (c *ChannelVersion) Replaces(existing *ChannelVersion) bool {
func (c *ChannelVersion) replaces(existing *ChannelVersion) bool {
if existing.Version != nil {
if c.Version == nil {
return false
@ -106,13 +111,25 @@ func (c *ChannelVersion) Replaces(existing *ChannelVersion) bool {
glog.Warningf("error parsing existing version %q", *existing.Version)
return true
}
return cVersion.GT(existingVersion)
if cVersion.LT(existingVersion) {
return false
} else if cVersion.GT(existingVersion) {
return true
} else {
// Same version; check ids
if c.Id == existing.Id {
return false
} else {
glog.V(4).Infof("Channels had same version %q but different ids (%q vs %q); will replace", *c.Version, c.Id, existing.Id)
}
}
}
glog.Warningf("ChannelVersion did not have a version; can't perform real version check")
if c.Version == nil {
return false
}
return true
}

View File

@ -14,18 +14,21 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
package cmd
import (
"github.com/spf13/cobra"
"io"
)
// applyCmd represents the apply command
var applyCmd = &cobra.Command{
Use: "apply",
Short: "apply resources from a channel",
}
func NewCmdApply(f Factory, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "apply",
Short: "apply resources from a channel",
}
func init() {
rootCommand.AddCommand(applyCmd)
// create subcommands
cmd.AddCommand(NewCmdApplyChannel(f, out))
return cmd
}

View File

@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
package cmd
import (
"fmt"
"github.com/blang/semver"
"github.com/spf13/cobra"
"io"
"k8s.io/kops/channels/pkg/channels"
"k8s.io/kops/util/pkg/tables"
"net/url"
@ -26,38 +28,54 @@ import (
"strings"
)
type ApplyChannelCmd struct {
type ApplyChannelOptions struct {
Yes bool
Files []string
}
var applyChannel ApplyChannelCmd
func NewCmdApplyChannel(f Factory, out io.Writer) *cobra.Command {
var options ApplyChannelOptions
func init() {
cmd := &cobra.Command{
Use: "channel",
Short: "Apply channel",
Run: func(cmd *cobra.Command, args []string) {
err := applyChannel.Run(args)
if err != nil {
exitWithError(err)
}
RunE: func(cmd *cobra.Command, args []string) error {
return RunApplyChannel(f, out, &options, args)
},
}
cmd.Flags().BoolVar(&applyChannel.Yes, "yes", false, "Apply update")
cmd.Flags().StringSliceVar(&applyChannel.Files, "f", []string{}, "Apply from a local file")
cmd.Flags().BoolVar(&options.Yes, "yes", false, "Apply update")
cmd.Flags().StringSliceVar(&options.Files, "f", []string{}, "Apply from a local file")
applyCmd.AddCommand(cmd)
return cmd
}
func (c *ApplyChannelCmd) Run(args []string) error {
k8sClient, err := rootCommand.KubernetesClient()
func RunApplyChannel(f Factory, out io.Writer, options *ApplyChannelOptions, args []string) error {
k8sClient, err := f.KubernetesClient()
if err != nil {
return err
}
var addons []*channels.Addon
kubernetesVersionInfo, err := k8sClient.Discovery().ServerVersion()
if err != nil {
return fmt.Errorf("error querying kubernetes version: %v", err)
}
//kubernetesVersion, err := semver.Parse(kubernetesVersionInfo.Major + "." + kubernetesVersionInfo.Minor + ".0")
//if err != nil {
// return fmt.Errorf("cannot parse kubernetes version %q", kubernetesVersionInfo.Major+"."+kubernetesVersionInfo.Minor + ".0")
//}
kubernetesVersion, err := semver.ParseTolerant(kubernetesVersionInfo.GitVersion)
if err != nil {
return fmt.Errorf("cannot parse kubernetes version %q", kubernetesVersionInfo.GitVersion)
}
// Remove Pre and Patch, as they make semver comparisons impractical
kubernetesVersion.Pre = nil
menu := channels.NewAddonMenu()
for _, name := range args {
location, err := url.Parse(name)
if err != nil {
@ -80,14 +98,14 @@ func (c *ApplyChannelCmd) Run(args []string) error {
return fmt.Errorf("error loading channel %q: %v", location, err)
}
current, err := o.GetCurrent()
current, err := o.GetCurrent(kubernetesVersion)
if err != nil {
return fmt.Errorf("error processing latest versions in %q: %v", location, err)
}
addons = append(addons, current...)
menu.MergeAddons(current)
}
for _, f := range c.Files {
for _, f := range options.Files {
location, err := url.Parse(f)
if err != nil {
return fmt.Errorf("unable to parse argument %q as url", f)
@ -108,16 +126,16 @@ func (c *ApplyChannelCmd) Run(args []string) error {
return fmt.Errorf("error loading file %q: %v", f, err)
}
current, err := o.GetCurrent()
current, err := o.GetCurrent(kubernetesVersion)
if err != nil {
return fmt.Errorf("error processing latest versions in %q: %v", f, err)
}
addons = append(addons, current...)
menu.MergeAddons(current)
}
var updates []*channels.AddonUpdate
var needUpdates []*channels.Addon
for _, addon := range addons {
for _, addon := range menu.Addons {
// TODO: Cache lookups to prevent repeated lookups?
update, err := addon.GetRequiredUpdates(k8sClient)
if err != nil {
@ -165,7 +183,7 @@ func (c *ApplyChannelCmd) Run(args []string) error {
}
}
if !c.Yes {
if !options.Yes {
fmt.Printf("\nMust specify --yes to update\n")
return nil
}
@ -178,7 +196,7 @@ func (c *ApplyChannelCmd) Run(args []string) error {
// Could have been a concurrent request
if update != nil {
if update.NewVersion.Version != nil {
fmt.Printf("Updated %q to %d\n", update.Name, *update.NewVersion)
fmt.Printf("Updated %q to %s\n", update.Name, *update.NewVersion.Version)
} else {
fmt.Printf("Updated %q\n", update.Name)
}

View File

@ -0,0 +1,59 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
type Factory interface {
KubernetesClient() (kubernetes.Interface, error)
}
type DefaultFactory struct {
kubernetesClient kubernetes.Interface
}
var _ Factory = &DefaultFactory{}
func (f *DefaultFactory) KubernetesClient() (kubernetes.Interface, error) {
if f.kubernetesClient == nil {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig
configOverrides := &clientcmd.ConfigOverrides{
ClusterDefaults: clientcmd.ClusterDefaults,
}
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
config, err := kubeConfig.ClientConfig()
if err != nil {
return nil, fmt.Errorf("cannot load kubecfg settings: %v", err)
}
k8sClient, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("cannot build kube client: %v", err)
}
f.kubernetesClient = k8sClient
}
return f.kubernetesClient, nil
}

View File

@ -14,36 +14,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
package cmd
import (
"github.com/spf13/cobra"
"io"
)
// GetCmd represents the get command
type GetCmd struct {
output string
cobraCommand *cobra.Command
}
var getCmd = GetCmd{
cobraCommand: &cobra.Command{
func NewCmdGet(f Factory, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "get",
SuggestFor: []string{"list"},
Short: "list or get objects",
},
}
const (
OutputYaml = "yaml"
OutputTable = "table"
)
func init() {
cmd := getCmd.cobraCommand
rootCommand.AddCommand(cmd)
cmd.PersistentFlags().StringVarP(&getCmd.output, "output", "o", OutputTable, "output format. One of: table, yaml")
}
// create subcommands
cmd.AddCommand(NewCmdGetAddons(f, out))
return cmd
}

View File

@ -14,11 +14,28 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"io"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/kops/channels/pkg/channels"
@ -26,26 +43,23 @@ import (
"os"
)
type GetAddonsCmd struct {
type GetAddonsOptions struct {
}
var getAddonsCmd GetAddonsCmd
func NewCmdGetAddons(f Factory, out io.Writer) *cobra.Command {
var options GetAddonsOptions
func init() {
cmd := &cobra.Command{
Use: "addons",
Aliases: []string{"addon"},
Short: "get addons",
Long: `List or get addons.`,
Run: func(cmd *cobra.Command, args []string) {
err := getAddonsCmd.Run(args)
if err != nil {
exitWithError(err)
}
RunE: func(cmd *cobra.Command, args []string) error {
return RunGetAddons(f, out, &options)
},
}
getCmd.cobraCommand.AddCommand(cmd)
return cmd
}
type addonInfo struct {
@ -54,8 +68,8 @@ type addonInfo struct {
Namespace *v1.Namespace
}
func (c *GetAddonsCmd) Run(args []string) error {
k8sClient, err := rootCommand.KubernetesClient()
func RunGetAddons(f Factory, out io.Writer, options *GetAddonsOptions) error {
k8sClient, err := f.KubernetesClient()
if err != nil {
return err
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
package cmd
import (
goflag "flag"
@ -22,48 +22,44 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"io"
)
type RootCmd struct {
type CmdRootOptions struct {
configFile string
cobraCommand *cobra.Command
}
var rootCommand = RootCmd{
cobraCommand: &cobra.Command{
Use: "channels",
Short: "channels applies software from a channel",
},
}
func Execute() {
goflag.Set("logtostderr", "true")
goflag.CommandLine.Parse([]string{})
if err := rootCommand.cobraCommand.Execute(); err != nil {
exitWithError(err)
}
}
func init() {
func Execute(f Factory, out io.Writer) error {
cobra.OnInitialize(initConfig)
cmd := rootCommand.cobraCommand
cmd := NewCmdRoot(f, out)
goflag.Set("logtostderr", "true")
goflag.CommandLine.Parse([]string{})
return cmd.Execute()
}
func NewCmdRoot(f Factory, out io.Writer) *cobra.Command {
options := &CmdRootOptions{}
cmd := &cobra.Command{
Use: "channels",
Short: "channels applies software from a channel",
}
cmd.PersistentFlags().AddGoFlagSet(goflag.CommandLine)
cmd.PersistentFlags().StringVar(&rootCommand.configFile, "config", "", "config file (default is $HOME/.channels.yaml)")
cmd.PersistentFlags().StringVar(&options.configFile, "config", "", "config file (default is $HOME/.channels.yaml)")
// create subcommands
cmd.AddCommand(NewCmdApply(f, out))
cmd.AddCommand(NewCmdGet(f, out))
return cmd
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if rootCommand.configFile != "" {
// enable ability to specify config file via flag
viper.SetConfigFile(rootCommand.configFile)
}
viper.SetConfigName(".channels") // name of config file (without extension)
viper.AddConfigPath("$HOME") // adding home directory as first search path
viper.AutomaticEnv() // read in environment variables that match
@ -73,28 +69,3 @@ func initConfig() {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}
func (c *RootCmd) AddCommand(cmd *cobra.Command) {
c.cobraCommand.AddCommand(cmd)
}
func (c *RootCmd) KubernetesClient() (kubernetes.Interface, error) {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig
configOverrides := &clientcmd.ConfigOverrides{
ClusterDefaults: clientcmd.ClusterDefaults,
}
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
config, err := kubeConfig.ClientConfig()
if err != nil {
return nil, fmt.Errorf("cannot load kubecfg settings: %v", err)
}
k8sClient, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("cannot build kube client: %v", err)
}
return k8sClient, err
}

View File

@ -690,14 +690,6 @@ func (m *MockEC2) DescribeInstancesPages(*ec2.DescribeInstancesInput, func(*ec2.
panic("Not implemented")
return nil
}
func (m *MockEC2) DescribeInternetGatewaysRequest(*ec2.DescribeInternetGatewaysInput) (*request.Request, *ec2.DescribeInternetGatewaysOutput) {
panic("Not implemented")
return nil, nil
}
func (m *MockEC2) DescribeInternetGateways(*ec2.DescribeInternetGatewaysInput) (*ec2.DescribeInternetGatewaysOutput, error) {
panic("Not implemented")
return nil, nil
}
func (m *MockEC2) DescribeMovingAddressesRequest(*ec2.DescribeMovingAddressesInput) (*request.Request, *ec2.DescribeMovingAddressesOutput) {
panic("Not implemented")
return nil, nil

View File

@ -144,3 +144,15 @@ func (m *MockEC2) DescribeVpcAttribute(request *ec2.DescribeVpcAttributeInput) (
return response, nil
}
func (m *MockEC2) DescribeInternetGatewaysRequest(*ec2.DescribeInternetGatewaysInput) (*request.Request, *ec2.DescribeInternetGatewaysOutput) {
panic("Not implemented")
return nil, nil
}
func (m *MockEC2) DescribeInternetGateways(*ec2.DescribeInternetGatewaysInput) (*ec2.DescribeInternetGatewaysOutput, error) {
return &ec2.DescribeInternetGatewaysOutput{
InternetGateways: []*ec2.InternetGateway{{
InternetGatewayId: aws.String("fake-ig"),
}},
}, nil
}

View File

@ -27,6 +27,7 @@ type zoneInfo struct {
ID string
hostedZone *route53.HostedZone
records []*route53.ResourceRecordSet
vpcs []*route53.VPC
}
type MockRoute53 struct {
@ -48,10 +49,11 @@ func (m *MockRoute53) findZone(hostedZoneId string) *zoneInfo {
return nil
}
func (m *MockRoute53) MockCreateZone(z *route53.HostedZone) {
func (m *MockRoute53) MockCreateZone(z *route53.HostedZone, vpcs []*route53.VPC) {
zi := &zoneInfo{
ID: aws.StringValue(z.Id),
hostedZone: z,
vpcs: vpcs,
}
m.Zones = append(m.Zones, zi)
}

View File

@ -45,7 +45,7 @@ func (m *MockRoute53) GetHostedZone(request *route53.GetHostedZoneInput) (*route
response := &route53.GetHostedZoneOutput{
// DelegationSet ???
HostedZone: &copy,
// VPCs
VPCs: zone.vpcs,
}
return response, nil
}
@ -89,6 +89,13 @@ func (m *MockRoute53) ListHostedZonesByNameRequest(*route53.ListHostedZonesByNam
}
func (m *MockRoute53) ListHostedZonesByName(*route53.ListHostedZonesByNameInput) (*route53.ListHostedZonesByNameOutput, error) {
panic("MockRoute53 ListHostedZonesByName not implemented")
return nil, nil
var zones []*route53.HostedZone
for _, z := range m.Zones {
zones = append(zones, z.hostedZone)
}
return &route53.ListHostedZonesByNameOutput{
HostedZones: zones,
}, nil
}

View File

@ -17,25 +17,48 @@ limitations under the License.
package main
import (
"fmt"
"io"
"bytes"
"github.com/golang/glog"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kops/cmd/kops/util"
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/v1alpha1"
"k8s.io/kops/util/pkg/vfs"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
)
type DeleteOptions struct {
resource.FilenameOptions
Yes bool
}
func NewCmdDelete(f *util.Factory, out io.Writer) *cobra.Command {
//options := &DeleteOptions{}
options := &DeleteOptions{}
cmd := &cobra.Command{
Use: "delete",
Short: "Delete clusters and other resources.",
Long: `Delete clusters`,
Use: "delete -f FILENAME [--yes]",
Short: "Delete clusters and instancegroups",
Long: `Delete clusters and instancegroups`,
SuggestFor: []string{"rm"},
Run: func(cmd *cobra.Command, args []string) {
if cmdutil.IsFilenameEmpty(options.Filenames) {
cmd.Help()
return
}
cmdutil.CheckErr(RunDelete(f, out, options))
},
}
cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename to use to delete the resource")
cmd.Flags().BoolVarP(&options.Yes, "yes", "y", options.Yes, "Specify --yes to delete the resource")
cmd.MarkFlagRequired("filename")
// create subcommands
cmd.AddCommand(NewCmdDeleteCluster(f, out))
cmd.AddCommand(NewCmdDeleteInstanceGroup(f, out))
@ -43,3 +66,68 @@ func NewCmdDelete(f *util.Factory, out io.Writer) *cobra.Command {
return cmd
}
func RunDelete(factory *util.Factory, out io.Writer, d *DeleteOptions) error {
// Codecs provides access to encoding and decoding for the scheme
codecs := kopsapi.Codecs //serializer.NewCodecFactory(scheme)
codec := codecs.UniversalDecoder(kopsapi.SchemeGroupVersion)
var sb bytes.Buffer
fmt.Fprintf(&sb, "\n")
for _, f := range d.Filenames {
contents, err := vfs.Context.ReadFile(f)
if err != nil {
return fmt.Errorf("error reading file %q: %v", f, err)
}
sections := bytes.Split(contents, []byte("\n---\n"))
for _, section := range sections {
defaults := &schema.GroupVersionKind{
Group: v1alpha1.SchemeGroupVersion.Group,
Version: v1alpha1.SchemeGroupVersion.Version,
}
o, gvk, err := codec.Decode(section, defaults, nil)
if err != nil {
return fmt.Errorf("error parsing file %q: %v", f, err)
}
switch v := o.(type) {
case *kopsapi.Cluster:
options := &DeleteClusterOptions{}
options.ClusterName = v.ObjectMeta.Name
options.Yes = d.Yes
err = RunDeleteCluster(factory, out, options)
if err != nil {
exitWithError(err)
}
if d.Yes {
fmt.Fprintf(&sb, "Deleted cluster/%s\n", v.ObjectMeta.Name)
}
case *kopsapi.InstanceGroup:
options := &DeleteInstanceGroupOptions{}
options.GroupName = v.ObjectMeta.Name
options.ClusterName = v.ObjectMeta.Labels[kopsapi.LabelClusterName]
options.Yes = d.Yes
err := RunDeleteInstanceGroup(factory, out, options)
if err != nil {
exitWithError(err)
}
if d.Yes {
fmt.Fprintf(&sb, "Deleted instancegroup/%s\n", v.ObjectMeta.Name)
}
default:
glog.V(2).Infof("Type of object was %T", v)
return fmt.Errorf("Unhandled kind %q in %s", gvk, f)
}
}
}
{
_, err := out.Write(sb.Bytes())
if err != nil {
return fmt.Errorf("error writing to output: %v", err)
}
}
return nil
}

View File

@ -102,6 +102,16 @@ func TestPrivateKopeio(t *testing.T) {
runTest(t, "privatekopeio.example.com", "../../tests/integration/privatekopeio", "v1alpha2", true, 1)
}
// TestPrivateDns runs the test on a configuration with private topology, private dns
func TestPrivateDns1(t *testing.T) {
runTest(t, "privatedns1.example.com", "../../tests/integration/privatedns1", "v1alpha2", true, 1)
}
// TestPrivateDns runs the test on a configuration with private topology, private dns, extant vpc
func TestPrivateDns2(t *testing.T) {
runTest(t, "privatedns2.example.com", "../../tests/integration/privatedns2", "v1alpha2", true, 1)
}
func runTest(t *testing.T, clusterName string, srcDir string, version string, private bool, zones int) {
var stdout bytes.Buffer
@ -369,7 +379,28 @@ func (h *IntegrationTestHarness) SetupMockAWS() {
mockRoute53.MockCreateZone(&route53.HostedZone{
Id: aws.String("/hostedzone/Z1AFAKE1ZON3YO"),
Name: aws.String("example.com."),
})
Config: &route53.HostedZoneConfig{
PrivateZone: aws.Bool(false),
},
}, nil)
mockRoute53.MockCreateZone(&route53.HostedZone{
Id: aws.String("/hostedzone/Z2AFAKE1ZON3NO"),
Name: aws.String("internal.example.com."),
Config: &route53.HostedZoneConfig{
PrivateZone: aws.Bool(true),
},
}, []*route53.VPC{{
VPCId: aws.String("vpc-234"),
}})
mockRoute53.MockCreateZone(&route53.HostedZone{
Id: aws.String("/hostedzone/Z3AFAKE1ZOMORE"),
Name: aws.String("private.example.com."),
Config: &route53.HostedZoneConfig{
PrivateZone: aws.Bool(true),
},
}, []*route53.VPC{{
VPCId: aws.String("vpc-123"),
}})
mockEC2.Images = append(mockEC2.Images, &ec2.Image{
ImageId: aws.String("ami-12345678"),

View File

@ -95,7 +95,7 @@ func NewCmdRollingUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
Short: "Rolling update a cluster",
Long: `Rolling update a cluster instance groups.
This command updates a kubernetes cluseter to match the cloud, and kops specifications.
This command updates a kubernetes cluster to match the cloud, and kops specifications.
To perform rolling update, you need to update the cloud resources first with "kops update cluster"

View File

@ -86,7 +86,7 @@ func NewCmdUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&options.Models, "model", options.Models, "Models to apply (separate multiple models with commas)")
cmd.Flags().StringVar(&options.SSHPublicKey, "ssh-public-key", options.SSHPublicKey, "SSH public key to use (deprecated: use kops create secret instead)")
cmd.Flags().StringVar(&options.OutDir, "out", options.OutDir, "Path to write any local output")
cmd.Flags().BoolVar(&options.CreateKubecfg, "create-kube-config", options.CreateKubecfg, "Will control automatically creating the kube config file on your local filesystem")
return cmd
}

View File

@ -89,6 +89,9 @@ func main() {
}
fi, err := os.Lstat(procSelfExe)
if err != nil {
glog.Fatalf("error doing lstat on %q: %v", procSelfExe, err)
}
if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
glog.Fatalf("file %v is not a symlink", procSelfExe)
}

View File

@ -299,7 +299,7 @@ func (c *DNSController) runOnce() error {
for key, changeset := range op.changesets {
glog.V(2).Infof("applying DNS changeset for zone %s", key)
if err := changeset.Apply(); err != nil {
glog.Warningf("error applying DNS changset for zone %s: %v", key, err)
glog.Warningf("error applying DNS changeset for zone %s: %v", key, err)
errors = append(errors, fmt.Errorf("error applying DNS changeset for zone %s: %v", key, err))
}
}

137
docs/addon_manager.md Normal file
View File

@ -0,0 +1,137 @@
## Addons Management
kops incorporates management of some addons; we _have_ to manage some addons which are needed before
the kubernetes API is functional.
In addition, kops offers end-user management of addons via the `channels` tool (which is still experimental,
but we are working on making it a recommended part of kubernetes addon management). We ship some
curated addons in the [addons directory](/addons), more information in the [addons document](addons.md).
kops uses the `channels` tool for system addon management also. Because kops uses the same tool
for *system* addon management as it does for *user* addon management, this means that
addons installed by kops as part of cluster bringup can be managed alongside additional addons.
(Though note that bootstrap addons are much more likely to be replaced during a kops upgrade).
The general kops philosophy is to try to make the set of bootstrap addons minimal, and
to make installation of subsequent addons easy.
Thus, `kube-dns` and the networking overlay (if any) are the canonical bootstrap addons.
But addons such as the dashboard or the EFK stack are easily installed after kops bootstrap,
with a `kubectl apply -f https://...` or with the channels tool.
In future, we may as a convenience make it easy to add optional addons to the kops manifest,
though this will just be a convenience wrapper around doing it manually.
## Versioning
The channels tool adds a manifest-of-manifests file, of `Kind: Addons`, which allows for a description
of the various manifest versions that are available. In this way kops can manage updates
as new versions of the addon are released. For example,
the [dashboard addon](https://github.com/kubernetes/kops/blob/master/addons/kubernetes-dashboard/addon.yaml)
lists multiple versions.
For example, a typical addons declaration might looks like this:
```
- version: 1.4.0
selector:
k8s-addon: kubernetes-dashboard.addons.k8s.io
manifest: v1.4.0.yaml
- version: 1.5.0
selector:
k8s-addon: kubernetes-dashboard.addons.k8s.io
manifest: v1.5.0.yaml
```
That declares two versions of an addon, with manifests at `v1.4.0.yaml` and at `v1.5.0.yaml`.
These are evaluated as relative paths to the Addons file itself. (The channels tool supports
a few more protocols than `kubectl` - for example `s3://...` for S3 hosted manifests).
The `version` field gives meaning to the alternative manifests. This is interpreted as a
semver. The channels tool keeps track of the current version installed (currently by means
of an annotation on the `kube-system` namespace), and it will not reapply the same version
of the manifest. This means that a user can edit a deployed addon, and changes will not
be replaced, until a new version of the addon is installed.
The long-term direction here is that addons will mostly be configured through a ConfigMap or Secret object,
and that the addon manager will (TODO) not replace the ConfigMap.
The `selector` determines the objects which make up the addon. This will be used
to construct a `--prune` argument (TODO), so that objects that existed in the
previous but not the new version will be removed as part of an upgrade.
## Kubernetes Version Selection
The addon manager now supports a `kubernetesVersion` field, which is a semver range specifier
on the kubernetes version. If the targeted version of kubernetes does not match the semver
specified, the addon version will be ignored.
This allows you to have different versions of the manifest for significant changes to the
kubernetes API. For example, 1.6 changed the taints & tolerations to a field, and RBAC moved
to beta. As such it is easier to have two separate manifests.
For example:
```
- version: 1.5.0
selector:
k8s-addon: kube-dashboard.addons.k8s.io
manifest: v1.5.0.yaml
kubernetesVersion: "<1.6.0"
id: "pre-k8s-16"
- version: 1.6.0
selector:
k8s-addon: kube-dashboard.addons.k8s.io
manifest: v1.6.0.yaml
kubernetesVersion: ">=1.6.0"
id: "k8s-16"
```
On kubernetes versions before 1.6, we will install `v1.5.0.yaml`, whereas from kubernetes
versions 1.6 on we will install `v1.6.0.yaml`.
Note that we remove the `pre-release` field of the kubernetes semver, so that `1.6.0-beta.1`
will match `>=1.6.0`. This matches the way kubernetes does pre-releases.
## Semver is not enough: `id`
However, semver is insufficient here with the kubernetes version selection. The problem is
arises in the following scenario:
* Install k8s 1.5, 1.5 version of manifest is installed
* Upgrade to k8s 1.6, 1.6 version of manifest is installed
* Downgrade to k8s 1.5; we want the 1.5 version of the manifest to be installed but the 1.6 version
will have a semver that is greater than or equal to the 1.5 semver.
We need a way to break the ties between the semvers, and thus we introduce the `id` field.
Thus a manifest will actually look like this:
```
- version: 1.6.0
selector:
k8s-addon: kube-dns.addons.k8s.io
manifest: pre-k8s-16.yaml
kubernetesVersion: "<1.6.0"
id: "pre-k8s-16"
- version: 1.6.0
selector:
k8s-addon: kube-dns.addons.k8s.io
manifest: k8s-16.yaml
kubernetesVersion: ">=1.6.0"
id: "k8s-16"
```
Note that the two addons have the same version, but a different `kubernetesVersion` selector.
But they have different `id` values; addons with matching semvers but different `id`s will
be upgraded. (We will never downgrade to an older semver though, regardless of `id`)
So now in the above scenario after the downgrade to 1.5, although the semver is the same,
the id will not match, and the `pre-k8s-16` will be installed. (And when we upgrade back
to 1.6, the `k8s-16` version will be installed.
A few tips:
* The `version` can now more closely mirror the upstream version.
* The manifest names should probably incorporate the `id`, for maintainability.

View File

@ -2,6 +2,8 @@
With kops you manage addons by using kubectl.
(For a description of the addon-manager, please see [addon_manager.md](addon_manager.md).)
Addons in kubernetes are traditionally done by copying files to `/etc/kubernetes/addons` on the master. But this
doesn't really make sense in HA master configurations. We also have kubectl available, and addons is just a thin
wrapper over calling kubectl.

View File

@ -1,11 +1,21 @@
## kops delete
delete clusters
Deletes a resource by filename or stdin
### Synopsis
Delete clusters or instancegroups by filename or stdin
Delete clusters
```
kops delete -f FILENAME [--yes]
```
### Options
```
-f, --filename stringSlice Filename to use to delete the resource
-y, --yes Specify --yes to delete the resource
```
### Options inherited from parent commands
@ -27,4 +37,3 @@ Delete clusters
* [kops delete cluster](kops_delete_cluster.md) - Delete cluster
* [kops delete instancegroup](kops_delete_instancegroup.md) - Delete instancegroup
* [kops delete secret](kops_delete_secret.md) - Delete secret

View File

@ -7,7 +7,7 @@ Rolling update a cluster
Rolling update a cluster instance groups.
This command updates a kubernetes cluseter to match the cloud, and kops specifications.
This command updates a kubernetes cluster to match the cloud, and kops specifications.
To perform rolling update, you need to update the cloud resources first with "kops update cluster"

View File

@ -14,6 +14,7 @@ kops update cluster
### Options
```
--create-kube-config Will control automatically creating the kube config file on your local filesystem (default true)
--model string Models to apply (separate multiple models with commas) (default "config,proto,cloudup")
--out string Path to write any local output
--ssh-public-key string SSH public key to use (deprecated: use kops create secret instead)

View File

@ -118,6 +118,23 @@ spec:
Will result in the flag `--runtime-config=batch/v2alpha1=true,apps/v1alpha1=true`. Note that `kube-apiserver` accepts `true` as a value for switch-like flags.
### kubelet
This block contains configurations for `kubelet`. See https://kubernetes.io/docs/admin/kubelet/
#### Feature Gates
```yaml
spec:
kubelet:
featureGates:
ExperimentalCriticalPodAnnotation: "true"
AllowExtTrafficLocalEndpoints: "false"
```
Will result in the flag `--feature-gates=ExperimentalCriticalPodAnnotation=true,AllowExtTrafficLocalEndpoints=false`
### networkID
On AWS, this is the id of the VPC the cluster is created in. If creating a cluster from scratch, this field doesn't need to be specified at create time; `kops` will create a `VPC` for you.

View File

@ -99,7 +99,7 @@ CoreOS support is highly experimental. Please report any issues.
The following steps are known:
* CoreOS AMIs can be found using `aws ec2 describe-images --region=us-east-1 --owner=595879546273 --filters Name=virtualization-type,Values=hvm`
* You can specify the name using the 'coreos.com` owner alias, for example `coreos.com/CoreOS-stable-1235.9.0-hvm`
* You can specify the name using the `coreos.com` owner alias, for example `coreos.com/CoreOS-stable-1235.9.0-hvm`

View File

@ -15,7 +15,7 @@ By default, a cluster has:
## Listing instance groups
`kops get instancegroups`
> ```
```
NAME ROLE MACHINETYPE MIN MAX ZONES
master-us-east-1c Master 1 1 us-east-1c
nodes Node t2.medium 2 2
@ -32,7 +32,7 @@ have not yet been applied (this may change soon though!).
To preview the change:
`kops update cluster <clustername>`
> ```
```
...
Will modify resources:
*awstasks.LaunchConfiguration launchConfiguration/mycluster.mydomain.com

View File

@ -7,7 +7,10 @@ There are two main types of labels that kops can create:
Both are specified at the InstanceGroup level.
A nice use for CloudLabels is to specify [AWS cost allocation tags](http://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html)
A nice use for cloudLabels is to specify [AWS cost allocation tags](http://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html).
A good use for nodeLables is to implement [nodeSelector labels](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#step-two-add-a-nodeselector-field-to-your-pod-configuration).
CloudLables and nodeLables are automatically applied to new nodes created by [AWS EC2 auto scaling groups](https://aws.amazon.com/autoscaling/).
An example:
@ -28,3 +31,10 @@ Note that keys and values are strings, so you need quotes around values that YAM
would otherwise treat as numbers or booleans.
To apply changes, you'll need to do a `kops update cluster` and then likely a `kops rolling-update cluster`
For AWS if `kops rolling-update cluster --instance-group nodes` returns "No rolling-update required." the
[kops rolling-update cluster](https://github.com/kubernetes/kops/blob/8bc48ef10a44a3e481b604f5dbb663420c68dcab/docs/cli/kops_rolling-update_cluster.md) `--force` flag can be used to force a rolling update, even when no changes are identified.
Example:
`kops rolling-update cluster --instance-group nodes --force`

View File

@ -1,6 +1,6 @@
## Building Kubernetes clusters with Terraform
Kops can generate Terraform configurations, and then you can then apply them using the `terraform plan` and `terraform apply` tools. This is very handy if you are already using Terraform, or if you want to check in the Terraform output into version control.
Kops can generate Terraform configurations, and then you can apply them using the `terraform plan` and `terraform apply` tools. This is very handy if you are already using Terraform, or if you want to check in the Terraform output into version control.
The gist of it is that, instead of letting kops apply the changes, you tell kops what you want, and then kops spits out what it wants done into a `.tf` file. **_You_** are then responsible for turning those plans into reality.

View File

@ -2,6 +2,7 @@ k8s.io/kops
k8s.io/kops/channels/cmd/channels
k8s.io/kops/channels/pkg/api
k8s.io/kops/channels/pkg/channels
k8s.io/kops/channels/pkg/cmd
k8s.io/kops/cloudmock/aws/mockautoscaling
k8s.io/kops/cloudmock/aws/mockec2
k8s.io/kops/cloudmock/aws/mockroute53

View File

@ -76,6 +76,7 @@ NODE_ZONES=${NODE_ZONES:-"us-west-2a,us-west-2b,us-west-2c"}
NODE_SIZE=${NODE_SIZE:-m4.xlarge}
MASTER_ZONES=${MASTER_ZONES:-"us-west-2a,us-west-2b,us-west-2c"}
MASTER_SIZE=${MASTER_SIZE:-m4.large}
KOPS_CREATE=${KOPS_CREATE:-yes}
# NETWORK
@ -90,15 +91,18 @@ cd $KOPS_DIRECTORY/..
GIT_VER=git-$(git describe --always)
[ -z "$GIT_VER" ] && echo "we do not have GIT_VER something is very wrong" && exit 1;
echo ==========
echo "Starting build"
make ci && S3_BUCKET=s3://${NODEUP_BUCKET} make upload
export CI=1
make && make test && S3_BUCKET=s3://${NODEUP_BUCKET} make upload
KOPS_CHANNEL=$(kops version | awk '{ print $2 }')
KOPS_CHANNEL=$(kops version | awk '{ print $2 }' |sed 's/\+/%2B/')
KOPS_BASE_URL="http://${NODEUP_BUCKET}.s3.amazonaws.com/kops/${KOPS_CHANNEL}/"
echo "KOPS_BASE_URL=${KOPS_BASE_URL}"
echo "NODEUP_URL=${KOPS_BASE_URL}linux/amd64/nodeup"
echo ==========
echo "Deleting cluster ${CLUSTER_NAME}. Elle est finie."
@ -111,25 +115,21 @@ kops delete cluster \
echo ==========
echo "Creating cluster ${CLUSTER_NAME}"
NODEUP_URL=${KOPS_BASE_URL}linux/amd64/nodeup \
KOPS_BASE_URL=${KOPS_BASE_URL} \
kops create cluster \
--name $CLUSTER_NAME \
--state $KOPS_STATE_STORE \
--node-count $NODE_COUNT \
--zones $NODE_ZONES \
--master-zones $MASTER_ZONES \
--cloud aws \
--node-size $NODE_SIZE \
--master-size $MASTER_SIZE \
-v $VERBOSITY \
--image $IMAGE \
--kubernetes-version "1.5.2" \
--topology $TOPOLOGY \
--networking $NETWORKING \
--bastion="true" \
--yes
kops_command="NODEUP_URL=${KOPS_BASE_URL}linux/amd64/nodeup KOPS_BASE_URL=${KOPS_BASE_URL} kops create cluster --name $CLUSTER_NAME --state $KOPS_STATE_STORE --node-count $NODE_COUNT --zones $NODE_ZONES --master-zones $MASTER_ZONES --node-size $NODE_SIZE --master-size $MASTER_SIZE -v $VERBOSITY --image $IMAGE --channel alpha --topology $TOPOLOGY --networking $NETWORKING"
if [[ $TOPOLOGY == "private" ]]; then
kops_command+=" --bastion='true'"
fi
if [ -n "${KOPS_FEATURE_FLAGS+x}" ]; then
kops_command=KOPS_FEATURE_FLAGS="${KOPS_FEATURE_FLAGS}" $kops_command
fi
if [[ $KOPS_CREATE == "yes" ]]; then
kops_command="$kops_command --yes"
fi
eval $kops_command
echo ==========
echo "Your k8s cluster ${CLUSTER_NAME}, awaits your bidding."

View File

@ -16,7 +16,7 @@
. $(dirname "${BASH_SOURCE}")/common.sh
BAD_HEADERS=$(${KUBE_ROOT}/hack/verify-boilerplate.sh | awk '{ print $6}')
BAD_HEADERS=$((${KUBE_ROOT}/hack/verify-boilerplate.sh || true) | awk '{ print $6}')
FORMATS="sh go Makefile Dockerfile"
for i in ${FORMATS}

View File

@ -34,5 +34,5 @@ cp /go/bin/channels /src/.build/artifacts/
# channels uses protokube
cd /src/.build/artifacts/
curl -O https://storage.googleapis.com/kubernetes-release/release/v1.6.0-beta.1/bin/linux/amd64/kubectl
curl -O https://storage.googleapis.com/kubernetes-release/release/v1.6.1/bin/linux/amd64/kubectl
chmod +x kubectl

View File

@ -37,18 +37,28 @@ func (b *CloudConfigBuilder) Build(c *fi.ModelBuilderContext) error {
// Add cloud config file if needed
var lines []string
cloudProvider := b.Cluster.Spec.CloudProvider
cloudConfig := b.Cluster.Spec.CloudConfig
if cloudConfig == nil {
cloudConfig = &kops.CloudConfiguration{}
}
if cloudConfig.NodeTags != nil {
lines = append(lines, "node-tags = "+*cloudConfig.NodeTags)
}
if cloudConfig.NodeInstancePrefix != nil {
lines = append(lines, "node-instance-prefix = "+*cloudConfig.NodeInstancePrefix)
}
if cloudConfig.Multizone != nil {
lines = append(lines, fmt.Sprintf("multizone = %t", *cloudConfig.Multizone))
switch cloudProvider {
case "gce":
if cloudConfig.NodeTags != nil {
lines = append(lines, "node-tags = "+*cloudConfig.NodeTags)
}
if cloudConfig.NodeInstancePrefix != nil {
lines = append(lines, "node-instance-prefix = "+*cloudConfig.NodeInstancePrefix)
}
if cloudConfig.Multizone != nil {
lines = append(lines, fmt.Sprintf("multizone = %t", *cloudConfig.Multizone))
}
case "aws":
if cloudConfig.DisableSecurityGroupIngress != nil {
lines = append(lines, fmt.Sprintf("DisableSecurityGroupIngress = %t", *cloudConfig.DisableSecurityGroupIngress))
}
}
config := "[global]\n" + strings.Join(lines, "\n") + "\n"

View File

@ -36,7 +36,6 @@ type NodeupModelContext struct {
Distribution distros.Distribution
IsMaster bool
UsesCNI bool
Assets *fi.AssetStore
KeyStore fi.CAStore
@ -83,7 +82,7 @@ func (c *NodeupModelContext) PathSrvSshproxy() string {
}
}
func (c *NodeupModelContext) NetworkPluginDir() string {
func (c *NodeupModelContext) CNIBinDir() string {
switch c.Distribution {
case distros.DistributionContainerOS:
return "/home/kubernetes/bin/"
@ -92,6 +91,10 @@ func (c *NodeupModelContext) NetworkPluginDir() string {
}
}
func (c *NodeupModelContext) CNIConfDir() string {
return "/etc/cni/net.d/"
}
func (c *NodeupModelContext) buildPKIKubeconfig(id string) (string, error) {
caCertificate, err := c.KeyStore.Cert(fi.CertificateId_CA)
if err != nil {
@ -171,3 +174,11 @@ func (c *NodeupModelContext) buildPKIKubeconfig(id string) (string, error) {
func (c *NodeupModelContext) IsKubernetesGTE(version string) bool {
return util.IsKubernetesGTE(version, c.KubernetesVersion)
}
func (c *NodeupModelContext) UsesCNI() bool {
networking := c.Cluster.Spec.Networking
if networking == nil || networking.Classic != nil {
return false
}
return true
}

View File

@ -141,6 +141,8 @@ var dockerVersions = []dockerVersion{
Hash: "52ec22128e70acc2f76b3a8e87ff96785995116a",
},
// 1.12.3 - k8s 1.5
// 1.12.3 - Jessie
{
DockerVersion: "1.12.3",
@ -199,6 +201,67 @@ var dockerVersions = []dockerVersion{
Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.3-1.el7.centos.noarch.rpm",
Hash: "a6b0243af348140236ed96f2e902b259c590eefa",
},
// 1.12.6 - k8s 1.6
// 1.12.6 - Jessie
{
DockerVersion: "1.12.6",
Name: "docker-engine",
Distros: []distros.Distribution{distros.DistributionJessie},
Architectures: []Architecture{ArchitectureAmd64},
Version: "1.12.6-0~debian-jessie",
Source: "http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.12.6-0~debian-jessie_amd64.deb",
Hash: "1a8b0c4e3386e12964676a126d284cebf599cc8e",
Dependencies: []string{"bridge-utils", "libapparmor1", "libltdl7", "perl"},
//Depends: iptables, init-system-helpers (>= 1.18~), libapparmor1 (>= 2.6~devel), libc6 (>= 2.17), libdevmapper1.02.1 (>= 2:1.02.90), libltdl7 (>= 2.4.2), libsystemd0
//Recommends: aufs-tools, ca-certificates, cgroupfs-mount | cgroup-lite, git, xz-utils
},
// 1.12.6 - Jessie on ARM
{
DockerVersion: "1.12.6",
Name: "docker-engine",
Distros: []distros.Distribution{distros.DistributionJessie},
Architectures: []Architecture{ArchitectureArm},
Version: "1.12.6-0~debian-jessie",
Source: "http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.12.6-0~debian-jessie_armhf.deb",
Hash: "ac148e1f7381e4201e139584dd3c102372ad96fb",
Dependencies: []string{"bridge-utils", "libapparmor1", "libltdl7", "perl"},
},
// 1.12.6 - Xenial
{
DockerVersion: "1.12.6",
Name: "docker-engine",
Distros: []distros.Distribution{distros.DistributionXenial},
Architectures: []Architecture{ArchitectureAmd64},
Version: "1.12.6-0~ubuntu-xenial",
Source: "http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.12.6-0~ubuntu-xenial_amd64.deb",
Hash: "fffc22da4ad5b20715bbb6c485b2d2bb7e84fd33",
Dependencies: []string{"bridge-utils", "libapparmor1", "libltdl7", "perl"},
},
// 1.12.6 - Centos / Rhel7 (two packages)
{
DockerVersion: "1.12.6",
Name: "docker-engine",
Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7},
Architectures: []Architecture{ArchitectureAmd64},
Version: "1.12.6",
Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.12.6-1.el7.centos.x86_64.rpm",
Hash: "776dbefa9dc7733000e46049293555a9a422c50e",
Dependencies: []string{"libtool-ltdl", "libseccomp"},
},
{
DockerVersion: "1.12.6",
Name: "docker-engine-selinux",
Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7},
Architectures: []Architecture{ArchitectureAmd64},
Version: "1.12.6",
Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.6-1.el7.centos.noarch.rpm",
Hash: "9a6ee0d631ca911b6927450a3c396e9a5be75047",
},
}
func (d *dockerVersion) matches(arch Architecture, dockerVersion string, distro distros.Distribution) bool {

View File

@ -17,14 +17,9 @@ limitations under the License.
package model
import (
"io/ioutil"
"k8s.io/kops/nodeup/pkg/distros"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/diff"
"k8s.io/kops/upup/pkg/fi"
"path"
"sort"
"strings"
"testing"
// Register our APIs
@ -90,64 +85,23 @@ func TestDockerBuilder_BuildFlags(t *testing.T) {
func runDockerBuilderTest(t *testing.T, key string) {
basedir := path.Join("tests/dockerbuilder/", key)
clusterYamlPath := path.Join(basedir, "cluster.yaml")
clusterYaml, err := ioutil.ReadFile(clusterYamlPath)
nodeUpModelContext, err := LoadModel(basedir)
if err != nil {
t.Fatalf("error reading cluster yaml file %q: %v", clusterYamlPath, err)
t.Fatalf("error parsing cluster yaml %q: %v", basedir, err)
return
}
obj, _, err := kops.ParseVersionedYaml(clusterYaml)
if err != nil {
t.Fatalf("error parsing cluster yaml %q: %v", clusterYamlPath, err)
}
cluster := obj.(*kops.Cluster)
context := &fi.ModelBuilderContext{
Tasks: make(map[string]fi.Task),
}
nodeUpModelContext := &NodeupModelContext{
Cluster: cluster,
Architecture: "amd64",
Distribution: distros.DistributionXenial,
}
builder := DockerBuilder{NodeupModelContext: nodeUpModelContext}
err = builder.Build(context)
if err != nil {
t.Fatalf("error from DockerBuilder Build: %v", err)
return
}
var keys []string
for key := range context.Tasks {
keys = append(keys, key)
}
sort.Strings(keys)
var yamls []string
for _, key := range keys {
task := context.Tasks[key]
yaml, err := kops.ToRawYaml(task)
if err != nil {
t.Fatalf("error serializing task: %v", err)
}
yamls = append(yamls, strings.TrimSpace(string(yaml)))
}
actualTasksYaml := strings.Join(yamls, "\n---\n")
tasksYamlPath := path.Join(basedir, "tasks.yaml")
expectedTasksYamlBytes, err := ioutil.ReadFile(tasksYamlPath)
if err != nil {
t.Fatalf("error reading file %q: %v", tasksYamlPath, err)
}
actualTasksYaml = strings.TrimSpace(actualTasksYaml)
expectedTasksYaml := strings.TrimSpace(string(expectedTasksYamlBytes))
if expectedTasksYaml != actualTasksYaml {
diffString := diff.FormatDiff(expectedTasksYaml, actualTasksYaml)
t.Logf("diff:\n%s\n", diffString)
t.Fatalf("tasks differed from expected for test %q", key)
}
ValidateTasks(t, basedir, context)
}

View File

@ -61,6 +61,18 @@ func (b *KubeAPIServerBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(t)
}
// Touch log file, so that docker doesn't create a directory instead
{
t := &nodetasks.File{
Path: "/var/log/kube-apiserver.log",
Contents: fi.NewStringResource(""),
Type: nodetasks.FileType_File,
Mode: s("0400"),
IfNotExists: true,
}
c.AddTask(t)
}
return nil
}

View File

@ -44,30 +44,10 @@ func (b *KubeletBuilder) Build(c *fi.ModelBuilderContext) error {
return fmt.Errorf("error building kubelet config: %v", err)
}
// Add sysconfig file
{
// TODO: Dump this - just complexity!
flags, err := flagbuilder.BuildFlags(kubeletConfig)
t, err := b.buildSystemdEnvironmentFile(kubeletConfig)
if err != nil {
return fmt.Errorf("error building kubelet flags: %v", err)
}
// Add cloud config file if needed
// We build this flag differently because it depends on CloudConfig, and to expose it directly
// would be a degree of freedom we don't have (we'd have to write the config to different files)
// We can always add this later if it is needed.
if b.Cluster.Spec.CloudConfig != nil {
flags += " --cloud-config=" + CloudConfigFilePath
}
flags += " --network-plugin-dir=" + b.NetworkPluginDir()
sysconfig := "DAEMON_ARGS=\"" + flags + "\"\n"
t := &nodetasks.File{
Path: "/etc/sysconfig/kubelet",
Contents: fi.NewStringResource(sysconfig),
Type: nodetasks.FileType_File,
return err
}
c.AddTask(t)
}
@ -77,6 +57,7 @@ func (b *KubeletBuilder) Build(c *fi.ModelBuilderContext) error {
// TODO: Extract to common function?
assetName := "kubelet"
assetPath := ""
// TODO make Find call to an interface, we cannot mock out this function because it finds a file on disk
asset, err := b.Assets.Find(assetName, assetPath)
if err != nil {
return fmt.Errorf("error trying to locate asset %q: %v", assetName, err)
@ -111,9 +92,9 @@ func (b *KubeletBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(t)
}
if b.UsesCNI {
if b.UsesCNI() {
t := &nodetasks.File{
Path: "/etc/cni/net.d/",
Path: b.CNIConfDir(),
Type: nodetasks.FileType_Directory,
}
c.AddTask(t)
@ -139,6 +120,41 @@ func (b *KubeletBuilder) kubeletPath() string {
return kubeletCommand
}
func (b *KubeletBuilder) buildSystemdEnvironmentFile(kubeletConfig *kops.KubeletConfigSpec) (*nodetasks.File, error) {
// TODO: Dump the separate file for flags - just complexity!
flags, err := flagbuilder.BuildFlags(kubeletConfig)
if err != nil {
return nil, fmt.Errorf("error building kubelet flags: %v", err)
}
// Add cloud config file if needed
// We build this flag differently because it depends on CloudConfig, and to expose it directly
// would be a degree of freedom we don't have (we'd have to write the config to different files)
// We can always add this later if it is needed.
if b.Cluster.Spec.CloudConfig != nil {
flags += " --cloud-config=" + CloudConfigFilePath
}
if b.UsesCNI() {
flags += " --cni-bin-dir=" + b.CNIBinDir()
flags += " --cni-conf-dir=" + b.CNIConfDir()
}
if b.Cluster.Spec.Networking != nil && b.Cluster.Spec.Networking.Kubenet != nil {
// Kubenet is neither CNI nor not-CNI, so we need to pass it `--network-plugin-dir` also
flags += " --network-plugin-dir=" + b.CNIBinDir()
}
sysconfig := "DAEMON_ARGS=\"" + flags + "\"\n"
t := &nodetasks.File{
Path: "/etc/sysconfig/kubelet",
Contents: fi.NewStringResource(sysconfig),
Type: nodetasks.FileType_File,
}
return t, nil
}
func (b *KubeletBuilder) buildSystemdService() *nodetasks.Service {
kubeletCommand := b.kubeletPath()

View File

@ -17,9 +17,20 @@ limitations under the License.
package model
import (
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
"bytes"
"io/ioutil"
"path"
"sort"
"strings"
"testing"
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kops/nodeup/pkg/distros"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/v1alpha2"
"k8s.io/kops/pkg/diff"
"k8s.io/kops/upup/pkg/fi"
)
func Test_InstanceGroupKubeletMerge(t *testing.T) {
@ -142,3 +153,115 @@ func stringSlicesEqual(exp, other []string) bool {
return true
}
func Test_RunKubeletBuilder(t *testing.T) {
basedir := "tests/kubelet/featuregates"
context := &fi.ModelBuilderContext{
Tasks: make(map[string]fi.Task),
}
nodeUpModelContext, err := LoadModel(basedir)
if err != nil {
t.Fatalf("error loading model %q: %v", basedir, err)
return
}
builder := KubeletBuilder{NodeupModelContext: nodeUpModelContext}
kubeletConfig, err := builder.buildKubeletConfig()
if err != nil {
t.Fatalf("error from KubeletBuilder buildKubeletConfig: %v", err)
return
}
fileTask, err := builder.buildSystemdEnvironmentFile(kubeletConfig)
if err != nil {
t.Fatalf("error from KubeletBuilder buildSystemdEnvironmentFile: %v", err)
return
}
context.AddTask(fileTask)
ValidateTasks(t, basedir, context)
}
func LoadModel(basedir string) (*NodeupModelContext, error) {
clusterYamlPath := path.Join(basedir, "cluster.yaml")
clusterYaml, err := ioutil.ReadFile(clusterYamlPath)
if err != nil {
return nil, fmt.Errorf("error reading cluster yaml file %q: %v", clusterYamlPath, err)
}
var cluster *kops.Cluster
var instanceGroup *kops.InstanceGroup
// Codecs provides access to encoding and decoding for the scheme
codecs := kops.Codecs
codec := codecs.UniversalDecoder(kops.SchemeGroupVersion)
sections := bytes.Split(clusterYaml, []byte("\n---\n"))
for _, section := range sections {
defaults := &schema.GroupVersionKind{
Group: v1alpha2.SchemeGroupVersion.Group,
Version: v1alpha2.SchemeGroupVersion.Version,
}
o, gvk, err := codec.Decode(section, defaults, nil)
if err != nil {
return nil, fmt.Errorf("error parsing file %v", err)
}
switch v := o.(type) {
case *kops.Cluster:
cluster = v
case *kops.InstanceGroup:
instanceGroup = v
default:
return nil, fmt.Errorf("Unhandled kind %q", gvk)
}
}
nodeUpModelContext := &NodeupModelContext{
Cluster: cluster,
Architecture: "amd64",
Distribution: distros.DistributionXenial,
InstanceGroup: instanceGroup,
}
return nodeUpModelContext, nil
}
func ValidateTasks(t *testing.T, basedir string, context *fi.ModelBuilderContext) {
var keys []string
for key := range context.Tasks {
keys = append(keys, key)
}
sort.Strings(keys)
var yamls []string
for _, key := range keys {
task := context.Tasks[key]
yaml, err := kops.ToRawYaml(task)
if err != nil {
t.Fatalf("error serializing task: %v", err)
}
yamls = append(yamls, strings.TrimSpace(string(yaml)))
}
actualTasksYaml := strings.Join(yamls, "\n---\n")
tasksYamlPath := path.Join(basedir, "tasks.yaml")
expectedTasksYamlBytes, err := ioutil.ReadFile(tasksYamlPath)
if err != nil {
t.Fatalf("error reading file %q: %v", tasksYamlPath, err)
}
actualTasksYaml = strings.TrimSpace(actualTasksYaml)
expectedTasksYaml := strings.TrimSpace(string(expectedTasksYamlBytes))
if expectedTasksYaml != actualTasksYaml {
diffString := diff.FormatDiff(expectedTasksYaml, actualTasksYaml)
t.Logf("diff:\n%s\n", diffString)
t.Fatalf("tasks differed from expected for test %q", basedir)
}
}

View File

@ -125,7 +125,7 @@ func (b *KubeProxyBuilder) buildPod() (*v1.Pod, error) {
}
image := c.Image
cmd := "echo -998 > /proc/$$$/oom_score_adj && kube-proxy --kubeconfig=/var/lib/kube-proxy/kubeconfig --resource-container=\"\" "
cmd := "echo -998 > /proc/$$$/oom_score_adj && kube-proxy --kubeconfig=/var/lib/kube-proxy/kubeconfig --conntrack-max-per-core=131072 --resource-container=\"\" "
cmd += flags
// cmd += " 1>>/var/log/kube-proxy.log 2>&1"

View File

@ -55,7 +55,7 @@ func (b *NetworkBuilder) Build(c *fi.ModelBuilderContext) error {
}
for _, assetName := range assetNames {
if err := b.addAsset(c, assetName); err != nil {
if err := b.addCNIBinAsset(c, assetName); err != nil {
return err
}
}
@ -63,7 +63,7 @@ func (b *NetworkBuilder) Build(c *fi.ModelBuilderContext) error {
return nil
}
func (b *NetworkBuilder) addAsset(c *fi.ModelBuilderContext, assetName string) error {
func (b *NetworkBuilder) addCNIBinAsset(c *fi.ModelBuilderContext, assetName string) error {
assetPath := ""
asset, err := b.Assets.Find(assetName, assetPath)
if err != nil {
@ -74,7 +74,7 @@ func (b *NetworkBuilder) addAsset(c *fi.ModelBuilderContext, assetName string) e
}
t := &nodetasks.File{
Path: filepath.Join(b.NetworkPluginDir(), assetName),
Path: filepath.Join(b.CNIBinDir(), assetName),
Contents: asset,
Type: nodetasks.FileType_File,
Mode: s("0755"),

View File

@ -95,10 +95,6 @@ func (b *SysctlBuilder) Build(c *fi.ModelBuilderContext) error {
"# Increase size of file handles and inode cache",
"fs.file-max = 2097152",
"",
"# Increase size of conntrack table size to avoid poor iptables performance",
"net.netfilter.nf_conntrack_max = 1000000",
"",
)
}

View File

@ -0,0 +1,60 @@
apiVersion: kops/v1alpha2
kind: Cluster
metadata:
creationTimestamp: "2016-12-10T22:42:27Z"
name: minimal.example.com
spec:
kubernetesApiAccess:
- 0.0.0.0/0
channel: stable
cloudProvider: aws
configBase: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- etcdMembers:
- instanceGroup: master-us-test-1a
name: master-us-test-1a
name: main
- etcdMembers:
- instanceGroup: master-us-test-1a
name: master-us-test-1a
name: events
kubelet:
featureGates:
ExperimentalCriticalPodAnnotation: "true"
AllowExtTrafficLocalEndpoints: "false"
kubernetesVersion: v1.5.0
masterInternalName: api.internal.minimal.example.com
masterPublicName: api.minimal.example.com
networkCIDR: 172.20.0.0/16
networking:
kubenet: {}
nonMasqueradeCIDR: 100.64.0.0/10
sshAccess:
- 0.0.0.0/0
topology:
masters: public
nodes: public
subnets:
- cidr: 172.20.32.0/19
name: us-test-1a
type: Public
zone: us-test-1a
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2016-12-10T22:42:28Z"
name: nodes
labels:
kops.k8s.io/cluster: minimal.example.com
spec:
associatePublicIp: true
image: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21
machineType: t2.medium
maxSize: 2
minSize: 2
role: Node
subnets:
- us-test-1a

View File

@ -0,0 +1,4 @@
contents: |
DAEMON_ARGS="--feature-gates=AllowExtTrafficLocalEndpoints=false,ExperimentalCriticalPodAnnotation=true --node-labels=kubernetes.io/role=node,node-role.kubernetes.io/node= --cni-bin-dir=/opt/cni/bin/ --cni-conf-dir=/etc/cni/net.d/ --network-plugin-dir=/opt/cni/bin/"
path: /etc/sysconfig/kubelet
type: file

View File

@ -319,6 +319,9 @@ type KubeletConfigSpec struct {
// Taints to add when registering a node in the cluster
Taints []string `json:"taints,omitempty" flag:"register-with-taints"`
// FeatureGates is set of key=value pairs that describe feature gates for alpha/experimental features.
FeatureGates map[string]string `json:"featureGates,omitempty" flag:"feature-gates"`
}
type KubeProxyConfig struct {
@ -686,4 +689,6 @@ type CloudConfiguration struct {
Multizone *bool `json:"multizone,omitempty"`
NodeTags *string `json:"nodeTags,omitempty"`
NodeInstancePrefix *string `json:"nodeInstancePrefix,omitempty"`
// AWS cloud-config options
DisableSecurityGroupIngress *bool `json:"disableSecurityGroupIngress,omitempty"`
}

View File

@ -318,6 +318,9 @@ type KubeletConfigSpec struct {
// Taints to add when registering a node in the cluster
Taints []string `json:"taints,omitempty" flag:"register-with-taints"`
// FeatureGates is set of key=value pairs that describe feature gates for alpha/experimental features.
FeatureGates map[string]string `json:"featureGates,omitempty" flag:"feature-gates"`
}
type KubeProxyConfig struct {

View File

@ -1365,6 +1365,7 @@ func autoConvert_v1alpha1_KubeletConfigSpec_To_kops_KubeletConfigSpec(in *Kubele
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
out.FeatureGates = in.FeatureGates
return nil
}
@ -1411,6 +1412,7 @@ func autoConvert_kops_KubeletConfigSpec_To_v1alpha1_KubeletConfigSpec(in *kops.K
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
out.FeatureGates = in.FeatureGates
return nil
}

View File

@ -140,6 +140,9 @@ type KubeletConfigSpec struct {
// Taints to add when registering a node in the cluster
Taints []string `json:"taints,omitempty" flag:"register-with-taints"`
// FeatureGates is set of key=value pairs that describe feature gates for alpha/experimental features.
FeatureGates map[string]string `json:"featureGates,omitempty" flag:"feature-gates"`
}
type KubeProxyConfig struct {

View File

@ -1463,6 +1463,7 @@ func autoConvert_v1alpha2_KubeletConfigSpec_To_kops_KubeletConfigSpec(in *Kubele
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
out.FeatureGates = in.FeatureGates
return nil
}
@ -1509,6 +1510,7 @@ func autoConvert_kops_KubeletConfigSpec_To_v1alpha2_KubeletConfigSpec(in *kops.K
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
out.FeatureGates = in.FeatureGates
return nil
}

View File

@ -89,6 +89,7 @@ func BuildFlags(options interface{}) (string, error) {
arg := fmt.Sprintf("%s=%s", k, v)
args = append(args, arg)
}
sort.Strings(args)
if len(args) != 0 {
flag := fmt.Sprintf("--%s=%s", flagName, strings.Join(args, ","))
flags = append(flags, flag)

View File

@ -48,7 +48,9 @@ func (b *DockerOptionsBuilder) BuildOptions(o interface{}) error {
}
dockerVersion := ""
if sv.Major == 1 && sv.Minor >= 5 {
if sv.Major == 1 && sv.Minor >= 6 {
dockerVersion = "1.12.6"
} else if sv.Major == 1 && sv.Minor >= 5 {
dockerVersion = "1.12.3"
} else if sv.Major == 1 && sv.Minor <= 4 {
dockerVersion = "1.11.2"

View File

@ -140,7 +140,7 @@ func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error
kcm.ConfigureCloudRoutes = fi.Bool(false)
} else if networking.Kopeio != nil {
// Kopeio is based on kubenet / external
kcm.ConfigureCloudRoutes = fi.Bool(true)
kcm.ConfigureCloudRoutes = fi.Bool(false)
} else {
return fmt.Errorf("no networking mode set")
}

View File

@ -180,7 +180,7 @@ func validateTheNodes(clusterName string, validationCluster *ValidationCluster)
}
validationCluster.NodesReady = true
if len(validationCluster.NodesNotReadyArray) != 0 || validationCluster.NodesCount != len(validationCluster.NodesReadyArray) {
if len(validationCluster.NodesNotReadyArray) != 0 || validationCluster.NodesCount > len(validationCluster.NodesReadyArray) {
validationCluster.NodesReady = false
}

View File

@ -196,6 +196,11 @@ func dummyClient(masterReady string, nodeReady string) kubernetes.Interface {
"kubernetes.io/role": "node",
NODE_READY: nodeReady,
},
{
"name": "node2",
"kubernetes.io/role": "node",
NODE_READY: "true",
},
},
))
}

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCtWu40XQo8dczLsCq0OWV+hxm9uV3WxeH9Kgh4sMzQxNtoU1pvW0XdjpkBesRKGoolfWeCLXWxpyQb1IaiMkKoz7MdhQ/6UKjMjP66aFWWp3pwD0uj0HuJ7tq4gKHKRYGTaZIRWpzUiANBrjugVgA+Sd7E/mYwc/DMXkIyRZbvhQ==

View File

@ -0,0 +1,102 @@
apiVersion: kops/v1alpha2
kind: Cluster
metadata:
creationTimestamp: "2016-12-12T04:13:14Z"
name: privatedns1.example.com
spec:
kubernetesApiAccess:
- 0.0.0.0/0
channel: stable
cloudProvider: aws
configBase: memfs://clusters.example.com/privatedns1.example.com
dnsZone: internal.example.com
etcdClusters:
- etcdMembers:
- instanceGroup: master-us-test-1a
name: us-test-1a
name: main
- etcdMembers:
- instanceGroup: master-us-test-1a
name: us-test-1a
name: events
kubernetesVersion: v1.4.6
masterInternalName: api.internal.privatedns1.example.com
masterPublicName: api.privatedns1.example.com
networkCIDR: 172.20.0.0/16
networking:
weave: {}
nonMasqueradeCIDR: 100.64.0.0/10
sshAccess:
- 0.0.0.0/0
topology:
dns:
type: Private
masters: private
nodes: private
subnets:
- cidr: 172.20.32.0/19
name: us-test-1a
type: Private
zone: us-test-1a
- cidr: 172.20.4.0/22
name: utility-us-test-1a
type: Utility
zone: us-test-1a
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2016-12-12T04:13:15Z"
name: master-us-test-1a
labels:
kops.k8s.io/cluster: privatedns1.example.com
spec:
associatePublicIp: true
image: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21
machineType: m3.medium
maxSize: 1
minSize: 1
role: Master
subnets:
- us-test-1a
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2016-12-12T04:13:15Z"
name: nodes
labels:
kops.k8s.io/cluster: privatedns1.example.com
spec:
associatePublicIp: true
image: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21
machineType: t2.medium
maxSize: 2
minSize: 2
role: Node
subnets:
- us-test-1a
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2016-12-14T15:32:41Z"
name: bastion
labels:
kops.k8s.io/cluster: privatedns1.example.com
spec:
associatePublicIp: true
image: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21
machineType: t2.micro
maxSize: 1
minSize: 1
role: Bastion
subnets:
- utility-us-test-1a

View File

@ -0,0 +1,653 @@
output "bastion_security_group_ids" {
value = ["${aws_security_group.bastion-privatedns1-example-com.id}"]
}
output "cluster_name" {
value = "privatedns1.example.com"
}
output "master_security_group_ids" {
value = ["${aws_security_group.masters-privatedns1-example-com.id}"]
}
output "node_security_group_ids" {
value = ["${aws_security_group.nodes-privatedns1-example-com.id}"]
}
output "node_subnet_ids" {
value = ["${aws_subnet.us-test-1a-privatedns1-example-com.id}"]
}
output "region" {
value = "us-test-1"
}
output "vpc_id" {
value = "${aws_vpc.privatedns1-example-com.id}"
}
resource "aws_autoscaling_attachment" "bastion-privatedns1-example-com" {
elb = "${aws_elb.bastion-privatedns1-example-com.id}"
autoscaling_group_name = "${aws_autoscaling_group.bastion-privatedns1-example-com.id}"
}
resource "aws_autoscaling_attachment" "master-us-test-1a-masters-privatedns1-example-com" {
elb = "${aws_elb.api-privatedns1-example-com.id}"
autoscaling_group_name = "${aws_autoscaling_group.master-us-test-1a-masters-privatedns1-example-com.id}"
}
resource "aws_autoscaling_group" "bastion-privatedns1-example-com" {
name = "bastion.privatedns1.example.com"
launch_configuration = "${aws_launch_configuration.bastion-privatedns1-example-com.id}"
max_size = 1
min_size = 1
vpc_zone_identifier = ["${aws_subnet.utility-us-test-1a-privatedns1-example-com.id}"]
tag = {
key = "KubernetesCluster"
value = "privatedns1.example.com"
propagate_at_launch = true
}
tag = {
key = "Name"
value = "bastion.privatedns1.example.com"
propagate_at_launch = true
}
tag = {
key = "k8s.io/role/bastion"
value = "1"
propagate_at_launch = true
}
}
resource "aws_autoscaling_group" "master-us-test-1a-masters-privatedns1-example-com" {
name = "master-us-test-1a.masters.privatedns1.example.com"
launch_configuration = "${aws_launch_configuration.master-us-test-1a-masters-privatedns1-example-com.id}"
max_size = 1
min_size = 1
vpc_zone_identifier = ["${aws_subnet.us-test-1a-privatedns1-example-com.id}"]
tag = {
key = "KubernetesCluster"
value = "privatedns1.example.com"
propagate_at_launch = true
}
tag = {
key = "Name"
value = "master-us-test-1a.masters.privatedns1.example.com"
propagate_at_launch = true
}
tag = {
key = "k8s.io/role/master"
value = "1"
propagate_at_launch = true
}
}
resource "aws_autoscaling_group" "nodes-privatedns1-example-com" {
name = "nodes.privatedns1.example.com"
launch_configuration = "${aws_launch_configuration.nodes-privatedns1-example-com.id}"
max_size = 2
min_size = 2
vpc_zone_identifier = ["${aws_subnet.us-test-1a-privatedns1-example-com.id}"]
tag = {
key = "KubernetesCluster"
value = "privatedns1.example.com"
propagate_at_launch = true
}
tag = {
key = "Name"
value = "nodes.privatedns1.example.com"
propagate_at_launch = true
}
tag = {
key = "k8s.io/role/node"
value = "1"
propagate_at_launch = true
}
}
resource "aws_ebs_volume" "us-test-1a-etcd-events-privatedns1-example-com" {
availability_zone = "us-test-1a"
size = 20
type = "gp2"
encrypted = false
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "us-test-1a.etcd-events.privatedns1.example.com"
"k8s.io/etcd/events" = "us-test-1a/us-test-1a"
"k8s.io/role/master" = "1"
}
}
resource "aws_ebs_volume" "us-test-1a-etcd-main-privatedns1-example-com" {
availability_zone = "us-test-1a"
size = 20
type = "gp2"
encrypted = false
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "us-test-1a.etcd-main.privatedns1.example.com"
"k8s.io/etcd/main" = "us-test-1a/us-test-1a"
"k8s.io/role/master" = "1"
}
}
resource "aws_eip" "us-test-1a-privatedns1-example-com" {
vpc = true
}
resource "aws_elb" "api-privatedns1-example-com" {
name = "api-privatedns1-example-c-lq96ht"
listener = {
instance_port = 443
instance_protocol = "TCP"
lb_port = 443
lb_protocol = "TCP"
}
security_groups = ["${aws_security_group.api-elb-privatedns1-example-com.id}"]
subnets = ["${aws_subnet.utility-us-test-1a-privatedns1-example-com.id}"]
health_check = {
target = "TCP:443"
healthy_threshold = 2
unhealthy_threshold = 2
interval = 10
timeout = 5
}
idle_timeout = 300
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "api.privatedns1.example.com"
}
}
resource "aws_elb" "bastion-privatedns1-example-com" {
name = "bastion-privatedns1-examp-mbgbef"
listener = {
instance_port = 22
instance_protocol = "TCP"
lb_port = 22
lb_protocol = "TCP"
}
security_groups = ["${aws_security_group.bastion-elb-privatedns1-example-com.id}"]
subnets = ["${aws_subnet.utility-us-test-1a-privatedns1-example-com.id}"]
health_check = {
target = "TCP:22"
healthy_threshold = 2
unhealthy_threshold = 2
interval = 10
timeout = 5
}
idle_timeout = 300
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "bastion.privatedns1.example.com"
}
}
resource "aws_iam_instance_profile" "bastions-privatedns1-example-com" {
name = "bastions.privatedns1.example.com"
roles = ["${aws_iam_role.bastions-privatedns1-example-com.name}"]
}
resource "aws_iam_instance_profile" "masters-privatedns1-example-com" {
name = "masters.privatedns1.example.com"
roles = ["${aws_iam_role.masters-privatedns1-example-com.name}"]
}
resource "aws_iam_instance_profile" "nodes-privatedns1-example-com" {
name = "nodes.privatedns1.example.com"
roles = ["${aws_iam_role.nodes-privatedns1-example-com.name}"]
}
resource "aws_iam_role" "bastions-privatedns1-example-com" {
name = "bastions.privatedns1.example.com"
assume_role_policy = "${file("${path.module}/data/aws_iam_role_bastions.privatedns1.example.com_policy")}"
}
resource "aws_iam_role" "masters-privatedns1-example-com" {
name = "masters.privatedns1.example.com"
assume_role_policy = "${file("${path.module}/data/aws_iam_role_masters.privatedns1.example.com_policy")}"
}
resource "aws_iam_role" "nodes-privatedns1-example-com" {
name = "nodes.privatedns1.example.com"
assume_role_policy = "${file("${path.module}/data/aws_iam_role_nodes.privatedns1.example.com_policy")}"
}
resource "aws_iam_role_policy" "bastions-privatedns1-example-com" {
name = "bastions.privatedns1.example.com"
role = "${aws_iam_role.bastions-privatedns1-example-com.name}"
policy = "${file("${path.module}/data/aws_iam_role_policy_bastions.privatedns1.example.com_policy")}"
}
resource "aws_iam_role_policy" "masters-privatedns1-example-com" {
name = "masters.privatedns1.example.com"
role = "${aws_iam_role.masters-privatedns1-example-com.name}"
policy = "${file("${path.module}/data/aws_iam_role_policy_masters.privatedns1.example.com_policy")}"
}
resource "aws_iam_role_policy" "nodes-privatedns1-example-com" {
name = "nodes.privatedns1.example.com"
role = "${aws_iam_role.nodes-privatedns1-example-com.name}"
policy = "${file("${path.module}/data/aws_iam_role_policy_nodes.privatedns1.example.com_policy")}"
}
resource "aws_internet_gateway" "privatedns1-example-com" {
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "privatedns1.example.com"
}
}
resource "aws_key_pair" "kubernetes-privatedns1-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157" {
key_name = "kubernetes.privatedns1.example.com-c4:a6:ed:9a:a8:89:b9:e2:c3:9c:d6:63:eb:9c:71:57"
public_key = "${file("${path.module}/data/aws_key_pair_kubernetes.privatedns1.example.com-c4a6ed9aa889b9e2c39cd663eb9c7157_public_key")}"
}
resource "aws_launch_configuration" "bastion-privatedns1-example-com" {
name_prefix = "bastion.privatedns1.example.com-"
image_id = "ami-12345678"
instance_type = "t2.micro"
key_name = "${aws_key_pair.kubernetes-privatedns1-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157.id}"
iam_instance_profile = "${aws_iam_instance_profile.bastions-privatedns1-example-com.id}"
security_groups = ["${aws_security_group.bastion-privatedns1-example-com.id}"]
associate_public_ip_address = true
root_block_device = {
volume_type = "gp2"
volume_size = 20
delete_on_termination = true
}
lifecycle = {
create_before_destroy = true
}
}
resource "aws_launch_configuration" "master-us-test-1a-masters-privatedns1-example-com" {
name_prefix = "master-us-test-1a.masters.privatedns1.example.com-"
image_id = "ami-12345678"
instance_type = "m3.medium"
key_name = "${aws_key_pair.kubernetes-privatedns1-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157.id}"
iam_instance_profile = "${aws_iam_instance_profile.masters-privatedns1-example-com.id}"
security_groups = ["${aws_security_group.masters-privatedns1-example-com.id}"]
associate_public_ip_address = false
user_data = "${file("${path.module}/data/aws_launch_configuration_master-us-test-1a.masters.privatedns1.example.com_user_data")}"
root_block_device = {
volume_type = "gp2"
volume_size = 20
delete_on_termination = true
}
ephemeral_block_device = {
device_name = "/dev/sdc"
virtual_name = "ephemeral0"
}
lifecycle = {
create_before_destroy = true
}
}
resource "aws_launch_configuration" "nodes-privatedns1-example-com" {
name_prefix = "nodes.privatedns1.example.com-"
image_id = "ami-12345678"
instance_type = "t2.medium"
key_name = "${aws_key_pair.kubernetes-privatedns1-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157.id}"
iam_instance_profile = "${aws_iam_instance_profile.nodes-privatedns1-example-com.id}"
security_groups = ["${aws_security_group.nodes-privatedns1-example-com.id}"]
associate_public_ip_address = false
user_data = "${file("${path.module}/data/aws_launch_configuration_nodes.privatedns1.example.com_user_data")}"
root_block_device = {
volume_type = "gp2"
volume_size = 20
delete_on_termination = true
}
lifecycle = {
create_before_destroy = true
}
}
resource "aws_nat_gateway" "us-test-1a-privatedns1-example-com" {
allocation_id = "${aws_eip.us-test-1a-privatedns1-example-com.id}"
subnet_id = "${aws_subnet.utility-us-test-1a-privatedns1-example-com.id}"
}
resource "aws_route" "0-0-0-0--0" {
route_table_id = "${aws_route_table.privatedns1-example-com.id}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.privatedns1-example-com.id}"
}
resource "aws_route" "private-us-test-1a-0-0-0-0--0" {
route_table_id = "${aws_route_table.private-us-test-1a-privatedns1-example-com.id}"
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = "${aws_nat_gateway.us-test-1a-privatedns1-example-com.id}"
}
resource "aws_route53_record" "api-privatedns1-example-com" {
name = "api.privatedns1.example.com"
type = "A"
alias = {
name = "${aws_elb.api-privatedns1-example-com.dns_name}"
zone_id = "${aws_elb.api-privatedns1-example-com.zone_id}"
evaluate_target_health = false
}
zone_id = "/hostedzone/Z2AFAKE1ZON3NO"
}
resource "aws_route53_zone_association" "internal-example-com" {
zone_id = "/hostedzone/Z2AFAKE1ZON3NO"
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
}
resource "aws_route_table" "private-us-test-1a-privatedns1-example-com" {
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "private-us-test-1a.privatedns1.example.com"
}
}
resource "aws_route_table" "privatedns1-example-com" {
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "privatedns1.example.com"
}
}
resource "aws_route_table_association" "private-us-test-1a-privatedns1-example-com" {
subnet_id = "${aws_subnet.us-test-1a-privatedns1-example-com.id}"
route_table_id = "${aws_route_table.private-us-test-1a-privatedns1-example-com.id}"
}
resource "aws_route_table_association" "utility-us-test-1a-privatedns1-example-com" {
subnet_id = "${aws_subnet.utility-us-test-1a-privatedns1-example-com.id}"
route_table_id = "${aws_route_table.privatedns1-example-com.id}"
}
resource "aws_security_group" "api-elb-privatedns1-example-com" {
name = "api-elb.privatedns1.example.com"
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
description = "Security group for api ELB"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "api-elb.privatedns1.example.com"
}
}
resource "aws_security_group" "bastion-elb-privatedns1-example-com" {
name = "bastion-elb.privatedns1.example.com"
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
description = "Security group for bastion ELB"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "bastion-elb.privatedns1.example.com"
}
}
resource "aws_security_group" "bastion-privatedns1-example-com" {
name = "bastion.privatedns1.example.com"
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
description = "Security group for bastion"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "bastion.privatedns1.example.com"
}
}
resource "aws_security_group" "masters-privatedns1-example-com" {
name = "masters.privatedns1.example.com"
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
description = "Security group for masters"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "masters.privatedns1.example.com"
}
}
resource "aws_security_group" "nodes-privatedns1-example-com" {
name = "nodes.privatedns1.example.com"
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
description = "Security group for nodes"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "nodes.privatedns1.example.com"
}
}
resource "aws_security_group_rule" "all-master-to-master" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
}
resource "aws_security_group_rule" "all-master-to-node" {
type = "ingress"
security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
}
resource "aws_security_group_rule" "all-node-to-node" {
type = "ingress"
security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
}
resource "aws_security_group_rule" "api-elb-egress" {
type = "egress"
security_group_id = "${aws_security_group.api-elb-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "bastion-egress" {
type = "egress"
security_group_id = "${aws_security_group.bastion-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "bastion-elb-egress" {
type = "egress"
security_group_id = "${aws_security_group.bastion-elb-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "bastion-to-master-ssh" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.bastion-privatedns1-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
}
resource "aws_security_group_rule" "bastion-to-node-ssh" {
type = "ingress"
security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.bastion-privatedns1-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
}
resource "aws_security_group_rule" "https-api-elb-0-0-0-0--0" {
type = "ingress"
security_group_id = "${aws_security_group.api-elb-privatedns1-example-com.id}"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "https-elb-to-master" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.api-elb-privatedns1-example-com.id}"
from_port = 443
to_port = 443
protocol = "tcp"
}
resource "aws_security_group_rule" "master-egress" {
type = "egress"
security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "node-egress" {
type = "egress"
security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "node-to-master-tcp-1-4000" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
from_port = 1
to_port = 4000
protocol = "tcp"
}
resource "aws_security_group_rule" "node-to-master-tcp-4003-65535" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
from_port = 4003
to_port = 65535
protocol = "tcp"
}
resource "aws_security_group_rule" "node-to-master-udp-1-65535" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns1-example-com.id}"
from_port = 1
to_port = 65535
protocol = "udp"
}
resource "aws_security_group_rule" "ssh-elb-to-bastion" {
type = "ingress"
security_group_id = "${aws_security_group.bastion-privatedns1-example-com.id}"
source_security_group_id = "${aws_security_group.bastion-elb-privatedns1-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
}
resource "aws_security_group_rule" "ssh-external-to-bastion-elb-0-0-0-0--0" {
type = "ingress"
security_group_id = "${aws_security_group.bastion-elb-privatedns1-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_subnet" "us-test-1a-privatedns1-example-com" {
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
cidr_block = "172.20.32.0/19"
availability_zone = "us-test-1a"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "us-test-1a.privatedns1.example.com"
}
}
resource "aws_subnet" "utility-us-test-1a-privatedns1-example-com" {
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
cidr_block = "172.20.4.0/22"
availability_zone = "us-test-1a"
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "utility-us-test-1a.privatedns1.example.com"
}
}
resource "aws_vpc" "privatedns1-example-com" {
cidr_block = "172.20.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "privatedns1.example.com"
}
}
resource "aws_vpc_dhcp_options" "privatedns1-example-com" {
domain_name = "us-test-1.compute.internal"
domain_name_servers = ["AmazonProvidedDNS"]
tags = {
KubernetesCluster = "privatedns1.example.com"
Name = "privatedns1.example.com"
}
}
resource "aws_vpc_dhcp_options_association" "privatedns1-example-com" {
vpc_id = "${aws_vpc.privatedns1-example-com.id}"
dhcp_options_id = "${aws_vpc_dhcp_options.privatedns1-example-com.id}"
}

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCtWu40XQo8dczLsCq0OWV+hxm9uV3WxeH9Kgh4sMzQxNtoU1pvW0XdjpkBesRKGoolfWeCLXWxpyQb1IaiMkKoz7MdhQ/6UKjMjP66aFWWp3pwD0uj0HuJ7tq4gKHKRYGTaZIRWpzUiANBrjugVgA+Sd7E/mYwc/DMXkIyRZbvhQ==

View File

@ -0,0 +1,103 @@
apiVersion: kops/v1alpha2
kind: Cluster
metadata:
creationTimestamp: "2016-12-12T04:13:14Z"
name: privatedns2.example.com
spec:
kubernetesApiAccess:
- 0.0.0.0/0
channel: stable
cloudProvider: aws
configBase: memfs://clusters.example.com/privatedns2.example.com
dnsZone: private.example.com
etcdClusters:
- etcdMembers:
- instanceGroup: master-us-test-1a
name: us-test-1a
name: main
- etcdMembers:
- instanceGroup: master-us-test-1a
name: us-test-1a
name: events
kubernetesVersion: v1.4.6
masterInternalName: api.internal.privatedns2.example.com
masterPublicName: api.privatedns2.example.com
networkCIDR: 172.20.0.0/16
networkID: vpc-123
networking:
weave: {}
nonMasqueradeCIDR: 100.64.0.0/10
sshAccess:
- 0.0.0.0/0
topology:
dns:
type: Private
masters: private
nodes: private
subnets:
- cidr: 172.20.32.0/19
name: us-test-1a
type: Private
zone: us-test-1a
- cidr: 172.20.4.0/22
name: utility-us-test-1a
type: Utility
zone: us-test-1a
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2016-12-12T04:13:15Z"
name: master-us-test-1a
labels:
kops.k8s.io/cluster: privatedns2.example.com
spec:
associatePublicIp: true
image: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21
machineType: m3.medium
maxSize: 1
minSize: 1
role: Master
subnets:
- us-test-1a
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2016-12-12T04:13:15Z"
name: nodes
labels:
kops.k8s.io/cluster: privatedns2.example.com
spec:
associatePublicIp: true
image: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21
machineType: t2.medium
maxSize: 2
minSize: 2
role: Node
subnets:
- us-test-1a
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2016-12-14T15:32:41Z"
name: bastion
labels:
kops.k8s.io/cluster: privatedns2.example.com
spec:
associatePublicIp: true
image: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21
machineType: t2.micro
maxSize: 1
minSize: 1
role: Bastion
subnets:
- utility-us-test-1a

View File

@ -0,0 +1,613 @@
output "bastion_security_group_ids" {
value = ["${aws_security_group.bastion-privatedns2-example-com.id}"]
}
output "cluster_name" {
value = "privatedns2.example.com"
}
output "master_security_group_ids" {
value = ["${aws_security_group.masters-privatedns2-example-com.id}"]
}
output "node_security_group_ids" {
value = ["${aws_security_group.nodes-privatedns2-example-com.id}"]
}
output "node_subnet_ids" {
value = ["${aws_subnet.us-test-1a-privatedns2-example-com.id}"]
}
output "region" {
value = "us-test-1"
}
output "vpc_id" {
value = "vpc-123"
}
resource "aws_autoscaling_attachment" "bastion-privatedns2-example-com" {
elb = "${aws_elb.bastion-privatedns2-example-com.id}"
autoscaling_group_name = "${aws_autoscaling_group.bastion-privatedns2-example-com.id}"
}
resource "aws_autoscaling_attachment" "master-us-test-1a-masters-privatedns2-example-com" {
elb = "${aws_elb.api-privatedns2-example-com.id}"
autoscaling_group_name = "${aws_autoscaling_group.master-us-test-1a-masters-privatedns2-example-com.id}"
}
resource "aws_autoscaling_group" "bastion-privatedns2-example-com" {
name = "bastion.privatedns2.example.com"
launch_configuration = "${aws_launch_configuration.bastion-privatedns2-example-com.id}"
max_size = 1
min_size = 1
vpc_zone_identifier = ["${aws_subnet.utility-us-test-1a-privatedns2-example-com.id}"]
tag = {
key = "KubernetesCluster"
value = "privatedns2.example.com"
propagate_at_launch = true
}
tag = {
key = "Name"
value = "bastion.privatedns2.example.com"
propagate_at_launch = true
}
tag = {
key = "k8s.io/role/bastion"
value = "1"
propagate_at_launch = true
}
}
resource "aws_autoscaling_group" "master-us-test-1a-masters-privatedns2-example-com" {
name = "master-us-test-1a.masters.privatedns2.example.com"
launch_configuration = "${aws_launch_configuration.master-us-test-1a-masters-privatedns2-example-com.id}"
max_size = 1
min_size = 1
vpc_zone_identifier = ["${aws_subnet.us-test-1a-privatedns2-example-com.id}"]
tag = {
key = "KubernetesCluster"
value = "privatedns2.example.com"
propagate_at_launch = true
}
tag = {
key = "Name"
value = "master-us-test-1a.masters.privatedns2.example.com"
propagate_at_launch = true
}
tag = {
key = "k8s.io/role/master"
value = "1"
propagate_at_launch = true
}
}
resource "aws_autoscaling_group" "nodes-privatedns2-example-com" {
name = "nodes.privatedns2.example.com"
launch_configuration = "${aws_launch_configuration.nodes-privatedns2-example-com.id}"
max_size = 2
min_size = 2
vpc_zone_identifier = ["${aws_subnet.us-test-1a-privatedns2-example-com.id}"]
tag = {
key = "KubernetesCluster"
value = "privatedns2.example.com"
propagate_at_launch = true
}
tag = {
key = "Name"
value = "nodes.privatedns2.example.com"
propagate_at_launch = true
}
tag = {
key = "k8s.io/role/node"
value = "1"
propagate_at_launch = true
}
}
resource "aws_ebs_volume" "us-test-1a-etcd-events-privatedns2-example-com" {
availability_zone = "us-test-1a"
size = 20
type = "gp2"
encrypted = false
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "us-test-1a.etcd-events.privatedns2.example.com"
"k8s.io/etcd/events" = "us-test-1a/us-test-1a"
"k8s.io/role/master" = "1"
}
}
resource "aws_ebs_volume" "us-test-1a-etcd-main-privatedns2-example-com" {
availability_zone = "us-test-1a"
size = 20
type = "gp2"
encrypted = false
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "us-test-1a.etcd-main.privatedns2.example.com"
"k8s.io/etcd/main" = "us-test-1a/us-test-1a"
"k8s.io/role/master" = "1"
}
}
resource "aws_eip" "us-test-1a-privatedns2-example-com" {
vpc = true
}
resource "aws_elb" "api-privatedns2-example-com" {
name = "api-privatedns2-example-c-6jft30"
listener = {
instance_port = 443
instance_protocol = "TCP"
lb_port = 443
lb_protocol = "TCP"
}
security_groups = ["${aws_security_group.api-elb-privatedns2-example-com.id}"]
subnets = ["${aws_subnet.utility-us-test-1a-privatedns2-example-com.id}"]
health_check = {
target = "TCP:443"
healthy_threshold = 2
unhealthy_threshold = 2
interval = 10
timeout = 5
}
idle_timeout = 300
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "api.privatedns2.example.com"
}
}
resource "aws_elb" "bastion-privatedns2-example-com" {
name = "bastion-privatedns2-examp-e704o2"
listener = {
instance_port = 22
instance_protocol = "TCP"
lb_port = 22
lb_protocol = "TCP"
}
security_groups = ["${aws_security_group.bastion-elb-privatedns2-example-com.id}"]
subnets = ["${aws_subnet.utility-us-test-1a-privatedns2-example-com.id}"]
health_check = {
target = "TCP:22"
healthy_threshold = 2
unhealthy_threshold = 2
interval = 10
timeout = 5
}
idle_timeout = 300
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "bastion.privatedns2.example.com"
}
}
resource "aws_iam_instance_profile" "bastions-privatedns2-example-com" {
name = "bastions.privatedns2.example.com"
roles = ["${aws_iam_role.bastions-privatedns2-example-com.name}"]
}
resource "aws_iam_instance_profile" "masters-privatedns2-example-com" {
name = "masters.privatedns2.example.com"
roles = ["${aws_iam_role.masters-privatedns2-example-com.name}"]
}
resource "aws_iam_instance_profile" "nodes-privatedns2-example-com" {
name = "nodes.privatedns2.example.com"
roles = ["${aws_iam_role.nodes-privatedns2-example-com.name}"]
}
resource "aws_iam_role" "bastions-privatedns2-example-com" {
name = "bastions.privatedns2.example.com"
assume_role_policy = "${file("${path.module}/data/aws_iam_role_bastions.privatedns2.example.com_policy")}"
}
resource "aws_iam_role" "masters-privatedns2-example-com" {
name = "masters.privatedns2.example.com"
assume_role_policy = "${file("${path.module}/data/aws_iam_role_masters.privatedns2.example.com_policy")}"
}
resource "aws_iam_role" "nodes-privatedns2-example-com" {
name = "nodes.privatedns2.example.com"
assume_role_policy = "${file("${path.module}/data/aws_iam_role_nodes.privatedns2.example.com_policy")}"
}
resource "aws_iam_role_policy" "bastions-privatedns2-example-com" {
name = "bastions.privatedns2.example.com"
role = "${aws_iam_role.bastions-privatedns2-example-com.name}"
policy = "${file("${path.module}/data/aws_iam_role_policy_bastions.privatedns2.example.com_policy")}"
}
resource "aws_iam_role_policy" "masters-privatedns2-example-com" {
name = "masters.privatedns2.example.com"
role = "${aws_iam_role.masters-privatedns2-example-com.name}"
policy = "${file("${path.module}/data/aws_iam_role_policy_masters.privatedns2.example.com_policy")}"
}
resource "aws_iam_role_policy" "nodes-privatedns2-example-com" {
name = "nodes.privatedns2.example.com"
role = "${aws_iam_role.nodes-privatedns2-example-com.name}"
policy = "${file("${path.module}/data/aws_iam_role_policy_nodes.privatedns2.example.com_policy")}"
}
resource "aws_key_pair" "kubernetes-privatedns2-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157" {
key_name = "kubernetes.privatedns2.example.com-c4:a6:ed:9a:a8:89:b9:e2:c3:9c:d6:63:eb:9c:71:57"
public_key = "${file("${path.module}/data/aws_key_pair_kubernetes.privatedns2.example.com-c4a6ed9aa889b9e2c39cd663eb9c7157_public_key")}"
}
resource "aws_launch_configuration" "bastion-privatedns2-example-com" {
name_prefix = "bastion.privatedns2.example.com-"
image_id = "ami-12345678"
instance_type = "t2.micro"
key_name = "${aws_key_pair.kubernetes-privatedns2-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157.id}"
iam_instance_profile = "${aws_iam_instance_profile.bastions-privatedns2-example-com.id}"
security_groups = ["${aws_security_group.bastion-privatedns2-example-com.id}"]
associate_public_ip_address = true
root_block_device = {
volume_type = "gp2"
volume_size = 20
delete_on_termination = true
}
lifecycle = {
create_before_destroy = true
}
}
resource "aws_launch_configuration" "master-us-test-1a-masters-privatedns2-example-com" {
name_prefix = "master-us-test-1a.masters.privatedns2.example.com-"
image_id = "ami-12345678"
instance_type = "m3.medium"
key_name = "${aws_key_pair.kubernetes-privatedns2-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157.id}"
iam_instance_profile = "${aws_iam_instance_profile.masters-privatedns2-example-com.id}"
security_groups = ["${aws_security_group.masters-privatedns2-example-com.id}"]
associate_public_ip_address = false
user_data = "${file("${path.module}/data/aws_launch_configuration_master-us-test-1a.masters.privatedns2.example.com_user_data")}"
root_block_device = {
volume_type = "gp2"
volume_size = 20
delete_on_termination = true
}
ephemeral_block_device = {
device_name = "/dev/sdc"
virtual_name = "ephemeral0"
}
lifecycle = {
create_before_destroy = true
}
}
resource "aws_launch_configuration" "nodes-privatedns2-example-com" {
name_prefix = "nodes.privatedns2.example.com-"
image_id = "ami-12345678"
instance_type = "t2.medium"
key_name = "${aws_key_pair.kubernetes-privatedns2-example-com-c4a6ed9aa889b9e2c39cd663eb9c7157.id}"
iam_instance_profile = "${aws_iam_instance_profile.nodes-privatedns2-example-com.id}"
security_groups = ["${aws_security_group.nodes-privatedns2-example-com.id}"]
associate_public_ip_address = false
user_data = "${file("${path.module}/data/aws_launch_configuration_nodes.privatedns2.example.com_user_data")}"
root_block_device = {
volume_type = "gp2"
volume_size = 20
delete_on_termination = true
}
lifecycle = {
create_before_destroy = true
}
}
resource "aws_nat_gateway" "us-test-1a-privatedns2-example-com" {
allocation_id = "${aws_eip.us-test-1a-privatedns2-example-com.id}"
subnet_id = "${aws_subnet.utility-us-test-1a-privatedns2-example-com.id}"
}
resource "aws_route" "0-0-0-0--0" {
route_table_id = "${aws_route_table.privatedns2-example-com.id}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "fake-ig"
}
resource "aws_route" "private-us-test-1a-0-0-0-0--0" {
route_table_id = "${aws_route_table.private-us-test-1a-privatedns2-example-com.id}"
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = "${aws_nat_gateway.us-test-1a-privatedns2-example-com.id}"
}
resource "aws_route53_record" "api-privatedns2-example-com" {
name = "api.privatedns2.example.com"
type = "A"
alias = {
name = "${aws_elb.api-privatedns2-example-com.dns_name}"
zone_id = "${aws_elb.api-privatedns2-example-com.zone_id}"
evaluate_target_health = false
}
zone_id = "/hostedzone/Z3AFAKE1ZOMORE"
}
resource "aws_route_table" "private-us-test-1a-privatedns2-example-com" {
vpc_id = "vpc-123"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "private-us-test-1a.privatedns2.example.com"
}
}
resource "aws_route_table" "privatedns2-example-com" {
vpc_id = "vpc-123"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "privatedns2.example.com"
}
}
resource "aws_route_table_association" "private-us-test-1a-privatedns2-example-com" {
subnet_id = "${aws_subnet.us-test-1a-privatedns2-example-com.id}"
route_table_id = "${aws_route_table.private-us-test-1a-privatedns2-example-com.id}"
}
resource "aws_route_table_association" "utility-us-test-1a-privatedns2-example-com" {
subnet_id = "${aws_subnet.utility-us-test-1a-privatedns2-example-com.id}"
route_table_id = "${aws_route_table.privatedns2-example-com.id}"
}
resource "aws_security_group" "api-elb-privatedns2-example-com" {
name = "api-elb.privatedns2.example.com"
vpc_id = "vpc-123"
description = "Security group for api ELB"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "api-elb.privatedns2.example.com"
}
}
resource "aws_security_group" "bastion-elb-privatedns2-example-com" {
name = "bastion-elb.privatedns2.example.com"
vpc_id = "vpc-123"
description = "Security group for bastion ELB"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "bastion-elb.privatedns2.example.com"
}
}
resource "aws_security_group" "bastion-privatedns2-example-com" {
name = "bastion.privatedns2.example.com"
vpc_id = "vpc-123"
description = "Security group for bastion"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "bastion.privatedns2.example.com"
}
}
resource "aws_security_group" "masters-privatedns2-example-com" {
name = "masters.privatedns2.example.com"
vpc_id = "vpc-123"
description = "Security group for masters"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "masters.privatedns2.example.com"
}
}
resource "aws_security_group" "nodes-privatedns2-example-com" {
name = "nodes.privatedns2.example.com"
vpc_id = "vpc-123"
description = "Security group for nodes"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "nodes.privatedns2.example.com"
}
}
resource "aws_security_group_rule" "all-master-to-master" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
}
resource "aws_security_group_rule" "all-master-to-node" {
type = "ingress"
security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
}
resource "aws_security_group_rule" "all-node-to-node" {
type = "ingress"
security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
}
resource "aws_security_group_rule" "api-elb-egress" {
type = "egress"
security_group_id = "${aws_security_group.api-elb-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "bastion-egress" {
type = "egress"
security_group_id = "${aws_security_group.bastion-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "bastion-elb-egress" {
type = "egress"
security_group_id = "${aws_security_group.bastion-elb-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "bastion-to-master-ssh" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.bastion-privatedns2-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
}
resource "aws_security_group_rule" "bastion-to-node-ssh" {
type = "ingress"
security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.bastion-privatedns2-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
}
resource "aws_security_group_rule" "https-api-elb-0-0-0-0--0" {
type = "ingress"
security_group_id = "${aws_security_group.api-elb-privatedns2-example-com.id}"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "https-elb-to-master" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.api-elb-privatedns2-example-com.id}"
from_port = 443
to_port = 443
protocol = "tcp"
}
resource "aws_security_group_rule" "master-egress" {
type = "egress"
security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "node-egress" {
type = "egress"
security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "node-to-master-tcp-1-4000" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
from_port = 1
to_port = 4000
protocol = "tcp"
}
resource "aws_security_group_rule" "node-to-master-tcp-4003-65535" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
from_port = 4003
to_port = 65535
protocol = "tcp"
}
resource "aws_security_group_rule" "node-to-master-udp-1-65535" {
type = "ingress"
security_group_id = "${aws_security_group.masters-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.nodes-privatedns2-example-com.id}"
from_port = 1
to_port = 65535
protocol = "udp"
}
resource "aws_security_group_rule" "ssh-elb-to-bastion" {
type = "ingress"
security_group_id = "${aws_security_group.bastion-privatedns2-example-com.id}"
source_security_group_id = "${aws_security_group.bastion-elb-privatedns2-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
}
resource "aws_security_group_rule" "ssh-external-to-bastion-elb-0-0-0-0--0" {
type = "ingress"
security_group_id = "${aws_security_group.bastion-elb-privatedns2-example-com.id}"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_subnet" "us-test-1a-privatedns2-example-com" {
vpc_id = "vpc-123"
cidr_block = "172.20.32.0/19"
availability_zone = "us-test-1a"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "us-test-1a.privatedns2.example.com"
}
}
resource "aws_subnet" "utility-us-test-1a-privatedns2-example-com" {
vpc_id = "vpc-123"
cidr_block = "172.20.4.0/22"
availability_zone = "us-test-1a"
tags = {
KubernetesCluster = "privatedns2.example.com"
Name = "utility-us-test-1a.privatedns2.example.com"
}
}

View File

@ -20,6 +20,8 @@ spec:
version: v1.6.0
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
# For 1.6, we keep the old tolerations in case of a downgrade to 1.5
scheduler.alpha.kubernetes.io/tolerations: '[{"key": "dedicated", "value": "master"}]'
spec:
tolerations:
- key: "node-role.kubernetes.io/master"
@ -72,6 +74,14 @@ rules:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
---

View File

@ -28,6 +28,7 @@ spec:
k8s-app: kube-dns-autoscaler
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
# For 1.6, we keep the old tolerations in case of a downgrade to 1.5
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
spec:
serviceAccountName: kube-dns-autoscaler
@ -79,6 +80,7 @@ spec:
k8s-app: kube-dns
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
# For 1.6, we keep the old tolerations in case of a downgrade to 1.5
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
spec:
dnsPolicy: Default # Don't use cluster DNS.

View File

@ -0,0 +1,109 @@
kind: ServiceAccount
apiVersion: v1
metadata:
name: flannel
namespace: kube-system
labels:
role.kubernetes.io/networking: "1"
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
k8s-app: flannel
role.kubernetes.io/networking: "1"
data:
cni-conf.json: |
{
"name": "cbr0",
"type": "flannel",
"delegate": {
"forceAddress": true,
"isDefaultGateway": true
}
}
net-conf.json: |
{
"Network": "100.64.0.0/10",
"Backend": {
"Type": "udp"
}
}
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: kube-flannel-ds
namespace: kube-system
labels:
k8s-app: flannel
role.kubernetes.io/networking: "1"
spec:
template:
metadata:
labels:
tier: node
app: flannel
role.kubernetes.io/networking: "1"
spec:
hostNetwork: true
nodeSelector:
beta.kubernetes.io/arch: amd64
serviceAccountName: flannel
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.7.0
command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ]
securityContext:
privileged: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- name: run
mountPath: /run
- name: flannel-cfg
mountPath: /etc/kube-flannel/
- name: install-cni
image: quay.io/coreos/flannel:v0.7.0
command: [ "/bin/sh", "-c", "set -e -x; cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/10-flannel.conf; while true; do sleep 3600; done" ]
resources:
limits:
cpu: 10m
memory: 25Mi
requests:
cpu: 10m
memory: 25Mi
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
volumes:
- name: run
hostPath:
path: /run
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg

View File

@ -0,0 +1,89 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: kopeio-networking-agent
namespace: kube-system
labels:
k8s-addon: networking.kope.io
role.kubernetes.io/networking: "1"
spec:
template:
metadata:
labels:
name: kopeio-networking-agent
role.kubernetes.io/networking: "1"
spec:
hostPID: true
hostIPC: true
hostNetwork: true
containers:
- resources:
requests:
cpu: 20m
memory: 100Mi
limits:
cpu: 20m
memory: 100Mi
securityContext:
privileged: true
image: kopeio/networking-agent:1.0.20170406
name: networking-agent
volumeMounts:
- name: lib-modules
mountPath: /lib/modules
readOnly: true
serviceAccountName: kopeio-networking-agent
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
volumes:
- name: lib-modules
hostPath:
path: /lib/modules
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: kopeio-networking-agent
namespace: kube-system
labels:
k8s-addon: networking.kope.io
role.kubernetes.io/networking: "1"
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
labels:
k8s-addon: networking.kope.io
name: kopeio:networking-agent
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- patch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
k8s-addon: networking.kope.io
name: kopeio:networking-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kopeio:networking-agent
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: system:serviceaccount:kube-system:kopeio-networking-agent

View File

@ -4,7 +4,7 @@ metadata:
name: kopeio-networking-agent
namespace: kube-system
labels:
k8s-addon: networking.addons.k8s.io
k8s-addon: networking.kope.io
role.kubernetes.io/networking: "1"
spec:
template:
@ -20,9 +20,13 @@ spec:
- resources:
requests:
cpu: 20m
memory: 100Mi
limits:
cpu: 20m
memory: 100Mi
securityContext:
privileged: true
image: kopeio/networking-agent:1.0.20161116
image: kopeio/networking-agent:1.0.20170406
name: networking-agent
volumeMounts:
- name: lib-modules

View File

@ -0,0 +1,201 @@
# This ConfigMap can be used to configure a self-hosted Canal installation.
# See `canal.yaml` for an example of a Canal deployment which uses
# the config in this ConfigMap.
kind: ConfigMap
apiVersion: v1
metadata:
name: canal-config
namespace: kube-system
data:
# The interface used by canal for host <-> host communication.
# If left blank, then the interface is chosing using the node's
# default route.
canal_iface: ""
# Whether or not to masquerade traffic to destinations not within
# the pod network.
masquerade: "true"
# The CNI network configuration to install on each node.
cni_network_config: |-
{
"name": "k8s-pod-network",
"type": "calico",
"log_level": "info",
"datastore_type": "kubernetes",
"hostname": "__KUBERNETES_NODE_NAME__",
"ipam": {
"type": "host-local",
"subnet": "usePodCidr"
},
"policy": {
"type": "k8s",
"k8s_auth_token": "__SERVICEACCOUNT_TOKEN__"
},
"kubernetes": {
"k8s_api_root": "https://__KUBERNETES_SERVICE_HOST__:__KUBERNETES_SERVICE_PORT__",
"kubeconfig": "__KUBECONFIG_FILEPATH__",
"node_name": "__KUBERNETES_NODE_NAME__"
}
}
# Flannel network configuration.
net-conf.json: |
{
"Network": "{{ .NonMasqueradeCIDR }}",
"Backend": {
"Type": "vxlan"
}
}
---
# This manifest installs the calico/node container, as well
# as the Calico CNI plugins and network config on
# each master and worker node in a Kubernetes cluster.
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: canal
namespace: kube-system
labels:
k8s-app: canal
role.kubernetes.io/networking: "1"
spec:
selector:
matchLabels:
k8s-app: canal
template:
metadata:
labels:
k8s-app: canal
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
spec:
hostNetwork: true
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: CriticalAddonsOnly
operator: Exists
containers:
# Runs calico/node container on each Kubernetes node. This
# container programs network policy and routes on each
# host.
- name: calico-node
image: calico/node:v1.0.2
resources:
requests:
cpu: 10m
env:
# Use Kubernetes API as the backing datastore.
- name: DATASTORE_TYPE
value: "kubernetes"
# Enable felix logging.
- name: FELIX_LOGSEVERITYSYS
value: "info"
# Don't enable BGP.
- name: CALICO_NETWORKING_BACKEND
value: "none"
# Disable file logging so `kubectl logs` works.
- name: CALICO_DISABLE_FILE_LOGGING
value: "true"
# No IP address needed.
- name: IP
value: ""
# Set the hostname based on the k8s node name.
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
securityContext:
privileged: true
volumeMounts:
- mountPath: /lib/modules
name: lib-modules
readOnly: true
- mountPath: /var/run/calico
name: var-run-calico
readOnly: false
# This container installs the Calico CNI binaries
# and CNI network config file on each node.
- name: install-cni
image: calico/cni:v1.5.6
command: ["/install-cni.sh"]
resources:
requests:
cpu: 10m
env:
# The CNI network config to install on each node.
- name: CNI_NETWORK_CONFIG
valueFrom:
configMapKeyRef:
name: canal-config
key: cni_network_config
# Set the hostname based on the k8s node name.
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- mountPath: /host/opt/cni/bin
name: cni-bin-dir
- mountPath: /host/etc/cni/net.d
name: cni-net-dir
# This container runs flannel using the kube-subnet-mgr backend
# for allocating subnets.
- name: kube-flannel
image: quay.io/coreos/flannel:v0.7.0
command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ]
securityContext:
privileged: true
resources:
requests:
cpu: 10m
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: FLANNELD_IFACE
valueFrom:
configMapKeyRef:
name: canal-config
key: canal_iface
- name: FLANNELD_IP_MASQ
valueFrom:
configMapKeyRef:
name: canal-config
key: masquerade
volumeMounts:
- name: run
mountPath: /run
- name: flannel-cfg
mountPath: /etc/kube-flannel/
volumes:
# Used by calico/node.
- name: lib-modules
hostPath:
path: /lib/modules
- name: var-run-calico
hostPath:
path: /var/run/calico
# Used to install CNI.
- name: cni-bin-dir
hostPath:
path: /opt/cni/bin
- name: cni-net-dir
hostPath:
path: /etc/cni/net.d
# Used by flannel.
- name: run
hostPath:
path: /run
- name: flannel-cfg
configMap:
name: canal-config

View File

@ -61,6 +61,7 @@ metadata:
namespace: kube-system
labels:
k8s-app: canal
role.kubernetes.io/networking: "1"
spec:
selector:
matchLabels:

View File

@ -0,0 +1,327 @@
# This ConfigMap is used to configure a self-hosted Calico installation.
kind: ConfigMap
apiVersion: v1
metadata:
name: calico-config
namespace: kube-system
data:
# The calico-etcd PetSet service IP:port
etcd_endpoints: "{{ $cluster := index .EtcdClusters 0 -}}
{{- range $j, $member := $cluster.Members -}}
{{- if $j }},{{ end -}}
http://etcd-{{ $member.Name }}.internal.{{ ClusterName }}:4001
{{- end }}"
# True enables BGP networking, false tells Calico to enforce
# policy only, using native networking.
enable_bgp: "true"
# The CNI network configuration to install on each node.
cni_network_config: |-
{
"name": "k8s-pod-network",
"type": "calico",
"etcd_endpoints": "__ETCD_ENDPOINTS__",
"log_level": "info",
"ipam": {
"type": "calico-ipam"
},
"policy": {
"type": "k8s",
"k8s_api_root": "https://__KUBERNETES_SERVICE_HOST__:__KUBERNETES_SERVICE_PORT__",
"k8s_auth_token": "__SERVICEACCOUNT_TOKEN__"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/__KUBECONFIG_FILENAME__"
}
}
# The default IP Pool to be created for the cluster.
# Pod IP addresses will be assigned from this pool.
ippool.yaml: |
apiVersion: v1
kind: ipPool
metadata:
cidr: {{ .NonMasqueradeCIDR }}
spec:
ipip:
enabled: true
nat-outgoing: true
---
# This manifest installs the calico/node container, as well
# as the Calico CNI plugins and network config on
# each master and worker node in a Kubernetes cluster.
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: calico-node
namespace: kube-system
labels:
k8s-app: calico-node
role.kubernetes.io/networking: "1"
spec:
selector:
matchLabels:
k8s-app: calico-node
template:
metadata:
labels:
k8s-app: calico-node
role.kubernetes.io/networking: "1"
spec:
hostNetwork: true
serviceAccountName: calico
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: CriticalAddonsOnly
operator: Exists
containers:
# Runs calico/node container on each Kubernetes node. This
# container programs network policy and routes on each
# host.
- name: calico-node
image: calico/node:v1.1.1
resources:
requests:
cpu: 10m
env:
# The location of the Calico etcd cluster.
- name: ETCD_ENDPOINTS
valueFrom:
configMapKeyRef:
name: calico-config
key: etcd_endpoints
# Enable BGP. Disable to enforce policy only.
- name: CALICO_NETWORKING
valueFrom:
configMapKeyRef:
name: calico-config
key: enable_bgp
# Disable file logging so `kubectl logs` works.
- name: CALICO_DISABLE_FILE_LOGGING
value: "true"
# Don't configure a default pool. This is done by the Job
# below.
- name: NO_DEFAULT_POOLS
value: "true"
# Auto-detect the BGP IP address.
- name: IP
value: ""
securityContext:
privileged: true
volumeMounts:
- mountPath: /lib/modules
name: lib-modules
readOnly: true
- mountPath: /var/run/calico
name: var-run-calico
readOnly: false
# This container installs the Calico CNI binaries
# and CNI network config file on each node.
- name: install-cni
image: calico/cni:v1.6.1
resources:
requests:
cpu: 10m
imagePullPolicy: Always
command: ["/install-cni.sh"]
env:
# The location of the Calico etcd cluster.
- name: ETCD_ENDPOINTS
valueFrom:
configMapKeyRef:
name: calico-config
key: etcd_endpoints
# The CNI network config to install on each node.
- name: CNI_NETWORK_CONFIG
valueFrom:
configMapKeyRef:
name: calico-config
key: cni_network_config
volumeMounts:
- mountPath: /host/opt/cni/bin
name: cni-bin-dir
- mountPath: /host/etc/cni/net.d
name: cni-net-dir
volumes:
# Used by calico/node.
- name: lib-modules
hostPath:
path: /lib/modules
- name: var-run-calico
hostPath:
path: /var/run/calico
# Used to install CNI.
- name: cni-bin-dir
hostPath:
path: /opt/cni/bin
- name: cni-net-dir
hostPath:
path: /etc/cni/net.d
---
# This manifest deploys the Calico policy controller on Kubernetes.
# See https://github.com/projectcalico/k8s-policy
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: calico-policy-controller
namespace: kube-system
labels:
k8s-app: calico-policy
role.kubernetes.io/networking: "1"
spec:
# The policy controller can only have a single active instance.
replicas: 1
template:
metadata:
name: calico-policy-controller
namespace: kube-system
labels:
k8s-app: calico-policy-controller
role.kubernetes.io/networking: "1"
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
spec:
# The policy controller must run in the host network namespace so that
# it isn't governed by policy that would prevent it from working.
hostNetwork: true
serviceAccountName: calico
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: CriticalAddonsOnly
operator: Exists
containers:
- name: calico-policy-controller
image: calico/kube-policy-controller:v0.5.4
resources:
requests:
cpu: 10m
env:
# The location of the Calico etcd cluster.
- name: ETCD_ENDPOINTS
valueFrom:
configMapKeyRef:
name: calico-config
key: etcd_endpoints
# The location of the Kubernetes API. Use the default Kubernetes
# service for API access.
- name: K8S_API
value: "https://kubernetes.default:443"
# Since we're running in the host namespace and might not have KubeDNS
# access, configure the container's /etc/hosts to resolve
# kubernetes.default to the correct service clusterIP.
- name: CONFIGURE_ETC_HOSTS
value: "true"
---
## This manifest deploys a Job which performs one time
# configuration of Calico
apiVersion: batch/v1
kind: Job
metadata:
name: configure-calico
namespace: kube-system
labels:
k8s-app: calico
role.kubernetes.io/networking: "1"
spec:
template:
metadata:
name: configure-calico
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
spec:
hostNetwork: true
serviceAccountName: calico
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: CriticalAddonsOnly
operator: Exists
restartPolicy: OnFailure
containers:
# Writes basic configuration to datastore.
- name: configure-calico
image: calico/ctl:v1.1.1
args:
- apply
- -f
- /etc/config/calico/ippool.yaml
volumeMounts:
- name: config-volume
mountPath: /etc/config
env:
# The location of the etcd cluster.
- name: ETCD_ENDPOINTS
valueFrom:
configMapKeyRef:
name: calico-config
key: etcd_endpoints
volumes:
- name: config-volume
configMap:
name: calico-config
items:
- key: ippool.yaml
path: calico/ippool.yaml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: calico
labels:
role.kubernetes.io/networking: "1"
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- networkpolicies
verbs:
- get
- list
- watch
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: calico
namespace: kube-system
labels:
role.kubernetes.io/networking: "1"
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: calico
labels:
role.kubernetes.io/networking: "1"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: calico
subjects:
- kind: ServiceAccount
name: calico
namespace: kube-system

View File

@ -77,7 +77,7 @@ spec:
# container programs network policy and routes on each
# host.
- name: calico-node
image: calico/node:v1.0.2
image: calico/node:v1.1.1
resources:
requests:
cpu: 10m
@ -116,7 +116,7 @@ spec:
# This container installs the Calico CNI binaries
# and CNI network config file on each node.
- name: install-cni
image: calico/cni:v1.5.6
image: calico/cni:v1.6.1
resources:
requests:
cpu: 10m
@ -189,7 +189,7 @@ spec:
hostNetwork: true
containers:
- name: calico-policy-controller
image: calico/kube-policy-controller:v0.5.2
image: calico/kube-policy-controller:v0.5.4
resources:
requests:
cpu: 10m
@ -237,7 +237,7 @@ spec:
containers:
# Writes basic configuration to datastore.
- name: configure-calico
image: calico/ctl:v1.0.2
image: calico/ctl:v1.1.1
args:
- apply
- -f
@ -258,4 +258,4 @@ spec:
name: calico-config
items:
- key: ippool.yaml
path: calico/ippool.yaml
path: calico/ippool.yaml

View File

@ -2,6 +2,8 @@ kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: weave-net
labels:
role.kubernetes.io/networking: "1"
rules:
- apiGroups:
- ""
@ -27,11 +29,15 @@ kind: ServiceAccount
metadata:
name: weave-net
namespace: kube-system
labels:
role.kubernetes.io/networking: "1"
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: weave-net
labels:
role.kubernetes.io/networking: "1"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
@ -46,11 +52,15 @@ kind: DaemonSet
metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
role.kubernetes.io/networking: "1"
spec:
template:
metadata:
labels:
name: weave-net
role.kubernetes.io/networking: "1"
spec:
hostNetwork: true
hostPID: true
@ -82,12 +92,20 @@ spec:
mountPath: /lib/modules
resources:
requests:
cpu: 10m
cpu: 100m
memory: 200Mi
limits:
cpu: 100m
memory: 200Mi
- name: weave-npc
image: weaveworks/weave-npc:1.9.4
resources:
requests:
cpu: 10m
cpu: 100m
memory: 200Mi
limits:
cpu: 100m
memory: 200Mi
securityContext:
privileged: true
restartPolicy: Always

View File

@ -4,6 +4,7 @@ metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
role.kubernetes.io/networking: "1"
spec:
template:
@ -26,7 +27,7 @@ spec:
hostPID: true
containers:
- name: weave
image: weaveworks/weave-kube:1.9.2
image: weaveworks/weave-kube:1.9.4
command:
- /home/weave/launch.sh
livenessProbe:
@ -58,7 +59,7 @@ spec:
cpu: 100m
memory: 200Mi
- name: weave-npc
image: weaveworks/weave-npc:1.9.2
image: weaveworks/weave-npc:1.9.4
resources:
requests:
cpu: 100m

View File

@ -1,84 +0,0 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
namespace: kube-system
labels:
role.kubernetes.io/networking: "1"
spec:
template:
metadata:
labels:
name: weave-net
role.kubernetes.io/networking: "1"
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "dedicated",
"operator": "Equal",
"value": "master",
"effect": "NoSchedule"
}
]
spec:
hostNetwork: true
hostPID: true
containers:
- name: weave
image: weaveworks/weave-kube:1.9.0
command:
- /home/weave/launch.sh
livenessProbe:
initialDelaySeconds: 30
httpGet:
host: 127.0.0.1
path: /status
port: 6784
securityContext:
privileged: true
volumeMounts:
- name: weavedb
mountPath: /weavedb
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: dbus
mountPath: /host/var/lib/dbus
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 100m
memory: 200Mi
- name: weave-npc
image: weaveworks/weave-npc:1.9.0
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 100m
memory: 200Mi
securityContext:
privileged: true
restartPolicy: Always
volumes:
- name: weavedb
emptyDir: {}
- name: cni-bin
hostPath:
path: /opt
- name: cni-bin2
hostPath:
path: /home
- name: cni-conf
hostPath:
path: /etc
- name: dbus
hostPath:
path: /var/lib/dbus

View File

@ -1,89 +0,0 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
namespace: kube-system
labels:
role.kubernetes.io/networking: "1"
spec:
template:
metadata:
labels:
name: weave-net
role.kubernetes.io/networking: "1"
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "dedicated",
"operator": "Equal",
"value": "master",
"effect": "NoSchedule"
}
]
spec:
hostNetwork: true
hostPID: true
containers:
- name: weave
image: weaveworks/weave-kube:1.9.3
command:
- /home/weave/launch.sh
livenessProbe:
initialDelaySeconds: 30
httpGet:
host: 127.0.0.1
path: /status
port: 6784
securityContext:
privileged: true
volumeMounts:
- name: weavedb
mountPath: /weavedb
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: dbus
mountPath: /host/var/lib/dbus
- name: lib-modules
mountPath: /lib/modules
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 100m
memory: 200Mi
- name: weave-npc
image: weaveworks/weave-npc:1.9.3
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 100m
memory: 200Mi
securityContext:
privileged: true
restartPolicy: Always
volumes:
- name: weavedb
emptyDir: {}
- name: cni-bin
hostPath:
path: /opt
- name: cni-bin2
hostPath:
path: /home
- name: cni-conf
hostPath:
path: /etc
- name: dbus
hostPath:
path: /var/lib/dbus
- name: lib-modules
hostPath:
path: /lib/modules

View File

@ -132,7 +132,7 @@ func (e *DNSZone) findExisting(cloud awsup.AWSCloud) (*route53.GetHostedZoneOutp
var zones []*route53.HostedZone
for _, zone := range response.HostedZones {
if aws.StringValue(zone.Name) == findName {
if aws.StringValue(zone.Name) == findName && fi.BoolValue(zone.Config.PrivateZone) == fi.BoolValue(e.Private) {
zones = append(zones, zone)
}
}
@ -219,10 +219,9 @@ func (_ *DNSZone) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *DNSZone) error
return nil
}
type terraformRoute53Zone struct {
Name *string `json:"name"`
VPCID *terraform.Literal `json:"vpc_id,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
type terraformRoute53ZoneAssociation struct {
ZoneID *terraform.Literal `json:"zone_id"`
VPCID *terraform.Literal `json:"vpc_id"`
Lifecycle *terraform.Lifecycle `json:"lifecycle,omitempty"`
}
@ -244,34 +243,45 @@ func (_ *DNSZone) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *D
glog.Infof("Existing zone %q found; will configure TF to reuse", aws.StringValue(z.HostedZone.Name))
e.ZoneID = z.HostedZone.Id
}
if z == nil {
// Because we expect most users to create their zones externally,
// we now block hostedzone creation in terraform.
// This lets us perform deeper DNS validation, but also solves the problem
// that otherwise we don't know if TF created the hosted zone
// (in which case we should output it) or whether it already existed (in which case we should not)
// The root problem here is that TF doesn't have a strong notion of an unmanaged resource
return fmt.Errorf("Creation of Route53 hosted zones is not supported for terraform")
//tf := &terraformRoute53Zone{
// Name: e.Name,
// //Tags: cloud.BuildTags(e.Name, nil),
//}
//
//tf.Lifecycle = &terraform.Lifecycle{
// PreventDestroy: fi.Bool(true),
//}
//
//return t.RenderResource("aws_route53_zone", *e.Name, tf)
} else {
// Same problem here also...
// If the user specifies dns=private we'll have a non-nil PrivateVPC that specifies the VPC
// that should used with the private Route53 zone. If the zone doesn't already know about the
// VPC, we add that association.
if e.PrivateVPC != nil {
return fmt.Errorf("Route53 private hosted zones are not supported for terraform")
assocNeeded := true
var vpcName string
if e.PrivateVPC.ID != nil {
vpcName = *e.PrivateVPC.ID
for _, vpc := range z.VPCs {
if *vpc.VPCId == vpcName {
glog.Infof("VPC %q already associated with zone %q", vpcName, aws.StringValue(z.HostedZone.Name))
assocNeeded = false
}
}
} else {
vpcName = *e.PrivateVPC.Name
}
if assocNeeded {
glog.Infof("No association between VPC %q and zone %q; adding", vpcName, aws.StringValue(z.HostedZone.Name))
tf := &terraformRoute53ZoneAssociation{
ZoneID: terraform.LiteralFromStringValue(*e.ZoneID),
VPCID: e.PrivateVPC.TerraformLink(),
}
return t.RenderResource("aws_route53_zone_association", *e.Name, tf)
}
}
return nil
}
// Because we expect most users to create their zones externally,
// we now block hostedzone creation in terraform.
// This lets us perform deeper DNS validation, but also solves the problem
// that otherwise we don't know if TF created the hosted zone
// (in which case we should output it) or whether it already existed (in which case we should not)
// The root problem here is that TF doesn't have a strong notion of an unmanaged resource
return fmt.Errorf("Creation of Route53 hosted zones is not supported for terraform")
}
func (e *DNSZone) TerraformLink() *terraform.Literal {

View File

@ -83,6 +83,9 @@ func (e *LaunchConfiguration) Find(c *fi.Context) (*LaunchConfiguration, error)
}
return true
})
if err != nil {
return nil, fmt.Errorf("error listing AutoscalingLaunchConfigurations: %v", err)
}
if len(configurations) == 0 {
return nil, nil
@ -111,6 +114,7 @@ func (e *LaunchConfiguration) Find(c *fi.Context) (*LaunchConfiguration, error)
AssociatePublicIP: lc.AssociatePublicIpAddress,
IAMInstanceProfile: &IAMInstanceProfile{Name: lc.IamInstanceProfile},
SpotPrice: aws.StringValue(lc.SpotPrice),
Tenancy: lc.PlacementTenancy,
}
securityGroups := []*SecurityGroup{}
@ -339,6 +343,7 @@ type terraformLaunchConfiguration struct {
EphemeralBlockDevice []*terraformBlockDevice `json:"ephemeral_block_device,omitempty"`
Lifecycle *terraform.Lifecycle `json:"lifecycle,omitempty"`
SpotPrice *string `json:"spot_price,omitempty"`
PlacementTenancy *string `json:"placement_tenancy,omitempty"`
}
type terraformBlockDevice struct {
@ -377,6 +382,10 @@ func (_ *LaunchConfiguration) RenderTerraform(t *terraform.TerraformTarget, a, e
tf.KeyName = e.SSHKey.TerraformLink()
}
if e.Tenancy != nil {
tf.PlacementTenancy = e.Tenancy
}
for _, sg := range e.SecurityGroups {
tf.SecurityGroups = append(tf.SecurityGroups, sg.TerraformLink())
}
@ -450,6 +459,7 @@ type cloudformationLaunchConfiguration struct {
SecurityGroups []*cloudformation.Literal `json:"SecurityGroups,omitempty"`
SpotPrice *string `json:"SpotPrice,omitempty"`
UserData *string `json:"UserData,omitempty"`
PlacementTenancy *string `json:"PlacementTenancy,omitempty"`
//NamePrefix *string `json:"name_prefix,omitempty"`
//Lifecycle *cloudformation.Lifecycle `json:"lifecycle,omitempty"`
@ -498,6 +508,10 @@ func (_ *LaunchConfiguration) RenderCloudformation(t *cloudformation.Cloudformat
cf.KeyName = e.SSHKey.Name
}
if e.Tenancy != nil {
cf.PlacementTenancy = e.Tenancy
}
for _, sg := range e.SecurityGroups {
cf.SecurityGroups = append(cf.SecurityGroups, sg.CloudformationLink())
}

View File

@ -21,7 +21,6 @@ import (
channelsapi "k8s.io/kops/channels/pkg/api"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/fitasks"
"k8s.io/kops/upup/pkg/fi/utils"
@ -73,11 +72,6 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri
addons.Kind = "Addons"
addons.ObjectMeta.Name = "bootstrap"
kv, err := util.ParseKubernetesVersion(b.cluster.Spec.KubernetesVersion)
if err != nil {
return nil, nil, fmt.Errorf("unable to determine kubernetes version from %q", b.cluster.Spec.KubernetesVersion)
}
{
key := "core.addons.k8s.io"
version := "1.4.0"
@ -95,25 +89,37 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri
{
key := "kube-dns.addons.k8s.io"
version := "1.6.1-alpha.2"
var version string
var location string
switch {
case kv.Major == 1 && kv.Minor <= 5:
version = "1.5.1"
location = key + "/k8s-1.5.yaml"
default:
version = "1.6.0"
location = key + "/k8s-1.6.yaml"
{
location := key + "/pre-k8s-1.6.yaml"
id := "pre-k8s-1.6"
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"k8s-addon": key},
Manifest: fi.String(location),
KubernetesVersion: "<1.6.0",
Id: id,
})
manifests[key+"-"+id] = "addons/" + location
}
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"k8s-addon": key},
Manifest: fi.String(location),
})
manifests[key] = "addons/" + location
{
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: map[string]string{"k8s-addon": key},
Manifest: fi.String(location),
KubernetesVersion: ">=1.6.0",
Id: id,
})
manifests[key+"-"+id] = "addons/" + location
}
}
{
@ -133,27 +139,37 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri
{
key := "dns-controller.addons.k8s.io"
version := "1.6.1-alpha.2"
var version string
var location string
switch {
case kv.Major == 1 && kv.Minor <= 5:
// This is awkward... we would like to do version 1.6.0,
// but if we do then we won't get the new manifest when we upgrade to 1.6.0
version = "1.5.3"
location = key + "/k8s-1.5.yaml"
default:
version = "1.6.0"
location = key + "/k8s-1.6.yaml"
{
location := key + "/pre-k8s-1.6.yaml"
id := "pre-k8s-1.6"
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"k8s-addon": key},
Manifest: fi.String(location),
KubernetesVersion: "<1.6.0",
Id: id,
})
manifests[key+"-"+id] = "addons/" + location
}
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"k8s-addon": key},
Manifest: fi.String(location),
})
manifests[key] = "addons/" + location
{
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: map[string]string{"k8s-addon": key},
Manifest: fi.String(location),
KubernetesVersion: ">=1.6.0",
Id: id,
})
manifests[key+"-"+id] = "addons/" + location
}
}
{
@ -184,95 +200,183 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri
// TODO: Create "empty" configurations for others, so we can delete e.g. the kopeio configuration
// if we switch to kubenet?
// TODO: Create configuration object for cni providers (maybe create it but orphan it)?
networkingSelector := map[string]string{"role.kubernetes.io/networking": "1"}
if b.cluster.Spec.Networking.Kopeio != nil {
key := "networking.kope.io"
version := "1.0.20161116"
version := "1.0.20170406"
// TODO: Create configuration object for cni providers (maybe create it but orphan it)?
location := key + "/v" + version + ".yaml"
{
location := key + "/pre-k8s-1.6.yaml"
id := "pre-k8s-1.6"
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"role.kubernetes.io/networking": "1"},
Manifest: fi.String(location),
})
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
}
manifests[key] = "addons/" + location
{
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
}
}
if b.cluster.Spec.Networking.Weave != nil {
key := "networking.weave"
var version string
switch {
case kv.Major == 1 && kv.Minor <= 5:
version = "1.9.3"
default:
version = "1.9.4"
version := "1.9.4"
{
location := key + "/pre-k8s-1.6.yaml"
id := "pre-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
}
// TODO: Create configuration object for cni providers (maybe create it but orphan it)?
location := key + "/v" + version + ".yaml"
{
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: map[string]string{"role.kubernetes.io/networking": "1"},
Manifest: fi.String(location),
})
manifests[key] = "addons/" + location
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
}
}
if b.cluster.Spec.Networking.Flannel != nil {
key := "networking.flannel"
version := "0.7.0"
// TODO: Create configuration object for cni providers (maybe create it but orphan it)?
location := key + "/v" + version + ".yaml"
{
location := key + "/pre-k8s-1.6.yaml"
id := "pre-k8s-1.6"
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"role.kubernetes.io/networking": "1"},
Manifest: fi.String(location),
})
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
}
manifests[key] = "addons/" + location
{
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
}
}
if b.cluster.Spec.Networking.Calico != nil {
key := "networking.projectcalico.org"
version := "2.0.2"
version := "2.1.1"
// TODO: Create configuration object for cni providers (maybe create it but orphan it)?
location := key + "/v" + version + ".yaml"
{
location := key + "/pre-k8s-1.6.yaml"
id := "pre-k8s-1.6"
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"role.kubernetes.io/networking": "1"},
Manifest: fi.String(location),
})
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
}
manifests[key] = "addons/" + location
{
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
}
}
if b.cluster.Spec.Networking.Canal != nil {
key := "networking.projectcalico.org.canal"
version := "1.0"
// TODO: Create configuration object for cni providers (maybe create it but orphan it)?
location := key + "/v" + version + ".yaml"
{
location := key + "/pre-k8s-1.6.yaml"
id := "pre-k8s-1.6"
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: map[string]string{"role.kubernetes.io/networking": "1"},
Manifest: fi.String(location),
})
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
}
manifests[key] = "addons/" + location
{
location := key + "/k8s-1.6.yaml"
id := "k8s-1.6"
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
Name: fi.String(key),
Version: fi.String(version),
Selector: networkingSelector,
Manifest: fi.String(location),
KubernetesVersion: ">=1.6.0",
Id: id,
})
manifests[key+"-"+id] = "addons/" + location
}
}
return addons, manifests, nil

View File

@ -50,7 +50,7 @@ func usesCNI(c *api.Cluster) bool {
}
if networkConfig.Flannel != nil {
// Weave uses CNI
// Flannel uses CNI
return true
}

View File

@ -43,9 +43,10 @@ const (
var masterMachineTypeExceptions = map[string]string{
// Some regions do not (currently) support the m3 family; the c4 large is the cheapest non-burstable instance
"us-east-2": "c4.large",
"ca-central-1": "c4.large",
"eu-west-2": "c4.large",
"us-east-2": "c4.large",
"ca-central-1": "c4.large",
"eu-west-2": "c4.large",
"ap-northeast-2": "c4.large",
}
var awsDedicatedInstanceExceptions = map[string]bool{

View File

@ -9,28 +9,55 @@ spec:
selector:
k8s-addon: core.addons.k8s.io
version: 1.4.0
- manifest: kube-dns.addons.k8s.io/k8s-1.5.yaml
- id: pre-k8s-1.6
kubernetesVersion: <1.6.0
manifest: kube-dns.addons.k8s.io/pre-k8s-1.6.yaml
name: kube-dns.addons.k8s.io
selector:
k8s-addon: kube-dns.addons.k8s.io
version: 1.5.1
version: 1.6.1-alpha.2
- id: k8s-1.6
kubernetesVersion: '>=1.6.0'
manifest: kube-dns.addons.k8s.io/k8s-1.6.yaml
name: kube-dns.addons.k8s.io
selector:
k8s-addon: kube-dns.addons.k8s.io
version: 1.6.1-alpha.2
- manifest: limit-range.addons.k8s.io/v1.5.0.yaml
name: limit-range.addons.k8s.io
selector:
k8s-addon: limit-range.addons.k8s.io
version: 1.5.0
- manifest: dns-controller.addons.k8s.io/k8s-1.5.yaml
- id: pre-k8s-1.6
kubernetesVersion: <1.6.0
manifest: dns-controller.addons.k8s.io/pre-k8s-1.6.yaml
name: dns-controller.addons.k8s.io
selector:
k8s-addon: dns-controller.addons.k8s.io
version: 1.5.3
version: 1.6.1-alpha.2
- id: k8s-1.6
kubernetesVersion: '>=1.6.0'
manifest: dns-controller.addons.k8s.io/k8s-1.6.yaml
name: dns-controller.addons.k8s.io
selector:
k8s-addon: dns-controller.addons.k8s.io
version: 1.6.1-alpha.2
- manifest: storage-aws.addons.k8s.io/v1.6.0.yaml
name: storage-aws.addons.k8s.io
selector:
k8s-addon: storage-aws.addons.k8s.io
version: 1.6.0
- manifest: networking.kope.io/v1.0.20161116.yaml
- id: pre-k8s-1.6
kubernetesVersion: <1.6.0
manifest: networking.kope.io/pre-k8s-1.6.yaml
name: networking.kope.io
selector:
role.kubernetes.io/networking: "1"
version: 1.0.20161116
version: 1.0.20170406
- id: k8s-1.6
kubernetesVersion: '>=1.6.0'
manifest: networking.kope.io/k8s-1.6.yaml
name: networking.kope.io
selector:
role.kubernetes.io/networking: "1"
version: 1.0.20170406

View File

@ -9,21 +9,39 @@ spec:
selector:
k8s-addon: core.addons.k8s.io
version: 1.4.0
- manifest: kube-dns.addons.k8s.io/k8s-1.5.yaml
- id: pre-k8s-1.6
kubernetesVersion: <1.6.0
manifest: kube-dns.addons.k8s.io/pre-k8s-1.6.yaml
name: kube-dns.addons.k8s.io
selector:
k8s-addon: kube-dns.addons.k8s.io
version: 1.5.1
version: 1.6.1-alpha.2
- id: k8s-1.6
kubernetesVersion: '>=1.6.0'
manifest: kube-dns.addons.k8s.io/k8s-1.6.yaml
name: kube-dns.addons.k8s.io
selector:
k8s-addon: kube-dns.addons.k8s.io
version: 1.6.1-alpha.2
- manifest: limit-range.addons.k8s.io/v1.5.0.yaml
name: limit-range.addons.k8s.io
selector:
k8s-addon: limit-range.addons.k8s.io
version: 1.5.0
- manifest: dns-controller.addons.k8s.io/k8s-1.5.yaml
- id: pre-k8s-1.6
kubernetesVersion: <1.6.0
manifest: dns-controller.addons.k8s.io/pre-k8s-1.6.yaml
name: dns-controller.addons.k8s.io
selector:
k8s-addon: dns-controller.addons.k8s.io
version: 1.5.3
version: 1.6.1-alpha.2
- id: k8s-1.6
kubernetesVersion: '>=1.6.0'
manifest: dns-controller.addons.k8s.io/k8s-1.6.yaml
name: dns-controller.addons.k8s.io
selector:
k8s-addon: dns-controller.addons.k8s.io
version: 1.6.1-alpha.2
- manifest: storage-aws.addons.k8s.io/v1.6.0.yaml
name: storage-aws.addons.k8s.io
selector:

View File

@ -37,7 +37,6 @@ import (
"k8s.io/kops/upup/pkg/fi/nodeup/cloudinit"
"k8s.io/kops/upup/pkg/fi/nodeup/local"
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
"k8s.io/kops/upup/pkg/fi/nodeup/tags"
"k8s.io/kops/upup/pkg/fi/utils"
"k8s.io/kops/util/pkg/vfs"
)
@ -208,7 +207,6 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
Architecture: model.ArchitectureAmd64,
InstanceGroup: c.instanceGroup,
IsMaster: nodeTags.Has(TagMaster),
UsesCNI: nodeTags.Has(tags.TagCNI),
Assets: assets,
KeyStore: tf.keyStore,
SecretStore: tf.secretStore,

Some files were not shown because too many files have changed in this diff Show More