Skip to content

Commit

Permalink
Add workload controller
Browse files Browse the repository at this point in the history
  • Loading branch information
zjkmxy committed Sep 11, 2020
1 parent ee46e10 commit d411da2
Show file tree
Hide file tree
Showing 6 changed files with 650 additions and 1 deletion.
19 changes: 19 additions & 0 deletions Dockerfile.workload-controller
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2020 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.

# This image requires ca-certificate, which is pre-installed in distroless.
FROM gcr.io/distroless/static:latest

ADD bin/ARG_ARCH/ARG_BIN /ARG_BIN
ENTRYPOINT ["/ARG_BIN"]
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ CONTAINER_BINARIES ?= \
e2e-test \
echo \
fuzzer \
glbc
glbc \
workload-controller

# Latest commit hash for current branch.
GIT_COMMIT := $(shell git rev-parse HEAD)
Expand Down
51 changes: 51 additions & 0 deletions cmd/workload-controller/app/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2020 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 app

import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/ingress-gce/pkg/flags"
"k8s.io/klog"

// Register the GCP authorization provider.
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
)

// NewKubeConfigForProtobuf returns a Kubernetes client config that uses protobufs
// for given the command line settings.
func NewKubeConfigForProtobuf() (*rest.Config, error) {
config, err := NewKubeConfig()
if err != nil {
return nil, err
}
// Use protobufs for communication with apiserver
config.ContentType = "application/vnd.kubernetes.protobuf"
return config, nil
}

// NewKubeConfig returns a Kubernetes client config given the command line settings.
func NewKubeConfig() (*rest.Config, error) {
if flags.F.InCluster {
klog.V(0).Infof("Using in cluster configuration")
return rest.InClusterConfig()
}

klog.V(0).Infof("Using APIServerHost=%q, KubeConfig=%q", flags.F.APIServerHost, flags.F.KubeConfigFile)
return clientcmd.BuildConfigFromFlags(flags.F.APIServerHost, flags.F.KubeConfigFile)
}
104 changes: 104 additions & 0 deletions cmd/workload-controller/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
Copyright 2020 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 main

import (
"fmt"
"math/rand"
"os"
"time"

flag "github.com/spf13/pflag"
crdclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/client-go/kubernetes"
"k8s.io/ingress-gce/cmd/workload-controller/app"
"k8s.io/ingress-gce/pkg/crd"
"k8s.io/ingress-gce/pkg/experimental/workload"
workloadclient "k8s.io/ingress-gce/pkg/experimental/workload/client/clientset/versioned"
"k8s.io/ingress-gce/pkg/flags"
_ "k8s.io/ingress-gce/pkg/klog"
"k8s.io/ingress-gce/pkg/version"
"k8s.io/klog"
)

func main() {
flags.Register()
rand.Seed(time.Now().UTC().UnixNano())
flag.Parse()

if flags.F.Version {
fmt.Printf("Controller version: %s\n", version.Version)
os.Exit(0)
}

klog.V(0).Infof("Starting GLBC image: %q, cluster name %q", version.Version, flags.F.ClusterName)
klog.V(0).Infof("Latest commit hash: %q", version.GitCommit)
for i, a := range os.Args {
klog.V(0).Infof("argv[%d]: %q", i, a)
}

klog.V(2).Infof("Flags = %+v", flags.F)
defer klog.Flush()
// Create kube-config that uses protobufs to communicate with API server.
kubeConfigForProtobuf, err := app.NewKubeConfigForProtobuf()
if err != nil {
klog.Fatalf("Failed to create kubernetes client config for protobuf: %v", err)
}

kubeClient, err := kubernetes.NewForConfig(kubeConfigForProtobuf)
if err != nil {
klog.Fatalf("Failed to create kubernetes client: %v", err)
}

// Create kube-config for CRDs.
// TODO(smatti): Migrate to use protobuf once CRD supports.
kubeConfig, err := app.NewKubeConfig()
if err != nil {
klog.Fatalf("Failed to create kubernetes client config: %v", err)
}
crdClient, err := crdclient.NewForConfig(kubeConfig)
if err != nil {
klog.Fatalf("Failed to create kubernetes CRD client: %v", err)
}
crdHandler := crd.NewCRDHandler(crdClient)
workloadCRDMeta := workload.CRDMeta()
if _, err := crdHandler.EnsureCRD(workloadCRDMeta); err != nil {
klog.Fatalf("Failed to ensure Workload CRD: %v", err)
}
workloadClient, err := workloadclient.NewForConfig(kubeConfig)
if err != nil {
klog.Fatalf("Failed to create Workload client: %v", err)
}

ctx := workload.NewControllerContext(kubeClient, workloadClient, flags.F.WatchNamespace, flags.F.ResyncPeriod)
// TODO: Leader Elect and Health Check?

runController(ctx)
}

func runController(ctx *workload.ControllerContext) {
stopCh := make(chan struct{})
controller := workload.NewController(ctx)
ctx.Start(stopCh)
klog.V(0).Infof("Workload controller started")
controller.Run(stopCh)

for {
klog.Warning("Handled quit, awaiting pod deletion.")
time.Sleep(30 * time.Second)
}
}
44 changes: 44 additions & 0 deletions hack/run-local-workload-controller.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

# Run workload-controller. First run `setup-local.sh` to set things up.
#
# Files touched: /tmp/kubectl-proxy.log /tmp/workload-controller.log

GOOGLE_APPLICATION_CREDENTIALS="${HOME}/.config/gcloud/application_default_credentials.json"

if [ ! -r ${GOOGLE_APPLICATION_CREDENTIALS} ]; then
echo "You must login your application default credentials"
echo "$ gcloud auth application-default login"
exit 1
fi

GCECONF=${GCECONF:-/tmp/gce.conf}
WLC=${WLC:-./workload-controller}
PORT=${PORT:-7127}
V=${V:-3}

echo "GCECONF=${GCECONF} WLC=${WLC} PORT=${PORT} V=${V}"

if [ ! -x "${WLC}" ]; then
echo "ERROR: No ${WLC} executable found" >&2
exit 1
fi

echo "$(date) start" >> /tmp/kubectl-proxy.log
kubectl proxy --port="${PORT}" \
>> /tmp/kubectl-proxy.log &

PROXY_PID=$!
cleanup() {
echo "Killing proxy (pid=${PROXY_PID})"
kill ${PROXY_PID}
}
trap cleanup EXIT

sleep 2 # Wait for proxy to start up
${WLC} \
--apiserver-host=http://localhost:${PORT} \
--running-in-cluster=false \
--logtostderr --v=${V} \
--config-file-path=${GCECONF} \
2>&1 | tee -a /tmp/workload-controller.log
Loading

0 comments on commit d411da2

Please sign in to comment.