Adding chart for SignalFx agent (#3946)

* Adding chart for SignalFx agent

* Fixing lint and using name templates

* Using best-practice service account handling

* Using github name in maintainers block

* Removing conditionals around Helm labels

* Removing superfluous conditionals and default

* Nesting image config in image key

* Making rolling update maxUnavailable configurable

* Making default access token a blank string

Otherwise it chokes the b64enc filter

* Making /etc/machine-id mount read only

* Removing container_name from docker dimension mapping

That gets populated automatically by the plugin

* Updating default agent version

* Using new docker-container-stats monitor instead of collectd/docker

* Using newer apiVersion for DaemonSet

* Updating agent version to latest

* Removing container_cpu_usage_seconds_total from default filter

* Making daemonset rendering conditional
This commit is contained in:
Ben Keith
2018-04-10 05:40:09 -07:00
committed by k8s-ci-robot
parent 48d7786189
commit 54dabb8989
12 changed files with 674 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
+17
View File
@@ -0,0 +1,17 @@
apiVersion: v1
description: The SignalFx Kubernetes agent
name: signalfx-agent
appVersion: 3.0.0
version: 0.1.0
keywords:
- monitoring
- alerting
- metrics
- stats
home: https://signalfx.com
sources:
- https://github.com/signalfx/signalfx-agent
maintainers:
- name: keitwb
email: bkeith@signalfx.com
icon: https://signalfx-82c9.kxcdn.com/wp-content/uploads/2015/12/signalfx-main-logo1.png
+27
View File
@@ -0,0 +1,27 @@
# SignalFx Agent
[SignalFx](https://signalfx.com) is a cloud monitoring and alerting solution
for modern enterprise infrastructures.
## Introduction
This chart will deploy the SignalFx agent as a DaemonSet to all nodes in your
cluster. It is designed to be run in only one release at a time.
See [the agent
docs](https://docs.signalfx.com/en/latest/integrations/kubernetes-quickstart.html)
for more information on how the agent works. The installation steps will be
different since you are using Helm but the agent otherwise behaves identically.
## Configuration
See the [values.yaml](./values.yaml) file for more information on how to
configure releases.
There are two **required** config options to run this chart: `signalFxAccessToken`
and `clusterName` (if not overridding the agent config template and providing your own
cluster name).
If you want to provide your own agent configuration, you can do so with the
`agentConfig` value. Otherwise, you can do a great deal of customization to
the provided config template using values.
+27
View File
@@ -0,0 +1,27 @@
{{- if not .Values.clusterName -}}
ERROR: You must set the value 'clusterName' to identify your cluster in
SignalFx. It can be any name you like.
{{- end }}
{{- if not .Values.signalFxAccessToken }}
ERROR: You must set the value 'signalFxAccessToken' to your organization's
access token.
If you do not have an access token, visit
https://docs.signalfx.com/en/latest/getting-started/index.html
and request a free trial.
{{- end }}
{{- if and .Values.signalFxAccessToken .Values.clusterName }}
The SignalFx agent is being deployed in your Kubernetes cluster. You should
see metrics flowing once the agent image is downloaded and started (this may
take a few minutes since it has to download the agent container image).
Assuming you are logged into SignalFx in your browser, visit
https://app.signalfx.com/#/navigator/kubernetes%20pods/kubernetes%20pods
to see all of the pods in your cluster.
{{- end }}
@@ -0,0 +1,43 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "signalfx-agent.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "signalfx-agent.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "signalfx-agent.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "signalfx-agent.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "signalfx-agent.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
@@ -0,0 +1,76 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "signalfx-agent.fullname" . }}
labels:
app: {{ template "signalfx-agent.name" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ template "signalfx-agent.chart" . }}
rules:
- apiGroups:
- ""
resources:
- events
- namespaces
- namespaces/status
- nodes
- nodes/spec
- pods
- pods/status
- replicationcontrollers
- replicationcontrollers/status
- services
# Only need to be able to view secrets if using k8s annotation
# agent.signalfx.com/configWithSecret.*. You can also whitelist specific
# secrets for finer-grain permission sets.
{{- if .Values.permitReadingSecrets }}
- secrets
{{- end }}
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- update
- create
- apiGroups:
- ""
resources:
- nodes/stats
verbs:
- get
- list
# We need create because kubelet takes a POST for the stat query
- create
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- replicasets
- statefulsets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- daemonsets
- deployments
- replicasets
verbs:
- get
- list
- watch
{{- with .Values.rbac.customRules }}
{{ toYaml . }}
{{- end }}
{{- end -}}
@@ -0,0 +1,19 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "signalfx-agent.fullname" . }}
labels:
app: {{ template "signalfx-agent.name" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ template "signalfx-agent.chart" . }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "signalfx-agent.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ template "signalfx-agent.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end -}}
@@ -0,0 +1,120 @@
{{- if and .Values.clusterName .Values.signalFxAccessToken -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "signalfx-agent.fullname" . }}
labels:
app: {{ template "signalfx-agent.name" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ template "signalfx-agent.chart" . }}
data:
agent.yaml: |
{{- if .Values.agentConfig }}
{{ toYaml .Values.agentConfig | indent 4 }}
{{- else }}
signalFxAccessToken: ${SFX_ACCESS_TOKEN}
intervalSeconds: {{ .Values.metricIntervalSeconds }}
logging:
level: {{ .Values.logLevel | default "info" }}
globalDimensions:
kubernetes_cluster: {{ .Values.clusterName }}
sendMachineID: true
observers:
- type: k8s-api
{{- if .Values.apiServerSkipVerify }}
kubernetesAPI:
skipVerify: true
{{- end }}
monitors:
- type: collectd/cpu
- type: collectd/cpufreq
- type: collectd/df
hostFSPath: /hostfs
- type: collectd/disk
- type: collectd/interface
- type: collectd/load
- type: collectd/memory
- type: collectd/protocols
- type: collectd/signalfx-metadata
procFSPath: /hostfs/proc
etcPath: /hostfs/etc
persistencePath: /run
- type: collectd/uptime
- type: collectd/vmem
- type: collectd/processes
processes:
- collectd
- signalfx-agent
- type: kubelet-stats
{{- if .Values.containerStatsIntervalSeconds }}
intervalSeconds: {{ .Values.containerStatsIntervalSeconds }}
{{- end }}
{{- if .Values.kubeletAPI }}
kubeletAPI:
{{ toYaml .Values.kubeletAPI | indent 8 | trim }}
{{- end }}
{{ if .Values.gatherClusterMetrics -}}
# Collects k8s cluster-level metrics
- type: kubernetes-cluster
{{- end }}
{{ if .Values.gatherDockerMetrics -}}
- type: docker-container-stats
dockerURL: unix:///var/run/docker.sock
excludedImages:
- '*pause-amd64*'
labelsToDimensions:
io.kubernetes.container.name: container_spec_name
io.kubernetes.pod.name: kubernetes_pod_name
io.kubernetes.pod.uid: kubernetes_pod_uid
io.kubernetes.pod.namespace: kubernetes_namespace
metricsToExclude:
- metricNames:
- 'cpu.usage*'
- 'cpu.percent'
- 'memory.usage*'
- 'memory.percent'
- 'blkio.io_service_bytes_recursive.*'
negated: true
{{- end }}
{{ range .Values.monitors -}}
- type: {{ .type }}
{{- with .discoveryRule }}
discoveryRule: {{ . }}
{{- end }}
{{- if (omit . "type" "discoveryRule") }}
{{ toYaml (omit . "type" "discoveryRule") | indent 6 | trim }}
{{- end }}
{{ end }}
collectd:
readThreads: {{ .Values.readThreads | default 5 }}
writeQueueLimitHigh: {{ .Values.writeQueueLimitHigh | default 500000 }}
writeQueueLimitLow: {{ .Values.writeQueueLimitLow | default 400000 }}
timeout: {{ .Values.timeout | default 40 }}
logLevel: {{ .Values.logLevel | default "notice" }}
metricsToExclude:
{{- if .Values.metricNamesToExclude }}
- metricNames:
{{- range .Values.metricNamesToExclude }}
- "{{ . }}"
{{- end }}
{{- end }}
{{- with .Values.metricsToExclude }}
{{ toYaml . | indent 6 }}
{{- end }}
{{- end }}
{{- end -}}
@@ -0,0 +1,102 @@
{{- if and .Values.clusterName .Values.signalFxAccessToken -}}
apiVersion: apps/v1beta2
kind: DaemonSet
metadata:
name: {{ template "signalfx-agent.fullname" . }}
labels:
app: {{ template "signalfx-agent.name" . }}
version: {{ .Values.agentVersion }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ template "signalfx-agent.chart" . }}
spec:
selector:
matchLabels:
app: {{ template "signalfx-agent.name" . }}
release: {{ .Release.Name }}
updateStrategy:
rollingUpdate:
maxUnavailable: {{ .Values.rollingUpdateMaxUnavailable | default 1 }}
type: RollingUpdate
template:
metadata:
labels:
app: {{ template "signalfx-agent.name" . }}
version: {{ .Values.agentVersion }}
release: {{ .Release.Name }}
{{ with .Values.extraPodLabels -}}
{{ toYaml . | indent 8 | trim }}
{{- end }}
spec:
# Use host network so we can access kubelet directly
hostNetwork: true
restartPolicy: Always
serviceAccountName: {{ template "signalfx-agent.serviceAccountName" . }}
{{ with .Values.image.pullSecret -}}
imagePullSecrets:
- name: {{ . }}
{{- end }}
tolerations:
{{ if .Values.runOnMaster -}}
- effect: NoSchedule
key: node.alpha.kubernetes.io/role
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
{{- end }}
{{ range .Values.tolerations -}}
- {{ toYaml . | indent 8 | trim }}
{{ end }}
containers:
- name: signalfx-agent
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Values.agentVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- /bin/signalfx-agent
volumeMounts:
- mountPath: /etc/signalfx
name: config
- mountPath: /etc/machine-id
name: machine-id
readOnly: true
- mountPath: /hostfs
name: hostfs
readOnly: true
- mountPath: /var/run/docker.sock
name: docker
readOnly: true
env:
- name: SFX_ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: {{ template "signalfx-agent.fullname" . }}
key: access-token
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: MY_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
volumes:
- name: config
configMap:
name: {{ template "signalfx-agent.fullname" . }}
- name: hostfs
hostPath:
path: /
- name: docker
hostPath:
path: /var/run/docker.sock
- name: machine-id
hostPath:
path: /etc/machine-id
{{- end -}}
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ template "signalfx-agent.fullname" . }}
labels:
app: {{ template "signalfx-agent.name" . }}
chart: {{ template "signalfx-agent.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
type: Opaque
data:
access-token: {{ .Values.signalFxAccessToken | b64enc | quote }}
@@ -0,0 +1,11 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: {{ template "signalfx-agent.name" . }}
chart: {{ template "signalfx-agent.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "signalfx-agent.serviceAccountName" . }}
{{- end -}}
+199
View File
@@ -0,0 +1,199 @@
# Version of the signalfx-agent to deploy. This will be the default for the
# docker image tag if not overridden with imageTag
agentVersion: 3.1.2
# The access token for SignalFx. REQUIRED
signalFxAccessToken: ""
# Docker image configuration
image:
# Image pull policy for the agent pod
pullPolicy: IfNotPresent
# The docker image to use for the agent
repository: quay.io/signalfx/signalfx-agent
# tag defaults to the agentVersion but can be overridden
tag:
# pullSecret is not needed for our standard image
pullSecret:
# How many agent pods can be unavailable at a time when rolling out a new
# version of the agent
rollingUpdateMaxUnavailable: 1
# RBAC config for the agent
rbac:
create: true
# You might need custom rules if you are pulling secrets to configure
# monitors.
customRules: []
# Service account config for the agent pods
serviceAccount:
# Specifies whether a ServiceAccount should be created
create: true
# The name of the ServiceAccount to use.
# If not set and create is true, a name is generated using the fullname template
name:
# This adds some tolerations to the pods that the DaemonSet creates that
# should allow the agent to run on the master nodes of newer versions of K8s
# that are deployed with standard master taints (see daemonset.yaml). If you
# need custom tolerations, see the 'tolerations' config option below.
runOnMaster: true
# You can specify additional tolerations for the pods that the DaemonSet
# creates.
tolerations: []
# Extra labels to put on agent pods. Values must be strings per the k8s label
# schema.
extraPodLabels: {}
# You can specify a custom agent config file with the agentConfig value. If
# you specify this, all of the options below here will no longer be applicable
# since they are used to render a default config (see configmap.yaml template).
agentConfig:
# clusterName must be provided. It is an arbitrary value that identifies this
# K8s cluster in SignalFx. This will be the value of the 'kubernetes_cluster'
# dimension on every metric sent by the agent.
clusterName:
# How frequently to send metrics by default in the agent. This can be
# overridden by individual monitors.
metricIntervalSeconds: 15
# The log level of the agent. Valid values are 'debug', 'info', 'warn', and
# 'error'. Info is a good default and won't be too spamy. Note that 'debug'
# may dump sensitive values in the provided configuration so use with care.
logLevel: info
# Whether to ignore TLS validation issue when connecting to the main K8s API
# server. This should almost never need to be set to true since the CA cert is
# provided with the service account token automatically by K8s.
apiServerSkipVerify: false
# Additional options for connecting to the Kubelet. These options are
# equivalent to what is under the 'kubeletAPI' key of the 'kubelet-stats'
# monitor. By default, the agent tries to use its service account if kubelet
# authentication is required.
kubeletAPI:
authType: serviceAccount
# Any values put in this object correspond to the 'collectd' config block of
# the agent config
collectd: {}
# How often to send cAdvisor-based container metrics. Defaults to whatever is
# in metricIntervalSeconds.
containerStatsIntervalSeconds:
# If true, K8s cluster-level metrics will be collected (e.g. pod counts,
# deployment status, etc). The agents will decide amongst themselves which
# instance should send the metrics so that they are only sent once.
gatherClusterMetrics: true
# Enables the docker-container-stats monitor with some specific config that
# causes it to send container stats from Docker with certain dimensions from
# container labels that makes it easy to correlate metrics between cadvisor and
# docker. Note that docker metrics are not sent for pause containers by
# default.
gatherDockerMetrics: true
# A list of metric names that are collected by monitors but are not to be sent
# to SignalFx. This default set include a lot of highly specific or duplicated
# cAdvisor metrics that cause a large increase in DPM for little value for most
# customers.
metricNamesToExclude:
- container_cpu_user_seconds_total
- container_cpu_system_seconds_total
- container_cpu_utilization_per_core
- container_fs_reads_total
- container_fs_sector_reads_total
- container_fs_reads_merged_total
- container_fs_read_seconds_total
- container_fs_writes_total
- container_fs_sector_writes_total
- container_fs_writes_merged_total
- container_fs_write_seconds_total
- container_fs_io_current
- container_fs_io_time_seconds_total
- container_fs_io_time_weighted_seconds_total
- container_last_seen
- container_tasks_state
- pod_network_receive_packets_total
- pod_network_receive_packets_dropped_total
- pod_network_transmit_packets_total
- pod_network_transmit_packets_dropped_total
- machine_cpu_frequency_khz
# A list of monitor configurations to include in the agent config. These
# values correspond exactly to what goes under 'monitors' in the agent config.
# The following are a set of monitors with discovery rules that should cover
# many standard deployments. Most users will want to override this with their
# own monitors and discovery rules.
monitors:
- type: collectd/activemq
discoveryRule: container_image =~ "activemq" && private_port == 1099
- type: collectd/apache
discoveryRule: container_image =~ "apache" && private_port == 80
- type: collectd/cassandra
discoveryRule: container_image =~ "cassandra" && private_port == 7199
- type: collectd/consul
discoveryRule: container_image =~ "consul" && private_port == 8500
- type: collectd/elasticsearch
discoveryRule: container_image =~ "elasticsearch" && port == 9200
- type: collectd/etcd
discoveryRule: container_image =~ "etcd" && port == 2379
# REQUIRED
clusterName: my-cluster
- type: collectd/haproxy
discoveryRule: container_image =~ "haproxy" && port == 9000
- type: collectd/kafka
discoveryRule: container_image =~ "kafka" && private_port == 9092
- type: collectd/memcached
discoveryRule: container_image =~ "memcache" && private_port == 11211
- type: collectd/mongodb
discoveryRule: container_image =~ "mongo" && private_port == 27017
# REQUIRED
databases:
- mydatabase
- type: collectd/mysql
discoveryRule: container_image =~ "mysql" && private_port == 3306
# REQUIRED
username: admin
databases:
- name: mydb
- type: collectd/nginx
discoveryRule: container_image =~ "nginx" && private_port == 80
- type: collectd/rabbitmq
discoveryRule: container_image =~ "rabbitmq" && private_port == 15672
- type: collectd/redis
discoveryRule: container_image =~ "redis" && private_port == 6379
- type: collectd/spark
discoveryRule: container_image =~ "spark" && private_port == 8080
isMaster: true
collectApplicationMetrics: true
clusterType: Standalone
- type: collectd/spark
discoveryRule: container_image =~ "spark" && private_port >= 8081
isMaster: false
clusterType: Standalone
- type: collectd/zookeeper
discoveryRule: container_image =~ "zookeeper" && private_port == 2181