Skip to content

Commit

Permalink
Add a HollowProxy to the HollowNode.
Browse files Browse the repository at this point in the history
  • Loading branch information
gmarek committed Oct 27, 2015
1 parent a10ed3e commit 5a4e4d4
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 32 deletions.
17 changes: 12 additions & 5 deletions cmd/kube-proxy/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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).
Expand All @@ -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()

Expand Down Expand Up @@ -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.")
}
67 changes: 50 additions & 17 deletions cmd/kubemark/hollow-node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {
Expand Down Expand Up @@ -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

hollowKubelet := kubemark.NewHollowKubelet(
config.NodeName,
cl,
cadvisorInterface,
fakeDockerClient,
config.KubeletPort,
config.KubeletReadOnlyPort,
)
hollowKubelet.Run()

if config.Morph == "kubelet" {
cadvisorInterface := new(cadvisor.Fake)

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()
}
}
89 changes: 89 additions & 0 deletions pkg/kubemark/hollow-proxy.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
71 changes: 71 additions & 0 deletions pkg/util/iptables/testing/fake.go
Original file line number Diff line number Diff line change
@@ -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{})
2 changes: 1 addition & 1 deletion test/kubemark/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 5a4e4d4

Please sign in to comment.