diff --git a/_apps/loki.yaml b/_apps/loki.yaml new file mode 100644 index 0000000..5aec284 --- /dev/null +++ b/_apps/loki.yaml @@ -0,0 +1,21 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: loki + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: loki + server: https://kubernetes.default.svc + project: default + source: + path: loki + repoURL: https://git.tbrnt.ch/tobru/gitops-tbrnt.git + targetRevision: HEAD +--- +apiVersion: v1 +kind: Namespace +metadata: + name: loki diff --git a/loki/Makefile b/loki/Makefile new file mode 100644 index 0000000..84017b8 --- /dev/null +++ b/loki/Makefile @@ -0,0 +1,8 @@ +build: + helm3 template loki --namespace=loki loki/loki-stack > loki.yaml +.PHONY: build + +update: + helm3 repo update + helm3 search repo loki-stack +.PHONY: update diff --git a/loki/loki.yaml b/loki/loki.yaml new file mode 100644 index 0000000..83cacaf --- /dev/null +++ b/loki/loki.yaml @@ -0,0 +1,835 @@ +--- +# Source: loki-stack/charts/loki/templates/podsecuritypolicy.yaml +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: loki + namespace: loki + labels: + app: loki + chart: loki-0.25.1 + heritage: Helm + release: loki +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'persistentVolumeClaim' + - 'secret' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: true + requiredDropCapabilities: + - ALL +--- +# Source: loki-stack/charts/promtail/templates/podsecuritypolicy.yaml +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: loki-promtail + namespace: loki + labels: + app: promtail + chart: promtail-0.19.2 + heritage: Helm + release: loki +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'secret' + - 'configMap' + - 'hostPath' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: true + requiredDropCapabilities: + - ALL +--- +# Source: loki-stack/charts/loki/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: loki + chart: loki-0.25.1 + heritage: Helm + release: loki + annotations: + {} + name: loki + namespace: loki +--- +# Source: loki-stack/charts/promtail/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: promtail + chart: promtail-0.19.2 + heritage: Helm + release: loki + name: loki-promtail + namespace: loki +--- +# Source: loki-stack/charts/loki/templates/secret.yaml +apiVersion: v1 +kind: Secret +metadata: + name: loki + namespace: loki + labels: + app: loki + chart: loki-0.25.1 + release: loki + heritage: Helm +data: + loki.yaml: YXV0aF9lbmFibGVkOiBmYWxzZQpjaHVua19zdG9yZV9jb25maWc6CiAgbWF4X2xvb2tfYmFja19wZXJpb2Q6IDAKaW5nZXN0ZXI6CiAgY2h1bmtfYmxvY2tfc2l6ZTogMjYyMTQ0CiAgY2h1bmtfaWRsZV9wZXJpb2Q6IDNtCiAgY2h1bmtfcmV0YWluX3BlcmlvZDogMW0KICBsaWZlY3ljbGVyOgogICAgcmluZzoKICAgICAga3ZzdG9yZToKICAgICAgICBzdG9yZTogaW5tZW1vcnkKICAgICAgcmVwbGljYXRpb25fZmFjdG9yOiAxCiAgbWF4X3RyYW5zZmVyX3JldHJpZXM6IDAKbGltaXRzX2NvbmZpZzoKICBlbmZvcmNlX21ldHJpY19uYW1lOiBmYWxzZQogIHJlamVjdF9vbGRfc2FtcGxlczogdHJ1ZQogIHJlamVjdF9vbGRfc2FtcGxlc19tYXhfYWdlOiAxNjhoCnNjaGVtYV9jb25maWc6CiAgY29uZmlnczoKICAtIGZyb206ICIyMDE4LTA0LTE1IgogICAgaW5kZXg6CiAgICAgIHBlcmlvZDogMTY4aAogICAgICBwcmVmaXg6IGluZGV4XwogICAgb2JqZWN0X3N0b3JlOiBmaWxlc3lzdGVtCiAgICBzY2hlbWE6IHY5CiAgICBzdG9yZTogYm9sdGRiCnNlcnZlcjoKICBodHRwX2xpc3Rlbl9wb3J0OiAzMTAwCnN0b3JhZ2VfY29uZmlnOgogIGJvbHRkYjoKICAgIGRpcmVjdG9yeTogL2RhdGEvbG9raS9pbmRleAogIGZpbGVzeXN0ZW06CiAgICBkaXJlY3Rvcnk6IC9kYXRhL2xva2kvY2h1bmtzCnRhYmxlX21hbmFnZXI6CiAgcmV0ZW50aW9uX2RlbGV0ZXNfZW5hYmxlZDogZmFsc2UKICByZXRlbnRpb25fcGVyaW9kOiAw +--- +# Source: loki-stack/charts/promtail/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: loki-promtail + namespace: loki + labels: + app: promtail + chart: promtail-0.19.2 + release: loki + heritage: Helm +data: + promtail.yaml: | + client: + backoff_config: + maxbackoff: 5s + maxretries: 20 + minbackoff: 100ms + batchsize: 102400 + batchwait: 1s + external_labels: {} + timeout: 10s + positions: + filename: /run/promtail/positions.yaml + server: + http_listen_port: 3101 + target_config: + sync_period: 10s + scrape_configs: + - job_name: kubernetes-pods-name + pipeline_stages: + - docker: {} + kubernetes_sd_configs: + - role: pod + relabel_configs: + - source_labels: + - __meta_kubernetes_pod_label_name + target_label: __service__ + - source_labels: + - __meta_kubernetes_pod_node_name + target_label: __host__ + - action: drop + regex: '' + source_labels: + - __service__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + replacement: $1 + separator: / + source_labels: + - __meta_kubernetes_namespace + - __service__ + target_label: job + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: instance + - action: replace + source_labels: + - __meta_kubernetes_pod_container_name + target_label: container_name + - replacement: /var/log/pods/*$1/*.log + separator: / + source_labels: + - __meta_kubernetes_pod_uid + - __meta_kubernetes_pod_container_name + target_label: __path__ + - job_name: kubernetes-pods-app + pipeline_stages: + - docker: {} + kubernetes_sd_configs: + - role: pod + relabel_configs: + - action: drop + regex: .+ + source_labels: + - __meta_kubernetes_pod_label_name + - source_labels: + - __meta_kubernetes_pod_label_app + target_label: __service__ + - source_labels: + - __meta_kubernetes_pod_node_name + target_label: __host__ + - action: drop + regex: '' + source_labels: + - __service__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + replacement: $1 + separator: / + source_labels: + - __meta_kubernetes_namespace + - __service__ + target_label: job + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: instance + - action: replace + source_labels: + - __meta_kubernetes_pod_container_name + target_label: container_name + - replacement: /var/log/pods/*$1/*.log + separator: / + source_labels: + - __meta_kubernetes_pod_uid + - __meta_kubernetes_pod_container_name + target_label: __path__ + - job_name: kubernetes-pods-direct-controllers + pipeline_stages: + - docker: {} + kubernetes_sd_configs: + - role: pod + relabel_configs: + - action: drop + regex: .+ + separator: '' + source_labels: + - __meta_kubernetes_pod_label_name + - __meta_kubernetes_pod_label_app + - action: drop + regex: '[0-9a-z-.]+-[0-9a-f]{8,10}' + source_labels: + - __meta_kubernetes_pod_controller_name + - source_labels: + - __meta_kubernetes_pod_controller_name + target_label: __service__ + - source_labels: + - __meta_kubernetes_pod_node_name + target_label: __host__ + - action: drop + regex: '' + source_labels: + - __service__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + replacement: $1 + separator: / + source_labels: + - __meta_kubernetes_namespace + - __service__ + target_label: job + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: instance + - action: replace + source_labels: + - __meta_kubernetes_pod_container_name + target_label: container_name + - replacement: /var/log/pods/*$1/*.log + separator: / + source_labels: + - __meta_kubernetes_pod_uid + - __meta_kubernetes_pod_container_name + target_label: __path__ + - job_name: kubernetes-pods-indirect-controller + pipeline_stages: + - docker: {} + kubernetes_sd_configs: + - role: pod + relabel_configs: + - action: drop + regex: .+ + separator: '' + source_labels: + - __meta_kubernetes_pod_label_name + - __meta_kubernetes_pod_label_app + - action: keep + regex: '[0-9a-z-.]+-[0-9a-f]{8,10}' + source_labels: + - __meta_kubernetes_pod_controller_name + - action: replace + regex: '([0-9a-z-.]+)-[0-9a-f]{8,10}' + source_labels: + - __meta_kubernetes_pod_controller_name + target_label: __service__ + - source_labels: + - __meta_kubernetes_pod_node_name + target_label: __host__ + - action: drop + regex: '' + source_labels: + - __service__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + replacement: $1 + separator: / + source_labels: + - __meta_kubernetes_namespace + - __service__ + target_label: job + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: instance + - action: replace + source_labels: + - __meta_kubernetes_pod_container_name + target_label: container_name + - replacement: /var/log/pods/*$1/*.log + separator: / + source_labels: + - __meta_kubernetes_pod_uid + - __meta_kubernetes_pod_container_name + target_label: __path__ + - job_name: kubernetes-pods-static + pipeline_stages: + - docker: {} + kubernetes_sd_configs: + - role: pod + relabel_configs: + - action: drop + regex: '' + source_labels: + - __meta_kubernetes_pod_annotation_kubernetes_io_config_mirror + - action: replace + source_labels: + - __meta_kubernetes_pod_label_component + target_label: __service__ + - source_labels: + - __meta_kubernetes_pod_node_name + target_label: __host__ + - action: drop + regex: '' + source_labels: + - __service__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + replacement: $1 + separator: / + source_labels: + - __meta_kubernetes_namespace + - __service__ + target_label: job + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: instance + - action: replace + source_labels: + - __meta_kubernetes_pod_container_name + target_label: container_name + - replacement: /var/log/pods/*$1/*.log + separator: / + source_labels: + - __meta_kubernetes_pod_annotation_kubernetes_io_config_mirror + - __meta_kubernetes_pod_container_name + target_label: __path__ +--- +# Source: loki-stack/templates/datasources.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: loki-loki-stack + namespace: loki + labels: + app: loki-stack + chart: loki-stack-0.32.1 + release: loki + heritage: Helm + grafana_datasource: "1" +data: + loki-stack-datasource.yaml: |- + apiVersion: 1 + datasources: + - name: Loki + type: loki + access: proxy + url: http://loki:3100 + version: 1 +--- +# Source: loki-stack/templates/tests/loki-test-configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: loki-loki-stack-test + labels: + app: loki-stack + chart: loki-stack-0.32.1 + release: loki + heritage: Helm +data: + test.sh: | + #!/usr/bin/env bash + + LOKI_URI="http://${LOKI_SERVICE}:${LOKI_PORT}" + + function setup() { + apk add -u curl jq + until (curl -s ${LOKI_URI}/api/prom/label/app/values | jq -e '.values[] | select(. == "loki")'); do + sleep 1 + done + } + + @test "Has labels" { + curl -s ${LOKI_URI}/api/prom/label | \ + jq -e '.values[] | select(. == "app")' + } + + @test "Query log entry" { + curl -sG ${LOKI_URI}/api/prom/query?limit=10 --data-urlencode 'query={app="loki"}' | \ + jq -e '.streams[].entries | length >= 1' + } + + @test "Push log entry legacy" { + local timestamp=$(date -Iseconds -u | sed 's/UTC/.000000000+00:00/') + local data=$(jq -n --arg timestamp "${timestamp}" '{"streams": [{"labels": "{app=\"loki-test\"}", "entries": [{"ts": $timestamp, "line": "foobar"}]}]}') + + curl -s -X POST -H "Content-Type: application/json" ${LOKI_URI}/api/prom/push -d "${data}" + + curl -sG ${LOKI_URI}/api/prom/query?limit=1 --data-urlencode 'query={app="loki-test"}' | \ + jq -e '.streams[].entries[].line == "foobar"' + } + + @test "Push log entry" { + local timestamp=$(date +%s000000000) + local data=$(jq -n --arg timestamp "${timestamp}" '{"streams": [{"stream": {"app": "loki-test"}, "values": [[$timestamp, "foobar"]]}]}') + + curl -s -X POST -H "Content-Type: application/json" ${LOKI_URI}/loki/api/v1/push -d "${data}" + + curl -sG ${LOKI_URI}/api/prom/query?limit=1 --data-urlencode 'query={app="loki-test"}' | \ + jq -e '.streams[].entries[].line == "foobar"' + } +--- +# Source: loki-stack/charts/promtail/templates/clusterrole.yaml +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + app: promtail + chart: promtail-0.19.2 + release: loki + heritage: Helm + name: loki-promtail-clusterrole + namespace: loki +rules: +- apiGroups: [""] # "" indicates the core API group + resources: + - nodes + - nodes/proxy + - services + - endpoints + - pods + verbs: ["get", "watch", "list"] +--- +# Source: loki-stack/charts/promtail/templates/clusterrolebinding.yaml +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: loki-promtail-clusterrolebinding + labels: + app: promtail + chart: promtail-0.19.2 + release: loki + heritage: Helm +subjects: + - kind: ServiceAccount + name: loki-promtail + namespace: loki +roleRef: + kind: ClusterRole + name: loki-promtail-clusterrole + apiGroup: rbac.authorization.k8s.io +--- +# Source: loki-stack/charts/loki/templates/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: loki + namespace: loki + labels: + app: loki + chart: loki-0.25.1 + heritage: Helm + release: loki +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [loki] +--- +# Source: loki-stack/charts/promtail/templates/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: loki-promtail + namespace: loki + labels: + app: promtail + chart: promtail-0.19.2 + heritage: Helm + release: loki +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [loki-promtail] +--- +# Source: loki-stack/charts/loki/templates/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: loki + namespace: loki + labels: + app: loki + chart: loki-0.25.1 + heritage: Helm + release: loki +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: loki +subjects: +- kind: ServiceAccount + name: loki +--- +# Source: loki-stack/charts/promtail/templates/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: loki-promtail + namespace: loki + labels: + app: promtail + chart: promtail-0.19.2 + heritage: Helm + release: loki +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: loki-promtail +subjects: +- kind: ServiceAccount + name: loki-promtail +--- +# Source: loki-stack/charts/loki/templates/service-headless.yaml +apiVersion: v1 +kind: Service +metadata: + name: loki-headless + namespace: loki + labels: + app: loki + chart: loki-0.25.1 + release: loki + heritage: Helm +spec: + clusterIP: None + ports: + - port: 3100 + protocol: TCP + name: http-metrics + targetPort: http-metrics + selector: + app: loki + release: loki +--- +# Source: loki-stack/charts/loki/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: loki + namespace: loki + labels: + app: loki + chart: loki-0.25.1 + release: loki + heritage: Helm + annotations: + {} +spec: + type: ClusterIP + ports: + - port: 3100 + protocol: TCP + name: http-metrics + targetPort: http-metrics + selector: + app: loki + release: loki +--- +# Source: loki-stack/charts/promtail/templates/daemonset.yaml +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: loki-promtail + namespace: loki + labels: + app: promtail + chart: promtail-0.19.2 + release: loki + heritage: Helm + annotations: + {} +spec: + selector: + matchLabels: + app: promtail + release: loki + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + app: promtail + release: loki + annotations: + checksum/config: e35bcb191a87ddcbe2a162db814362dae2ce3a9d967ea86fdbd7b6b011b4a523 + prometheus.io/port: http-metrics + prometheus.io/scrape: "true" + spec: + serviceAccountName: loki-promtail + containers: + - name: promtail + image: "grafana/promtail:v1.3.0" + imagePullPolicy: IfNotPresent + args: + - "-config.file=/etc/promtail/promtail.yaml" + - "-client.url=http://loki:3100/loki/api/v1/push" + volumeMounts: + - name: config + mountPath: /etc/promtail + - name: run + mountPath: /run/promtail + - mountPath: /var/lib/docker/containers + name: docker + readOnly: true + - mountPath: /var/log/pods + name: pods + readOnly: true + env: + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + ports: + - containerPort: 3101 + name: http-metrics + securityContext: + readOnlyRootFilesystem: true + runAsGroup: 0 + runAsUser: 0 + readinessProbe: + failureThreshold: 5 + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + {} + nodeSelector: + {} + affinity: + {} + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + volumes: + - name: config + configMap: + name: loki-promtail + - name: run + hostPath: + path: /run/promtail + - hostPath: + path: /var/lib/docker/containers + name: docker + - hostPath: + path: /var/log/pods + name: pods +--- +# Source: loki-stack/charts/loki/templates/statefulset.yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: loki + namespace: loki + labels: + app: loki + chart: loki-0.25.1 + release: loki + heritage: Helm + annotations: + {} +spec: + podManagementPolicy: OrderedReady + replicas: 1 + selector: + matchLabels: + app: loki + release: loki + serviceName: loki-headless + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + app: loki + name: loki + release: loki + annotations: + checksum/config: ea7491868832b6a8a6963c7fe5a75dce7af6613b9afec86e8d2dcce9ebb33a89 + prometheus.io/port: http-metrics + prometheus.io/scrape: "true" + spec: + serviceAccountName: loki + securityContext: + fsGroup: 10001 + runAsGroup: 10001 + runAsNonRoot: true + runAsUser: 10001 + initContainers: + [] + containers: + - name: loki + image: "grafana/loki:v1.3.0" + imagePullPolicy: IfNotPresent + args: + - "-config.file=/etc/loki/loki.yaml" + volumeMounts: + - name: config + mountPath: /etc/loki + - name: storage + mountPath: "/data" + subPath: + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + livenessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + readinessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + resources: + {} + securityContext: + readOnlyRootFilesystem: true + env: + nodeSelector: + {} + affinity: + {} + tolerations: + [] + terminationGracePeriodSeconds: 4800 + volumes: + - name: config + secret: + secretName: loki + - name: storage + emptyDir: {} +--- +# Source: loki-stack/templates/tests/loki-test-pod.yaml +apiVersion: v1 +kind: Pod +metadata: + annotations: + "helm.sh/hook": test-success + labels: + app: loki-stack + chart: loki-stack-0.32.1 + release: loki + heritage: Helm + name: loki-loki-stack-test +spec: + containers: + - name: test + image: bats/bats:v1.1.0 + args: + - /var/lib/loki/test.sh + env: + - name: LOKI_SERVICE + value: loki + - name: LOKI_PORT + value: "3100" + volumeMounts: + - name: tests + mountPath: /var/lib/loki + restartPolicy: Never + volumes: + - name: tests + configMap: + name: loki-loki-stack-test