Skip to content

Commit

Permalink
Add BearerToken Defaults for Kubernetes Plugins
Browse files Browse the repository at this point in the history
Due to Kubernetes RBAC policies, it's extremely rare and unlikely that
anyone will run these plugins outside of the cluster. With that in-mind,
we should use as many defaults as possible to remove configuration.

All pods within Kubernetes have a ServiceAccount token mounted in to this
location, which shouldn't need to be repeated each time.
  • Loading branch information
rawkode committed Oct 25, 2019
1 parent be7c71a commit f128183
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 31 deletions.
30 changes: 16 additions & 14 deletions plugins/inputs/kube_inventory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ avoid cardinality issues:
# namespace = "default"

## Use bearer token for authorization. ('bearer_token' takes priority)
## If both of these are empty, we'll use the default serviceaccount:
## at: /run/secrets/kubernetes.io/serviceaccount/token
# bearer_token = "/path/to/bearer/token"
## OR
# bearer_token_string = "abc_123"
Expand Down Expand Up @@ -236,25 +238,25 @@ subjects:

The persistentvolume "phase" is saved in the `phase` tag with a correlated numeric field called `phase_type` corresponding with that tag value.

|Tag value |Corresponding field value|
-----------|-------------------------|
|bound | 0 |
|failed | 1 |
|pending | 2 |
|released | 3 |
|available | 4 |
|unknown | 5 |
| Tag value | Corresponding field value |
| --------- | ------------------------- |
| bound | 0 |
| failed | 1 |
| pending | 2 |
| released | 3 |
| available | 4 |
| unknown | 5 |

#### pvc `phase_type`

The persistentvolumeclaim "phase" is saved in the `phase` tag with a correlated numeric field called `phase_type` corresponding with that tag value.

|Tag value |Corresponding field value|
-----------|-------------------------|
|bound | 0 |
|lost | 1 |
|pending | 2 |
|unknown | 3 |
| Tag value | Corresponding field value |
| --------- | ------------------------- |
| bound | 0 |
| lost | 1 |
| pending | 2 |
| unknown | 3 |


### Example Output:
Expand Down
44 changes: 28 additions & 16 deletions plugins/inputs/kube_inventory/kube_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import (
"github.com/influxdata/telegraf/plugins/inputs"
)

const (
defaultServiceAccountPath = "/run/secrets/kubernetes.io/serviceaccount/token"
)

// KubernetesInventory represents the config object for the plugin.
type KubernetesInventory struct {
URL string `toml:"url"`
Expand All @@ -42,6 +46,8 @@ var sampleConfig = `
# namespace = "default"
## Use bearer token for authorization. ('bearer_token' takes priority)
## If both of these are empty, we'll use the default serviceaccount:
## at: /run/secrets/kubernetes.io/serviceaccount/token
# bearer_token = "/path/to/bearer/token"
## OR
# bearer_token_string = "abc_123"
Expand Down Expand Up @@ -77,14 +83,32 @@ func (ki *KubernetesInventory) Description() string {
return "Read metrics from the Kubernetes api"
}

// Gather collects kubernetes metrics from a given URL.
func (ki *KubernetesInventory) Gather(acc telegraf.Accumulator) (err error) {
if ki.client == nil {
if ki.client, err = ki.initClient(); err != nil {
func (ki *KubernetesInventory) Init() error {
// If neither are provided, use the default service account.
if ki.BearerToken == "" && ki.BearerTokenString == "" {
ki.BearerToken = defaultServiceAccountPath
}

if ki.BearerToken != "" {
token, err := ioutil.ReadFile(ki.BearerToken)
if err != nil {
return err
}
ki.BearerTokenString = strings.TrimSpace(string(token))
}

var err error
ki.client, err = newClient(ki.URL, ki.Namespace, ki.BearerTokenString, ki.ResponseTimeout.Duration, ki.ClientConfig)

if err != nil {
return err
}

return nil
}

// Gather collects kubernetes metrics from a given URL.
func (ki *KubernetesInventory) Gather(acc telegraf.Accumulator) (err error) {
resourceFilter, err := filter.NewIncludeExcludeFilter(ki.ResourceInclude, ki.ResourceExclude)
if err != nil {
return err
Expand Down Expand Up @@ -121,18 +145,6 @@ var availableCollectors = map[string]func(ctx context.Context, acc telegraf.Accu
"statefulsets": collectStatefulSets,
}

func (ki *KubernetesInventory) initClient() (*client, error) {
if ki.BearerToken != "" {
token, err := ioutil.ReadFile(ki.BearerToken)
if err != nil {
return nil, err
}
ki.BearerTokenString = strings.TrimSpace(string(token))
}

return newClient(ki.URL, ki.Namespace, ki.BearerTokenString, ki.ResponseTimeout.Duration, ki.ClientConfig)
}

func atoi(s string) int64 {
i, err := strconv.ParseInt(s, 10, 64)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions plugins/inputs/kubernetes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ avoid cardinality issues:
url = "http://127.0.0.1:10255"

## Use bearer token for authorization. ('bearer_token' takes priority)
## If both of these are empty, we'll use the default serviceaccount:
## at: /run/secrets/kubernetes.io/serviceaccount/token
# bearer_token = "/path/to/bearer/token"
## OR
# bearer_token_string = "abc_123"
Expand Down
13 changes: 12 additions & 1 deletion plugins/inputs/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"time"

Expand Down Expand Up @@ -36,6 +37,8 @@ var sampleConfig = `
url = "http://127.0.0.1:10255"
## Use bearer token for authorization. ('bearer_token' takes priority)
## If both of these are empty, we'll use the default serviceaccount:
## at: /run/secrets/kubernetes.io/serviceaccount/token
# bearer_token = "/path/to/bearer/token"
## OR
# bearer_token_string = "abc_123"
Expand All @@ -52,7 +55,8 @@ var sampleConfig = `
`

const (
summaryEndpoint = `%s/stats/summary`
summaryEndpoint = `%s/stats/summary`
defaultServiceAccountPath = "/run/secrets/kubernetes.io/serviceaccount/token"
)

func init() {
Expand Down Expand Up @@ -108,6 +112,13 @@ func (k *Kubernetes) gatherSummary(baseURL string, acc telegraf.Accumulator) err
}
}

// Even neither are provided, use the default service account.
if k.BearerToken == "" && k.BearerTokenString == "" {
if _, err := os.Stat(defaultServiceAccountPath); err == nil {
k.BearerToken = defaultServiceAccountPath
}
}

if k.BearerToken != "" {
token, err := ioutil.ReadFile(k.BearerToken)
if err != nil {
Expand Down

0 comments on commit f128183

Please sign in to comment.