Skip to content

Modernize the container #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
k8s/
test/
Makefile
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test/test.sh -text eol=lf
start.sh -text eol=lf

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.k3d*
.helm-setup
9 changes: 6 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
FROM centos:7
FROM alpine:3.13.5
ENV RSYSLOG_PORT=514 RSYSLOG_PROTOCOL=udp

RUN curl -s -L -o /etc/yum.repos.d/rsyslog.repo http://rpms.adiscon.com/v8-stable/rsyslog.repo
RUN yum -y install rsyslog gettext && yum clean all
RUN apk add --no-cache rsyslog gettext

COPY rsyslog.conf.template /etc/rsyslog.conf.template
COPY start.sh /start.sh

# So we can make the root file system read-only
RUN ln -sf /var/lib/rsyslog/rsyslog.conf /etc/rsyslog.conf

RUN chmod +x /start.sh

CMD /start.sh
87 changes: 87 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
IMAGE=localhost:5000/syslog-agent
DEFAULT_METRICS=kube-state-metrics
LOCAL_PORT=8081

## make build -- build the image
build: .k3d-image

.k3d-image: Dockerfile start.sh rsyslog.conf.template
docker build -t $(IMAGE) .
@touch $@

## make push -- push the image to the local k3d registry
push: .k3d-registry .k3d-image
docker push $(IMAGE)

## make test -- install all components and run a simple test by cURLing the NGINX container and looking for the access record
test: build up k8s ready
bash test/test.sh

## run a Snyk scan on the image
scan:
docker scan $(IMAGE)

## make k8s or make deploy -- install the components into the cluster
k8s deploy: push .k3d
kubectl apply -f k8s -f test

## make up -- create and configure the testing cluster
k3d-up k3d cluster cluster-up up: .k3d

## make down -- delete the testing cluster
k3d-down cluster-down down:
k3d cluster delete syslog
k3d registry delete local
rm -f .k3d-*

## make ready -- wait for all components to be ready
ready:
@echo -n "Waiting for pod count..."
@while [ "$$(kubectl get pods -A | wc -l)" -lt 4 ] ; do sleep 2; echo -n .; done || true
@echo "DONE"
@echo -n "Waiting for pods ready..."
@while kubectl get pods -A | grep -q -E 'Pending|ContainerCreating'; do sleep 2; echo -n . ; done || true
@echo "READY"

.k3d: .k3d-cluster .k3d-kube-state-metrics

.k3d-cluster: .k3d-registry
k3d cluster create syslog -p "$(LOCAL_PORT):80@loadbalancer" --registry-use local
# @echo "Waiting for cluster to initialize"
# @while [ -n "kubectl get -n kube-system pods | grep ContainerCreating" ]; do echo -n "."; sleep 3; done
# @echo DONE
touch $@

.k3d-registry:
k3d registry create local -p 5000
touch $@


# Install the selected metrics server package
metrics: .k3d-$(DEFAULT_METRICS)

.k3d-kube-state-metrics: .helm-setup
helm install -n kube-system metrics prometheus-community/kube-state-metrics
touch $@

.k3d-prometheus:
helm install -n kube-system prometheus prometheus-community/kube-prometheus-stack
touch $@ .k3d-kube-state-metrics

# Run a local helm setup
helm: .helm-setup

.helm-setup:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
touch $@

clean:
-make -f $(lastword $(MAKEFILE_LIST)) down >/dev/null 2>/dev/null
rm -f .helm-setup

real-clean: clean
docker image rm $(IMAGE)

help:
awk '/^##/{print}' $(lastword $(MAKEFILE_LIST))
30 changes: 23 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
# Kubernetes Container Log Syslog Forwarder

