From 07255dfd88592dfe7861949b8f4d5ba3ccbe227f Mon Sep 17 00:00:00 2001 From: Hamed Bahadorzadeh Date: Sat, 6 Feb 2021 14:20:07 +0330 Subject: [PATCH 1/4] helm chart added --- deploy/kubernetes-event-exporter/.helmignore | 23 +++++++ deploy/kubernetes-event-exporter/Chart.yaml | 24 +++++++ .../templates/NOTES.txt | 1 + .../templates/_config.yaml | 17 +++++ .../templates/_helpers.tpl | 62 +++++++++++++++++ .../templates/configmap.yaml | 7 ++ .../templates/deployment.yaml | 56 ++++++++++++++++ .../templates/rbac.yaml | 11 +++ .../templates/serviceaccount.yaml | 12 ++++ deploy/kubernetes-event-exporter/values.yaml | 67 +++++++++++++++++++ go.mod | 1 - 11 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 deploy/kubernetes-event-exporter/.helmignore create mode 100644 deploy/kubernetes-event-exporter/Chart.yaml create mode 100644 deploy/kubernetes-event-exporter/templates/NOTES.txt create mode 100644 deploy/kubernetes-event-exporter/templates/_config.yaml create mode 100644 deploy/kubernetes-event-exporter/templates/_helpers.tpl create mode 100644 deploy/kubernetes-event-exporter/templates/configmap.yaml create mode 100644 deploy/kubernetes-event-exporter/templates/deployment.yaml create mode 100644 deploy/kubernetes-event-exporter/templates/rbac.yaml create mode 100644 deploy/kubernetes-event-exporter/templates/serviceaccount.yaml create mode 100644 deploy/kubernetes-event-exporter/values.yaml diff --git a/deploy/kubernetes-event-exporter/.helmignore b/deploy/kubernetes-event-exporter/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/deploy/kubernetes-event-exporter/.helmignore @@ -0,0 +1,23 @@ +# 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 +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deploy/kubernetes-event-exporter/Chart.yaml b/deploy/kubernetes-event-exporter/Chart.yaml new file mode 100644 index 00000000..af5f9414 --- /dev/null +++ b/deploy/kubernetes-event-exporter/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: kubernetes-event-exporter +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/deploy/kubernetes-event-exporter/templates/NOTES.txt b/deploy/kubernetes-event-exporter/templates/NOTES.txt new file mode 100644 index 00000000..f446d52c --- /dev/null +++ b/deploy/kubernetes-event-exporter/templates/NOTES.txt @@ -0,0 +1 @@ +Event exporter is running! diff --git a/deploy/kubernetes-event-exporter/templates/_config.yaml b/deploy/kubernetes-event-exporter/templates/_config.yaml new file mode 100644 index 00000000..d55cedac --- /dev/null +++ b/deploy/kubernetes-event-exporter/templates/_config.yaml @@ -0,0 +1,17 @@ +{{- define "config.yaml"}} +{{- if .Values.configOverride }} +{{- toYaml .Values.configOverride }} +{{- else }} +logLevel: {{ .Values.config.log.level}} +logFormat: {{ .Values.config.log.format}} +route: + routes: + {{- range .Values.config.routes }} + - {{- toYaml . | nindent 6}} + {{- end }} +receivers: + {{- range .Values.config.receivers }} + - {{- toYaml . | nindent 6}} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/kubernetes-event-exporter/templates/_helpers.tpl b/deploy/kubernetes-event-exporter/templates/_helpers.tpl new file mode 100644 index 00000000..aa259cd9 --- /dev/null +++ b/deploy/kubernetes-event-exporter/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "kubernetes-event-exporter.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 "kubernetes-event-exporter.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 "kubernetes-event-exporter.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "kubernetes-event-exporter.labels" -}} +helm.sh/chart: {{ include "kubernetes-event-exporter.chart" . }} +{{ include "kubernetes-event-exporter.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kubernetes-event-exporter.selectorLabels" -}} +app.kubernetes.io/name: {{ include "kubernetes-event-exporter.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "kubernetes-event-exporter.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "kubernetes-event-exporter.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/kubernetes-event-exporter/templates/configmap.yaml b/deploy/kubernetes-event-exporter/templates/configmap.yaml new file mode 100644 index 00000000..32ac10e5 --- /dev/null +++ b/deploy/kubernetes-event-exporter/templates/configmap.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: event-exporter-cfg +data: + config.yaml: | +{{ include "config.yaml" . | indent 4}} \ No newline at end of file diff --git a/deploy/kubernetes-event-exporter/templates/deployment.yaml b/deploy/kubernetes-event-exporter/templates/deployment.yaml new file mode 100644 index 00000000..f9bedea3 --- /dev/null +++ b/deploy/kubernetes-event-exporter/templates/deployment.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "kubernetes-event-exporter.fullname" . }} + labels: + {{- include "kubernetes-event-exporter.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "kubernetes-event-exporter.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "kubernetes-event-exporter.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "kubernetes-event-exporter.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - -conf=/data/config.yaml + volumeMounts: + - mountPath: /data + name: cfg + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: cfg + configMap: + name: event-exporter-cfg + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deploy/kubernetes-event-exporter/templates/rbac.yaml b/deploy/kubernetes-event-exporter/templates/rbac.yaml new file mode 100644 index 00000000..53421c45 --- /dev/null +++ b/deploy/kubernetes-event-exporter/templates/rbac.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "kubernetes-event-exporter.serviceAccountName" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: view +subjects: + - kind: ServiceAccount + name: {{ include "kubernetes-event-exporter.serviceAccountName" . }} \ No newline at end of file diff --git a/deploy/kubernetes-event-exporter/templates/serviceaccount.yaml b/deploy/kubernetes-event-exporter/templates/serviceaccount.yaml new file mode 100644 index 00000000..92fd788e --- /dev/null +++ b/deploy/kubernetes-event-exporter/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "kubernetes-event-exporter.serviceAccountName" . }} + labels: + {{- include "kubernetes-event-exporter.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/kubernetes-event-exporter/values.yaml b/deploy/kubernetes-event-exporter/values.yaml new file mode 100644 index 00000000..6eef954f --- /dev/null +++ b/deploy/kubernetes-event-exporter/values.yaml @@ -0,0 +1,67 @@ +# Default values for kubernetes-event-exporter. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: opsgenie/kubernetes-event-exporter + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "0.9" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +config: + log: + level: error + format: json + routes: + - match: + - receiver: "dump" + receivers: + - name: "dump" + file: + path: "/dev/stdout" \ No newline at end of file diff --git a/go.mod b/go.mod index 2da3632d..b16a9269 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/opsgenie/kubernetes-event-exporter go 1.14 require ( - cloud.google.com/go v0.60.0 // indirect cloud.google.com/go/bigquery v1.9.0 cloud.google.com/go/pubsub v1.3.1 github.com/Masterminds/goutils v1.1.0 // indirect From e1ad05cde2a87cff1a94ef513b2d43a7660f85d3 Mon Sep 17 00:00:00 2001 From: Hamed Bahadorzadeh Date: Sat, 6 Feb 2021 14:40:54 +0330 Subject: [PATCH 2/4] this file was not meant to be changed in last commit --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index b16a9269..ecc9cec1 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/opsgenie/kubernetes-event-exporter go 1.14 require ( + cloud.google.com/go v0.60.0 // indirect cloud.google.com/go/bigquery v1.9.0 cloud.google.com/go/pubsub v1.3.1 github.com/Masterminds/goutils v1.1.0 // indirect From 9402357521e7c8441cfbf572dea3c860b6c42078 Mon Sep 17 00:00:00 2001 From: Hamed Bahadorzadeh Date: Sun, 7 Feb 2021 12:48:00 +0330 Subject: [PATCH 3/4] udp logger added --- config.example.yaml | 4 +++ pkg/sinks/receiver.go | 5 +++ pkg/sinks/udp.go | 84 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 pkg/sinks/udp.go diff --git a/config.example.yaml b/config.example.yaml index 21300a7f..4831de38 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -7,6 +7,7 @@ route: # This route allows dumping all events because it has no fields to match and no drop rules. - match: - receiver: "dump" + - receiver: "syslog" # This starts another route, drops all the events in *test* namespaces and Normal events # for capturing critical events - drop: @@ -27,6 +28,9 @@ receivers: hosts: - "http://localhost:9200" indexFormat: "kube-events-{2006-01-02}" + - name: "syslog" + udp: + host: "localhost:514" - name: "alert" opsgenie: apiKey: "" diff --git a/pkg/sinks/receiver.go b/pkg/sinks/receiver.go index 6733d3e0..ba1d9e22 100644 --- a/pkg/sinks/receiver.go +++ b/pkg/sinks/receiver.go @@ -19,6 +19,7 @@ type ReceiverConfig struct { Opscenter *OpsCenterConfig `yaml:"opscenter"` Teams *TeamsConfig `yaml:"teams"` BigQuery *BigQueryConfig `yaml:"bigquery"` + Udp *UDPConfig `yaml:"udp"` } func (r *ReceiverConfig) Validate() error { @@ -87,5 +88,9 @@ func (r *ReceiverConfig) GetSink() (Sink, error) { return NewBigQuerySink(r.BigQuery) } + if r.Udp != nil{ + return NewUDPClient(r.Udp) + } + return nil, errors.New("unknown sink") } diff --git a/pkg/sinks/udp.go b/pkg/sinks/udp.go new file mode 100644 index 00000000..d92c5f49 --- /dev/null +++ b/pkg/sinks/udp.go @@ -0,0 +1,84 @@ +package sinks + +import ( + "context" + "encoding/json" + "fmt" + "github.com/opsgenie/kubernetes-event-exporter/pkg/kube" + "github.com/rs/zerolog/log" + "net" +) + +type UDPConfig struct { + Host string `yaml:"host"` + Layout map[string]interface{} `yaml:"layout"` +} + +type UDPClient struct { + msgChan chan []byte + context context.Context + conn net.Conn + cfg *UDPConfig +} + +func NewUDPClient(cfg *UDPConfig)(*UDPClient, error){ + raddr, err := net.ResolveUDPAddr("udp", cfg.Host) + if err != nil { + return nil, err + } + conn, err := net.DialUDP("udp", nil, raddr) + if err != nil { + return nil, err + } + client := &UDPClient{ + msgChan: make(chan []byte), + context: context.Background(), + conn: conn, + cfg: cfg, + } + + go client.loop() + + return client, nil +} + +func (u *UDPClient) loop(){ + for { + select { + case msg := <-u.msgChan: + _, err := fmt.Fprintf(u.conn, "%s", msg) + if err != nil { + log.Debug().Str("sink", "udp").Str("event", err.Error()).Msg("failed to send log") + } + log.Debug().Str("sink", "udp").Msg("log send successfully") + case <-u.context.Done(): + log.Debug().Str("sink", "udp").Msg("context done") + return + } + } +} + +func (u *UDPClient) Send(ctx context.Context, ev *kube.EnhancedEvent) error { + var toSend []byte + + if u.cfg.Layout != nil { + res, err := convertLayoutTemplate(u.cfg.Layout, ev) + if err != nil { + return err + } + + toSend, err = json.Marshal(res) + if err != nil { + return err + } + } else { + toSend = ev.ToJSON() + } + + u.msgChan <- append(toSend, '\n') + return nil +} + +func (u *UDPClient) Close() { + u.conn.Close() +} From ea6eec72f27d6c99a696d65a028aa4faa966147e Mon Sep 17 00:00:00 2001 From: Hamed Bahadorzadeh Date: Sun, 7 Feb 2021 13:06:50 +0330 Subject: [PATCH 4/4] Updated README file --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f0ee5405..610bd018 100644 --- a/README.md +++ b/README.md @@ -339,10 +339,20 @@ receivers: timeout_seconds: ``` +# Udp + +It could be used to send json logs to logstash +```yaml +receivers: + - name: "my-udp" + udp: + host: +``` + + ### Planned Receivers -- Big Query - AWS Firehose - Splunk - Redis -- Logstash +- Logstash(Upd Receiver?)