Skip to content

Commit

Permalink
Initial release of Kubebernets deployment events Logz.io integration
Browse files Browse the repository at this point in the history
- Watches for deployment events when a Kubernetes resource object is created, modified or deleted using Kubernetes GoLang SDK.
- Correlates deployment events with related resources.
- Currently supports resource kinds: deployments, daemonsets, statefulsets, configmaps, secrets, service accounts, cluster roles & cluster role bindings.
- Sends the deployment events using Logz.io SDK.
- Added Github workflow automation to update DockerHub.
  • Loading branch information
ralongit committed Sep 2, 2023
1 parent 3fae031 commit c68f969
Show file tree
Hide file tree
Showing 13 changed files with 2,024 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/update-docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Docker Image CI

on:
release:
types: [published]


jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Build and push version
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
logzio/logzio-k8s-events:${{ github.event.release.tag_name }}
logzio/logzio-k8s-events:latest
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.19-alpine AS build

LABEL authors="ralongit"
WORKDIR /app

COPY . .

RUN go build -o main .

FROM alpine:3.14
COPY --from=build /app/main /app/main

CMD ["/app/main"]
84 changes: 84 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[![Docker Image CI](https://github.com/logzio/logzio-k8s-events/actions/workflows/update-docker.yaml/badge.svg)](https://github.com/logzio/logzio-k8s-events/actions/workflows/update-docker.yaml)
# logzio-k8s-events
Integration to send Kubernetes deployment events logs.

# Logz.io Kubernetes Events

Helm is a tool for managing packages of pre-configured Kubernetes resources using Charts.
Logzio-K8S-Events helm chart allows you to deploy a daemonset that will ship deployment event logs from your Kubernetes cluster to Logz.io.


**Note**: This chart is for shipping Kubernetes deployment event logs only. For a chart that ships all telemetry (logs, metrics, traces, spm) - use our [Logzio Monitoring chart](https://github.com/logzio/logzio-helm/tree/master/charts/logzio-monitoring).


### Prerequisites:
* [Helm CLI](https://helm.sh/docs/intro/install/) installed
* Allow outgoing traffic to destination port 8071


**Note:** Helm 2 will reach [EOL on November 2020](https://helm.sh/blog/2019-10-22-helm-2150-released/#:~:text=6%20months%20after%20Helm%203's,Helm%202%20will%20formally%20end). This document follows the command syntax recommended for Helm 3, but the Chart will work with both Helm 2 and Helm 3.


<div id="standard-config">

### Configuration deployment:

#### 1. Add logzio-helm repo to your helm repo list

```shell
helm repo add logzio-helm https://logzio.github.io/logzio-helm
helm repo update
```

#### 2. Deploy

Replace `<<SHIPPING-TOKEN>>` with the [token](https://app.logz.io/#/dashboard/settings/general) of the account you want to ship to.

Replace `<<LISTENER-HOST>>` with your region’s host address (for example, `listener-eu.logz.io`). For more information on finding your account’s region, see [Account region](https://docs.logz.io/user-guide/accounts/account-region.html).

Replace `<<ENV-ID>>` with your environment name.

```shell
helm install --namespace=monitoring \
--set secrets.logzioShippingToken='<<SHIPPING-TOKEN>>' \
--set secrets.logzioListener='<<LISTENER-HOST>>' \
--set secrets.env_id='<<ENV-ID>>' \
logzio-informer-events logzio-helm/logzio-informer-events
```

#### 3. Check Logz.io for your logs
Give your logs some time to get from your system to ours, and then open [Logz.io](https://app.logz.io/).

</div>

### Uninstalling the Chart

The command removes all the k8s components associated with the chart and deletes the release.
To uninstall the `logzio-k8s-events` deployment:

```shell
helm uninstall --namespace=monitoring logzio-informer-events
```

## Sending logs from nodes with taints

If you want to ship logs from any of the nodes that have a taint, make sure that the taint key values are listed in your in your daemonset configuration as follows:

```yaml
tolerations:
- key:
operator:
value:
effect:
```
To determine if a node uses taints as well as to display the taint keys, run:
```sh
kubectl get nodes -o json | jq ".items[]|{name:.metadata.name, taints:.spec.taints}"
```


## Change log
- **0.0.1**:
- Initial release.
48 changes: 48 additions & 0 deletions common/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package common

import (
"fmt"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"log"
"os"
)

var K8sClient *kubernetes.Clientset
var DynamicClient *dynamic.DynamicClient

func CreateClusterClient() {
// Create a Kubernetes client.
config, err := rest.InClusterConfig()
if err != nil {
fmt.Println(err)
return
}
K8sClient, err = kubernetes.NewForConfig(config)
if err != nil {
fmt.Println(err)
return
}
}

func ConfigureClusterDynamicClient() (clusterClient *dynamic.DynamicClient) {
//
var err error
var clusterConfig *rest.Config
kubeConfig := os.Getenv("KUBECONFIG")
if kubeConfig != "" {
clusterConfig, err = clientcmd.BuildConfigFromFlags("", kubeConfig)
} else {
clusterConfig, err = rest.InClusterConfig()
}
if err != nil {
log.Fatalln(err)
}
clusterClient, err = dynamic.NewForConfig(clusterConfig)
if err != nil {
log.Fatalln(err)
}
return clusterClient
}
86 changes: 86 additions & 0 deletions common/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package common

import (
"encoding/json"
"fmt"
"github.com/logzio/logzio-go"
"log"
"os"
"time"
)

var LogzioLogger *logzio.LogzioSender

func ConfigureLogzioLogger() (LogzioLogger *logzio.LogzioSender) {
// Creates a resources using Logz.io output configuration: https://app.logz.io/#/dashboard/send-your-data/log-sources/go
var err error
LogzioToken := os.Getenv("LOGZIO_TOKEN") // Log shipping token for Logz.io
if LogzioToken != "" {
LogzioListener := os.Getenv("LOGZIO_LISTENER")
if LogzioListener == "" {
LogzioListener = "https://listener.logz.io:8071" // Defaults to us-east-1 region
}
LogzioLogger, err = logzio.New(
LogzioToken,
logzio.SetDebug(os.Stderr),
logzio.SetUrl(LogzioListener),
logzio.SetDrainDuration(time.Second*5),
logzio.SetTempDirectory("myQueue"),
logzio.SetDrainDiskThreshold(99),
)
if err != nil {
log.Fatalf("\n[FATAL] Failed to configure the Logz.io resources.\nERROR: %v\n", err)
}
} else {
log.Fatalf("\n[FATAL] Invalid token configured for LOGZIO_TOKEN environemt variable.\n")
}
return LogzioLogger
}
func shipLogMessage(message string) {

log.Printf("\n[LOG]: %s\n", message)
err := LogzioLogger.Send([]byte(message))
if err != nil {
log.Printf("\nFailed to send log:\n%v to Logz.io.\nRelated error:\n%v.", message, err)
return
}

LogzioLogger.Drain()
}
func SendLog(msg string, extraFields ...interface{}) {
var err error
var parsedEventLog []byte
var logMap map[string]interface{}
environmentID := os.Getenv("ENV_ID")
logType := os.Getenv("LOG_TYPE")
if logType == "" {
logType = "logzio-informer-events"
}
logEvent := LogEvent{Message: msg, Type: logType, EnvironmentID: environmentID}

if len(extraFields) > 0 {
extra := fmt.Sprintf("%s", extraFields...)

log.Printf("\n[DEBUG] Attemping to parse log extra data(%T): %s\tlog(%T):\n%v to Logz.io.\n", extra, extra, logEvent, logEvent)

if err := json.Unmarshal([]byte(extra), &logEvent); err != nil && extra != "" {
log.Printf("\n[ERROR] Failed to parse log extra data(%T): %s\tlog(%T):\n%v to Logz.io.\nRelated error:\n%v", extra, logEvent, extra, logEvent, err)

}
}
logByte, _ := json.Marshal(&logEvent)
json.Unmarshal(logByte, &logMap)
parsedLogMap := parseLogzioLimits(logMap)
parsedEventLog, err = json.Marshal(parsedLogMap)
if err != nil {
log.Printf("\n[ERROR] Failed to parse event log:\n%v\nERROR:\n%v", logEvent, err)
}

message := fmt.Sprintf("%s", string(parsedEventLog))
if message == "" {
log.Printf("\n[DEBUG]: Empty message, not sending to Logz.io.\n")
} else {
go shipLogMessage(message)
}

}
Loading

0 comments on commit c68f969

Please sign in to comment.