Add a HollowProxy to the HollowNode.

pull/6/head
gmarek 2015-09-01 15:35:38 +02:00
parent a10ed3e2b1
commit 5a4e4d4d57
7 changed files with 256 additions and 30 deletions

View File

@ -62,7 +62,7 @@ type ProxyServerConfig struct {
ProxyMode string ProxyMode string
IptablesSyncPeriod time.Duration IptablesSyncPeriod time.Duration
ConfigSyncPeriod time.Duration ConfigSyncPeriod time.Duration
nodeRef *api.ObjectReference // Reference to this node. NodeRef *api.ObjectReference // Reference to this node.
MasqueradeAll bool MasqueradeAll bool
CleanupAndExit bool CleanupAndExit bool
KubeApiQps float32 KubeApiQps float32
@ -71,9 +71,11 @@ type ProxyServerConfig struct {
} }
type ProxyServer struct { type ProxyServer struct {
Client *kubeclient.Client
Config *ProxyServerConfig Config *ProxyServerConfig
IptInterface utiliptables.Interface IptInterface utiliptables.Interface
Proxier proxy.ProxyProvider Proxier proxy.ProxyProvider
Broadcaster record.EventBroadcaster
Recorder record.EventRecorder Recorder record.EventRecorder
} }
@ -129,15 +131,19 @@ func NewProxyConfig() *ProxyServerConfig {
} }
func NewProxyServer( func NewProxyServer(
client *kubeclient.Client,
config *ProxyServerConfig, config *ProxyServerConfig,
iptInterface utiliptables.Interface, iptInterface utiliptables.Interface,
proxier proxy.ProxyProvider, proxier proxy.ProxyProvider,
broadcaster record.EventBroadcaster,
recorder record.EventRecorder, recorder record.EventRecorder,
) (*ProxyServer, error) { ) (*ProxyServer, error) {
return &ProxyServer{ return &ProxyServer{
Client: client,
Config: config, Config: config,
IptInterface: iptInterface, IptInterface: iptInterface,
Proxier: proxier, Proxier: proxier,
Broadcaster: broadcaster,
Recorder: recorder, Recorder: recorder,
}, nil }, nil
} }
@ -207,7 +213,6 @@ func NewProxyServerDefault(config *ProxyServerConfig) (*ProxyServer, error) {
hostname := nodeutil.GetHostname(config.HostnameOverride) hostname := nodeutil.GetHostname(config.HostnameOverride)
eventBroadcaster := record.NewBroadcaster() eventBroadcaster := record.NewBroadcaster()
recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: hostname}) recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: hostname})
eventBroadcaster.StartRecordingToSink(client.Events(""))
var proxier proxy.ProxyProvider var proxier proxy.ProxyProvider
var endpointsHandler proxyconfig.EndpointsConfigHandler var endpointsHandler proxyconfig.EndpointsConfigHandler
@ -269,13 +274,13 @@ func NewProxyServerDefault(config *ProxyServerConfig) (*ProxyServer, error) {
endpointsConfig.Channel("api"), endpointsConfig.Channel("api"),
) )
config.nodeRef = &api.ObjectReference{ config.NodeRef = &api.ObjectReference{
Kind: "Node", Kind: "Node",
Name: hostname, Name: hostname,
UID: types.UID(hostname), UID: types.UID(hostname),
Namespace: "", Namespace: "",
} }
return NewProxyServer(config, iptInterface, proxier, recorder) return NewProxyServer(client, config, iptInterface, proxier, eventBroadcaster, recorder)
} }
// Run runs the specified ProxyServer. This should never exit (unless CleanupAndExit is set). // Run runs the specified ProxyServer. This should never exit (unless CleanupAndExit is set).
@ -290,6 +295,8 @@ func (s *ProxyServer) Run(_ []string) error {
return nil return nil
} }
s.Broadcaster.StartRecordingToSink(s.Client.Events(""))
// Birth Cry after the birth is successful // Birth Cry after the birth is successful
s.birthCry() s.birthCry()
@ -353,5 +360,5 @@ func mayTryIptablesProxy(proxyMode string, client nodeGetter, hostname string) b
} }
func (s *ProxyServer) birthCry() { func (s *ProxyServer) birthCry() {
s.Recorder.Eventf(s.Config.nodeRef, "Starting", "Starting kube-proxy.") s.Recorder.Eventf(s.Config.NodeRef, "Starting", "Starting kube-proxy.")
} }

