diff --git a/Dockerfile b/Dockerfile index 4c306a6..d2439ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:19.10 LABEL maintainer="dmlabs.ch" -RUN groupadd -g 10000 sentry && useradd -u 10000 -g 10000 -s /bin/bash -m sentry +RUN groupadd -g 10000 sentry-outpost && useradd -u 10000 -g 10000 -s /bin/bash -m sentry-outpost RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y --no-install-recommends tzdata curl ca-certificates jq gnupg gnupg2 gnupg1 apt-transport-https bc && \ @@ -12,7 +12,7 @@ RUN apt-get update && \ apt-get -y autoremove && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -COPY --chown=sentry:sentry sentry-metrics.bash /opt/sentry-metrics.bash -USER sentry -WORKDIR /home/sentry -ENTRYPOINT ["/opt/sentry-metrics.bash"] \ No newline at end of file +COPY --chown=sentry-outpost:sentry-outpost collect-metrics.bash /opt/collect-metrics.bash +USER sentry-outpost +WORKDIR /home/sentry-outpost +ENTRYPOINT ["/opt/collect-metrics.bash"] \ No newline at end of file diff --git a/Helm/sentry-outpost/.helmignore b/Helm/sentry-outpost/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/Helm/sentry-outpost/.helmignore @@ -0,0 +1,22 @@ +# 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 +.vscode/ diff --git a/Helm/sentry-outpost/Chart.yaml b/Helm/sentry-outpost/Chart.yaml new file mode 100644 index 0000000..24148a0 --- /dev/null +++ b/Helm/sentry-outpost/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +name: sentry-outpost +description: A Helm chart for Sentry the simple monitoring tool for remote Kubernetes clusters + +# 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. +version: 0.1.0 \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/NOTES.txt b/Helm/sentry-outpost/templates/NOTES.txt new file mode 100644 index 0000000..9f8a2a1 --- /dev/null +++ b/Helm/sentry-outpost/templates/NOTES.txt @@ -0,0 +1,5 @@ +1. Sentry Outpost was successfully deployed +2. Make sure to add the needed Kubernetes secrets for the Sentry mission control like this: +kubectl create secret generic sentry-secrets --from-literal=INFLUXDB_USER= --from-literal=INFLUXDB_PW= -n +For example: +kubectl create secret generic sentry-secrets --from-literal=INFLUXDB_USER=foo --from-literal=INFLUXDB_PW=bar -n sentry \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/clusterrole-sentry-outpost.yaml b/Helm/sentry-outpost/templates/clusterrole-sentry-outpost.yaml new file mode 100644 index 0000000..fc7f7df --- /dev/null +++ b/Helm/sentry-outpost/templates/clusterrole-sentry-outpost.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app: sentry-outpost + name: sentry-outpost +rules: +- apiGroups: + - "" + resources: + - componentstatuses + - nodes + - endpoints + verbs: + - get + - list + - watch \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/clusterrolebinding-sentry-outpost.yaml b/Helm/sentry-outpost/templates/clusterrolebinding-sentry-outpost.yaml new file mode 100644 index 0000000..9fef4e7 --- /dev/null +++ b/Helm/sentry-outpost/templates/clusterrolebinding-sentry-outpost.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app: sentry-outpost + name: sentry-outpost +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: sentry-outpost +subjects: +- kind: ServiceAccount + name: sentry-outpost + namespace: sentry-outpost \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/configmap-sentry-outpost.yaml b/Helm/sentry-outpost/templates/configmap-sentry-outpost.yaml new file mode 100644 index 0000000..e3953c6 --- /dev/null +++ b/Helm/sentry-outpost/templates/configmap-sentry-outpost.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: sentry-config +data: + TZ: {{ .Values.clusterInformation.tz }} + CLUSTER_NAME: {{ .Values.clusterInformation.clusterName }} + INFLUXDB_URL: {{ .Values.sentryMissionControl.influxDBUrl | quote }} + INFLUXDB_PORT: {{ .Values.sentryMissionControl.influxDBPort | quote }} + INFLUXDB_NAME: {{ .Values.sentryMissionControl.influxDBName }} \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/cronjob-sentry-outpost.yaml b/Helm/sentry-outpost/templates/cronjob-sentry-outpost.yaml new file mode 100644 index 0000000..d5d04cb --- /dev/null +++ b/Helm/sentry-outpost/templates/cronjob-sentry-outpost.yaml @@ -0,0 +1,73 @@ +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + labels: + app: sentry + role: outpost + name: sentry-outpost +spec: + schedule: {{ .Values.sentryOutpost.schedule | quote }} + successfulJobsHistoryLimit: 2 + failedJobsHistoryLimit: 2 + concurrencyPolicy: Replace + jobTemplate: + spec: + template: + metadata: + labels: + app: sentry + role: outpost + spec: + securityContext: + runAsUser: 10000 + runAsGroup: 10000 + fsGroup: 10000 + containers: + - name: sentry-outpost + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + env: + - name: TZ + valueFrom: + configMapKeyRef: + name: sentry-config + key: TZ + - name: CLUSTER_NAME + valueFrom: + configMapKeyRef: + name: sentry-config + key: CLUSTER_NAME + - name: INFLUXDB_URL + valueFrom: + configMapKeyRef: + name: sentry-config + key: INFLUXDB_URL + - name: INFLUXDB_PORT + valueFrom: + configMapKeyRef: + name: sentry-config + key: INFLUXDB_PORT + - name: INFLUXDB_NAME + valueFrom: + configMapKeyRef: + name: sentry-config + key: INFLUXDB_NAME + - name: INFLUXDB_USER + valueFrom: + secretKeyRef: + name: sentry-secrets + key: INFLUXDB_USER + - name: INFLUXDB_PW + valueFrom: + secretKeyRef: + name: sentry-secrets + key: INFLUXDB_PW + resources: + requests: + memory: "45Mi" + cpu: "15m" + limits: + memory: "80Mi" + cpu: "1000m" + restartPolicy: OnFailure + serviceAccountName: sentry-outpost \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/network-policy-default-deny-allow-dns.yaml b/Helm/sentry-outpost/templates/network-policy-default-deny-allow-dns.yaml new file mode 100644 index 0000000..0dea65d --- /dev/null +++ b/Helm/sentry-outpost/templates/network-policy-default-deny-allow-dns.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: netpol-default-deny-allow-dns +spec: + podSelector: + matchLabels: {} + policyTypes: + - Ingress + - Egress + egress: + - to: + - namespaceSelector: + matchLabels: + name: kube-system + podSelector: + matchLabels: + name: kube-dns + - ports: + - protocol: TCP + port: 53 + - protocol: UDP + port: 53 \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/networkpolicy-sentry-outpost.yaml b/Helm/sentry-outpost/templates/networkpolicy-sentry-outpost.yaml new file mode 100644 index 0000000..2ea0256 --- /dev/null +++ b/Helm/sentry-outpost/templates/networkpolicy-sentry-outpost.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: netpol-sentry +spec: + podSelector: + matchLabels: + app: sentry + policyTypes: + - Ingress + - Egress + egress: + - to: [] + ports: + - protocol: TCP + port: {{ .Values.clusterInformation.kubeAPIServerPort }} + - protocol: TCP + port: {{ .Values.sentryMissionControl.influxDBPort }} \ No newline at end of file diff --git a/Helm/sentry-outpost/templates/servcieaccount-sentry-outpost.yaml b/Helm/sentry-outpost/templates/servcieaccount-sentry-outpost.yaml new file mode 100644 index 0000000..6e060cd --- /dev/null +++ b/Helm/sentry-outpost/templates/servcieaccount-sentry-outpost.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: sentry-outpost + name: sentry-outpost \ No newline at end of file diff --git a/Helm/sentry-outpost/values.yaml b/Helm/sentry-outpost/values.yaml new file mode 100644 index 0000000..69669c0 --- /dev/null +++ b/Helm/sentry-outpost/values.yaml @@ -0,0 +1,25 @@ +# Default values for kube-guard. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +image: + repository: quay.io/dmlabs/sentry + tag: latest + pullPolicy: IfNotPresent + +clusterInformation: + # Kubernetes cluster information for sentry to collect the correct metrics + clusterName: dmlabs-apps-prod + kubeAPIServerPort: 6443 + tz: Europe/Zurich + +sentryOutpost: + schedule: "*/1 * * * *" + +sentryMissionControl: + # InfluxDB URL and InfluxDB Name of the Sentry mission control + # NOTE: This chart expects InfluxDB with authentication and you need to create a Kubernetes secret with that information + # -> kubectl create secret generic sentry-secrets --from-literal=INFLUXDB_USER= --from-literal=INFLUXDB_PW= -n + influxDBUrl: http://influxdb.apps.dmlabs.ch + influxDBPort: 80 + influxDBName: sentry \ No newline at end of file diff --git a/README.md b/README.md index c2c4561..172d4fb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ -# sentry +# Sentry Simple monitoring tool for remote Kubernetes clusters + +# Licence + Copyright 2020 dmlabs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/sentry-metrics.bash b/collect-metrics.bash similarity index 68% rename from sentry-metrics.bash rename to collect-metrics.bash index 6ff563e..7481a21 100755 --- a/sentry-metrics.bash +++ b/collect-metrics.bash @@ -1,7 +1,63 @@ #!/bin/bash +# Prerequisites +# This script needs this environment variables to be set +# - CLUSTER_NAME +# - INFLUXDB_URL +# - INFLUXDB_PORT +# - INFLUXDB_NAME +# - INFLUXDB_USER +# - INFLUXDB_PW + STARTTIME=$(date +%s.%N) +# Define varialbes for log output +if [ -f /var/run/secrets/kubernetes.io/serviceaccount/ca.crt ] + then + OKLOGTARGET="/proc/1/fd/1" + ERRORLOGTARGET="/proc/1/fd/2" + else + OKLOGTARGET="/dev/stdout" + ERRORLOGTARGET="/dev/stderr" +fi + +# Check environment variables +if [[ -z $CLUSTER_NAME ]] + then + echo "ERROR - CLUSTER_NAME environment variable is not set" > $ERRORLOGTARGET + exit 0 +fi + +if [[ -z $INFLUXDB_URL ]] + then + echo "ERROR - INFLUXDB_URL environment variable is not set" > $ERRORLOGTARGET + exit 0 +fi + +if [[ -z $INFLUXDB_PORT ]] + then + echo "ERROR - INFLUXDB_PORT environment variable is not set" > $ERRORLOGTARGET + exit 0 +fi + +if [[ -z $INFLUXDB_NAME ]] + then + echo "ERROR - INFLUXDB_NAME environment variable is not set" > $ERRORLOGTARGET + exit 0 +fi + +if [[ -z $INFLUXDB_USER ]] + then + echo "ERROR - INFLUXDB_USER environment variable is not set" > $ERRORLOGTARGET + exit 0 +fi + +if [[ -z $INFLUXDB_PW ]] + then + echo "ERROR - INFLUXDB_PW environment variable is not set" > $ERRORLOGTARGET + exit 0 +fi + # Define global varialbes TEMPFILEPATH="/tmp" METRICSFILE="$TEMPFILEPATH/metrics.txt" @@ -42,6 +98,8 @@ if [ -f $ENDPOINTSFILE ] rm $ENDPOINTSFILE fi +echo "OK - preflight checks successful, start collecting metrics" > $OKLOGTARGET + # Actual script kubectl get endpoints -n default kubernetes >> /dev/null if (( $? != "0" )) @@ -125,6 +183,16 @@ echo "sentry_apiserver_endpoints_total,cluster=$CLUSTER_NAME value=$ENDPOINTSCOU ECHO_OVERALL_STATUS ECHO_DURATION -curl -i -XPOST "$INFLUXDB_URL/write?db=$INFLUXDB_NAME&u=$INFLUXDB_USER&p=$INFLUXDB_PW" --data-binary @$METRICSFILE +echo "OK - collecting metrics successful, start uploading to Sentry mission control: $INFLUXDB_URL:$INFLUXDB_PORT/write?db=$INFLUXDB_NAME" > $OKLOGTARGET + +curl -i -XPOST "$INFLUXDB_URL:$INFLUXDB_PORT/write?db=$INFLUXDB_NAME&u=$INFLUXDB_USER&p=$INFLUXDB_PW" --data-binary @$METRICSFILE + +if (( $? != "0" )) + then + echo "ERROR - uploading to Sentry mission control not successful" > $ERRORLOGTARGET + exit 0 + else + echo "OK - uploading to Sentry mission control successful" > $OKLOGTARGET +fi exit 0 \ No newline at end of file