mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2024-12-14 11:57:51 +00:00
nfd-master: switch to klog
This commit is contained in:
parent
a8232ccd2b
commit
3ffb7b8fc5
5 changed files with 112 additions and 33 deletions
|
@ -23,6 +23,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
master "sigs.k8s.io/node-feature-discovery/pkg/nfd-master"
|
master "sigs.k8s.io/node-feature-discovery/pkg/nfd-master"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
||||||
|
@ -39,6 +41,8 @@ func main() {
|
||||||
printVersion := flags.Bool("version", false, "Print version and exit.")
|
printVersion := flags.Bool("version", false, "Print version and exit.")
|
||||||
|
|
||||||
args := initFlags(flags)
|
args := initFlags(flags)
|
||||||
|
// Inject klog flags
|
||||||
|
klog.InitFlags(flags)
|
||||||
|
|
||||||
_ = flags.Parse(os.Args[1:])
|
_ = flags.Parse(os.Args[1:])
|
||||||
if len(flags.Args()) > 0 {
|
if len(flags.Args()) > 0 {
|
||||||
|
|
|
@ -204,3 +204,81 @@ Example:
|
||||||
```bash
|
```bash
|
||||||
nfd-master -resource-labels=vendor-1.com/feature-1,vendor-2.io/feature-2
|
nfd-master -resource-labels=vendor-1.com/feature-1,vendor-2.io/feature-2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
The following logging-related flags are inherited from the
|
||||||
|
[klog](https://pkg.go.dev/k8s.io/klog/v2) package.
|
||||||
|
|
||||||
|
#### -add_dir_header
|
||||||
|
|
||||||
|
If true, adds the file directory to the header of the log messages.
|
||||||
|
|
||||||
|
Default: false
|
||||||
|
|
||||||
|
#### -alsologtostderr
|
||||||
|
|
||||||
|
Log to standard error as well as files.
|
||||||
|
|
||||||
|
Default: false
|
||||||
|
|
||||||
|
#### -log_backtrace_at
|
||||||
|
|
||||||
|
When logging hits line file:N, emit a stack trace.
|
||||||
|
|
||||||
|
Default: *empty*
|
||||||
|
|
||||||
|
#### -log_dir
|
||||||
|
|
||||||
|
If non-empty, write log files in this directory.
|
||||||
|
|
||||||
|
Default: *empty*
|
||||||
|
|
||||||
|
#### -log_file
|
||||||
|
|
||||||
|
If non-empty, use this log file.
|
||||||
|
|
||||||
|
Default: *empty*
|
||||||
|
|
||||||
|
#### -log_file_max_size
|
||||||
|
|
||||||
|
Defines the maximum size a log file can grow to. Unit is megabytes. If the
|
||||||
|
value is 0, the maximum file size is unlimited.
|
||||||
|
|
||||||
|
Default: 1800
|
||||||
|
|
||||||
|
#### -logtostderr
|
||||||
|
|
||||||
|
Log to standard error instead of files
|
||||||
|
|
||||||
|
Default: true
|
||||||
|
|
||||||
|
#### -skip_headers
|
||||||
|
|
||||||
|
If true, avoid header prefixes in the log messages.
|
||||||
|
|
||||||
|
Default: false
|
||||||
|
|
||||||
|
#### -skip_log_headers
|
||||||
|
|
||||||
|
If true, avoid headers when opening log files.
|
||||||
|
|
||||||
|
Default: false
|
||||||
|
|
||||||
|
#### -stderrthreshold
|
||||||
|
|
||||||
|
Logs at or above this threshold go to stderr.
|
||||||
|
|
||||||
|
Default: 2
|
||||||
|
|
||||||
|
#### -v
|
||||||
|
|
||||||
|
Number for the log level verbosity.
|
||||||
|
|
||||||
|
Default: 0
|
||||||
|
|
||||||
|
#### -vmodule
|
||||||
|
|
||||||
|
Comma-separated list of `pattern=N` settings for file-filtered logging.
|
||||||
|
|
||||||
|
Default: *empty*
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -21,6 +21,7 @@ require (
|
||||||
k8s.io/api v0.19.4
|
k8s.io/api v0.19.4
|
||||||
k8s.io/apimachinery v0.19.4
|
k8s.io/apimachinery v0.19.4
|
||||||
k8s.io/client-go v11.0.0+incompatible
|
k8s.io/client-go v11.0.0+incompatible
|
||||||
|
k8s.io/klog/v2 v2.2.0
|
||||||
k8s.io/kubernetes v1.18.6
|
k8s.io/kubernetes v1.18.6
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
|
@ -157,7 +157,7 @@ func TestUpdateNodeFeatures(t *testing.T) {
|
||||||
err := mockMaster.updateNodeFeatures(mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources)
|
err := mockMaster.updateNodeFeatures(mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources)
|
||||||
|
|
||||||
Convey("Error is produced", func() {
|
Convey("Error is produced", func() {
|
||||||
So(err, ShouldEqual, expectedError)
|
So(err.Error(), ShouldEndWith, expectedError.Error())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ func TestUpdateMasterNode(t *testing.T) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
mockErr := errors.New("mock-error")
|
mockErr := errors.New("failed to patch node annotations: mock-error'")
|
||||||
Convey("When getting API client fails", func() {
|
Convey("When getting API client fails", func() {
|
||||||
mockHelper.On("GetClient").Return(mockClient, mockErr)
|
mockHelper.On("GetClient").Return(mockClient, mockErr)
|
||||||
err := mockMaster.updateMasterNode()
|
err := mockMaster.updateMasterNode()
|
||||||
|
@ -206,7 +206,7 @@ func TestUpdateMasterNode(t *testing.T) {
|
||||||
mockHelper.On("PatchNode", mockClient, mockNodeName, mock.Anything).Return(mockErr)
|
mockHelper.On("PatchNode", mockClient, mockNodeName, mock.Anything).Return(mockErr)
|
||||||
err := mockMaster.updateMasterNode()
|
err := mockMaster.updateMasterNode()
|
||||||
Convey("An error should be returned", func() {
|
Convey("An error should be returned", func() {
|
||||||
So(err, ShouldEqual, mockErr)
|
So(err.Error(), ShouldEndWith, mockErr.Error())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
@ -36,6 +35,8 @@ import (
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
|
"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
|
||||||
pb "sigs.k8s.io/node-feature-discovery/pkg/labeler"
|
pb "sigs.k8s.io/node-feature-discovery/pkg/labeler"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
||||||
|
@ -56,12 +57,6 @@ const (
|
||||||
workerVersionAnnotation = "worker.version"
|
workerVersionAnnotation = "worker.version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// package loggers
|
|
||||||
var (
|
|
||||||
stdoutLogger = log.New(os.Stdout, "", log.LstdFlags)
|
|
||||||
stderrLogger = log.New(os.Stderr, "", log.LstdFlags)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Labels are a Kubernetes representation of discovered features.
|
// Labels are a Kubernetes representation of discovered features.
|
||||||
type Labels map[string]string
|
type Labels map[string]string
|
||||||
|
|
||||||
|
@ -142,11 +137,11 @@ func NewNfdMaster(args *Args) (NfdMaster, error) {
|
||||||
// Run NfdMaster server. The method returns in case of fatal errors or if Stop()
|
// Run NfdMaster server. The method returns in case of fatal errors or if Stop()
|
||||||
// is called.
|
// is called.
|
||||||
func (m *nfdMaster) Run() error {
|
func (m *nfdMaster) Run() error {
|
||||||
stdoutLogger.Printf("Node Feature Discovery Master %s", version.Get())
|
klog.Infof("Node Feature Discovery Master %s", version.Get())
|
||||||
if m.args.Instance != "" {
|
if m.args.Instance != "" {
|
||||||
stdoutLogger.Printf("Master instance: '%s'", m.args.Instance)
|
klog.Infof("Master instance: %q", m.args.Instance)
|
||||||
}
|
}
|
||||||
stdoutLogger.Printf("NodeName: '%s'", m.nodeName)
|
klog.Infof("NodeName: %q", m.nodeName)
|
||||||
|
|
||||||
if m.args.Prune {
|
if m.args.Prune {
|
||||||
return m.prune()
|
return m.prune()
|
||||||
|
@ -184,7 +179,7 @@ func (m *nfdMaster) Run() error {
|
||||||
}
|
}
|
||||||
caPool := x509.NewCertPool()
|
caPool := x509.NewCertPool()
|
||||||
if ok := caPool.AppendCertsFromPEM(caCert); !ok {
|
if ok := caPool.AppendCertsFromPEM(caCert); !ok {
|
||||||
return fmt.Errorf("failed to add certificate from '%s'", m.args.CaFile)
|
return fmt.Errorf("failed to add certificate from %q", m.args.CaFile)
|
||||||
}
|
}
|
||||||
// Create TLS config
|
// Create TLS config
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
|
@ -196,7 +191,7 @@ func (m *nfdMaster) Run() error {
|
||||||
}
|
}
|
||||||
m.server = grpc.NewServer(serverOpts...)
|
m.server = grpc.NewServer(serverOpts...)
|
||||||
pb.RegisterLabelerServer(m.server, m)
|
pb.RegisterLabelerServer(m.server, m)
|
||||||
stdoutLogger.Printf("gRPC server serving on port: %d", m.args.Port)
|
klog.Infof("gRPC server serving on port: %d", m.args.Port)
|
||||||
return m.server.Serve(lis)
|
return m.server.Serve(lis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +228,7 @@ func (m *nfdMaster) prune() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range nodes.Items {
|
for _, node := range nodes.Items {
|
||||||
stdoutLogger.Printf("pruning node %q...", node.Name)
|
klog.Infof("pruning node %q...", node.Name)
|
||||||
|
|
||||||
// Prune labels and extended resources
|
// Prune labels and extended resources
|
||||||
err := m.updateNodeFeatures(node.Name, Labels{}, Annotations{}, ExtendedResources{})
|
err := m.updateNodeFeatures(node.Name, Labels{}, Annotations{}, ExtendedResources{})
|
||||||
|
@ -255,7 +250,6 @@ func (m *nfdMaster) prune() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to prune annotations from node %q: %v", node.Name, err)
|
return fmt.Errorf("failed to prune annotations from node %q: %v", node.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -278,8 +272,7 @@ func (m *nfdMaster) updateMasterNode() error {
|
||||||
"/metadata/annotations")
|
"/metadata/annotations")
|
||||||
err = m.apihelper.PatchNode(cli, node.Name, p)
|
err = m.apihelper.PatchNode(cli, node.Name, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stderrLogger.Printf("failed to patch node annotations: %v", err)
|
return fmt.Errorf("failed to patch node annotations: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -301,14 +294,14 @@ func filterFeatureLabels(labels Labels, extraLabelNs map[string]struct{}, labelW
|
||||||
// Check label namespace, filter out if ns is not whitelisted
|
// Check label namespace, filter out if ns is not whitelisted
|
||||||
if ns != LabelNs {
|
if ns != LabelNs {
|
||||||
if _, ok := extraLabelNs[ns]; !ok {
|
if _, ok := extraLabelNs[ns]; !ok {
|
||||||
stderrLogger.Printf("Namespace '%s' is not allowed. Ignoring label '%s'\n", ns, label)
|
klog.Errorf("Namespace %q is not allowed. Ignoring label %q\n", ns, label)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if label doesn't match labelWhiteList
|
// Skip if label doesn't match labelWhiteList
|
||||||
if !labelWhiteList.MatchString(name) {
|
if !labelWhiteList.MatchString(name) {
|
||||||
stderrLogger.Printf("%s (%s) does not match the whitelist (%s) and will not be published.", name, label, labelWhiteList.String())
|
klog.Errorf("%s (%s) does not match the whitelist (%s) and will not be published.", name, label, labelWhiteList.String())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
outLabels[label] = value
|
outLabels[label] = value
|
||||||
|
@ -321,7 +314,7 @@ func filterFeatureLabels(labels Labels, extraLabelNs map[string]struct{}, labelW
|
||||||
extendedResourceName = addNs(extendedResourceName, LabelNs)
|
extendedResourceName = addNs(extendedResourceName, LabelNs)
|
||||||
if value, ok := outLabels[extendedResourceName]; ok {
|
if value, ok := outLabels[extendedResourceName]; ok {
|
||||||
if _, err := strconv.Atoi(value); err != nil {
|
if _, err := strconv.Atoi(value); err != nil {
|
||||||
stderrLogger.Printf("bad label value (%s: %s) encountered for extended resource: %s", extendedResourceName, value, err.Error())
|
klog.Errorf("bad label value (%s: %s) encountered for extended resource: %s", extendedResourceName, value, err.Error())
|
||||||
continue // non-numeric label can't be used
|
continue // non-numeric label can't be used
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,25 +333,30 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se
|
||||||
// Check that the node name matches the CN from the TLS cert
|
// Check that the node name matches the CN from the TLS cert
|
||||||
client, ok := peer.FromContext(c)
|
client, ok := peer.FromContext(c)
|
||||||
if !ok {
|
if !ok {
|
||||||
stderrLogger.Printf("gRPC request error: failed to get peer (client)")
|
klog.Errorf("gRPC request error: failed to get peer (client)")
|
||||||
return &pb.SetLabelsReply{}, fmt.Errorf("failed to get peer (client)")
|
return &pb.SetLabelsReply{}, fmt.Errorf("failed to get peer (client)")
|
||||||
}
|
}
|
||||||
tlsAuth, ok := client.AuthInfo.(credentials.TLSInfo)
|
tlsAuth, ok := client.AuthInfo.(credentials.TLSInfo)
|
||||||
if !ok {
|
if !ok {
|
||||||
stderrLogger.Printf("gRPC request error: incorrect client credentials from '%v'", client.Addr)
|
klog.Errorf("gRPC request error: incorrect client credentials from '%v'", client.Addr)
|
||||||
return &pb.SetLabelsReply{}, fmt.Errorf("incorrect client credentials")
|
return &pb.SetLabelsReply{}, fmt.Errorf("incorrect client credentials")
|
||||||
}
|
}
|
||||||
if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 {
|
if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 {
|
||||||
stderrLogger.Printf("gRPC request error: client certificate verification for '%v' failed", client.Addr)
|
klog.Errorf("gRPC request error: client certificate verification for '%v' failed", client.Addr)
|
||||||
return &pb.SetLabelsReply{}, fmt.Errorf("client certificate verification failed")
|
return &pb.SetLabelsReply{}, fmt.Errorf("client certificate verification failed")
|
||||||
}
|
}
|
||||||
cn := tlsAuth.State.VerifiedChains[0][0].Subject.CommonName
|
cn := tlsAuth.State.VerifiedChains[0][0].Subject.CommonName
|
||||||
if cn != r.NodeName {
|
if cn != r.NodeName {
|
||||||
stderrLogger.Printf("gRPC request error: authorization for %v failed: cert valid for '%s', requested node name '%s'", client.Addr, cn, r.NodeName)
|
klog.Errorf("gRPC request error: authorization for %v failed: cert valid for %q, requested node name %q", client.Addr, cn, r.NodeName)
|
||||||
return &pb.SetLabelsReply{}, fmt.Errorf("request authorization failed: cert valid for '%s', requested node name '%s'", cn, r.NodeName)
|
return &pb.SetLabelsReply{}, fmt.Errorf("request authorization failed: cert valid for %q, requested node name %q", cn, r.NodeName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stdoutLogger.Printf("REQUEST Node: %s NFD-version: %s Labels: %s", r.NodeName, r.NfdVersion, r.Labels)
|
if klog.V(1).Enabled() {
|
||||||
|
klog.Infof("REQUEST Node: %q NFD-version: %q Labels: %s", r.NodeName, r.NfdVersion, r.Labels)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
klog.Infof("received labeling request for node %q", r.NodeName)
|
||||||
|
}
|
||||||
|
|
||||||
labels, extendedResources := filterFeatureLabels(r.Labels, m.args.ExtraLabelNs, m.args.LabelWhiteList.Regexp, m.args.ResourceLabels)
|
labels, extendedResources := filterFeatureLabels(r.Labels, m.args.ExtraLabelNs, m.args.LabelWhiteList.Regexp, m.args.ResourceLabels)
|
||||||
|
|
||||||
|
@ -368,7 +366,7 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se
|
||||||
|
|
||||||
err := m.updateNodeFeatures(r.NodeName, labels, annotations, extendedResources)
|
err := m.updateNodeFeatures(r.NodeName, labels, annotations, extendedResources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stderrLogger.Printf("failed to advertise labels: %s", err.Error())
|
klog.Errorf("failed to advertise labels: %v", err)
|
||||||
return &pb.SetLabelsReply{}, err
|
return &pb.SetLabelsReply{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,16 +418,14 @@ func (m *nfdMaster) updateNodeFeatures(nodeName string, labels Labels, annotatio
|
||||||
// Patch the node object in the apiserver
|
// Patch the node object in the apiserver
|
||||||
err = m.apihelper.PatchNode(cli, node.Name, patches)
|
err = m.apihelper.PatchNode(cli, node.Name, patches)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stderrLogger.Printf("error while patching node object: %s", err.Error())
|
return fmt.Errorf("error while patching node object: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// patch node status with extended resource changes
|
// patch node status with extended resource changes
|
||||||
patches = m.createExtendedResourcePatches(node, extendedResources)
|
patches = m.createExtendedResourcePatches(node, extendedResources)
|
||||||
err = m.apihelper.PatchNodeStatus(cli, node.Name, patches)
|
err = m.apihelper.PatchNodeStatus(cli, node.Name, patches)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stderrLogger.Printf("error while patching extended resources: %s", err.Error())
|
return fmt.Errorf("error while patching extended resources: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in a new issue