This container is designed to run as a DaemonSet and forwards pod logs to a syslog
listener for all pods running on a node. Log forwarding is implemented with
[RSYSLOG](http://www.rsyslog.com/) and uses [omfwd](http://www.rsyslog.com/doc/v8-stable/configuration/modules/omfwd.html) module.
This container is designed to run as a DaemonSet and forwards pod logs to a syslog listener for all
pods running on a node. Log forwarding is implemented with
[RSYSLOG](http://www.rsyslog.com/) and
uses [omfwd](http://www.rsyslog.com/doc/v8-stable/configuration/modules/omfwd.html) module.

## Configuration Options

Configuration can be done with environment variables:

* **RSYSLOG_TARGET** - Remote syslog listener
* **RSYSLOG_PORT** - Remote syslog listener port
* **RSYSLOG_PROTOCOL** - Remote syslog listener protocol (udp/tcp)

## Example DaemonSet
DaemonSet example requires a privileged SCC if using k8s v1.5+ or OpenShift and
probably needs rsyslog already installed in order to use /var/lib/rsyslog on the
host as the place for the file state directory
## DaemonSet

A working example of a deployment daemonset can be found in the [k8s](./k8s) directory, along with
an example ConfigMap. You will need to adjust the configmap to suit your system.

## Hacking

The `Makefile` included here is set up to assist development *and* testing of the system,
using [`k3d`](https://k3d.io/). It will fully set up a test cluster, install all necessary
components, and run a simple test.

Use `make test` to perform all of these

**NOTE:** there is currently an occasional timing issue where the test will fail right after the
cluster is up. If this happens, wait 30 seconds and attempt `make test` again.

Use `make help` to display information about available targets

39 changes: 39 additions & 0 deletions k8s/agent.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: syslog-agent
labels:
app: syslog-agent
spec:
selector:
matchLabels:
app: syslog-agent
template:
metadata:
labels:
app: syslog-agent
spec:
containers:
- name: syslog-agent
image: k3d-local:5000/syslog-agent
envFrom:
- configMapRef:
name: syslog-agent-config
volumeMounts:
- mountPath: /var/log
name: logs
readOnly: true
- mountPath: /var/lib/rsyslog
name: work
securityContext:
readOnlyRootFilesystem: true
volumes:
- name: logs
hostPath:
path: /var/log
- name: work
emptyDir: {}




8 changes: 8 additions & 0 deletions k8s/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: syslog-agent-config
data:
RSYSLOG_PORT: "514"
RSYSLOG_PROTOCOL: UDP
RSYSLOG_TARGET: rsyslog
8 changes: 3 additions & 5 deletions start.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/bin/bash
#!/bin/sh

rm -f /etc/rsyslog.conf
envsubst < /etc/rsyslog.conf.template > /var/lib/rsyslog/rsyslog.conf

envsubst < /etc/rsyslog.conf.template > /etc/rsyslog.conf

exec /sbin/rsyslogd -n
exec /usr/sbin/rsyslogd -n
59 changes: 59 additions & 0 deletions test/nginx.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
resources: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: ClusterIP
---
# apiVersion: networking.k8s.io/v1beta1 # for k3s < v1.19
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
59 changes: 59 additions & 0 deletions test/rsyslog.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
apiVersion: v1
kind: Service
metadata:
name: rsyslog
labels:
app: rsyslog
spec:
selector:
app: rsyslog
ports:
- protocol: UDP
port: 514
targetPort: 514
name: syslog-udp
- protocol: TCP
port: 514
targetPort: 514
name: syslog-tcp
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: rsyslog
name: rsyslog
spec:
replicas: 1
selector:
matchLabels:
app: rsyslog
template:
metadata:
labels:
app: rsyslog
spec:
containers:
- image: voxxit/rsyslog
name: rsyslog
ports:
- containerPort: 514
protocol: UDP
name: syslog-udp
- containerPort: 514
protocol: TCP
name: syslog-tcp
env:
- name: TZ
value: America/New_York
livenessProbe:
tcpSocket:
port: 514
readinessProbe:
exec:
command:
- test
- -s
- /var/log/messages

15 changes: 15 additions & 0 deletions test/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

# purpose: test the k8s cluster to see if a log message gets through

DATE=$(date +%y%m%d%H%M%S)
curl -s "http://localhost:8081/testing/${DATE}" > /dev/null

pod=$(kubectl get pods -l app=rsyslog | awk '!/NAME/{print $1}')
if kubectl exec "$pod" -- grep -q "testing/${DATE}" /var/log/messages
then
echo "PASS"
else
echo "FAIL"
exit 1
fi