simplified configuration
Signed-off-by: mickeyzzc <mickey_zzc@163.com>
This commit is contained in:
parent
f8b0cb75ca
commit
539f57d75d
|
|
@ -24,7 +24,6 @@ spec:
|
|||
- args:
|
||||
- --resources=pods
|
||||
- --node=""
|
||||
- --enable-no-node-scrape
|
||||
image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.0
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error {
|
|||
|
||||
namespaces := opts.Namespaces.GetNamespaces()
|
||||
nsFieldSelector := namespaces.GetExcludeNSFieldSelector(opts.NamespacesDenylist)
|
||||
nodeFieldSelector := opts.Node.GetNodeFieldSelector(opts.NoNodeScrape)
|
||||
nodeFieldSelector := opts.Node.GetNodeFieldSelector()
|
||||
merged, err := storeBuilder.MergeFieldSelectors([]string{nsFieldSelector, nodeFieldSelector})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ func NewOptions() *Options {
|
|||
MetricAllowlist: MetricSet{},
|
||||
MetricDenylist: MetricSet{},
|
||||
MetricOptInList: MetricSet{},
|
||||
Node: NodeType{},
|
||||
AnnotationsAllowList: LabelsAllowList{},
|
||||
LabelsAllowList: LabelsAllowList{},
|
||||
}
|
||||
|
|
@ -121,7 +122,6 @@ func (o *Options) AddFlags(cmd *cobra.Command) {
|
|||
|
||||
o.cmd.Flags().BoolVar(&o.CustomResourcesOnly, "custom-resource-state-only", false, "Only provide Custom Resource State metrics (experimental)")
|
||||
o.cmd.Flags().BoolVar(&o.EnableGZIPEncoding, "enable-gzip-encoding", false, "Gzip responses when requested by clients via 'Accept-Encoding: gzip' header.")
|
||||
o.cmd.Flags().BoolVar(&o.NoNodeScrape, "enable-no-node-scrape", false, "This configuration is used in conjunction with node configuration. When this configuration is true, node configuration is empty and the metric of no scheduled pods is scraped. This is experimental.")
|
||||
o.cmd.Flags().BoolVarP(&o.Help, "help", "h", false, "Print Help text")
|
||||
o.cmd.Flags().BoolVarP(&o.UseAPIServerCache, "use-apiserver-cache", "", false, "Sets resourceVersion=0 for ListWatch requests, using cached resources from the apiserver instead of an etcd quorum read.")
|
||||
o.cmd.Flags().Int32Var(&o.Shard, "shard", int32(0), "The instances shard nominal (zero indexed) within the total number of shards. (default 0)")
|
||||
|
|
@ -138,7 +138,7 @@ func (o *Options) AddFlags(cmd *cobra.Command) {
|
|||
o.cmd.Flags().StringVar(&o.TLSConfig, "tls-config", "", "Path to the TLS configuration file")
|
||||
o.cmd.Flags().StringVar(&o.TelemetryHost, "telemetry-host", "::", `Host to expose kube-state-metrics self metrics on.`)
|
||||
o.cmd.Flags().StringVar(&o.Config, "config", "", "Path to the kube-state-metrics options config file")
|
||||
o.cmd.Flags().StringVar((*string)(&o.Node), "node", "", "Name of the node that contains the kube-state-metrics pod. Most likely it should be passed via the downward API. This is used for daemonset sharding. Only available for resources (pod metrics) that support spec.nodeName fieldSelector. This is experimental.")
|
||||
o.cmd.Flags().Var(&o.Node, "node", "Name of the node that contains the kube-state-metrics pod. Most likely it should be passed via the downward API. This is used for daemonset sharding. Only available for resources (pod metrics) that support spec.nodeName fieldSelector. This is experimental.")
|
||||
o.cmd.Flags().Var(&o.AnnotationsAllowList, "metric-annotations-allowlist", "Comma-separated list of Kubernetes annotations keys that will be used in the resource' labels metric. By default the annotations metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. A single '*' can be provided per resource instead to allow any annotations, but that has severe performance implications (Example: '=pods=[*]').")
|
||||
o.cmd.Flags().Var(&o.LabelsAllowList, "metric-labels-allowlist", "Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the labels metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (Example: '=pods=[*]'). Additionally, an asterisk (*) can be provided as a key, which will resolve to all resources, i.e., assuming '--resources=deployments,pods', '=*=[*]' will resolve to '=deployments=[*],pods=[*]'.")
|
||||
o.cmd.Flags().Var(&o.MetricAllowlist, "metric-allowlist", "Comma-separated list of metrics to be exposed. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive.")
|
||||
|
|
@ -163,7 +163,7 @@ func (o *Options) Usage() {
|
|||
// Validate validates arguments
|
||||
func (o *Options) Validate() error {
|
||||
shardableResource := "pods"
|
||||
if o.Node == "" {
|
||||
if o.Node.String() == "" {
|
||||
return nil
|
||||
}
|
||||
for _, x := range o.Resources.AsSlice() {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package options
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
|
@ -105,17 +106,52 @@ func (r *ResourceSet) Type() string {
|
|||
}
|
||||
|
||||
// NodeType represents a nodeName to query from.
|
||||
type NodeType string
|
||||
type NodeType map[string]struct{}
|
||||
|
||||
func (n *NodeType) Set(value string) error {
|
||||
s := *n
|
||||
cols := strings.Split(value, ",")
|
||||
for _, col := range cols {
|
||||
col = strings.TrimSpace(col)
|
||||
if len(col) != 0 {
|
||||
s[col] = struct{}{}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n NodeType) AsSlice() []string {
|
||||
cols := make([]string, 0, len(n))
|
||||
for col := range n {
|
||||
cols = append(cols, col)
|
||||
}
|
||||
return cols
|
||||
}
|
||||
|
||||
func (n NodeType) String() string {
|
||||
return strings.Join(n.AsSlice(), ",")
|
||||
}
|
||||
|
||||
func (n *NodeType) Type() string {
|
||||
return "string"
|
||||
}
|
||||
|
||||
// GetNodeFieldSelector returns a nodename field selector.
|
||||
func (n *NodeType) GetNodeFieldSelector(b bool) string {
|
||||
if string(*n) != "" {
|
||||
return fields.OneTermEqualSelector("spec.nodeName", string(*n)).String()
|
||||
func (n *NodeType) GetNodeFieldSelector() string {
|
||||
if nil == n || len(*n) == 0 {
|
||||
klog.InfoS("Using node type is nil")
|
||||
return EmptyFieldSelector()
|
||||
}
|
||||
if b {
|
||||
return fields.OneTermEqualSelector("spec.nodeName", "").String()
|
||||
}
|
||||
return EmptyFieldSelector()
|
||||
pattern := "[^a-zA-Z0-9_,-]+"
|
||||
re := regexp.MustCompile(pattern)
|
||||
result := re.ReplaceAllString(n.String(), "")
|
||||
klog.InfoS("Using node type", "node", result)
|
||||
return fields.OneTermEqualSelector("spec.nodeName", result).String()
|
||||
|
||||
}
|
||||
|
||||
type NodeValue interface {
|
||||
GetNodeFieldSelector() string
|
||||
}
|
||||
|
||||
// EmptyFieldSelector returns an empty field selector.
|
||||
|
|
|
|||
|
|
@ -162,38 +162,32 @@ func TestNodeFieldSelector(t *testing.T) {
|
|||
Wanted string
|
||||
}{
|
||||
{
|
||||
Desc: "empty node name",
|
||||
Node: "",
|
||||
Desc: "with node name",
|
||||
Wanted: "",
|
||||
},
|
||||
{
|
||||
Desc: "with node name",
|
||||
Node: "k8s-node-1",
|
||||
Desc: "empty node name",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"": {},
|
||||
},
|
||||
),
|
||||
Wanted: "spec.nodeName=",
|
||||
},
|
||||
{
|
||||
Desc: "with node name",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"k8s-node-1": {},
|
||||
},
|
||||
),
|
||||
Wanted: "spec.nodeName=k8s-node-1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
node := test.Node
|
||||
actual := node.GetNodeFieldSelector(false)
|
||||
if !reflect.DeepEqual(actual, test.Wanted) {
|
||||
t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual)
|
||||
}
|
||||
}
|
||||
tests1 := []struct {
|
||||
Desc string
|
||||
Node NodeType
|
||||
Wanted string
|
||||
}{
|
||||
{
|
||||
Desc: "empty node name",
|
||||
Node: "",
|
||||
Wanted: "spec.nodeName=",
|
||||
},
|
||||
}
|
||||
for _, test := range tests1 {
|
||||
node := test.Node
|
||||
actual := node.GetNodeFieldSelector(true)
|
||||
actual := node.GetNodeFieldSelector()
|
||||
if !reflect.DeepEqual(actual, test.Wanted) {
|
||||
t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual)
|
||||
}
|
||||
|
|
@ -212,43 +206,67 @@ func TestMergeFieldSelectors(t *testing.T) {
|
|||
Desc: "empty DeniedNamespaces",
|
||||
Namespaces: NamespaceList{"default", "kube-system"},
|
||||
DeniedNamespaces: NamespaceList{},
|
||||
Node: "",
|
||||
Wanted: "",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"": {},
|
||||
},
|
||||
),
|
||||
Wanted: "spec.nodeName=",
|
||||
},
|
||||
{
|
||||
Desc: "all DeniedNamespaces",
|
||||
Namespaces: DefaultNamespaces,
|
||||
DeniedNamespaces: NamespaceList{"some-system"},
|
||||
Node: "",
|
||||
Wanted: "metadata.namespace!=some-system",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"": {},
|
||||
},
|
||||
),
|
||||
Wanted: "metadata.namespace!=some-system,spec.nodeName=",
|
||||
},
|
||||
{
|
||||
Desc: "general case",
|
||||
Namespaces: DefaultNamespaces,
|
||||
DeniedNamespaces: NamespaceList{"case1-system", "case2-system"},
|
||||
Node: "",
|
||||
Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"": {},
|
||||
},
|
||||
),
|
||||
Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system,spec.nodeName=",
|
||||
},
|
||||
{
|
||||
Desc: "empty DeniedNamespaces",
|
||||
Namespaces: NamespaceList{"default", "kube-system"},
|
||||
DeniedNamespaces: NamespaceList{},
|
||||
Node: "k8s-node-1",
|
||||
Wanted: "spec.nodeName=k8s-node-1",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"k8s-node-1": {},
|
||||
},
|
||||
),
|
||||
Wanted: "spec.nodeName=k8s-node-1",
|
||||
},
|
||||
{
|
||||
Desc: "all DeniedNamespaces",
|
||||
Namespaces: DefaultNamespaces,
|
||||
DeniedNamespaces: NamespaceList{"some-system"},
|
||||
Node: "k8s-node-1",
|
||||
Wanted: "metadata.namespace!=some-system,spec.nodeName=k8s-node-1",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"k8s-node-1": {},
|
||||
},
|
||||
),
|
||||
Wanted: "metadata.namespace!=some-system,spec.nodeName=k8s-node-1",
|
||||
},
|
||||
{
|
||||
Desc: "general case",
|
||||
Namespaces: DefaultNamespaces,
|
||||
DeniedNamespaces: NamespaceList{"case1-system", "case2-system"},
|
||||
Node: "k8s-node-1",
|
||||
Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system,spec.nodeName=k8s-node-1",
|
||||
Node: NodeType(
|
||||
map[string]struct{}{
|
||||
"k8s-node-1": {},
|
||||
},
|
||||
),
|
||||
Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system,spec.nodeName=k8s-node-1",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -256,7 +274,7 @@ func TestMergeFieldSelectors(t *testing.T) {
|
|||
ns := test.Namespaces
|
||||
deniedNS := test.DeniedNamespaces
|
||||
selector1 := ns.GetExcludeNSFieldSelector(deniedNS)
|
||||
selector2 := test.Node.GetNodeFieldSelector(false)
|
||||
selector2 := test.Node.GetNodeFieldSelector()
|
||||
actual, err := MergeFieldSelectors([]string{selector1, selector2})
|
||||
if err != nil {
|
||||
t.Errorf("Test error for Desc: %s. Can't merge field selector %v.", test.Desc, err)
|
||||
|
|
|
|||
Loading…
Reference in New Issue