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
IptablesSyncPeriod time.Duration
ConfigSyncPeriod time.Duration
nodeRef *api.ObjectReference // Reference to this node.
NodeRef *api.ObjectReference // Reference to this node.
MasqueradeAll bool
CleanupAndExit bool
KubeApiQps float32
@ -71,9 +71,11 @@ type ProxyServerConfig struct {
}
type ProxyServer struct {
Client *kubeclient.Client
Config *ProxyServerConfig
IptInterface utiliptables.Interface
Proxier proxy.ProxyProvider
Broadcaster record.EventBroadcaster
Recorder record.EventRecorder
}
@ -129,15 +131,19 @@ func NewProxyConfig() *ProxyServerConfig {
}
func NewProxyServer(
client *kubeclient.Client,
config *ProxyServerConfig,
iptInterface utiliptables.Interface,
proxier proxy.ProxyProvider,
broadcaster record.EventBroadcaster,
recorder record.EventRecorder,
) (*ProxyServer, error) {
return &ProxyServer{
Client: client,
Config: config,
IptInterface: iptInterface,
Proxier: proxier,
Broadcaster: broadcaster,
Recorder: recorder,
}, nil
}
@ -207,7 +213,6 @@ func NewProxyServerDefault(config *ProxyServerConfig) (*ProxyServer, error) {
hostname := nodeutil.GetHostname(config.HostnameOverride)
eventBroadcaster := record.NewBroadcaster()
recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: hostname})
eventBroadcaster.StartRecordingToSink(client.Events(""))
var proxier proxy.ProxyProvider
var endpointsHandler proxyconfig.EndpointsConfigHandler
@ -269,13 +274,13 @@ func NewProxyServerDefault(config *ProxyServerConfig) (*ProxyServer, error) {
endpointsConfig.Channel("api"),
)
config.nodeRef = &api.ObjectReference{
config.NodeRef = &api.ObjectReference{
Kind: "Node",
Name: hostname,
UID: types.UID(hostname),
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).
@ -290,6 +295,8 @@ func (s *ProxyServer) Run(_ []string) error {
return nil
}
s.Broadcaster.StartRecordingToSink(s.Client.Events(""))
// Birth Cry after the birth is successful
s.birthCry()
@ -353,5 +360,5 @@ func mayTryIptablesProxy(proxyMode string, client nodeGetter, hostname string) b
}
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"
docker "github.com/fsouza/go-dockerclient"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/record"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/kubelet/cadvisor"
"k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/pkg/kubemark"
proxyconfig "k8s.io/kubernetes/pkg/proxy/config"
"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/spf13/pflag"
@ -37,16 +43,20 @@ type HollowNodeConfig struct {
KubeconfigPath string
KubeletPort int
KubeletReadOnlyPort int
Morph string
NodeName string
ServerPort int
}
var knownMorphs = sets.NewString("kubelet", "proxy")
func (c *HollowNodeConfig) addFlags(fs *pflag.FlagSet) {
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.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.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) {
@ -75,25 +85,48 @@ func main() {
config.addFlags(pflag.CommandLine)
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)
if err != nil {
glog.Fatal("Failed to create a Client. Exiting.")
}
cadvisorInterface := new(cadvisor.Fake)
fakeDockerClient := &dockertools.FakeDockerClient{}
fakeDockerClient.VersionInfo = docker.Env{"ApiVersion=1.18"}
fakeDockerClient.ContainerMap = make(map[string]*docker.Container)
fakeDockerClient.EnableSleep = true
if config.Morph == "kubelet" {
cadvisorInterface := new(cadvisor.Fake)
hollowKubelet := kubemark.NewHollowKubelet(
config.NodeName,
cl,
cadvisorInterface,
fakeDockerClient,
config.KubeletPort,
config.KubeletReadOnlyPort,
)
hollowKubelet.Run()
fakeDockerClient := &dockertools.FakeDockerClient{}
fakeDockerClient.VersionInfo = docker.Env{"ApiVersion=1.18"}
fakeDockerClient.ContainerMap = make(map[string]*docker.Container)
fakeDockerClient.EnableSleep = true
hollowKubelet := kubemark.NewHollowKubelet(
config.NodeName,
cl,
cadvisorInterface,
fakeDockerClient,
config.KubeletPort,
config.KubeletReadOnlyPort,
)
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
# limitations under the License.
source "${KUBE_ROOT}/cluster/kubemark/util.sh"
source "${KUBE_ROOT}/cluster/kubemark/config-default.sh"
source "${KUBE_ROOT}/cluster/kubemark/util.sh"
detect-project &> /dev/null
export PROJECT

View File

@ -2,20 +2,20 @@
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "hollow-kubelet",
"name": "hollow-node",
"labels": {
"name": "hollow-kubelet"
"name": "hollow-node"
}
},
"spec": {
"replicas": ##numreplicas##,
"selector": {
"name": "hollow-kubelet"
"name": "hollow-node"
},
"template": {
"metadata": {
"labels": {
"name": "hollow-kubelet"
"name": "hollow-node"
}
},
"spec": {
@ -27,7 +27,8 @@
}
}
],
"containers": [{
"containers": [
{
"name": "hollow-kubelet",
"image": "gcr.io/##project##/kubemark:latest",
"ports": [
@ -39,7 +40,8 @@
"./kubemark.sh"
],
"args": [
"--v=3"
"--v=3",
"--morph=kubelet"
],
"volumeMounts": [
{
@ -53,6 +55,30 @@
"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
EOF
sed "s/##numreplicas##/${NUM_MINIONS:-10}/g" ${KUBE_ROOT}/test/kubemark/hollow-kubelet_template.json > ${KUBE_ROOT}/test/kubemark/hollow-kubelet.json
sed -i'' -e "s/##project##/${PROJECT}/g" ${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-node.json
kubectl create -f ${KUBE_ROOT}/test/kubemark/kubemark-ns.json
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}