diff --git a/stable/signalfx-agent/.helmignore b/stable/signalfx-agent/.helmignore new file mode 100644 index 0000000000..f0c1319444 --- /dev/null +++ b/stable/signalfx-agent/.helmignore @@ -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 diff --git a/stable/signalfx-agent/Chart.yaml b/stable/signalfx-agent/Chart.yaml new file mode 100644 index 0000000000..7b8dd0ca0f --- /dev/null +++ b/stable/signalfx-agent/Chart.yaml @@ -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 diff --git a/stable/signalfx-agent/README.md b/stable/signalfx-agent/README.md new file mode 100644 index 0000000000..b941d7ea81 --- /dev/null +++ b/stable/signalfx-agent/README.md @@ -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. diff --git a/stable/signalfx-agent/templates/NOTES.txt b/stable/signalfx-agent/templates/NOTES.txt new file mode 100644 index 0000000000..a622dbe8c5 --- /dev/null +++ b/stable/signalfx-agent/templates/NOTES.txt @@ -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 }} diff --git a/stable/signalfx-agent/templates/_helpers.tpl b/stable/signalfx-agent/templates/_helpers.tpl new file mode 100644 index 0000000000..ab802cc34a --- /dev/null +++ b/stable/signalfx-agent/templates/_helpers.tpl @@ -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 -}} diff --git a/stable/signalfx-agent/templates/clusterrole.yaml b/stable/signalfx-agent/templates/clusterrole.yaml new file mode 100644 index 0000000000..56f278150d --- /dev/null +++ b/stable/signalfx-agent/templates/clusterrole.yaml @@ -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 -}} diff --git a/stable/signalfx-agent/templates/clusterrolebinding.yaml b/stable/signalfx-agent/templates/clusterrolebinding.yaml new file mode 100644 index 0000000000..aeb59561ab --- /dev/null +++ b/stable/signalfx-agent/templates/clusterrolebinding.yaml @@ -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 -}} diff --git a/stable/signalfx-agent/templates/configmap.yaml b/stable/signalfx-agent/templates/configmap.yaml new file mode 100644 index 0000000000..5f2d562283 --- /dev/null +++ b/stable/signalfx-agent/templates/configmap.yaml @@ -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 -}} diff --git a/stable/signalfx-agent/templates/daemonset.yaml b/stable/signalfx-agent/templates/daemonset.yaml new file mode 100644 index 0000000000..c0534088d8 --- /dev/null +++ b/stable/signalfx-agent/templates/daemonset.yaml @@ -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 -}} diff --git a/stable/signalfx-agent/templates/secrets.yaml b/stable/signalfx-agent/templates/secrets.yaml new file mode 100644 index 0000000000..3facecd0f2 --- /dev/null +++ b/stable/signalfx-agent/templates/secrets.yaml @@ -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 }} diff --git a/stable/signalfx-agent/templates/serviceaccount.yaml b/stable/signalfx-agent/templates/serviceaccount.yaml new file mode 100644 index 0000000000..a5b9ecad50 --- /dev/null +++ b/stable/signalfx-agent/templates/serviceaccount.yaml @@ -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 -}} diff --git a/stable/signalfx-agent/values.yaml b/stable/signalfx-agent/values.yaml new file mode 100644 index 0000000000..1c7f823e98 --- /dev/null +++ b/stable/signalfx-agent/values.yaml @@ -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