View File

@ -22,12 +22,18 @@ import (
"time" "time"
docker "github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/record"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/kubelet/cadvisor" "k8s.io/kubernetes/pkg/kubelet/cadvisor"
"k8s.io/kubernetes/pkg/kubelet/dockertools" "k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/pkg/kubemark" "k8s.io/kubernetes/pkg/kubemark"
proxyconfig "k8s.io/kubernetes/pkg/proxy/config"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
fakeiptables "k8s.io/kubernetes/pkg/util/iptables/testing"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -37,16 +43,20 @@ type HollowNodeConfig struct {
KubeconfigPath string KubeconfigPath string
KubeletPort int KubeletPort int
KubeletReadOnlyPort int KubeletReadOnlyPort int
Morph string
NodeName string NodeName string
ServerPort int ServerPort int
} }
var knownMorphs = sets.NewString("kubelet", "proxy")
func (c *HollowNodeConfig) addFlags(fs *pflag.FlagSet) { func (c *HollowNodeConfig) addFlags(fs *pflag.FlagSet) {
fs.StringVar(&c.KubeconfigPath, "kubeconfig", "/kubeconfig/kubeconfig", "Path to kubeconfig file.") fs.StringVar(&c.KubeconfigPath, "kubeconfig", "/kubeconfig/kubeconfig", "Path to kubeconfig file.")
fs.IntVar(&c.KubeletPort, "kubelet-port", 10250, "Port on which HollowKubelet should be listening.") fs.IntVar(&c.KubeletPort, "kubelet-port", 10250, "Port on which HollowKubelet should be listening.")
fs.IntVar(&c.KubeletReadOnlyPort, "kubelet-read-only-port", 10255, "Read-only port on which Kubelet is listening.") fs.IntVar(&c.KubeletReadOnlyPort, "kubelet-read-only-port", 10255, "Read-only port on which Kubelet is listening.")
fs.StringVar(&c.NodeName, "name", "fake-node", "Name of this Hollow Node.") fs.StringVar(&c.NodeName, "name", "fake-node", "Name of this Hollow Node.")
fs.IntVar(&c.ServerPort, "api-server-port", 443, "Port on which API server is listening.") fs.IntVar(&c.ServerPort, "api-server-port", 443, "Port on which API server is listening.")
fs.StringVar(&c.Morph, "morph", "", fmt.Sprintf("Specifies into which Hollow component this binary should morph. Allowed values: %v", knownMorphs.List()))
} }
func createClientFromFile(path string) (*client.Client, error) { func createClientFromFile(path string) (*client.Client, error) {
@ -75,11 +85,17 @@ func main() {
config.addFlags(pflag.CommandLine) config.addFlags(pflag.CommandLine)
util.InitFlags() util.InitFlags()
// create a client for Kubelet to communicate with API server. if !knownMorphs.Has(config.Morph) {
glog.Fatal("Unknown morph: %v. Allowed values: %v", config.Morph, knownMorphs.List())
}
// create a client to communicate with API server.
cl, err := createClientFromFile(config.KubeconfigPath) cl, err := createClientFromFile(config.KubeconfigPath)
if err != nil { if err != nil {
glog.Fatal("Failed to create a Client. Exiting.") glog.Fatal("Failed to create a Client. Exiting.")
} }
if config.Morph == "kubelet" {
cadvisorInterface := new(cadvisor.Fake) cadvisorInterface := new(cadvisor.Fake)
fakeDockerClient := &dockertools.FakeDockerClient{} fakeDockerClient := &dockertools.FakeDockerClient{}
@ -97,3 +113,20 @@ func main() {
) )
hollowKubelet.Run() hollowKubelet.Run()
} }
if config.Morph == "proxy" {
eventBroadcaster := record.NewBroadcaster()
recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: config.NodeName})
iptInterface := fakeiptables.NewFake()
serviceConfig := proxyconfig.NewServiceConfig()
serviceConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
endpointsConfig := proxyconfig.NewEndpointsConfig()
endpointsConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
hollowProxy := kubemark.NewHollowProxyOrDie(config.NodeName, cl, endpointsConfig, serviceConfig, iptInterface, eventBroadcaster, recorder)
hollowProxy.Run()
}
}

