Skip to content
Snippets Groups Projects
Commit 9c2477c7 authored by Karol Wychowaniec's avatar Karol Wychowaniec
Browse files

Use ComponentConfig in Nanny

parent 444a51af
Branches
Tags
No related merge requests found
......@@ -13,14 +13,11 @@ The cluster size is periodically checked, and used to calculate the expected res
```
Usage of pod_nanny:
--config-dir="": The name of directory used to specify resources for scaled container.
--container="pod-nanny": The name of the container to watch. This defaults to the nanny itself.
--cpu="MISSING": The base CPU resource requirement.
--deployment="": The name of the deployment being monitored. This is required.
--extra-cpu="0": The amount of CPU to add per node.
--extra-memory="0Mi": The amount of memory to add per node.
--extra-storage="0Gi": The amount of storage to add per node.
--log-flush-frequency=5s: Maximum number of seconds between log flushes
--memory="MISSING": The base memory resource requirement.
--namespace=$MY_POD_NAMESPACE: The namespace of the ward. This defaults to the nanny's own pod.
--pod=$MY_POD_NAME: The name of the pod to watch. This defaults to the nanny's own pod.
--poll-period=10000: The time, in milliseconds, to poll the dependent container.
......@@ -33,6 +30,20 @@ Usage of pod_nanny:
The following yaml is an example deployment where the nanny watches and resizes itself.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nannyconfig
namespace: default
data:
NannyConfiguration: |-
apiVersion: nannyconfig/v1alpha1
kind: NannyConfiguration
baseCPU: "80m"
cpuPerNode: "0.5"
baseMemory: "140Mi"
memoryPerNode: "4"
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
......@@ -55,7 +66,7 @@ spec:
kubernetes.io/cluster-service: "true"
spec:
containers:
- image: gcr.io/google_containers/addon-resizer:1.0
- image: gcr.io/google_containers/addon-resizer:1.7
imagePullPolicy: Always
name: pod-nanny
resources:
......@@ -74,12 +85,16 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
name: nanny-config-volume
mountPath: /etc/config
command:
- /pod_nanny
- --cpu=300m
- --extra-cpu=20m
- --memory=200Mi
- --extra-memory=10Mi
- --config-dir=/etc/config
- --threshold=5
- --deployment=nanny-v1
volumes:
- name: nanny-config-volume
configMap:
name: nannyconfig
```
......@@ -19,8 +19,8 @@ package nanny
import (
"testing"
"k8s.io/apimachinery/pkg/api/resource"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
)
var (
......
......@@ -21,12 +21,12 @@ import (
"time"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/cache"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
)
type kubernetesClient struct {
......
......@@ -17,28 +17,31 @@ limitations under the License.
package main
import (
"fmt"
"io/ioutil"
"os"
"time"
"github.com/golang/glog"
flag "github.com/spf13/pflag"
"k8s.io/autoscaler/addon-resizer/nanny"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/autoscaler/addon-resizer/nanny"
client "k8s.io/client-go/kubernetes"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/autoscaler/addon-resizer/nanny/apis/nannyconfig"
nannyscheme "k8s.io/autoscaler/addon-resizer/nanny/apis/nannyconfig/scheme"
nannyconfigalpha "k8s.io/autoscaler/addon-resizer/nanny/apis/nannyconfig/v1alpha1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"path/filepath"
)
const noValue = "MISSING"
var (
// Flags to define the resource requirements.
baseCPU = flag.String("cpu", noValue, "The base CPU resource requirement.")
cpuPerNode = flag.String("extra-cpu", "0", "The amount of CPU to add per node.")
baseMemory = flag.String("memory", noValue, "The base memory resource requirement.")
memoryPerNode = flag.String("extra-memory", "0Mi", "The amount of memory to add per node.")
baseStorage = flag.String("storage", noValue, "The base storage resource requirement.")
configDir = flag.String("config-dir", nannyconfig.NoValue, "Path of configuration containing base resource requirements.")
baseStorage = flag.String("storage", nannyconfig.NoValue, "The base storage resource requirement.")
storagePerNode = flag.String("extra-storage", "0Gi", "The amount of storage to add per node.")
threshold = flag.Int("threshold", 0, "A number between 0-100. The dependent's resources are rewritten when they deviate from expected by more than threshold.")
// Flags to identify the container to nanny.
......@@ -66,7 +69,7 @@ func main() {
}
glog.Infof("Watching namespace: %s, pod: %s, container: %s.", *podNamespace, *podName, *containerName)
glog.Infof("cpu: %s, extra_cpu: %s, memory: %s, extra_memory: %s, storage: %s, extra_storage: %s", *baseCPU, *cpuPerNode, *baseMemory, *memoryPerNode, *baseStorage, *storagePerNode)
glog.Infof("storage: %s, extra_storage: %s", *baseStorage, *storagePerNode)
// Set up work objects.
config, err := rest.InClusterConfig()
......@@ -74,35 +77,41 @@ func main() {
glog.Fatal(err)
}
clientset, err := client.NewForConfig(config)
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
glog.Fatal(err)
}
k8s := nanny.NewKubernetesClient(*podNamespace, *deployment, *podName, *containerName, clientset)
nannycfg, err := loadNannyConfiguration(*configDir)
if err != nil {
glog.Fatal(err)
}
glog.Infof("cpu: %s, extra_cpu: %s, memory: %s, extra_memory: %s", nannycfg.BaseCPU, nannycfg.CPUPerNode, nannycfg.BaseMemory, nannycfg.MemoryPerNode)
var resources []nanny.Resource
// Monitor only the resources specified.
if *baseCPU != noValue {
if nannycfg.BaseCPU != nannyconfig.NoValue {
resources = append(resources, nanny.Resource{
Base: resource.MustParse(*baseCPU),
ExtraPerNode: resource.MustParse(*cpuPerNode),
Base: resource.MustParse(nannycfg.BaseCPU),
ExtraPerNode: resource.MustParse(nannycfg.CPUPerNode),
Name: "cpu",
})
}
if *baseMemory != noValue {
if nannycfg.BaseMemory != nannyconfig.NoValue {
resources = append(resources, nanny.Resource{
Base: resource.MustParse(*baseMemory),
ExtraPerNode: resource.MustParse(*memoryPerNode),
Base: resource.MustParse(nannycfg.BaseMemory),
ExtraPerNode: resource.MustParse(nannycfg.MemoryPerNode),
Name: "memory",
})
}
if *baseStorage != noValue {
if *baseStorage != nannyconfig.NoValue {
resources = append(resources, nanny.Resource{
Base: resource.MustParse(*baseStorage),
ExtraPerNode: resource.MustParse(*memoryPerNode),
ExtraPerNode: resource.MustParse(nannycfg.MemoryPerNode),
Name: "storage",
})
}
......@@ -126,3 +135,41 @@ func main() {
// Begin nannying.
nanny.PollAPIServer(k8s, est, *containerName, pollPeriod, uint64(*threshold))
}
func loadNannyConfiguration(configDir string) (*nannyconfig.NannyConfiguration, error) {
path := filepath.Join(configDir, "NannyConfiguration")
scheme, codecs, err := nannyscheme.NewSchemeAndCodecs()
if err != nil {
return nil, err
}
data, err := ioutil.ReadFile(path)
if err != nil {
glog.V(0).Infof("Failed to read data from config file %q: %v, using default parameters", path, err)
config := &nannyconfigalpha.NannyConfiguration{}
nannyconfigalpha.SetDefaults_NannyConfiguration(config)
return convertNannyConfiguration(config, scheme)
}
return decodeNannyConfiguration(data, scheme, codecs)
}
func convertNannyConfiguration(configAlpha *nannyconfigalpha.NannyConfiguration, scheme *runtime.Scheme) (*nannyconfig.NannyConfiguration, error) {
config := &nannyconfig.NannyConfiguration{}
err := scheme.Convert(configAlpha, config, nil)
if err != nil {
return nil, err
}
return config, nil
}
func decodeNannyConfiguration(data []byte, scheme *runtime.Scheme, codecs *serializer.CodecFactory) (*nannyconfig.NannyConfiguration, error) {
obj, err := runtime.Decode(codecs.UniversalDecoder(nannyconfigalpha.SchemeGroupVersion), data)
if err != nil {
return nil, fmt.Errorf("failed to decode, error: %v", err)
}
externalHC, ok := obj.(*nannyconfigalpha.NannyConfiguration)
if !ok {
return nil, fmt.Errorf("failed to cast object to NannyConfiguration, object: %#v", obj)
}
return convertNannyConfiguration(externalHC, scheme)
}
......@@ -19,8 +19,8 @@ package nanny
import (
"testing"
"k8s.io/apimachinery/pkg/api/resource"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
)
var (
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment