mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-01 15:58:37 +00:00
Merge branch 'master' into correct-deprecation-errors
This commit is contained in:
commit
213f3c7e6e
@ -66,7 +66,7 @@
|
|||||||
- [Downloads for v1.6.0](#downloads-for-v160)
|
- [Downloads for v1.6.0](#downloads-for-v160)
|
||||||
- [Client Binaries](#client-binaries-9)
|
- [Client Binaries](#client-binaries-9)
|
||||||
- [Server Binaries](#server-binaries-9)
|
- [Server Binaries](#server-binaries-9)
|
||||||
- [WARNING: etcd backup strongly recommended](#warning:-etcd-backup-strongly-recommended)
|
- [WARNING: etcd backup strongly recommended](#warning-etcd-backup-strongly-recommended)
|
||||||
- [Major updates and release themes](#major-updates-and-release-themes)
|
- [Major updates and release themes](#major-updates-and-release-themes)
|
||||||
- [Action Required](#action-required-3)
|
- [Action Required](#action-required-3)
|
||||||
- [Certificates API](#certificates-api)
|
- [Certificates API](#certificates-api)
|
||||||
@ -393,8 +393,8 @@
|
|||||||
- [Known Issues](#known-issues-1)
|
- [Known Issues](#known-issues-1)
|
||||||
- [Notable Changes to Existing Behavior](#notable-changes-to-existing-behavior-1)
|
- [Notable Changes to Existing Behavior](#notable-changes-to-existing-behavior-1)
|
||||||
- [Deployments](#deployments)
|
- [Deployments](#deployments)
|
||||||
- [kubectl rolling-update: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-rolling-update:-<-v140-client-vs->=v140-cluster)
|
- [kubectl rolling-update: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-rolling-update--v140-client-vs-v140-cluster)
|
||||||
- [kubectl delete: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-delete:-<-v140-client-vs->=v140-cluster)
|
- [kubectl delete: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-delete--v140-client-vs-v140-cluster)
|
||||||
- [DELETE operation in REST API](#delete-operation-in-rest-api)
|
- [DELETE operation in REST API](#delete-operation-in-rest-api)
|
||||||
- [Action Required Before Upgrading](#action-required-before-upgrading-1)
|
- [Action Required Before Upgrading](#action-required-before-upgrading-1)
|
||||||
- [optionally, remove the old secret](#optionally-remove-the-old-secret)
|
- [optionally, remove the old secret](#optionally-remove-the-old-secret)
|
||||||
|
38
cluster/addons/ip-masq-agent/ip-masq-agent.yaml
Normal file
38
cluster/addons/ip-masq-agent/ip-masq-agent.yaml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# https://github.com/kubernetes-incubator/ip-masq-agent/blob/v2.0.0/README.md
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: ip-masq-agent
|
||||||
|
namespace: kube-system
|
||||||
|
labels:
|
||||||
|
addonmanager.kubernetes.io/mode: Reconcile
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: ip-masq-agent
|
||||||
|
annotations:
|
||||||
|
scheduler.alpha.kubernetes.io/critical-pod: ''
|
||||||
|
scheduler.alpha.kubernetes.io/tolerations: |
|
||||||
|
[{"key": "dedicated", "value": "master", "effect": "NoSchedule" },
|
||||||
|
{"key":"CriticalAddonsOnly", "operator":"Exists"}]
|
||||||
|
spec:
|
||||||
|
hostNetwork: true
|
||||||
|
containers:
|
||||||
|
- name: ip-masq-agent
|
||||||
|
image: gcr.io/google-containers/ip-masq-agent-amd64:v2.0.0
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/config
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
# Note this ConfigMap must be created in the same namespace as the daemon pods - this spec uses kube-system
|
||||||
|
name: ip-masq-agent
|
||||||
|
optional: true
|
||||||
|
items:
|
||||||
|
# The daemon looks for its config in a YAML file at /etc/config/ip-masq-agent
|
||||||
|
- key: config
|
||||||
|
path: ip-masq-agent
|
@ -1424,6 +1424,9 @@ function start-kube-addons {
|
|||||||
if [[ "${ENABLE_DEFAULT_STORAGE_CLASS:-}" == "true" ]]; then
|
if [[ "${ENABLE_DEFAULT_STORAGE_CLASS:-}" == "true" ]]; then
|
||||||
setup-addon-manifests "addons" "storage-class/gce"
|
setup-addon-manifests "addons" "storage-class/gce"
|
||||||
fi
|
fi
|
||||||
|
if [[ "${NON_MASQUERADE_CIDR:-}" == "0.0.0.0/0" ]]; then
|
||||||
|
setup-addon-manifests "addons" "ip-masq-agent"
|
||||||
|
fi
|
||||||
|
|
||||||
# Place addon manager pod manifest.
|
# Place addon manager pod manifest.
|
||||||
cp "${src_dir}/kube-addon-manager.yaml" /etc/kubernetes/manifests
|
cp "${src_dir}/kube-addon-manager.yaml" /etc/kubernetes/manifests
|
||||||
|
@ -45,6 +45,9 @@ go_library(
|
|||||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||||
@ -67,9 +70,11 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/apis/componentconfig:go_default_library",
|
"//pkg/apis/componentconfig:go_default_library",
|
||||||
|
"//pkg/util:go_default_library",
|
||||||
"//pkg/util/iptables:go_default_library",
|
"//pkg/util/iptables:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,11 +25,15 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
"runtime"
|
"os"
|
||||||
|
goruntime "runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
@ -89,6 +93,8 @@ func checkKnownProxyMode(proxyMode string) bool {
|
|||||||
type Options struct {
|
type Options struct {
|
||||||
// ConfigFile is the location of the proxy server's configuration file.
|
// ConfigFile is the location of the proxy server's configuration file.
|
||||||
ConfigFile string
|
ConfigFile string
|
||||||
|
// WriteConfigTo is the path where the default configuration will be written.
|
||||||
|
WriteConfigTo string
|
||||||
// CleanupAndExit, when true, makes the proxy server clean up iptables rules, then exit.
|
// CleanupAndExit, when true, makes the proxy server clean up iptables rules, then exit.
|
||||||
CleanupAndExit bool
|
CleanupAndExit bool
|
||||||
|
|
||||||
@ -104,11 +110,15 @@ type Options struct {
|
|||||||
master string
|
master string
|
||||||
// healthzPort is the port to be used by the healthz server.
|
// healthzPort is the port to be used by the healthz server.
|
||||||
healthzPort int32
|
healthzPort int32
|
||||||
|
|
||||||
|
scheme *runtime.Scheme
|
||||||
|
codecs serializer.CodecFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFlags adds flags to fs and binds them to options.
|
// AddFlags adds flags to fs and binds them to options.
|
||||||
func AddFlags(options *Options, fs *pflag.FlagSet) {
|
func AddFlags(options *Options, fs *pflag.FlagSet) {
|
||||||
fs.StringVar(&options.ConfigFile, "config", options.ConfigFile, "The path to the configuration file.")
|
fs.StringVar(&options.ConfigFile, "config", options.ConfigFile, "The path to the configuration file.")
|
||||||
|
fs.StringVar(&options.WriteConfigTo, "write-config-to", options.WriteConfigTo, "If set, write the default configuration values to this file and exit.")
|
||||||
fs.BoolVar(&options.CleanupAndExit, "cleanup-iptables", options.CleanupAndExit, "If true cleanup iptables rules and exit.")
|
fs.BoolVar(&options.CleanupAndExit, "cleanup-iptables", options.CleanupAndExit, "If true cleanup iptables rules and exit.")
|
||||||
|
|
||||||
// All flags below here are deprecated and will eventually be removed.
|
// All flags below here are deprecated and will eventually be removed.
|
||||||
@ -151,17 +161,37 @@ func AddFlags(options *Options, fs *pflag.FlagSet) {
|
|||||||
utilfeature.DefaultFeatureGate.AddFlag(fs)
|
utilfeature.DefaultFeatureGate.AddFlag(fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewOptions() (*Options, error) {
|
||||||
|
o := &Options{
|
||||||
|
config: new(componentconfig.KubeProxyConfiguration),
|
||||||
|
healthzPort: 10256,
|
||||||
|
}
|
||||||
|
|
||||||
|
o.scheme = runtime.NewScheme()
|
||||||
|
o.codecs = serializer.NewCodecFactory(o.scheme)
|
||||||
|
|
||||||
|
if err := componentconfig.AddToScheme(o.scheme); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := v1alpha1.AddToScheme(o.scheme); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Complete completes all the required options.
|
// Complete completes all the required options.
|
||||||
func (o Options) Complete() error {
|
func (o *Options) Complete() error {
|
||||||
if len(o.ConfigFile) == 0 {
|
if len(o.ConfigFile) == 0 && len(o.WriteConfigTo) == 0 {
|
||||||
glog.Warning("WARNING: all flags other than --config and --cleanup-iptables are deprecated. Please begin using a config file ASAP.")
|
glog.Warning("WARNING: all flags other than --config, --write-config-to, and --cleanup-iptables are deprecated. Please begin using a config file ASAP.")
|
||||||
o.applyDeprecatedHealthzPortToConfig()
|
o.applyDeprecatedHealthzPortToConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates all the required options.
|
// Validate validates all the required options.
|
||||||
func (o Options) Validate(args []string) error {
|
func (o *Options) Validate(args []string) error {
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
return errors.New("no arguments are supported")
|
return errors.New("no arguments are supported")
|
||||||
}
|
}
|
||||||
@ -169,11 +199,15 @@ func (o Options) Validate(args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) Run() error {
|
func (o *Options) Run() error {
|
||||||
config := o.config
|
config := o.config
|
||||||
|
|
||||||
|
if len(o.WriteConfigTo) > 0 {
|
||||||
|
return o.writeConfigFile()
|
||||||
|
}
|
||||||
|
|
||||||
if len(o.ConfigFile) > 0 {
|
if len(o.ConfigFile) > 0 {
|
||||||
if c, err := loadConfigFromFile(o.ConfigFile); err != nil {
|
if c, err := o.loadConfigFromFile(o.ConfigFile); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
config = c
|
config = c
|
||||||
@ -182,7 +216,7 @@ func (o Options) Run() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyServer, err := NewProxyServer(config, o.CleanupAndExit, o.master)
|
proxyServer, err := NewProxyServer(config, o.CleanupAndExit, o.scheme, o.master)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -190,13 +224,43 @@ func (o Options) Run() error {
|
|||||||
return proxyServer.Run()
|
return proxyServer.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Options) writeConfigFile() error {
|
||||||
|
var encoder runtime.Encoder
|
||||||
|
mediaTypes := o.codecs.SupportedMediaTypes()
|
||||||
|
for _, info := range mediaTypes {
|
||||||
|
if info.MediaType == "application/yaml" {
|
||||||
|
encoder = info.Serializer
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if encoder == nil {
|
||||||
|
return errors.New("unable to locate yaml encoder")
|
||||||
|
}
|
||||||
|
encoder = json.NewYAMLSerializer(json.DefaultMetaFactory, o.scheme, o.scheme)
|
||||||
|
encoder = o.codecs.EncoderForVersion(encoder, v1alpha1.SchemeGroupVersion)
|
||||||
|
|
||||||
|
configFile, err := os.Create(o.WriteConfigTo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer configFile.Close()
|
||||||
|
|
||||||
|
if err := encoder.Encode(o.config, configFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Wrote configuration to: %s\n", o.WriteConfigTo)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// applyDeprecatedHealthzPortToConfig sets o.config.HealthzBindAddress from
|
// applyDeprecatedHealthzPortToConfig sets o.config.HealthzBindAddress from
|
||||||
// flags passed on the command line based on the following rules:
|
// flags passed on the command line based on the following rules:
|
||||||
//
|
//
|
||||||
// 1. If --healthz-port is 0, disable the healthz server.
|
// 1. If --healthz-port is 0, disable the healthz server.
|
||||||
// 2. Otherwise, use the value of --healthz-port for the port portion of
|
// 2. Otherwise, use the value of --healthz-port for the port portion of
|
||||||
// o.config.HealthzBindAddress
|
// o.config.HealthzBindAddress
|
||||||
func (o Options) applyDeprecatedHealthzPortToConfig() {
|
func (o *Options) applyDeprecatedHealthzPortToConfig() {
|
||||||
if o.healthzPort == 0 {
|
if o.healthzPort == 0 {
|
||||||
o.config.HealthzBindAddress = ""
|
o.config.HealthzBindAddress = ""
|
||||||
return
|
return
|
||||||
@ -212,13 +276,18 @@ func (o Options) applyDeprecatedHealthzPortToConfig() {
|
|||||||
|
|
||||||
// loadConfigFromFile loads the contents of file and decodes it as a
|
// loadConfigFromFile loads the contents of file and decodes it as a
|
||||||
// KubeProxyConfiguration object.
|
// KubeProxyConfiguration object.
|
||||||
func loadConfigFromFile(file string) (*componentconfig.KubeProxyConfiguration, error) {
|
func (o *Options) loadConfigFromFile(file string) (*componentconfig.KubeProxyConfiguration, error) {
|
||||||
data, err := ioutil.ReadFile(file)
|
data, err := ioutil.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
configObj, gvk, err := api.Codecs.UniversalDecoder().Decode(data, nil, nil)
|
return o.loadConfig(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadConfig decodes data as a KubeProxyConfiguration object.
|
||||||
|
func (o *Options) loadConfig(data []byte) (*componentconfig.KubeProxyConfiguration, error) {
|
||||||
|
configObj, gvk, err := o.codecs.UniversalDecoder().Decode(data, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -229,15 +298,15 @@ func loadConfigFromFile(file string) (*componentconfig.KubeProxyConfiguration, e
|
|||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyDefaults(in *componentconfig.KubeProxyConfiguration) (*componentconfig.KubeProxyConfiguration, error) {
|
func (o *Options) applyDefaults(in *componentconfig.KubeProxyConfiguration) (*componentconfig.KubeProxyConfiguration, error) {
|
||||||
external, err := api.Scheme.ConvertToVersion(in, v1alpha1.SchemeGroupVersion)
|
external, err := o.scheme.ConvertToVersion(in, v1alpha1.SchemeGroupVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
api.Scheme.Default(external)
|
o.scheme.Default(external)
|
||||||
|
|
||||||
internal, err := api.Scheme.ConvertToVersion(external, componentconfig.SchemeGroupVersion)
|
internal, err := o.scheme.ConvertToVersion(external, componentconfig.SchemeGroupVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -249,9 +318,9 @@ func applyDefaults(in *componentconfig.KubeProxyConfiguration) (*componentconfig
|
|||||||
|
|
||||||
// NewProxyCommand creates a *cobra.Command object with default parameters
|
// NewProxyCommand creates a *cobra.Command object with default parameters
|
||||||
func NewProxyCommand() *cobra.Command {
|
func NewProxyCommand() *cobra.Command {
|
||||||
opts := Options{
|
opts, err := NewOptions()
|
||||||
config: new(componentconfig.KubeProxyConfiguration),
|
if err != nil {
|
||||||
healthzPort: 10256,
|
glog.Fatalf("Unable to initialize command options: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -270,14 +339,13 @@ with the apiserver API to configure the proxy.`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
opts.config, err = opts.applyDefaults(opts.config)
|
||||||
opts.config, err = applyDefaults(opts.config)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("unable to create flag defaults: %v", err)
|
glog.Fatalf("unable to create flag defaults: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
AddFlags(&opts, flags)
|
AddFlags(opts, flags)
|
||||||
|
|
||||||
cmd.MarkFlagFilename("config", "yaml", "yml", "json")
|
cmd.MarkFlagFilename("config", "yaml", "yml", "json")
|
||||||
|
|
||||||
@ -344,7 +412,7 @@ func createClients(config componentconfig.ClientConnectionConfiguration, masterO
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewProxyServer returns a new ProxyServer.
|
// NewProxyServer returns a new ProxyServer.
|
||||||
func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndExit bool, master string) (*ProxyServer, error) {
|
func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndExit bool, scheme *runtime.Scheme, master string) (*ProxyServer, error) {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return nil, errors.New("config is required")
|
return nil, errors.New("config is required")
|
||||||
}
|
}
|
||||||
@ -367,7 +435,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx
|
|||||||
// Create a iptables utils.
|
// Create a iptables utils.
|
||||||
execer := exec.New()
|
execer := exec.New()
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if goruntime.GOOS == "windows" {
|
||||||
netshInterface = utilnetsh.New(execer)
|
netshInterface = utilnetsh.New(execer)
|
||||||
} else {
|
} else {
|
||||||
dbus = utildbus.New()
|
dbus = utildbus.New()
|
||||||
@ -387,7 +455,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx
|
|||||||
// Create event recorder
|
// Create event recorder
|
||||||
hostname := nodeutil.GetHostname(config.HostnameOverride)
|
hostname := nodeutil.GetHostname(config.HostnameOverride)
|
||||||
eventBroadcaster := record.NewBroadcaster()
|
eventBroadcaster := record.NewBroadcaster()
|
||||||
recorder := eventBroadcaster.NewRecorder(api.Scheme, clientv1.EventSource{Component: "kube-proxy", Host: hostname})
|
recorder := eventBroadcaster.NewRecorder(scheme, clientv1.EventSource{Component: "kube-proxy", Host: hostname})
|
||||||
|
|
||||||
var healthzServer *healthcheck.HealthzServer
|
var healthzServer *healthcheck.HealthzServer
|
||||||
if len(config.HealthzBindAddress) > 0 {
|
if len(config.HealthzBindAddress) > 0 {
|
||||||
@ -434,7 +502,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx
|
|||||||
userspace.CleanupLeftovers(iptInterface)
|
userspace.CleanupLeftovers(iptInterface)
|
||||||
} else {
|
} else {
|
||||||
glog.V(0).Info("Using userspace Proxier.")
|
glog.V(0).Info("Using userspace Proxier.")
|
||||||
if runtime.GOOS == "windows" {
|
if goruntime.GOOS == "windows" {
|
||||||
// This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for
|
// This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for
|
||||||
// our config.EndpointsConfigHandler.
|
// our config.EndpointsConfigHandler.
|
||||||
loadBalancer := winuserspace.NewLoadBalancerRR()
|
loadBalancer := winuserspace.NewLoadBalancerRR()
|
||||||
@ -479,7 +547,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx
|
|||||||
proxier = proxierUserspace
|
proxier = proxierUserspace
|
||||||
}
|
}
|
||||||
// Remove artifacts from the pure-iptables Proxier, if not on Windows.
|
// Remove artifacts from the pure-iptables Proxier, if not on Windows.
|
||||||
if runtime.GOOS != "windows" {
|
if goruntime.GOOS != "windows" {
|
||||||
glog.V(0).Info("Tearing down pure-iptables proxy rules.")
|
glog.V(0).Info("Tearing down pure-iptables proxy rules.")
|
||||||
// TODO this has side effects that should only happen when Run() is invoked.
|
// TODO this has side effects that should only happen when Run() is invoked.
|
||||||
iptables.CleanupLeftovers(iptInterface)
|
iptables.CleanupLeftovers(iptInterface)
|
||||||
@ -487,7 +555,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add iptables reload function, if not on Windows.
|
// Add iptables reload function, if not on Windows.
|
||||||
if runtime.GOOS != "windows" {
|
if goruntime.GOOS != "windows" {
|
||||||
iptInterface.AddReloadFunc(proxier.Sync)
|
iptInterface.AddReloadFunc(proxier.Sync)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,7 +648,7 @@ func (s *ProxyServer) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tune conntrack, if requested
|
// Tune conntrack, if requested
|
||||||
if s.Conntracker != nil && runtime.GOOS != "windows" {
|
if s.Conntracker != nil && goruntime.GOOS != "windows" {
|
||||||
max, err := getConntrackMax(s.ConntrackConfiguration)
|
max, err := getConntrackMax(s.ConntrackConfiguration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -654,7 +722,7 @@ func getConntrackMax(config componentconfig.KubeProxyConntrackConfiguration) (in
|
|||||||
}
|
}
|
||||||
if config.MaxPerCore > 0 {
|
if config.MaxPerCore > 0 {
|
||||||
floor := int(config.Min)
|
floor := int(config.Min)
|
||||||
scaled := int(config.MaxPerCore) * runtime.NumCPU()
|
scaled := int(config.MaxPerCore) * goruntime.NumCPU()
|
||||||
if scaled > floor {
|
if scaled > floor {
|
||||||
glog.V(3).Infof("getConntrackMax: using scaled conntrack-max-per-core")
|
glog.V(3).Infof("getConntrackMax: using scaled conntrack-max-per-core")
|
||||||
return scaled, nil
|
return scaled, nil
|
||||||
|
@ -18,15 +18,19 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/componentconfig"
|
"k8s.io/kubernetes/pkg/apis/componentconfig"
|
||||||
|
"k8s.io/kubernetes/pkg/util"
|
||||||
"k8s.io/kubernetes/pkg/util/iptables"
|
"k8s.io/kubernetes/pkg/util/iptables"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -132,14 +136,17 @@ func Test_getProxyMode(t *testing.T) {
|
|||||||
|
|
||||||
// This test verifies that Proxy Server does not crash when CleanupAndExit is true.
|
// This test verifies that Proxy Server does not crash when CleanupAndExit is true.
|
||||||
func TestProxyServerWithCleanupAndExit(t *testing.T) {
|
func TestProxyServerWithCleanupAndExit(t *testing.T) {
|
||||||
options := Options{
|
options, err := NewOptions()
|
||||||
config: &componentconfig.KubeProxyConfiguration{
|
if err != nil {
|
||||||
BindAddress: "0.0.0.0",
|
t.Fatal(err)
|
||||||
},
|
|
||||||
CleanupAndExit: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.master)
|
options.config = &componentconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "0.0.0.0",
|
||||||
|
}
|
||||||
|
options.CleanupAndExit = true
|
||||||
|
|
||||||
|
proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.scheme, options.master)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, proxyserver)
|
assert.NotNil(t, proxyserver)
|
||||||
@ -203,3 +210,82 @@ func TestGetConntrackMax(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadConfig(t *testing.T) {
|
||||||
|
yaml := `apiVersion: componentconfig/v1alpha1
|
||||||
|
bindAddress: 9.8.7.6
|
||||||
|
clientConnection:
|
||||||
|
acceptContentTypes: "abc"
|
||||||
|
burst: 100
|
||||||
|
contentType: content-type
|
||||||
|
kubeconfig: "/path/to/kubeconfig"
|
||||||
|
qps: 7
|
||||||
|
clusterCIDR: "1.2.3.0/24"
|
||||||
|
configSyncPeriod: 15s
|
||||||
|
conntrack:
|
||||||
|
max: 4
|
||||||
|
maxPerCore: 2
|
||||||
|
min: 1
|
||||||
|
tcpCloseWaitTimeout: 10s
|
||||||
|
tcpEstablishedTimeout: 20s
|
||||||
|
featureGates: "all"
|
||||||
|
healthzBindAddress: 1.2.3.4:12345
|
||||||
|
hostnameOverride: "foo"
|
||||||
|
iptables:
|
||||||
|
masqueradeAll: true
|
||||||
|
masqueradeBit: 17
|
||||||
|
minSyncPeriod: 10s
|
||||||
|
syncPeriod: 60s
|
||||||
|
kind: KubeProxyConfiguration
|
||||||
|
metricsBindAddress: 2.3.4.5:23456
|
||||||
|
mode: "iptables"
|
||||||
|
oomScoreAdj: 17
|
||||||
|
portRange: "2-7"
|
||||||
|
resourceContainer: /foo
|
||||||
|
udpTimeoutMilliseconds: 123ms
|
||||||
|
`
|
||||||
|
|
||||||
|
expected := &componentconfig.KubeProxyConfiguration{
|
||||||
|
BindAddress: "9.8.7.6",
|
||||||
|
ClientConnection: componentconfig.ClientConnectionConfiguration{
|
||||||
|
AcceptContentTypes: "abc",
|
||||||
|
Burst: 100,
|
||||||
|
ContentType: "content-type",
|
||||||
|
KubeConfigFile: "/path/to/kubeconfig",
|
||||||
|
QPS: 7,
|
||||||
|
},
|
||||||
|
ClusterCIDR: "1.2.3.0/24",
|
||||||
|
ConfigSyncPeriod: metav1.Duration{Duration: 15 * time.Second},
|
||||||
|
Conntrack: componentconfig.KubeProxyConntrackConfiguration{
|
||||||
|
Max: 4,
|
||||||
|
MaxPerCore: 2,
|
||||||
|
Min: 1,
|
||||||
|
TCPCloseWaitTimeout: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
TCPEstablishedTimeout: metav1.Duration{Duration: 20 * time.Second},
|
||||||
|
},
|
||||||
|
FeatureGates: "all",
|
||||||
|
HealthzBindAddress: "1.2.3.4:12345",
|
||||||
|
HostnameOverride: "foo",
|
||||||
|
IPTables: componentconfig.KubeProxyIPTablesConfiguration{
|
||||||
|
MasqueradeAll: true,
|
||||||
|
MasqueradeBit: util.Int32Ptr(17),
|
||||||
|
MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||||
|
SyncPeriod: metav1.Duration{Duration: 60 * time.Second},
|
||||||
|
},
|
||||||
|
MetricsBindAddress: "2.3.4.5:23456",
|
||||||
|
Mode: "iptables",
|
||||||
|
OOMScoreAdj: util.Int32Ptr(17),
|
||||||
|
PortRange: "2-7",
|
||||||
|
ResourceContainer: "/foo",
|
||||||
|
UDPIdleTimeout: metav1.Duration{Duration: 123 * time.Millisecond},
|
||||||
|
}
|
||||||
|
|
||||||
|
options, err := NewOptions()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
config, err := options.loadConfig([]byte(yaml))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if !reflect.DeepEqual(expected, config) {
|
||||||
|
t.Fatalf("unexpected config, diff = %s", diff.ObjectDiff(config, expected))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -716,6 +716,7 @@ watch-cache-sizes
|
|||||||
watch-only
|
watch-only
|
||||||
whitelist-override-label
|
whitelist-override-label
|
||||||
windows-line-endings
|
windows-line-endings
|
||||||
|
write-config-to
|
||||||
www-prefix
|
www-prefix
|
||||||
zone-id
|
zone-id
|
||||||
zone-name
|
zone-name
|
||||||
|
@ -605,7 +605,7 @@ type KubeletConfiguration struct {
|
|||||||
// This flag specifies the various Node Allocatable enforcements that Kubelet needs to perform.
|
// This flag specifies the various Node Allocatable enforcements that Kubelet needs to perform.
|
||||||
// This flag accepts a list of options. Acceptible options are `pods`, `system-reserved` & `kube-reserved`.
|
// This flag accepts a list of options. Acceptible options are `pods`, `system-reserved` & `kube-reserved`.
|
||||||
// Refer to [Node Allocatable](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) doc for more information.
|
// Refer to [Node Allocatable](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) doc for more information.
|
||||||
EnforceNodeAllocatable []string `json:"enforceNodeAllocatable,omitempty"`
|
EnforceNodeAllocatable []string `json:"enforceNodeAllocatable"`
|
||||||
// This flag, if set, will avoid including `EvictionHard` limits while computing Node Allocatable.
|
// This flag, if set, will avoid including `EvictionHard` limits while computing Node Allocatable.
|
||||||
// Refer to [Node Allocatable](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) doc for more information.
|
// Refer to [Node Allocatable](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) doc for more information.
|
||||||
ExperimentalNodeAllocatableIgnoreEvictionThreshold bool `json:"experimentalNodeAllocatableIgnoreEvictionThreshold,omitempty"`
|
ExperimentalNodeAllocatableIgnoreEvictionThreshold bool `json:"experimentalNodeAllocatableIgnoreEvictionThreshold,omitempty"`
|
||||||
|
@ -729,7 +729,11 @@ func autoConvert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfigu
|
|||||||
out.KubeReserved = *(*map[string]string)(unsafe.Pointer(&in.KubeReserved))
|
out.KubeReserved = *(*map[string]string)(unsafe.Pointer(&in.KubeReserved))
|
||||||
out.SystemReservedCgroup = in.SystemReservedCgroup
|
out.SystemReservedCgroup = in.SystemReservedCgroup
|
||||||
out.KubeReservedCgroup = in.KubeReservedCgroup
|
out.KubeReservedCgroup = in.KubeReservedCgroup
|
||||||
out.EnforceNodeAllocatable = *(*[]string)(unsafe.Pointer(&in.EnforceNodeAllocatable))
|
if in.EnforceNodeAllocatable == nil {
|
||||||
|
out.EnforceNodeAllocatable = make([]string, 0)
|
||||||
|
} else {
|
||||||
|
out.EnforceNodeAllocatable = *(*[]string)(unsafe.Pointer(&in.EnforceNodeAllocatable))
|
||||||
|
}
|
||||||
out.ExperimentalNodeAllocatableIgnoreEvictionThreshold = in.ExperimentalNodeAllocatableIgnoreEvictionThreshold
|
out.ExperimentalNodeAllocatableIgnoreEvictionThreshold = in.ExperimentalNodeAllocatableIgnoreEvictionThreshold
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
|
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/api/v1/resource"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/qos"
|
"k8s.io/kubernetes/pkg/kubelet/qos"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -84,28 +85,41 @@ func MilliCPUToShares(milliCPU int64) int64 {
|
|||||||
|
|
||||||
// ResourceConfigForPod takes the input pod and outputs the cgroup resource config.
|
// ResourceConfigForPod takes the input pod and outputs the cgroup resource config.
|
||||||
func ResourceConfigForPod(pod *v1.Pod) *ResourceConfig {
|
func ResourceConfigForPod(pod *v1.Pod) *ResourceConfig {
|
||||||
// sum requests and limits, track if limits were applied for each resource.
|
// sum requests and limits.
|
||||||
|
reqs, limits, err := resource.PodRequestsAndLimits(pod)
|
||||||
|
if err != nil {
|
||||||
|
return &ResourceConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
cpuRequests := int64(0)
|
cpuRequests := int64(0)
|
||||||
cpuLimits := int64(0)
|
cpuLimits := int64(0)
|
||||||
memoryLimits := int64(0)
|
memoryLimits := int64(0)
|
||||||
memoryLimitsDeclared := true
|
if request, found := reqs[v1.ResourceCPU]; found {
|
||||||
cpuLimitsDeclared := true
|
cpuRequests = request.MilliValue()
|
||||||
for _, container := range pod.Spec.Containers {
|
}
|
||||||
cpuRequests += container.Resources.Requests.Cpu().MilliValue()
|
if limit, found := limits[v1.ResourceCPU]; found {
|
||||||
cpuLimits += container.Resources.Limits.Cpu().MilliValue()
|
cpuLimits = limit.MilliValue()
|
||||||
if container.Resources.Limits.Cpu().IsZero() {
|
}
|
||||||
cpuLimitsDeclared = false
|
if limit, found := limits[v1.ResourceMemory]; found {
|
||||||
}
|
memoryLimits = limit.Value()
|
||||||
memoryLimits += container.Resources.Limits.Memory().Value()
|
|
||||||
if container.Resources.Limits.Memory().IsZero() {
|
|
||||||
memoryLimitsDeclared = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert to CFS values
|
// convert to CFS values
|
||||||
cpuShares := MilliCPUToShares(cpuRequests)
|
cpuShares := MilliCPUToShares(cpuRequests)
|
||||||
cpuQuota, cpuPeriod := MilliCPUToQuota(cpuLimits)
|
cpuQuota, cpuPeriod := MilliCPUToQuota(cpuLimits)
|
||||||
|
|
||||||
|
// track if limits were applied for each resource.
|
||||||
|
memoryLimitsDeclared := true
|
||||||
|
cpuLimitsDeclared := true
|
||||||
|
for _, container := range pod.Spec.Containers {
|
||||||
|
if container.Resources.Limits.Cpu().IsZero() {
|
||||||
|
cpuLimitsDeclared = false
|
||||||
|
}
|
||||||
|
if container.Resources.Limits.Memory().IsZero() {
|
||||||
|
memoryLimitsDeclared = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// determine the qos class
|
// determine the qos class
|
||||||
qosClass := qos.GetPodQOS(pod)
|
qosClass := qos.GetPodQOS(pod)
|
||||||
|
|
||||||
|
@ -818,8 +818,12 @@ func printISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, w PrefixWriter) {
|
|||||||
" Lun:\t%v\n"+
|
" Lun:\t%v\n"+
|
||||||
" ISCSIInterface\t%v\n"+
|
" ISCSIInterface\t%v\n"+
|
||||||
" FSType:\t%v\n"+
|
" FSType:\t%v\n"+
|
||||||
" ReadOnly:\t%v\n",
|
" ReadOnly:\t%v\n"+
|
||||||
iscsi.TargetPortal, iscsi.IQN, iscsi.Lun, iscsi.ISCSIInterface, iscsi.FSType, iscsi.ReadOnly)
|
" Portals:\t%v\n"+
|
||||||
|
" DiscoveryCHAPAuth:\t%v\n"+
|
||||||
|
" SessionCHAPAuth:\t%v\n"+
|
||||||
|
" SecretRef:\t%v\n",
|
||||||
|
iscsi.TargetPortal, iscsi.IQN, iscsi.Lun, iscsi.ISCSIInterface, iscsi.FSType, iscsi.ReadOnly, iscsi.Portals, iscsi.DiscoveryCHAPAuth, iscsi.SessionCHAPAuth, iscsi.SecretRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printGlusterfsVolumeSource(glusterfs *api.GlusterfsVolumeSource, w PrefixWriter) {
|
func printGlusterfsVolumeSource(glusterfs *api.GlusterfsVolumeSource, w PrefixWriter) {
|
||||||
|
@ -196,8 +196,19 @@ func (c *nodePlugin) admitPodStatus(nodeName string, a admission.Attributes) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *nodePlugin) admitNode(nodeName string, a admission.Attributes) error {
|
func (c *nodePlugin) admitNode(nodeName string, a admission.Attributes) error {
|
||||||
if a.GetName() != nodeName {
|
requestedName := a.GetName()
|
||||||
return admission.NewForbidden(a, fmt.Errorf("cannot modify other nodes"))
|
|
||||||
|
// On create, get name from new object if unset in admission
|
||||||
|
if len(requestedName) == 0 && a.GetOperation() == admission.Create {
|
||||||
|
node, ok := a.GetObject().(*api.Node)
|
||||||
|
if !ok {
|
||||||
|
return admission.NewForbidden(a, fmt.Errorf("unexpected type %T", a.GetObject()))
|
||||||
|
}
|
||||||
|
requestedName = node.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestedName != nodeName {
|
||||||
|
return admission.NewForbidden(a, fmt.Errorf("node %s cannot modify node %s", nodeName, requestedName))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -356,6 +356,12 @@ func Test_nodePlugin_Admit(t *testing.T) {
|
|||||||
attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, mynode),
|
attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, mynode),
|
||||||
err: "",
|
err: "",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "allow create of my node pulling name from object",
|
||||||
|
podsGetter: noExistingPods,
|
||||||
|
attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, mynode),
|
||||||
|
err: "",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "allow update of my node",
|
name: "allow update of my node",
|
||||||
podsGetter: existingPods,
|
podsGetter: existingPods,
|
||||||
@ -380,25 +386,31 @@ func Test_nodePlugin_Admit(t *testing.T) {
|
|||||||
name: "forbid create of other node",
|
name: "forbid create of other node",
|
||||||
podsGetter: noExistingPods,
|
podsGetter: noExistingPods,
|
||||||
attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Create, mynode),
|
attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Create, mynode),
|
||||||
err: "cannot modify other nodes",
|
err: "cannot modify node",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "forbid create of other node pulling name from object",
|
||||||
|
podsGetter: noExistingPods,
|
||||||
|
attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, "", nodeResource, "", admission.Create, mynode),
|
||||||
|
err: "cannot modify node",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "forbid update of other node",
|
name: "forbid update of other node",
|
||||||
podsGetter: existingPods,
|
podsGetter: existingPods,
|
||||||
attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Update, mynode),
|
attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Update, mynode),
|
||||||
err: "cannot modify other nodes",
|
err: "cannot modify node",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "forbid delete of other node",
|
name: "forbid delete of other node",
|
||||||
podsGetter: existingPods,
|
podsGetter: existingPods,
|
||||||
attributes: admission.NewAttributesRecord(nil, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Delete, mynode),
|
attributes: admission.NewAttributesRecord(nil, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Delete, mynode),
|
||||||
err: "cannot modify other nodes",
|
err: "cannot modify node",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "forbid update of other node status",
|
name: "forbid update of other node status",
|
||||||
podsGetter: existingPods,
|
podsGetter: existingPods,
|
||||||
attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "status", admission.Update, mynode),
|
attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "status", admission.Update, mynode),
|
||||||
err: "cannot modify other nodes",
|
err: "cannot modify node",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Unrelated objects
|
// Unrelated objects
|
||||||
|
Loading…
Reference in New Issue
Block a user