View File

@ -0,0 +1,89 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 kubemark
import (
"time"
proxyapp "k8s.io/kubernetes/cmd/kube-proxy/app"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/record"
client "k8s.io/kubernetes/pkg/client/unversioned"
proxyconfig "k8s.io/kubernetes/pkg/proxy/config"
"k8s.io/kubernetes/pkg/types"
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
"github.com/golang/glog"
)
type HollowProxy struct {
ProxyServer *proxyapp.ProxyServer
}
type FakeProxyHandler struct{}
func (*FakeProxyHandler) OnServiceUpdate(services []api.Service) {}
func (*FakeProxyHandler) OnEndpointsUpdate(endpoints []api.Endpoints) {}
type FakeProxier struct{}
func (*FakeProxier) OnServiceUpdate(services []api.Service) {}
func (*FakeProxier) Sync() {}
func (*FakeProxier) SyncLoop() {
select {}
}
func NewHollowProxyOrDie(
nodeName string,
client *client.Client,
endpointsConfig *proxyconfig.EndpointsConfig,
serviceConfig *proxyconfig.ServiceConfig,
iptInterface utiliptables.Interface,
broadcaster record.EventBroadcaster,
recorder record.EventRecorder,
) *HollowProxy {
// Create and start Hollow Proxy
config := proxyapp.NewProxyConfig()
config.OOMScoreAdj = 0
config.ResourceContainer = ""
config.NodeRef = &api.ObjectReference{
Kind: "Node",
Name: nodeName,
UID: types.UID(nodeName),
Namespace: "",
}
proxyconfig.NewSourceAPI(
client,
30*time.Second,
serviceConfig.Channel("api"),
endpointsConfig.Channel("api"),
)
hollowProxy, err := proxyapp.NewProxyServer(client, config, iptInterface, &FakeProxier{}, broadcaster, recorder)
if err != nil {
glog.Fatalf("Error while creating ProxyServer: %v\n", err)
}
return &HollowProxy{
ProxyServer: hollowProxy,
}
}
func (hp *HollowProxy) Run() {
if err := hp.ProxyServer.Run(make([]string, 0)); err != nil {
glog.Fatalf("Error while running proxy: %v\n", err)
}
}

View File

@ -0,0 +1,71 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 testing
import "k8s.io/kubernetes/pkg/util/iptables"
// no-op implemenatation of iptables Interface
type fake struct{}
func NewFake() *fake {
return &fake{}
}
func (*fake) EnsureChain(table iptables.Table, chain iptables.Chain) (bool, error) {
return true, nil
}
func (*fake) FlushChain(table iptables.Table, chain iptables.Chain) error {
return nil
}
func (*fake) DeleteChain(table iptables.Table, chain iptables.Chain) error {
return nil
}
func (*fake) EnsureRule(position iptables.RulePosition, table iptables.Table, chain iptables.Chain, args ...string) (bool, error) {
return true, nil
}
func (*fake) DeleteRule(table iptables.Table, chain iptables.Chain, args ...string) error {
return nil
}
func (*fake) IsIpv6() bool {
return false
}
func (*fake) Save(table iptables.Table) ([]byte, error) {
return make([]byte, 0), nil
}
func (*fake) SaveAll() ([]byte, error) {
return make([]byte, 0), nil
}
func (*fake) Restore(table iptables.Table, data []byte, flush iptables.FlushFlag, counters iptables.RestoreCountersFlag) error {
return nil
}
func (*fake) RestoreAll(data []byte, flush iptables.FlushFlag, counters iptables.RestoreCountersFlag) error {
return nil
}
func (*fake) AddReloadFunc(reloadFunc func()) {}
func (*fake) Destroy() {}
var _ = iptables.Interface(&fake{})

View File

@ -14,8 +14,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
source "${KUBE_ROOT}/cluster/kubemark/util.sh"
source "${KUBE_ROOT}/cluster/kubemark/config-default.sh" source "${KUBE_ROOT}/cluster/kubemark/config-default.sh"
source "${KUBE_ROOT}/cluster/kubemark/util.sh"
detect-project &> /dev/null detect-project &> /dev/null
export PROJECT export PROJECT

View File

@ -2,20 +2,20 @@
"kind": "ReplicationController", "kind": "ReplicationController",
"apiVersion": "v1", "apiVersion": "v1",
"metadata": { "metadata": {
"name": "hollow-kubelet", "name": "hollow-node",
"labels": { "labels": {
"name": "hollow-kubelet" "name": "hollow-node"
} }
}, },
"spec": { "spec": {
"replicas": ##numreplicas##, "replicas": ##numreplicas##,
"selector": { "selector": {
"name": "hollow-kubelet" "name": "hollow-node"
}, },
"template": { "template": {
"metadata": { "metadata": {
"labels": { "labels": {
"name": "hollow-kubelet" "name": "hollow-node"
} }
}, },
"spec": { "spec": {
@ -27,7 +27,8 @@
} }
} }
], ],
"containers": [{ "containers": [
{
"name": "hollow-kubelet", "name": "hollow-kubelet",
"image": "gcr.io/##project##/kubemark:latest", "image": "gcr.io/##project##/kubemark:latest",
"ports": [ "ports": [
@ -39,7 +40,8 @@
"./kubemark.sh" "./kubemark.sh"
], ],
"args": [ "args": [
"--v=3" "--v=3",
"--morph=kubelet"
], ],
"volumeMounts": [ "volumeMounts": [
{ {
@ -53,6 +55,30 @@
"memory": "100M" "memory": "100M"
} }
} }
},
{
"name": "hollow-proxy",
"image": "gcr.io/##project##/kubemark:latest",
"command": [
"./kubemark.sh"
],
"args": [
"--v=3",
"--morph=proxy"
],
"volumeMounts": [
{
"name": "kubeconfig-volume",
"mountPath": "/kubeconfig"
}
],
"resources": {
"requests": {
"cpu": "20m",
"memory": "100M"
}
}
}] }]
} }
} }

View File

@ -200,11 +200,11 @@ contexts:
current-context: kubemark-context current-context: kubemark-context
EOF EOF
sed "s/##numreplicas##/${NUM_MINIONS:-10}/g" ${KUBE_ROOT}/test/kubemark/hollow-kubelet_template.json > ${KUBE_ROOT}/test/kubemark/hollow-kubelet.json sed "s/##numreplicas##/${NUM_MINIONS:-10}/g" ${KUBE_ROOT}/test/kubemark/hollow-node_template.json > ${KUBE_ROOT}/test/kubemark/hollow-node.json
sed -i'' -e "s/##project##/${PROJECT}/g" ${KUBE_ROOT}/test/kubemark/hollow-kubelet.json sed -i'' -e "s/##project##/${PROJECT}/g" ${KUBE_ROOT}/test/kubemark/hollow-node.json
kubectl create -f ${KUBE_ROOT}/test/kubemark/kubemark-ns.json kubectl create -f ${KUBE_ROOT}/test/kubemark/kubemark-ns.json
kubectl create -f ${KUBECONFIG_SECRET} --namespace="kubemark" kubectl create -f ${KUBECONFIG_SECRET} --namespace="kubemark"
kubectl create -f ${KUBE_ROOT}/test/kubemark/hollow-kubelet.json --namespace="kubemark" kubectl create -f ${KUBE_ROOT}/test/kubemark/hollow-node.json --namespace="kubemark"
rm ${KUBECONFIG_SECRET} rm ${KUBECONFIG_SECRET}