├── tests ├── modified │ ├── sidecar │ └── operator │ │ ├── pod-with-cr │ │ ├── 00-install.yaml │ │ ├── 01-update.yaml │ │ ├── 01-assert.yaml │ │ └── 00-assert.yaml │ │ ├── pod-with-annotations │ │ ├── 01-update.yaml │ │ ├── 00-install.yaml │ │ ├── 00-assert.yaml │ │ └── 01-assert.yaml │ │ ├── pod-without-annotations │ │ ├── 00-install.yaml │ │ └── 00-assert.yaml │ │ ├── daemonset-with-annotations │ │ ├── 00-install.yaml │ │ └── 00-assert.yaml │ │ ├── deployment-with-annotations │ │ ├── 00-install.yaml │ │ ├── 01-update.yaml │ │ ├── 00-assert.yaml │ │ └── 01-assert.yaml │ │ └── statefulset-with-annotations │ │ ├── 00-install.yaml │ │ └── 00-assert.yaml ├── operator │ ├── pod-without-annotations │ │ ├── 00-assert.yaml │ │ └── 00-install.yaml │ ├── pod-with-cr │ │ ├── 01-assert.yaml │ │ ├── 00-assert.yaml │ │ ├── 01-update.yaml │ │ └── 00-install.yaml │ ├── pod-with-annotations │ │ ├── 00-assert.yaml │ │ ├── 01-assert.yaml │ │ ├── 01-update.yaml │ │ └── 00-install.yaml │ ├── daemonset-with-annotations │ │ ├── 00-assert.yaml │ │ └── 00-install.yaml │ ├── statefulset-with-annotations │ │ ├── 00-assert.yaml │ │ └── 00-install.yaml │ └── deployment-with-annotations │ │ ├── 00-assert.yaml │ │ ├── 01-assert.yaml │ │ ├── 01-update.yaml │ │ └── 00-install.yaml └── sidecar │ └── pod-with-sidecar │ ├── 00-assert.yaml │ └── 00-install.yaml ├── sidecar ├── otelcol │ ├── .gitignore │ ├── config.yaml │ ├── Dockerfile │ ├── .otelcol-builder.yaml │ ├── Makefile │ └── .goreleaser.yaml └── fluentbit │ ├── conf │ ├── plugins.conf │ └── fluent-bit.conf │ ├── examples │ ├── example1.log │ ├── example2.log │ └── pod_with_tailing_sidecars.yaml │ ├── out_gstdout │ ├── Makefile │ ├── go.mod │ ├── README.md │ ├── go.sum │ └── out_gstdout.go │ ├── tests │ └── test.sh │ ├── Dockerfile.ubi │ ├── Makefile │ ├── Dockerfile │ └── docker-bake.hcl ├── helm ├── tailing-sidecar-operator │ ├── templates │ │ ├── NOTES.txt │ │ ├── checks.txt │ │ ├── configmap.yaml │ │ ├── sidecar-configmap.yaml │ │ ├── scc.yaml │ │ ├── _operator-webhook.tpl │ │ ├── _operator-webhook-with-cert-manager.tpl │ │ └── _helpers.tpl │ ├── .helmignore │ ├── Chart.yaml │ ├── conf │ │ └── operator.yaml │ ├── README.md │ └── values.yaml └── tests │ ├── values.yaml │ ├── values.withCertManager.yaml │ ├── values.withOtelcolCustomConfiguration.yaml │ └── values.withFluentBitCustomConfiguration.yaml ├── operator ├── config │ ├── prometheus │ │ ├── kustomization.yaml │ │ └── monitor.yaml │ ├── certmanager │ │ ├── kustomization.yaml │ │ ├── kustomizeconfig.yaml │ │ └── certificate.yaml │ ├── rbac │ │ ├── service_account.yaml │ │ ├── auth_proxy_client_clusterrole.yaml │ │ ├── role_binding.yaml │ │ ├── auth_proxy_role_binding.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── auth_proxy_role.yaml │ │ ├── auth_proxy_service.yaml │ │ ├── kustomization.yaml │ │ ├── tailingsidecar_viewer_role.yaml │ │ ├── tailingsidecar_editor_role.yaml │ │ ├── leader_election_role.yaml │ │ └── role.yaml │ ├── webhook │ │ ├── kustomization.yaml │ │ ├── service.yaml │ │ ├── manifests.yaml │ │ └── kustomizeconfig.yaml │ ├── scorecard │ │ ├── bases │ │ │ └── config.yaml │ │ ├── patches │ │ │ ├── basic.config.yaml │ │ │ └── olm.config.yaml │ │ └── kustomization.yaml │ ├── samples │ │ ├── kustomization.yaml │ │ ├── tailing-sidecar-update_v1_tailingsidecar.yaml │ │ ├── tailing-sidecar_v1_tailingsidecar.yaml │ │ └── tailing-sidecar_v1_tailingsidecar_match_expressions.yaml │ ├── manager │ │ ├── kustomization.yaml │ │ └── manager.yaml │ ├── default │ │ ├── role_binding_patch.yaml │ │ ├── webhook_admission_ca_injection_patch.yaml │ │ ├── webhook_validating_ca_injection_patch.yaml │ │ ├── manager_patch.yaml │ │ ├── cluster_roles_binding_patches.yaml │ │ ├── webhook_patch.yaml │ │ ├── manager_auth_proxy_patch.yaml │ │ ├── manager_webhook_patch.yaml │ │ └── kustomization.yaml │ └── crd │ │ ├── patches │ │ ├── cainjection_in_tailingsidecars.yaml │ │ └── webhook_in_tailingsidecars.yaml │ │ ├── kustomizeconfig.yaml │ │ └── kustomization.yaml ├── .dockerignore ├── handler │ ├── testdata │ │ ├── patch_remove_tailing_sidecar.json │ │ ├── patch_update_volume.json │ │ ├── patch_update_1_tailing_sidecar.json │ │ ├── patch_with_2_tailing_sidecars.json │ │ ├── patch_with_2_tailing_sidecars_with_configuration.json │ │ ├── patch_with_2_tailing_sidecars_different_namespace.json │ │ ├── patch_with_3_named_not_named_tailing_sidecars.json │ │ ├── patch_with_3_named_tailing_sidecars.json │ │ ├── patch_with_3_tailing_sidecars.json │ │ └── patch_with_3_tailing_sidecars_raw_and_predefined.json │ └── annotations.go ├── PROJECT ├── .gitignore ├── hack │ └── boilerplate.go.txt ├── examples │ ├── cr_with_resources.yaml │ ├── pod_without_annotations.yaml │ ├── pod_with_tailing_sidecar_config.yaml │ ├── pod_with_tailing_sidecar_config_update.yaml │ ├── pod_with_tailing_sidecar_config_resources.yaml │ ├── pod_with_annotations.yaml │ ├── pod_with_annotations_update.yaml │ ├── daemonset_with_annotations.yaml │ ├── deployment_with_annotations_update.yaml │ ├── deployment_with_annotations.yaml │ └── statefulset_with_annotations.yaml ├── Dockerfile ├── tests │ ├── functions.sh │ ├── test-resources.sh │ ├── test-update.sh │ └── test.sh ├── Dockerfile.ubi ├── api │ └── v1 │ │ ├── groupversion_info.go │ │ └── tailingsidecar_types.go ├── controllers │ ├── suite_test.go │ └── tailingsidecar_controller.go ├── config.go ├── go.mod ├── README.md ├── config_test.go └── docs │ └── configuration.md ├── images └── sumo_logic_logo.png ├── .github ├── CODEOWNERS └── dependabot.yml ├── kind.yaml ├── vagrant ├── values.yaml └── provision.sh ├── .yamllint.yaml ├── CONTRIBUTING.md ├── .vscode └── snippets.code-snippets ├── .gitignore ├── .markdownlint.jsonc ├── ci ├── push-helm-chart.sh └── _build_functions.sh ├── kuttl-test-helm.yaml ├── kuttl-test-helm-otelcol-custom-configuration.yaml ├── kuttl-test.yaml ├── kuttl-test-helm-fluentbit-custom-configuration.yaml ├── kuttl-test-helm-certmanager.yaml ├── .markdownlint └── style.rb ├── Vagrantfile ├── docs ├── release.md └── dev.md ├── README.md └── Makefile /tests/modified/sidecar: -------------------------------------------------------------------------------- 1 | ../sidecar -------------------------------------------------------------------------------- /sidecar/otelcol/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | cmd/ 3 | dist/ 4 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Happy tailing! 2 | -------------------------------------------------------------------------------- /operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /sidecar/fluentbit/conf/plugins.conf: -------------------------------------------------------------------------------- 1 | [PLUGINS] 2 | Path /tailing-sidecar/lib/out_gstdout.so 3 | -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-cr/00-install.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/pod-with-cr/00-install.yaml -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-cr/01-update.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/pod-with-cr/01-update.yaml -------------------------------------------------------------------------------- /images/sumo_logic_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SumoLogic/tailing-sidecar/HEAD/images/sumo_logic_logo.png -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-annotations/01-update.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/pod-with-annotations/01-update.yaml -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/pod-with-annotations/00-install.yaml -------------------------------------------------------------------------------- /tests/modified/operator/pod-without-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/pod-without-annotations/00-install.yaml -------------------------------------------------------------------------------- /sidecar/fluentbit/examples/example1.log: -------------------------------------------------------------------------------- 1 | This is the first line of example1.log 2 | This is the second line of example1.log 3 | -------------------------------------------------------------------------------- /sidecar/fluentbit/examples/example2.log: -------------------------------------------------------------------------------- 1 | This is the first line of example2.log 2 | This is the second line of example2.log 3 | -------------------------------------------------------------------------------- /tests/modified/operator/daemonset-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/daemonset-with-annotations/00-install.yaml -------------------------------------------------------------------------------- /tests/modified/operator/deployment-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/deployment-with-annotations/00-install.yaml -------------------------------------------------------------------------------- /tests/modified/operator/deployment-with-annotations/01-update.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/deployment-with-annotations/01-update.yaml -------------------------------------------------------------------------------- /operator/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !api 3 | !controllers 4 | !handler 5 | 6 | !*.go 7 | !**/*.go 8 | !go.mod 9 | !go.sum 10 | -------------------------------------------------------------------------------- /tests/modified/operator/statefulset-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | ../../../operator/statefulset-with-annotations/00-install.yaml -------------------------------------------------------------------------------- /operator/config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: service-account 5 | namespace: system 6 | -------------------------------------------------------------------------------- /operator/config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Learn about CODEOWNERS file format: 2 | # https://help.github.com/en/articles/about-code-owners 3 | 4 | * @SumoLogic/open-source-collection-team 5 | -------------------------------------------------------------------------------- /sidecar/fluentbit/out_gstdout/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go build -buildmode=c-shared -o out_gstdout.so . 3 | 4 | fast: 5 | go build out_gstdout.go 6 | 7 | clean: 8 | rm -rf *.so *.h *~ 9 | -------------------------------------------------------------------------------- /operator/config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /tests/operator/pod-without-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-without-annotations 5 | status: 6 | phase: Running 7 | containerStatuses: 8 | - name: count 9 | -------------------------------------------------------------------------------- /tests/modified/operator/pod-without-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-without-annotations 5 | status: 6 | phase: Running 7 | containerStatuses: 8 | - name: count 9 | -------------------------------------------------------------------------------- /operator/config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples you want in your CSV to this file as resources ## 2 | resources: 3 | - tailing-sidecar_v1_tailingsidecar.yaml 4 | # +kubebuilder:scaffold:manifestskustomizesamples 5 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | name: tailing-sidecar-operator-e2e 4 | nodes: 5 | - role: control-plane 6 | image: kindest/node:v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72 7 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_remove_tailing_sidecar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "remove", 4 | "path": "/spec/volumes/2" 5 | }, 6 | { 7 | "op": "remove", 8 | "path": "/spec/containers/1" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /sidecar/fluentbit/out_gstdout/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/fluent/fluent-bit-go/examples/gstdout 2 | 3 | go 1.20 4 | 5 | require github.com/fluent/fluent-bit-go v0.0.0-20201210173045-3fd1e0486df2 6 | 7 | require github.com/ugorji/go/codec v1.1.7 // indirect 8 | -------------------------------------------------------------------------------- /vagrant/values.yaml: -------------------------------------------------------------------------------- 1 | operator: 2 | image: 3 | repository: localhost:32000/sumologic/tailing-sidecar-operator 4 | tag: latest 5 | 6 | sidecar: 7 | image: 8 | repository: localhost:32000/sumologic/tailing-sidecar 9 | tag: latest 10 | -------------------------------------------------------------------------------- /operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: localhost:32000/sumologic/tailing-sidecar-operator 8 | newTag: latest 9 | -------------------------------------------------------------------------------- /operator/config/default/role_binding_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | subjects: 6 | - kind: ServiceAccount 7 | name: tailing-sidecar-service-account 8 | namespace: tailing-sidecar-system 9 | -------------------------------------------------------------------------------- /operator/config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: tailing-sidecar-operator 13 | -------------------------------------------------------------------------------- /.yamllint.yaml: -------------------------------------------------------------------------------- 1 | extends: relaxed 2 | 3 | rules: 4 | comments: enable 5 | comments-indentation: disable 6 | 7 | line-length: 8 | max: 140 9 | level: warning 10 | 11 | indentation: 12 | level: warning 13 | indent-sequences: consistent 14 | -------------------------------------------------------------------------------- /operator/config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.2.0 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | To contribute you will need to ensure you have the following setup: 4 | 5 | - [Docker](https://www.docker.com/) environment 6 | - [Kubernetes](https://kubernetes.io/) environment 7 | - [Go](https://golang.org/doc/install) environment 8 | - [Operator SDK](https://sdk.operatorframework.io/) 9 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/checks.txt: -------------------------------------------------------------------------------- 1 | {{/* Check if leader election is set to true when replicaCount > 1 */}} 2 | {{- if and (gt (.Values.operator.replicaCount | toString) "1") (not .Values.operator.leaderElection.enabled) }} 3 | {{- fail "\nValues.operator.leaderElection should be set to true when replicaCount > 1" -}} 4 | {{- end }} -------------------------------------------------------------------------------- /operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: sumologic.com 2 | layout: go.kubebuilder.io/v2 3 | projectName: operator 4 | repo: github.com/SumoLogic/tailing-sidecar/operator 5 | resources: 6 | - group: tailing-sidecar 7 | kind: TailingSidecarConfig 8 | version: v1 9 | version: 3-alpha 10 | plugins: 11 | go.sdk.operatorframework.io/v2-alpha: {} 12 | -------------------------------------------------------------------------------- /sidecar/fluentbit/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | [[ $(kubectl logs --tail 5 example-with-tailling-sidecars sidecar1 | grep example1 | wc -l) -ne 5 ]] && exit 1 6 | [[ $(kubectl logs --tail 5 example-with-tailling-sidecars sidecar2 | grep example2 | wc -l) -ne 5 ]] && exit 1 7 | 8 | echo "ok" 9 | exit 0 10 | -------------------------------------------------------------------------------- /.vscode/snippets.code-snippets: -------------------------------------------------------------------------------- 1 | // https://code.visualstudio.com/docs/editor/userdefinedsnippets 2 | { 3 | "Link to pull request": { 4 | "scope": "markdown", 5 | "prefix": ["PR"], 6 | "body": ["[#${1:123}]: https://github.com/SumoLogic/tailing-sidecar/pull/${1}"], 7 | "description": "Link to GitHub pull request", 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ template "tailing-sidecar-operator.configMap.name" . }} 5 | labels: 6 | {{- include "tailing-sidecar-operator.labels" . | nindent 4 }} 7 | data: 8 | config.yaml: | 9 | {{- (tpl (.Files.Get "conf/operator.yaml") .) | nindent 4 }} 10 | -------------------------------------------------------------------------------- /operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: tailing-sidecar-operator 6 | name: operator-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: tailing-sidecar-operator 15 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/sidecar-configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if not (empty .Values.sidecar.config.content) }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ template "tailing-sidecar.configMap.name" . }} 6 | labels: 7 | {{- include "tailing-sidecar-operator.labels" . | nindent 4 }} 8 | data: 9 | {{- toYaml .Values.sidecar.config.content | nindent 2 }} 10 | {{- end }} -------------------------------------------------------------------------------- /helm/tests/values.yaml: -------------------------------------------------------------------------------- 1 | operator: 2 | image: 3 | repository: registry.localhost:5000/sumologic/tailing-sidecar-operator 4 | tag: test 5 | 6 | sidecar: 7 | image: 8 | repository: registry.localhost:5000/sumologic/sidecar 9 | tag: test 10 | 11 | resources: 12 | limits: 13 | cpu: "0" 14 | memory: "0" 15 | requests: 16 | cpu: "0" 17 | memory: "0" 18 | -------------------------------------------------------------------------------- /sidecar/fluentbit/out_gstdout/README.md: -------------------------------------------------------------------------------- 1 | # out_gstdout 2 | 3 | out_gstdout is a simple Fluent Bit output plugin that prints the records to the standard output interface (STDOUT). 4 | This plugin is a modified version of example Fluent Bit plugin, with any unnecessary output stripped down. 5 | See the [original sources](https://github.com/fluent/fluent-bit-go/tree/3fd1e0486df2b8dce5096451740c9e98f10a8985/examples/out_gstdout). 6 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | # Common backup files 9 | *.swp 10 | *.bak 11 | *.tmp 12 | *.orig 13 | *~ 14 | # Various IDEs 15 | .project 16 | .idea/ 17 | *.tmproj 18 | .vscode/ 19 | -------------------------------------------------------------------------------- /operator/config/crd/patches/cainjection_in_tailingsidecars.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: tailingsidecars.tailing-sidecar.sumologic.com 9 | -------------------------------------------------------------------------------- /helm/tests/values.withCertManager.yaml: -------------------------------------------------------------------------------- 1 | operator: 2 | image: 3 | repository: registry.localhost:5000/sumologic/tailing-sidecar-operator 4 | tag: test 5 | 6 | sidecar: 7 | image: 8 | repository: registry.localhost:5000/sumologic/sidecar 9 | tag: test 10 | resources: 11 | limits: 12 | cpu: "0" 13 | memory: "0" 14 | requests: 15 | cpu: "0" 16 | memory: "0" 17 | 18 | certManager: 19 | enabled: true 20 | -------------------------------------------------------------------------------- /operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: tailing-sidecar-operator 8 | name: operator-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | selector: 15 | matchLabels: 16 | control-plane: tailing-sidecar-operator 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Vagrant ignores 2 | .vagrant 3 | ubuntu-bionic-18.04-cloudimg-console.log 4 | .kube-config 5 | 6 | # Fluent Bit ignores 7 | sidecar/fluentbit/out_gstdout/out_gstdout.h 8 | sidecar/fluentbit/out_gstdout/out_gstdout.so 9 | sidecar/fluentbit/var/ 10 | 11 | .vscode/* 12 | !.vscode/snippets.code-snippets 13 | 14 | # Kuttl test artifact dir 15 | tests/_build 16 | 17 | .kubeconfig 18 | kubeconfig 19 | 20 | # Go workspace files 21 | go.work 22 | go.work.sum -------------------------------------------------------------------------------- /operator/config/default/webhook_admission_ca_injection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch adds annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | -------------------------------------------------------------------------------- /operator/config/default/webhook_validating_ca_injection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch adds annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: ValidatingWebhookConfiguration 5 | metadata: 6 | name: validating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | -------------------------------------------------------------------------------- /operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - service_account.yaml 3 | - role.yaml 4 | - role_binding.yaml 5 | - leader_election_role.yaml 6 | - leader_election_role_binding.yaml 7 | # Comment the following 4 lines if you want to disable 8 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 9 | # which protects your /metrics endpoint. 10 | - auth_proxy_service.yaml 11 | - auth_proxy_role.yaml 12 | - auth_proxy_role_binding.yaml 13 | - auth_proxy_client_clusterrole.yaml 14 | -------------------------------------------------------------------------------- /operator/config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | patchesJson6902: 4 | - path: patches/basic.config.yaml 5 | target: 6 | group: scorecard.operatorframework.io 7 | version: v1alpha3 8 | kind: Configuration 9 | name: config 10 | - path: patches/olm.config.yaml 11 | target: 12 | group: scorecard.operatorframework.io 13 | version: v1alpha3 14 | kind: Configuration 15 | name: config 16 | # +kubebuilder:scaffold:patchesJson6902 17 | -------------------------------------------------------------------------------- /operator/config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Kubernetes Generated files - skip generated files, except for vendored files 17 | 18 | !vendor/**/zz_generated.* 19 | 20 | # editor and IDE paraphernalia 21 | .idea 22 | *.swp 23 | *.swo 24 | *~ 25 | 26 | # test tools 27 | testbin 28 | -------------------------------------------------------------------------------- /.markdownlint.jsonc: -------------------------------------------------------------------------------- 1 | /** 2 | * Note: This configuration is used by VS Code's Markdownlint extension and is only included for convenience. 3 | * The original and primary Markdownlint configuration as used in CI is .markdownlint/style.rb. 4 | */ 5 | { 6 | "default": true, 7 | "MD004": { "style": "dash" }, 8 | "MD013": { "line_length": 120, "code_blocks": false, "tables": false }, 9 | "MD033": false, // no-inline-html 10 | "MD034": false, // no-bare-urls 11 | "MD040": false // fenced-code-language 12 | } 13 | -------------------------------------------------------------------------------- /sidecar/fluentbit/out_gstdout/go.sum: -------------------------------------------------------------------------------- 1 | github.com/fluent/fluent-bit-go v0.0.0-20201210173045-3fd1e0486df2 h1:G57WNyWS0FQf43hjRXLy5JT1V5LWVsSiEpkUcT67Ugk= 2 | github.com/fluent/fluent-bit-go v0.0.0-20201210173045-3fd1e0486df2/go.mod h1:L92h+dgwElEyUuShEwjbiHjseW410WIcNz+Bjutc8YQ= 3 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 4 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 5 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 6 | -------------------------------------------------------------------------------- /operator/config/default/manager_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch adds tailing sidecar image as container args 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: operator 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | serviceAccountName: tailing-sidecar-service-account 11 | containers: 12 | - name: manager 13 | args: 14 | - "--metrics-addr=127.0.0.1:8080" 15 | - "--enable-leader-election" 16 | - "--tailing-sidecar-image=sumologic/tailing-sidecar:latest" 17 | -------------------------------------------------------------------------------- /operator/config/rbac/tailingsidecar_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view tailingsidecars. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: tailingsidecar-viewer-role 6 | rules: 7 | - apiGroups: 8 | - tailing-sidecar.sumologic.com 9 | resources: 10 | - tailingsidecarconfigs 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - tailing-sidecar.sumologic.com 17 | resources: 18 | - tailingsidecarconfigs/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: tailing-sidecar-operator 3 | description: Installs Tailing Sidecar Operator 4 | type: application 5 | version: 0.18.0 6 | appVersion: 0.18.0 7 | keywords: 8 | - tailing-sidecar 9 | - k8s-logging 10 | - kubernetes-logging 11 | - k8s-logs-pod 12 | icon: https://raw.githubusercontent.com/SumoLogic/tailing-sidecar/main/images/sumo_logic_logo.png 13 | home: https://sumologic.github.io/tailing-sidecar 14 | sources: 15 | - https://github.com/SumoLogic/tailing-sidecar 16 | -------------------------------------------------------------------------------- /operator/config/default/cluster_roles_binding_patches.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | subjects: 6 | - kind: ServiceAccount 7 | name: tailing-sidecar-service-account 8 | namespace: tailing-sidecar-system 9 | --- 10 | apiVersion: rbac.authorization.k8s.io/v1 11 | kind: ClusterRoleBinding 12 | metadata: 13 | name: manager-rolebinding 14 | subjects: 15 | - kind: ServiceAccount 16 | name: tailing-sidecar-service-account 17 | namespace: tailing-sidecar-system 18 | -------------------------------------------------------------------------------- /operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | group: apiextensions.k8s.io 8 | path: spec/conversion/webhookClientConfig/service/name 9 | 10 | namespace: 11 | - kind: CustomResourceDefinition 12 | group: apiextensions.k8s.io 13 | path: spec/conversion/webhookClientConfig/service/namespace 14 | create: false 15 | 16 | varReference: 17 | - path: metadata/annotations 18 | -------------------------------------------------------------------------------- /operator/config/rbac/tailingsidecar_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit tailingsidecars. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: tailingsidecar-editor-role 6 | rules: 7 | - apiGroups: 8 | - tailing-sidecar.sumologic.com 9 | resources: 10 | - tailingsidecarconfigs 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - tailing-sidecar.sumologic.com 21 | resources: 22 | - tailingsidecarconfigs/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /operator/config/default/webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admissionregistration.k8s.io/v1 2 | kind: MutatingWebhookConfiguration 3 | metadata: 4 | name: mutating-webhook-configuration 5 | webhooks: 6 | - clientConfig: 7 | name: tailing-sidecar.sumologic.com 8 | reinvocationPolicy: Never 9 | ## enable the example below to limit to namespaces with specific labels only 10 | # namespaceSelector: 11 | # matchLabels: 12 | # tailing-sidecar: "true" 13 | ## enable the example below to limit to objects with specific labels only 14 | # objectSelector: 15 | # matchLabels: 16 | # tailing-sidecar: "true" 17 | -------------------------------------------------------------------------------- /operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - configmaps/status 23 | verbs: 24 | - get 25 | - update 26 | - patch 27 | - apiGroups: 28 | - "" 29 | resources: 30 | - events 31 | verbs: 32 | - create 33 | - patch 34 | -------------------------------------------------------------------------------- /ci/push-helm-chart.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | readonly ROOT_DIR="$(dirname "$(dirname "${0}")")" 4 | # shellcheck disable=SC1090 5 | source "${ROOT_DIR}"/ci/_build_functions.sh 6 | 7 | fetch_current_branch 8 | VERSION="$(git describe --tags --abbrev=40)" 9 | readonly VERSION="${VERSION#v}" 10 | 11 | pushd "${ROOT_DIR}" || exit 1 12 | echo "Starting to push helm chart in: $(pwd) with version tag: ${VERSION}" 13 | 14 | set_up_github 15 | 16 | if is_checkout_on_tag; then 17 | push_helm_chart "${VERSION}" "." 18 | else 19 | push_helm_chart "${VERSION}" "./dev" 20 | fi 21 | 22 | popd || exit 1 23 | 24 | echo "DONE" 25 | -------------------------------------------------------------------------------- /operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /kuttl-test-helm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | artifactsDir: ./tests/_build/artifacts/ 4 | testDirs: 5 | - ./tests/sidecar/ 6 | - ./tests/operator/ 7 | timeout: 150 8 | parallel: 4 9 | startKIND: true 10 | kindNodeCache: true 11 | kindContainers: 12 | - registry.localhost:5000/sumologic/tailing-sidecar-operator:test 13 | - registry.localhost:5000/sumologic/sidecar:test 14 | commands: 15 | - command: helm upgrade --install test-release ./helm/tailing-sidecar-operator -f ./helm/tests/values.yaml -n tailing-sidecar-system --create-namespace 16 | 17 | - command: make e2e-wait-until-operator-ready 18 | -------------------------------------------------------------------------------- /sidecar/otelcol/config.yaml: -------------------------------------------------------------------------------- 1 | receivers: 2 | filelog: 3 | include: 4 | - ${PATH_TO_TAIL} 5 | start_at: beginning 6 | storage: file_storage 7 | 8 | exporters: 9 | file: 10 | path: /dev/stdout 11 | encoding: text_encoding 12 | 13 | extensions: 14 | text_encoding: 15 | file_storage: 16 | directory: /var/lib/otc 17 | 18 | service: 19 | extensions: 20 | - text_encoding 21 | - file_storage 22 | telemetry: 23 | metrics: 24 | level: none 25 | logs: 26 | output_paths: 27 | - /var/log/otelcol.log 28 | pipelines: 29 | logs: 30 | exporters: [file] 31 | receivers: [filelog] 32 | -------------------------------------------------------------------------------- /operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: manager-role 6 | rules: 7 | - apiGroups: 8 | - tailing-sidecar.sumologic.com 9 | resources: 10 | - tailingsidecarconfigs 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - tailing-sidecar.sumologic.com 21 | resources: 22 | - tailingsidecarconfigs/status 23 | verbs: 24 | - get 25 | - patch 26 | - update 27 | - apiGroups: 28 | - tailing-sidecar.sumologic.com 29 | resources: 30 | - tailingsidecars/finalizers 31 | verbs: 32 | - update 33 | -------------------------------------------------------------------------------- /kuttl-test-helm-otelcol-custom-configuration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | artifactsDir: ./tests/_build/artifacts/ 4 | testDirs: 5 | - ./tests/sidecar/ 6 | - ./tests/operator/ 7 | timeout: 150 8 | parallel: 4 9 | startKIND: true 10 | kindNodeCache: true 11 | kindContainers: 12 | - registry.localhost:5000/sumologic/tailing-sidecar-operator:test 13 | - registry.localhost:5000/sumologic/sidecar:test 14 | commands: 15 | - command: helm upgrade --install test-release ./helm/tailing-sidecar-operator -f ./helm/tests/values.withOtelcolCustomConfiguration.yaml -n tailing-sidecar-system --create-namespace 16 | - command: make e2e-wait-until-operator-ready 17 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_update_volume.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "replace", 4 | "path": "/spec/volumes/2/name", 5 | "value": "volume-sidecar-1" 6 | }, 7 | { 8 | "op": "replace", 9 | "path": "/spec/containers/1/volumeMounts/1/name", 10 | "value": "volume-sidecar-1" 11 | }, 12 | { 13 | "op": "add", 14 | "path": "/spec/containers/1/volumeMounts/0/readOnly", 15 | "value": true 16 | }, 17 | { 18 | "op": "add", 19 | "path": "/spec/containers/1/volumeMounts/0/mountPropagation", 20 | "value": "Bidirectional" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /kuttl-test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | artifactsDir: ./tests/_build/artifacts/ 4 | testDirs: 5 | - ./tests/sidecar/ 6 | - ./tests/operator/ 7 | timeout: 150 8 | parallel: 4 9 | startKIND: true 10 | kindNodeCache: true 11 | kindContainers: 12 | - registry.localhost:5000/sumologic/tailing-sidecar-operator:test 13 | - registry.localhost:5000/sumologic/sidecar:test 14 | commands: 15 | - command: make -C ./operator deploy-cert-manager 16 | - command: make -C ./operator deploy IMG="registry.localhost:5000/sumologic/tailing-sidecar-operator:test" TAILING_SIDECAR_IMG="registry.localhost:5000/sumologic/sidecar:test" 17 | - command: make e2e-wait-until-operator-ready 18 | -------------------------------------------------------------------------------- /operator/examples/cr_with_resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tailing-sidecar.sumologic.com/v1 2 | kind: TailingSidecarConfig 3 | metadata: 4 | name: tailingsidecar-sample 5 | namespace: tailing-sidecar-system 6 | spec: 7 | annotationsPrefix: tailing-sidecar.sumologic.com 8 | podSelector: 9 | matchLabels: 10 | tailing-sidecar-resource: "true" 11 | configs: 12 | sidecar-1: 13 | volumeMount: 14 | name: varlog 15 | mountPath: /var/log 16 | path: /var/log/example0.log 17 | annotations: 18 | sourceCategory: sourceCategory-2 19 | annotation-2: "true" 20 | resources: 21 | requests: 22 | cpu: 100m 23 | memory: 100Mi 24 | -------------------------------------------------------------------------------- /kuttl-test-helm-fluentbit-custom-configuration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | artifactsDir: ./tests/_build/artifacts/ 4 | testDirs: 5 | - ./tests/modified/sidecar/ 6 | - ./tests/modified/operator/ 7 | timeout: 150 8 | parallel: 4 9 | startKIND: true 10 | kindNodeCache: true 11 | kindContainers: 12 | - registry.localhost:5000/sumologic/tailing-sidecar-operator:test 13 | - registry.localhost:5000/sumologic/sidecar:test 14 | commands: 15 | - command: helm upgrade --install test-release ./helm/tailing-sidecar-operator -f ./helm/tests/values.withFluentBitCustomConfiguration.yaml -n tailing-sidecar-system --create-namespace 16 | - command: make e2e-wait-until-operator-ready 17 | -------------------------------------------------------------------------------- /kuttl-test-helm-certmanager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | artifactsDir: ./tests/_build/artifacts/ 4 | testDirs: 5 | - ./tests/sidecar/ 6 | - ./tests/operator/ 7 | timeout: 150 8 | parallel: 4 9 | startKIND: true 10 | kindNodeCache: true 11 | kindContainers: 12 | - registry.localhost:5000/sumologic/tailing-sidecar-operator:test 13 | - registry.localhost:5000/sumologic/sidecar:test 14 | commands: 15 | - command: make -C ./operator deploy-cert-manager 16 | - command: helm upgrade --install test-release ./helm/tailing-sidecar-operator -f ./helm/tests/values.withCertManager.yaml -n tailing-sidecar-system --create-namespace 17 | - command: make e2e-wait-until-operator-ready 18 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/conf/operator.yaml: -------------------------------------------------------------------------------- 1 | sidecar: 2 | image: {{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag | default .Chart.AppVersion }} 3 | resources: 4 | {{- .Values.sidecar.resources | toYaml | nindent 4 }} 5 | {{- if not (empty .Values.sidecar.config.content) }} 6 | config: 7 | name: {{ template "tailing-sidecar.configMap.name" . }} 8 | mountPath: {{ .Values.sidecar.config.mountPath }} 9 | namespace: {{ .Release.Namespace }} 10 | {{- end }} 11 | leaderElection: 12 | leaseDuration: {{ .Values.operator.leaderElection.leaseDuration }} 13 | renewDeadline: {{ .Values.operator.leaderElection.renewDeadline }} 14 | retryPeriod: {{ .Values.operator.leaderElection.retryPeriod }} 15 | -------------------------------------------------------------------------------- /operator/config/webhook/manifests.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | creationTimestamp: null 7 | name: mutating-webhook-configuration 8 | webhooks: 9 | - admissionReviewVersions: 10 | - v1 11 | - v1beta1 12 | clientConfig: 13 | caBundle: Cg== 14 | service: 15 | name: webhook-service 16 | namespace: system 17 | path: /add-tailing-sidecars-v1-pod 18 | failurePolicy: Ignore 19 | name: tailing-sidecar.sumologic.com 20 | rules: 21 | - apiGroups: 22 | - "" 23 | apiVersions: 24 | - v1 25 | operations: 26 | - CREATE 27 | - DELETE 28 | resources: 29 | - pods 30 | sideEffects: None 31 | -------------------------------------------------------------------------------- /tests/operator/pod-with-cr/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-tailing-sidecar-config 5 | status: 6 | phase: Running 7 | containerStatuses: 8 | - name: count 9 | - name: sidecar-2 10 | --- 11 | apiVersion: kuttl.dev/v1beta1 12 | kind: TestAssert 13 | collectors: 14 | - pod: pod-with-tailing-sidecar-config 15 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | - selector: control-plane=tailing-sidecar-operator 19 | namespace: tailing-sidecar-system 20 | tail: 100 21 | commands: 22 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-2 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 23 | -------------------------------------------------------------------------------- /.markdownlint/style.rb: -------------------------------------------------------------------------------- 1 | # Documentation regarding rules used below can be found at: 2 | # https://github.com/markdownlint/markdownlint/blob/master/docs/RULES.md 3 | rule 'MD002' 4 | rule 'MD003' 5 | rule 'MD004', :style => :dash 6 | rule 'MD005' 7 | rule 'MD006' 8 | rule 'MD007' 9 | rule 'MD009' 10 | rule 'MD010' 11 | rule 'MD011' 12 | rule 'MD012' 13 | rule 'MD013', :line_length => 120 14 | rule 'MD014' 15 | rule 'MD018' 16 | rule 'MD019' 17 | rule 'MD020' 18 | rule 'MD021' 19 | rule 'MD022' 20 | rule 'MD023' 21 | rule 'MD024' 22 | rule 'MD026' 23 | rule 'MD027' 24 | rule 'MD028' 25 | rule 'MD029' 26 | rule 'MD030' 27 | rule 'MD031' 28 | rule 'MD032' 29 | rule 'MD035' 30 | rule 'MD037' 31 | rule 'MD038' 32 | rule 'MD039' 33 | rule 'MD046' 34 | -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-cr/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-tailing-sidecar-config 5 | status: 6 | phase: Running 7 | containerStatuses: 8 | - name: count 9 | - name: sidecar-2 10 | --- 11 | apiVersion: kuttl.dev/v1beta1 12 | kind: TestAssert 13 | collectors: 14 | - pod: pod-with-tailing-sidecar-config 15 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | - selector: control-plane=tailing-sidecar-operator 19 | namespace: tailing-sidecar-system 20 | tail: 100 21 | commands: 22 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-2 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 23 | -------------------------------------------------------------------------------- /operator/config/crd/patches/webhook_in_tailingsidecars.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: tailingsidecars.tailing-sidecar.sumologic.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /operator/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: operator 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: quay.io/brancz/kube-rbac-proxy:v0.18.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | 23 | -------------------------------------------------------------------------------- /tests/operator/pod-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations 5 | status: 6 | phase: Running 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - pod: pod-with-annotations 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs pod-with-annotations tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs pod-with-annotations named-container -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 21 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure('2') do |config| 5 | config.vm.box = 'ubuntu/bionic64' 6 | config.disksize.size = '50GB' 7 | config.vm.box_check_update = false 8 | config.vm.host_name = 'sumologic-tailing-sidecar' 9 | # Vbox 6.1.28+ restricts host-only adapters to 192.168.56.0/21 10 | # See: https://www.virtualbox.org/manual/ch06.html#network_hostonly 11 | config.vm.network :private_network, ip: "192.168.56.87" 12 | 13 | config.vm.provider 'virtualbox' do |vb| 14 | vb.gui = false 15 | vb.cpus = 4 16 | vb.memory = 8192 17 | vb.name = 'sumologic-tailing-sidecar' 18 | end 19 | 20 | config.vm.provision 'shell', path: 'vagrant/provision.sh' 21 | config.vm.synced_folder ".", "/tailing-sidecar" 22 | end 23 | -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations 5 | status: 6 | phase: Running 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - pod: pod-with-annotations 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs pod-with-annotations tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs pod-with-annotations named-container -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 21 | -------------------------------------------------------------------------------- /operator/config/samples/tailing-sidecar-update_v1_tailingsidecar.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tailing-sidecar.sumologic.com/v1 2 | kind: TailingSidecarConfig 3 | metadata: 4 | name: tailingsidecar-sample 5 | spec: 6 | annotationsPrefix: tailing-sidecar.sumologic.com 7 | podSelector: 8 | matchLabels: 9 | tailing-sidecar: "true" 10 | configs: 11 | sidecar-2: 12 | volumeMount: 13 | name: varlogconfig 14 | mountPath: /varconfig-new-dir/log 15 | path: /varconfig-new-dir/log/example2.log 16 | annotations: 17 | sourceCategory: sourceCategory-2 18 | annotation-2: "true" 19 | resources: 20 | requests: 21 | cpu: 100m 22 | memory: 100Mi 23 | limits: 24 | cpu: 200m 25 | memory: 200Mi 26 | -------------------------------------------------------------------------------- /tests/sidecar/pod-with-sidecar/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: example-with-tailling-sidecars 5 | status: 6 | phase: Running 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - pod: example-with-tailling-sidecars 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs -n $NAMESPACE --tail 5 example-with-tailling-sidecars sidecar1 | grep example1 | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs -n $NAMESPACE --tail 5 example-with-tailling-sidecars sidecar2 | grep example2 | wc -l) -eq 5 ]" 21 | -------------------------------------------------------------------------------- /operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.24.5 AS builder 3 | 4 | WORKDIR /workspace 5 | 6 | # Copy the go source 7 | COPY go.mod go.sum ./ 8 | 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | COPY . . 14 | 15 | # Build 16 | RUN CGO_ENABLED=0 GOOS=linux GO111MODULE=on go build -a -o manager main.go config.go 17 | 18 | # Use distroless as minimal base image to package the manager binary 19 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 20 | FROM gcr.io/distroless/static:nonroot 21 | WORKDIR / 22 | COPY --from=builder /workspace/manager . 23 | USER nonroot:nonroot 24 | 25 | ENTRYPOINT ["/manager"] 26 | -------------------------------------------------------------------------------- /sidecar/otelcol/Dockerfile: -------------------------------------------------------------------------------- 1 | # Prepare the necessary directories in an Alpine container where we have the necessary tooling 2 | FROM alpine:3.21.3 AS directories 3 | RUN mkdir /etc/otel/ 4 | RUN mkdir /var/lib/otc 5 | RUN touch /var/log/otelcol.log 6 | 7 | FROM scratch 8 | 9 | ARG USER_UID=10001 10 | USER ${USER_UID} 11 | 12 | COPY --from=directories --chown=${USER_UID}:${USER_UID} /etc/otel/ /etc/otel/ 13 | COPY --from=directories --chown=${USER_UID}:${USER_UID} /var/lib/otc /var/lib/otc 14 | COPY --from=directories --chown=${USER_UID}:${USER_UID} /var/log/otelcol.log /var/log/otelcol.log 15 | 16 | # copy the default tailing-sidecar configuration file 17 | COPY ./config.yaml /etc/otel/config.yaml 18 | 19 | COPY otelcol-sidecar /otelcol 20 | ENTRYPOINT ["/otelcol"] 21 | CMD ["--config", "/etc/otel/config.yaml"] 22 | -------------------------------------------------------------------------------- /tests/operator/pod-without-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-without-annotations 5 | spec: 6 | containers: 7 | - name: count 8 | image: busybox 9 | args: 10 | - /bin/sh 11 | - -c 12 | - > 13 | i=0; 14 | while true; 15 | do 16 | echo "example0: $i $(date)" >> /var/log/example0.log; 17 | echo "example1: $i $(date)" >> /var/log/example1.log; 18 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 19 | i=$((i+1)); 20 | sleep 1; 21 | done 22 | volumeMounts: 23 | - name: varlog 24 | mountPath: /var/log 25 | - name: varlogconfig 26 | mountPath: /varconfig/log 27 | volumes: 28 | - name: varlog 29 | emptyDir: {} 30 | - name: varlogconfig 31 | emptyDir: {} 32 | -------------------------------------------------------------------------------- /tests/operator/daemonset-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: daemonset-with-annotations 5 | status: 6 | numberReady: 1 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - selector: app=daemonset-with-annotations 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs -l app=daemonset-with-annotations -c tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs -l app=daemonset-with-annotations -c tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 21 | -------------------------------------------------------------------------------- /tests/modified/operator/daemonset-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: daemonset-with-annotations 5 | status: 6 | numberReady: 1 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - selector: app=daemonset-with-annotations 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs -l app=daemonset-with-annotations -c tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs -l app=daemonset-with-annotations -c tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 21 | -------------------------------------------------------------------------------- /tests/operator/statefulset-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: statefulset-with-annotations 5 | status: 6 | replicas: 1 7 | readyReplicas: 1 8 | --- 9 | apiVersion: kuttl.dev/v1beta1 10 | kind: TestAssert 11 | collectors: 12 | - pod: statefulset-with-annotations-0 13 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 14 | namespace: tailing-sidecar-system 15 | tail: 100 16 | - selector: control-plane=tailing-sidecar-operator 17 | namespace: tailing-sidecar-system 18 | tail: 100 19 | commands: 20 | - script: "[ $(kubectl logs statefulset-with-annotations-0 my-named-sidecar -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs statefulset-with-annotations-0 tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /operator/examples/pod_without_annotations.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-without-annotations 5 | namespace: tailing-sidecar-system 6 | spec: 7 | containers: 8 | - name: count 9 | image: busybox 10 | args: 11 | - /bin/sh 12 | - -c 13 | - > 14 | i=0; 15 | while true; 16 | do 17 | echo "example0: $i $(date)" >> /var/log/example0.log; 18 | echo "example1: $i $(date)" >> /var/log/example1.log; 19 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 20 | i=$((i+1)); 21 | sleep 1; 22 | done 23 | volumeMounts: 24 | - name: varlog 25 | mountPath: /var/log 26 | - name: varlogconfig 27 | mountPath: /varconfig/log 28 | volumes: 29 | - name: varlog 30 | emptyDir: {} 31 | - name: varlogconfig 32 | emptyDir: {} 33 | -------------------------------------------------------------------------------- /tests/modified/operator/statefulset-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: statefulset-with-annotations 5 | status: 6 | replicas: 1 7 | readyReplicas: 1 8 | --- 9 | apiVersion: kuttl.dev/v1beta1 10 | kind: TestAssert 11 | collectors: 12 | - pod: statefulset-with-annotations-0 13 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 14 | namespace: tailing-sidecar-system 15 | tail: 100 16 | - selector: control-plane=tailing-sidecar-operator 17 | namespace: tailing-sidecar-system 18 | tail: 100 19 | commands: 20 | - script: "[ $(kubectl logs statefulset-with-annotations-0 my-named-sidecar -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs statefulset-with-annotations-0 tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /tests/operator/deployment-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | status: 6 | replicas: 1 7 | readyReplicas: 1 8 | --- 9 | apiVersion: kuttl.dev/v1beta1 10 | kind: TestAssert 11 | collectors: 12 | - selector: app=deployment-with-annotations 13 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 14 | namespace: tailing-sidecar-system 15 | tail: 100 16 | - selector: control-plane=tailing-sidecar-operator 17 | namespace: tailing-sidecar-system 18 | tail: 100 19 | commands: 20 | - script: "[ $(kubectl logs -l app=deployment-with-annotations -c tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs -l app=deployment-with-annotations -c tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /tests/modified/operator/deployment-with-annotations/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | status: 6 | replicas: 1 7 | readyReplicas: 1 8 | --- 9 | apiVersion: kuttl.dev/v1beta1 10 | kind: TestAssert 11 | collectors: 12 | - selector: app=deployment-with-annotations 13 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 14 | namespace: tailing-sidecar-system 15 | tail: 100 16 | - selector: control-plane=tailing-sidecar-operator 17 | namespace: tailing-sidecar-system 18 | tail: 100 19 | commands: 20 | - script: "[ $(kubectl logs -l app=deployment-with-annotations -c tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs -l app=deployment-with-annotations -c tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /tests/operator/deployment-with-annotations/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | status: 6 | replicas: 1 7 | readyReplicas: 1 8 | --- 9 | apiVersion: v1 10 | kind: Pod 11 | status: 12 | phase: Running 13 | containerStatuses: 14 | - name: count 15 | - name: tailing-sidecar-0 16 | --- 17 | apiVersion: kuttl.dev/v1beta1 18 | kind: TestAssert 19 | collectors: 20 | - selector: app=deployment-with-annotations 21 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 22 | namespace: tailing-sidecar-system 23 | tail: 100 24 | - selector: control-plane=tailing-sidecar-operator 25 | namespace: tailing-sidecar-system 26 | tail: 100 27 | commands: 28 | - script: "[ $(kubectl logs -l app=deployment-with-annotations -c tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 29 | -------------------------------------------------------------------------------- /tests/modified/operator/deployment-with-annotations/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | status: 6 | replicas: 1 7 | readyReplicas: 1 8 | --- 9 | apiVersion: v1 10 | kind: Pod 11 | status: 12 | phase: Running 13 | containerStatuses: 14 | - name: count 15 | - name: tailing-sidecar-0 16 | --- 17 | apiVersion: kuttl.dev/v1beta1 18 | kind: TestAssert 19 | collectors: 20 | - selector: app=deployment-with-annotations 21 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 22 | namespace: tailing-sidecar-system 23 | tail: 100 24 | - selector: control-plane=tailing-sidecar-operator 25 | namespace: tailing-sidecar-system 26 | tail: 100 27 | commands: 28 | - script: "[ $(kubectl logs -l app=deployment-with-annotations -c tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 29 | -------------------------------------------------------------------------------- /tests/operator/pod-with-cr/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-tailing-sidecar-config 5 | status: 6 | phase: Running 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - pod: pod-with-tailing-sidecar-config 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-2 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /operator/config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting vars. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | 24 | varReference: 25 | - path: metadata/annotations 26 | -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-cr/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-tailing-sidecar-config 5 | status: 6 | phase: Running 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - pod: pod-with-tailing-sidecar-config 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-0 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-1 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs pod-with-tailing-sidecar-config sidecar-2 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /tests/operator/pod-with-annotations/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations-updated 5 | status: 6 | phase: Running 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - pod: pod-with-annotations-updated 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs pod-with-annotations-updated tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs pod-with-annotations-updated named-sidecar -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs pod-with-annotations-updated tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /tests/modified/operator/pod-with-annotations/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations-updated 5 | status: 6 | phase: Running 7 | --- 8 | apiVersion: kuttl.dev/v1beta1 9 | kind: TestAssert 10 | collectors: 11 | - pod: pod-with-annotations-updated 12 | - selector: app.kubernetes.io/name=tailing-sidecar-operator 13 | namespace: tailing-sidecar-system 14 | tail: 100 15 | - selector: control-plane=tailing-sidecar-operator 16 | namespace: tailing-sidecar-system 17 | tail: 100 18 | commands: 19 | - script: "[ $(kubectl logs pod-with-annotations-updated tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 20 | - script: "[ $(kubectl logs pod-with-annotations-updated named-sidecar -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 21 | - script: "[ $(kubectl logs pod-with-annotations-updated tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep modified | wc -l) -eq 5 ]" 22 | -------------------------------------------------------------------------------- /operator/examples/pod_with_tailing_sidecar_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-tailing-sidecar-config 5 | namespace: tailing-sidecar-system 6 | labels: 7 | app: pod-with-tailing-sidecar-config 8 | tailing-sidecar: "true" 9 | spec: 10 | containers: 11 | - name: count 12 | image: busybox 13 | args: 14 | - /bin/sh 15 | - -c 16 | - > 17 | i=0; 18 | while true; 19 | do 20 | echo "example0: $i $(date)" >> /var/log/example0.log; 21 | echo "example1: $i $(date)" >> /var/log/example1.log; 22 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 23 | i=$((i+1)); 24 | sleep 1; 25 | done 26 | volumeMounts: 27 | - name: varlog 28 | mountPath: /var/log 29 | - name: varlogconfig 30 | mountPath: /varconfig/log 31 | volumes: 32 | - name: varlog 33 | emptyDir: {} 34 | - name: varlogconfig 35 | emptyDir: {} 36 | -------------------------------------------------------------------------------- /operator/examples/pod_with_tailing_sidecar_config_update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-tailing-sidecar-config 5 | namespace: tailing-sidecar-system 6 | labels: 7 | app: pod-with-tailing-sidecar-config 8 | tailing-sidecar: "true" 9 | spec: 10 | containers: 11 | - name: count 12 | image: busybox 13 | args: 14 | - /bin/sh 15 | - -c 16 | - > 17 | i=0; 18 | while true; 19 | do 20 | echo "example0: $i $(date)" >> /var/log/example0.log; 21 | echo "example1: $i $(date)" >> /var/log/example1.log; 22 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 23 | i=$((i+1)); 24 | sleep 1; 25 | done 26 | volumeMounts: 27 | - name: varlog 28 | mountPath: /var/log 29 | - name: varlogconfig 30 | mountPath: /varconfig/log 31 | volumes: 32 | - name: varlog 33 | emptyDir: {} 34 | - name: varlogconfig 35 | emptyDir: {} 36 | -------------------------------------------------------------------------------- /operator/tests/functions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function wait_for_pod() { 4 | local namespace="$1" 5 | local pod="$2" 6 | local time="$3" 7 | local state="Running" 8 | 9 | for i in $(seq 0 $time) 10 | do 11 | get="$(kubectl get pods -n $namespace $pod)" 12 | if [[ ! $get =~ $state ]]; then 13 | echo "Waiting for pod $pod in $i iteration" 14 | sleep 1 15 | else 16 | echo "Found pod $pod" 17 | break 18 | fi 19 | done 20 | } 21 | 22 | function wait_for_all_pods_running() { 23 | local namespace="$1" 24 | local time="$2" 25 | 26 | for i in $(seq 0 $time) 27 | do 28 | running_pods="$(kubectl get pods -n $namespace | grep Running | wc -l)" 29 | pods="$(kubectl get pods -n $namespace | tail -n +2 | wc -l)" 30 | if [[ $pods -eq $running_pods ]]; then 31 | echo "All Pods are in Running state" 32 | break 33 | fi 34 | echo "$(kubectl get pods -n $namespace)" 35 | sleep 1 36 | done 37 | } 38 | -------------------------------------------------------------------------------- /docs/release.md: -------------------------------------------------------------------------------- 1 | # Tailing Sidecar Release Instruction 2 | 3 | 1. Create and Merge release pull request with Helm Chart version change in [Chart.yaml](../helm/tailing-sidecar-operator/Chart.yaml). 4 | 5 | 1. Create the release tag for commit with Helm Chart version change, e.g. when release tag = 0.1.0 6 | 7 | ```bash 8 | export VERSION=0.1.0 9 | git checkout main 10 | git pull 11 | git tag -a "v${VERSION}" -m "Release v${VERSION}" 12 | ``` 13 | 14 | 1. Push the release tag, e.g. 15 | 16 | ```bash 17 | git push origin "v${VERSION}" 18 | ``` 19 | 20 | 1. For major and minor version change prepare release branch, e.g. 21 | 22 | ```bash 23 | git checkout -b "release-v${VERSION%.*}" 24 | git push origin "release-v${VERSION%.*}" 25 | ``` 26 | 27 | 1. Cut the release 28 | 29 | - Go to https://github.com/SumoLogic/tailing-sidecar/releases and click "Draft a new release". 30 | - Compare changes since the last release. 31 | - Prepare release notes. 32 | -------------------------------------------------------------------------------- /operator/config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: tailing-sidecar-operator 6 | name: system 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: operator 12 | namespace: system 13 | labels: 14 | control-plane: tailing-sidecar-operator 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: tailing-sidecar-operator 19 | replicas: 1 20 | template: 21 | metadata: 22 | labels: 23 | control-plane: tailing-sidecar-operator 24 | spec: 25 | containers: 26 | - command: 27 | - /manager 28 | args: 29 | - --enable-leader-election 30 | image: controller:latest 31 | name: manager 32 | resources: 33 | limits: 34 | cpu: 100m 35 | memory: 30Mi 36 | requests: 37 | cpu: 100m 38 | memory: 20Mi 39 | terminationGracePeriodSeconds: 10 40 | -------------------------------------------------------------------------------- /operator/examples/pod_with_tailing_sidecar_config_resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-tailing-sidecar-config-resources 5 | namespace: tailing-sidecar-system 6 | labels: 7 | app: pod-with-tailing-sidecar-config-resources 8 | tailing-sidecar-resource: "true" 9 | spec: 10 | containers: 11 | - name: count 12 | image: busybox 13 | args: 14 | - /bin/sh 15 | - -c 16 | - > 17 | i=0; 18 | while true; 19 | do 20 | echo "example0: $i $(date)" >> /var/log/example0.log; 21 | echo "example1: $i $(date)" >> /var/log/example1.log; 22 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 23 | i=$((i+1)); 24 | sleep 1; 25 | done 26 | volumeMounts: 27 | - name: varlog 28 | mountPath: /var/log 29 | - name: varlogconfig 30 | mountPath: /varconfig/log 31 | volumes: 32 | - name: varlog 33 | emptyDir: {} 34 | - name: varlogconfig 35 | emptyDir: {} 36 | -------------------------------------------------------------------------------- /operator/examples/pod_with_annotations.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations 5 | namespace: tailing-sidecar-system 6 | annotations: 7 | tailing-sidecar: varlog:/var/log/example0.log;named-container:varlog:/var/log/example1.log 8 | labels: 9 | app: pod-with-annotations 10 | spec: 11 | containers: 12 | - name: count 13 | image: busybox 14 | args: 15 | - /bin/sh 16 | - -c 17 | - > 18 | i=0; 19 | while true; 20 | do 21 | echo "example0: $i $(date)" >> /var/log/example0.log; 22 | echo "example1: $i $(date)" >> /var/log/example1.log; 23 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 24 | i=$((i+1)); 25 | sleep 1; 26 | done 27 | volumeMounts: 28 | - name: varlog 29 | mountPath: /var/log 30 | - name: varlogconfig 31 | mountPath: /varconfig/log 32 | volumes: 33 | - name: varlog 34 | emptyDir: {} 35 | - name: varlogconfig 36 | emptyDir: {} 37 | -------------------------------------------------------------------------------- /tests/operator/pod-with-annotations/01-update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations-updated 5 | annotations: 6 | tailing-sidecar: varlog:/var/log/example0.log;varlog:/var/log/example1.log;named-sidecar:varlog:/var/log/example3.log 7 | spec: 8 | containers: 9 | - name: count 10 | image: busybox 11 | args: 12 | - /bin/sh 13 | - -c 14 | - > 15 | i=0; 16 | while true; 17 | do 18 | echo "example0: $i $(date)" >> /var/log/example0.log; 19 | echo "example1: $i $(date)" >> /var/log/example1.log; 20 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 21 | echo "example3: $i $(date)" >> /var/log/example3.log; 22 | i=$((i+1)); 23 | sleep 1; 24 | done 25 | volumeMounts: 26 | - name: varlog 27 | mountPath: /var/log 28 | - name: varlogconfig 29 | mountPath: /varconfig/log 30 | volumes: 31 | - name: varlog 32 | emptyDir: {} 33 | - name: varlogconfig 34 | emptyDir: {} 35 | 36 | -------------------------------------------------------------------------------- /tests/operator/pod-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations 5 | annotations: 6 | tailing-sidecar: varlog:/var/log/example0.log;named-container:varlog:/var/log/example1.log 7 | labels: 8 | app: pod-with-annotations 9 | spec: 10 | containers: 11 | - name: count 12 | image: busybox 13 | args: 14 | - /bin/sh 15 | - -c 16 | - > 17 | i=0; 18 | while true; 19 | do 20 | echo "example0: $i $(date)" >> /var/log/example0.log; 21 | echo "example1: $i $(date)" >> /var/log/example1.log; 22 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 23 | echo "example3: $i $(date)" >> /var/log/example3.log; 24 | i=$((i+1)); 25 | sleep 1; 26 | done 27 | volumeMounts: 28 | - name: varlog 29 | mountPath: /var/log 30 | - name: varlogconfig 31 | mountPath: /varconfig/log 32 | volumes: 33 | - name: varlog 34 | emptyDir: {} 35 | - name: varlogconfig 36 | emptyDir: {} 37 | 38 | -------------------------------------------------------------------------------- /operator/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/tailing-sidecar.sumologic.com_tailingsidecarconfigs.yaml 6 | # +kubebuilder:scaffold:crdkustomizeresource 7 | 8 | patchesStrategicMerge: 9 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 10 | # patches here are for enabling the conversion webhook for each CRD 11 | #- patches/webhook_in_tailingsidecars.yaml 12 | # +kubebuilder:scaffold:crdkustomizewebhookpatch 13 | 14 | # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. 15 | # patches here are for enabling the CA injection for each CRD 16 | #- patches/cainjection_in_tailingsidecars.yaml 17 | # +kubebuilder:scaffold:crdkustomizecainjectionpatch 18 | 19 | # the following config is for teaching kustomize how to do kustomization for CRDs. 20 | configurations: 21 | - kustomizeconfig.yaml 22 | -------------------------------------------------------------------------------- /operator/config/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | # WARNING: Targets CertManager 0.11 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for 4 | # breaking changes 5 | apiVersion: cert-manager.io/v1 6 | kind: Issuer 7 | metadata: 8 | name: selfsigned-issuer 9 | namespace: system 10 | spec: 11 | selfSigned: {} 12 | --- 13 | apiVersion: cert-manager.io/v1 14 | kind: Certificate 15 | metadata: 16 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 17 | namespace: system 18 | spec: 19 | # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize 20 | dnsNames: 21 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc 22 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local 23 | issuerRef: 24 | kind: Issuer 25 | name: selfsigned-issuer 26 | secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize 27 | -------------------------------------------------------------------------------- /operator/examples/pod_with_annotations_update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-with-annotations 5 | namespace: tailing-sidecar-system 6 | annotations: 7 | tailing-sidecar: varlog:/var/log/example0.log;varlog:/var/log/example1.log;named-sidecar:varlog:/var/log/example3.log 8 | spec: 9 | containers: 10 | - name: count 11 | image: busybox 12 | args: 13 | - /bin/sh 14 | - -c 15 | - > 16 | i=0; 17 | while true; 18 | do 19 | echo "example0: $i $(date)" >> /var/log/example0.log; 20 | echo "example1: $i $(date)" >> /var/log/example1.log; 21 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 22 | echo "example3: $i $(date)" >> /var/log/example3.log; 23 | i=$((i+1)); 24 | sleep 1; 25 | done 26 | volumeMounts: 27 | - name: varlog 28 | mountPath: /var/log 29 | - name: varlogconfig 30 | mountPath: /varconfig/log 31 | volumes: 32 | - name: varlog 33 | emptyDir: {} 34 | - name: varlogconfig 35 | emptyDir: {} 36 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | time: "06:27" 8 | timezone: "Europe/Warsaw" 9 | 10 | - package-ecosystem: "docker" 11 | directory: "/operator" 12 | schedule: 13 | interval: "daily" 14 | time: "06:27" 15 | timezone: "Europe/Warsaw" 16 | 17 | - package-ecosystem: "gomod" 18 | directory: "/operator" 19 | schedule: 20 | interval: "daily" 21 | time: "06:27" 22 | timezone: "Europe/Warsaw" 23 | groups: 24 | kubernetes: 25 | patterns: 26 | - "k8s.io/*" 27 | - "sigs.k8s.io/*" 28 | 29 | - package-ecosystem: "docker" 30 | directory: "/sidecar/fluentbit" 31 | schedule: 32 | interval: "daily" 33 | time: "06:27" 34 | timezone: "Europe/Warsaw" 35 | 36 | - package-ecosystem: "gomod" 37 | directory: "/sidecar/fluentbit/out_gstdout" 38 | schedule: 39 | interval: "daily" 40 | time: "06:27" 41 | timezone: "Europe/Warsaw" 42 | -------------------------------------------------------------------------------- /operator/config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: operator 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | startupProbe: 16 | httpGet: 17 | path: /readyz 18 | port: 8081 19 | periodSeconds: 3 20 | readinessProbe: 21 | httpGet: 22 | path: /readyz 23 | port: 8081 24 | periodSeconds: 10 25 | livenessProbe: 26 | httpGet: 27 | path: /healthz 28 | port: 8081 29 | initialDelaySeconds: 1 30 | periodSeconds: 10 31 | volumeMounts: 32 | - mountPath: /tmp/k8s-webhook-server/serving-certs 33 | name: cert 34 | readOnly: true 35 | volumes: 36 | - name: cert 37 | secret: 38 | defaultMode: 420 39 | secretName: webhook-server-cert 40 | -------------------------------------------------------------------------------- /operator/tests/test-resources.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | readonly ROOT_DIR="$(dirname "$(dirname "${0}")")" 6 | source "${ROOT_DIR}"/tests/functions.sh 7 | 8 | readonly NAMESPACE="tailing-sidecar-system" 9 | readonly TIME=60 10 | 11 | wait_for_all_pods_running ${NAMESPACE} ${TIME} 12 | 13 | # Check Sidecar resources configuration in tailingsidecar-sample 14 | readonly POD="pod-with-tailing-sidecar-config-resources" 15 | if [ $(kubectl get pod ${POD} -n ${NAMESPACE} -o jsonpath='{.spec.containers[?(@.name=="sidecar-1")].resources.requests.cpu}') != "100m" ];then 16 | exit 1 17 | fi 18 | if [ $(kubectl get pod ${POD} -n ${NAMESPACE} -o jsonpath='{.spec.containers[?(@.name=="sidecar-1")].resources.requests.memory}') != "100Mi" ];then 19 | exit 1 20 | fi 21 | if [ $(kubectl get pod ${POD} -n ${NAMESPACE} -o jsonpath='{.spec.containers[?(@.name=="sidecar-1")].resources.limits.cpu}') != "500m" ];then 22 | exit 1 23 | fi 24 | if [ $(kubectl get pod ${POD} -n ${NAMESPACE} -o jsonpath='{.spec.containers[?(@.name=="sidecar-1")].resources.limits.memory}') != "500Mi" ];then 25 | exit 1 26 | fi 27 | 28 | echo "ok" 29 | exit 0 30 | -------------------------------------------------------------------------------- /operator/config/samples/tailing-sidecar_v1_tailingsidecar.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tailing-sidecar.sumologic.com/v1 2 | kind: TailingSidecarConfig 3 | metadata: 4 | name: tailingsidecar-sample 5 | spec: 6 | annotationsPrefix: tailing-sidecar.sumologic.com 7 | podSelector: 8 | matchLabels: 9 | tailing-sidecar: "true" 10 | configs: 11 | sidecar-0: 12 | volumeMount: 13 | name: varlog 14 | mountPath: /var/log 15 | path: /var/log/example0.log 16 | annotations: 17 | sourceCategory: sourceCategory-0 18 | annotation-0: "true" 19 | sidecar-1: 20 | volumeMount: 21 | name: varlog 22 | mountPath: /var/log 23 | path: /var/log/example1.log 24 | annotations: 25 | sourceCategory: sourceCategory-1 26 | annotation-1: "true" 27 | sidecar-2: 28 | volumeMount: 29 | name: varlogconfig 30 | mountPath: /varconfig-new-dir/log 31 | readOnly: true 32 | mountPropagation: HostToContainer 33 | path: /varconfig-new-dir/log/example2.log 34 | annotations: 35 | sourceCategory: sourceCategory-2 36 | annotation-2: "true" 37 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_update_1_tailing_sidecar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/spec/containers/2", 5 | "value": { 6 | "env": [ 7 | { 8 | "name": "PATH_TO_TAIL", 9 | "value": "/var/log/example1.log" 10 | }, 11 | { 12 | "name": "TAILING_SIDECAR", 13 | "value": "true" 14 | } 15 | ], 16 | "image": "tailing-sidecar-image:test", 17 | "name": "tailing-sidecar-1", 18 | "resources": {}, 19 | "volumeMounts": [ 20 | { 21 | "mountPath": "/var/log", 22 | "name": "varlog" 23 | }, 24 | { 25 | "mountPath": "/tailing-sidecar/var", 26 | "name": "volume-sidecar-1" 27 | } 28 | ] 29 | } 30 | }, 31 | { 32 | "op": "add", 33 | "path": "/spec/volumes/3", 34 | "value": { 35 | "emptyDir": {}, 36 | "name": "volume-sidecar-1" 37 | } 38 | } 39 | ] 40 | -------------------------------------------------------------------------------- /operator/config/samples/tailing-sidecar_v1_tailingsidecar_match_expressions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tailing-sidecar.sumologic.com/v1 2 | kind: TailingSidecarConfig 3 | metadata: 4 | name: tailingsidecar-sample 5 | spec: 6 | annotationsPrefix: tailing-sidecar.sumologic.com 7 | podSelector: 8 | matchExpressions: 9 | - {key: tailing-sidecar, operator: In, values: ["true"]} 10 | configs: 11 | sidecar-0: 12 | volumeMount: 13 | name: varlog 14 | mountPath: /var/log 15 | path: /var/log/example0.log 16 | annotations: 17 | sourceCategory: sourceCategory-0 18 | annotation-0: "true" 19 | sidecar-1: 20 | volumeMount: 21 | name: varlog 22 | mountPath: /var/log 23 | path: /var/log/example1.log 24 | annotations: 25 | sourceCategory: sourceCategory-1 26 | annotation-1: "true" 27 | sidecar-2: 28 | volumeMount: 29 | name: varlogconfig 30 | mountPath: /varconfig-new-dir/log 31 | readonly: true 32 | mountPropagation: HostToContainer 33 | path: /varconfig-new-dir/log/example2.log 34 | annotations: 35 | sourceCategory: sourceCategory-2 36 | annotation-2: "true" 37 | -------------------------------------------------------------------------------- /sidecar/fluentbit/Dockerfile.ubi: -------------------------------------------------------------------------------- 1 | FROM golang:1.24.5 AS go-builder 2 | RUN mkdir /build 3 | ADD ./out_gstdout /build/ 4 | WORKDIR /build 5 | RUN make all 6 | 7 | # ToDo: build and use the latest fluent-bit image 8 | FROM public.ecr.aws/sumologic/fluent-bit:4.0.1-ubi 9 | 10 | ARG VERSION=${VERSION} 11 | ARG RELEASE_NUMBER=${RELEASE_NUMBER} 12 | 13 | ENV SUMMARY="UBI based Tailing Sidecar" \ 14 | DESCRIPTION="Tailing sidecar is a streaming sidecar container which can be used with Tailing Sidecar Operator." 15 | 16 | LABEL name="Tailing Sidecar" \ 17 | maintainer="collection@sumologic.com" \ 18 | vendor="Sumo Logic" \ 19 | version=${VERSION} \ 20 | release=${RELEASE_NUMBER} \ 21 | summary="$SUMMARY" \ 22 | description="$DESCRIPTION" \ 23 | io.k8s.description="$DESCRIPTION" 24 | 25 | ADD https://raw.githubusercontent.com/SumoLogic/tailing-sidecar/release-v0.3/LICENSE /licenses/LICENSE 26 | 27 | ENV LOG_LEVEL=warning 28 | 29 | COPY --from=go-builder \ 30 | /build/out_gstdout.so \ 31 | /tailing-sidecar/lib/ 32 | 33 | COPY conf/fluent-bit.conf \ 34 | conf/plugins.conf \ 35 | /fluent-bit/etc/ 36 | 37 | USER nobody 38 | 39 | CMD ["/fluent-bit/bin/fluent-bit", "-c", "/fluent-bit/etc/fluent-bit.conf", "--quiet"] 40 | -------------------------------------------------------------------------------- /tests/operator/daemonset-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: daemonset-with-annotations 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: daemonset-with-annotations 9 | template: 10 | metadata: 11 | labels: 12 | app: daemonset-with-annotations 13 | annotations: 14 | tailing-sidecar: varlog:/var/log/example0.log;varlog:/var/log/example1.log 15 | spec: 16 | containers: 17 | - name: count 18 | image: busybox 19 | args: 20 | - /bin/sh 21 | - -c 22 | - > 23 | i=0; 24 | while true; 25 | do 26 | echo "example0: $i $(date)" >> /var/log/example0.log; 27 | echo "example1: $i $(date)" >> /var/log/example1.log; 28 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 29 | i=$((i+1)); 30 | sleep 1; 31 | done 32 | volumeMounts: 33 | - name: varlog 34 | mountPath: /var/log 35 | - name: varlogconfig 36 | mountPath: /varconfig/log 37 | volumes: 38 | - name: varlog 39 | emptyDir: {} 40 | - name: varlogconfig 41 | emptyDir: {} 42 | -------------------------------------------------------------------------------- /tests/operator/deployment-with-annotations/01-update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: deployment-with-annotations 10 | template: 11 | metadata: 12 | labels: 13 | app: deployment-with-annotations 14 | annotations: 15 | tailing-sidecar: varlog:/var/log/example0.log 16 | spec: 17 | containers: 18 | - name: count 19 | image: busybox 20 | args: 21 | - /bin/sh 22 | - -c 23 | - > 24 | i=0; 25 | while true; 26 | do 27 | echo "example0: $i $(date)" >> /var/log/example0.log; 28 | echo "example1: $i $(date)" >> /var/log/example1.log; 29 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 30 | i=$((i+1)); 31 | sleep 1; 32 | done 33 | volumeMounts: 34 | - name: varlog 35 | mountPath: /var/log 36 | - name: varlogconfig 37 | mountPath: /varconfig/log 38 | volumes: 39 | - name: varlog 40 | emptyDir: {} 41 | - name: varlogconfig 42 | emptyDir: {} 43 | 44 | -------------------------------------------------------------------------------- /tests/operator/deployment-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: deployment-with-annotations 10 | template: 11 | metadata: 12 | labels: 13 | app: deployment-with-annotations 14 | annotations: 15 | tailing-sidecar: varlog:/var/log/example0.log;varlog:/var/log/example1.log 16 | spec: 17 | containers: 18 | - name: count 19 | image: busybox 20 | args: 21 | - /bin/sh 22 | - -c 23 | - > 24 | i=0; 25 | while true; 26 | do 27 | echo "example0: $i $(date)" >> /var/log/example0.log; 28 | echo "example1: $i $(date)" >> /var/log/example1.log; 29 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 30 | i=$((i+1)); 31 | sleep 1; 32 | done 33 | volumeMounts: 34 | - name: varlog 35 | mountPath: /var/log 36 | - name: varlogconfig 37 | mountPath: /varconfig/log 38 | volumes: 39 | - name: varlog 40 | emptyDir: {} 41 | - name: varlogconfig 42 | emptyDir: {} 43 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/scc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.scc.create (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} 2 | apiVersion: security.openshift.io/v1 3 | kind: SecurityContextConstraints 4 | metadata: 5 | annotations: 6 | kubernetes.io/description: | 7 | This provides the minimum requirements Sumo Logic Kubernetes Collection to run in Openshift. 8 | name: tailing-sidecar-operator 9 | labels: 10 | app: tailing-sidecar-operator 11 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 12 | release: "{{ .Release.Name }}" 13 | heritage: "{{ .Release.Service }}" 14 | allowHostDirVolumePlugin: true 15 | allowHostIPC: false 16 | allowHostNetwork: false 17 | allowHostPID: false 18 | allowHostPorts: false 19 | allowPrivilegeEscalation: true 20 | allowPrivilegedContainer: true 21 | allowedCapabilities: [] 22 | allowedUnsafeSysctls: [] 23 | defaultAddCapabilities: [] 24 | fsGroup: 25 | type: RunAsAny 26 | groups: 27 | - system:authenticated 28 | priority: 0 29 | readOnlyRootFilesystem: false 30 | requiredDropCapabilities: [] 31 | runAsUser: 32 | type: RunAsAny 33 | seLinuxContext: 34 | type: MustRunAs 35 | seccompProfiles: [] 36 | supplementalGroups: 37 | type: RunAsAny 38 | users: [] 39 | volumes: 40 | - "*" 41 | {{- end }} 42 | -------------------------------------------------------------------------------- /operator/examples/daemonset_with_annotations.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: daemonset-with-annotations 5 | namespace: tailing-sidecar-system 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: daemonset-with-annotations 10 | template: 11 | metadata: 12 | labels: 13 | app: daemonset-with-annotations 14 | annotations: 15 | tailing-sidecar: varlog:/var/log/example0.log;varlog:/var/log/example1.log 16 | spec: 17 | containers: 18 | - name: count 19 | image: busybox 20 | args: 21 | - /bin/sh 22 | - -c 23 | - > 24 | i=0; 25 | while true; 26 | do 27 | echo "example0: $i $(date)" >> /var/log/example0.log; 28 | echo "example1: $i $(date)" >> /var/log/example1.log; 29 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 30 | i=$((i+1)); 31 | sleep 1; 32 | done 33 | volumeMounts: 34 | - name: varlog 35 | mountPath: /var/log 36 | - name: varlogconfig 37 | mountPath: /varconfig/log 38 | volumes: 39 | - name: varlog 40 | emptyDir: {} 41 | - name: varlogconfig 42 | emptyDir: {} 43 | -------------------------------------------------------------------------------- /operator/examples/deployment_with_annotations_update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | namespace: tailing-sidecar-system 6 | spec: 7 | replicas: 3 8 | selector: 9 | matchLabels: 10 | app: deployment-with-annotations 11 | template: 12 | metadata: 13 | labels: 14 | app: deployment-with-annotations 15 | annotations: 16 | tailing-sidecar: varlog:/var/log/example0.log 17 | spec: 18 | containers: 19 | - name: count 20 | image: busybox 21 | args: 22 | - /bin/sh 23 | - -c 24 | - > 25 | i=0; 26 | while true; 27 | do 28 | echo "example0: $i $(date)" >> /var/log/example0.log; 29 | echo "example1: $i $(date)" >> /var/log/example1.log; 30 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 31 | i=$((i+1)); 32 | sleep 1; 33 | done 34 | volumeMounts: 35 | - name: varlog 36 | mountPath: /var/log 37 | - name: varlogconfig 38 | mountPath: /varconfig/log 39 | volumes: 40 | - name: varlog 41 | emptyDir: {} 42 | - name: varlogconfig 43 | emptyDir: {} 44 | -------------------------------------------------------------------------------- /operator/examples/deployment_with_annotations.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-with-annotations 5 | namespace: tailing-sidecar-system 6 | spec: 7 | replicas: 3 8 | selector: 9 | matchLabels: 10 | app: deployment-with-annotations 11 | template: 12 | metadata: 13 | labels: 14 | app: deployment-with-annotations 15 | annotations: 16 | tailing-sidecar: varlog:/var/log/example0.log;varlog:/var/log/example1.log 17 | spec: 18 | containers: 19 | - name: count 20 | image: busybox 21 | args: 22 | - /bin/sh 23 | - -c 24 | - > 25 | i=0; 26 | while true; 27 | do 28 | echo "example0: $i $(date)" >> /var/log/example0.log; 29 | echo "example1: $i $(date)" >> /var/log/example1.log; 30 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 31 | i=$((i+1)); 32 | sleep 1; 33 | done 34 | volumeMounts: 35 | - name: varlog 36 | mountPath: /var/log 37 | - name: varlogconfig 38 | mountPath: /varconfig/log 39 | volumes: 40 | - name: varlog 41 | emptyDir: {} 42 | - name: varlogconfig 43 | emptyDir: {} 44 | -------------------------------------------------------------------------------- /helm/tests/values.withOtelcolCustomConfiguration.yaml: -------------------------------------------------------------------------------- 1 | operator: 2 | image: 3 | repository: registry.localhost:5000/sumologic/tailing-sidecar-operator 4 | tag: test 5 | 6 | sidecar: 7 | image: 8 | repository: registry.localhost:5000/sumologic/sidecar 9 | tag: test 10 | 11 | resources: 12 | limits: 13 | cpu: "0" 14 | memory: "0" 15 | requests: 16 | cpu: "0" 17 | memory: "0" 18 | 19 | config: 20 | content: 21 | mountPath: /etc/otel/ 22 | config.yaml: | 23 | receivers: 24 | filelog: 25 | include: 26 | - ${PATH_TO_TAIL} 27 | start_at: beginning 28 | storage: file_storage 29 | 30 | exporters: 31 | file: 32 | path: /dev/stdout 33 | encoding: text_encoding 34 | 35 | extensions: 36 | text_encoding: 37 | file_storage: 38 | directory: /var/lib/otc 39 | 40 | service: 41 | extensions: 42 | - text_encoding 43 | - file_storage 44 | telemetry: 45 | metrics: 46 | level: none 47 | logs: 48 | output_paths: 49 | - /var/log/otelcol.log 50 | pipelines: 51 | logs: 52 | exporters: [file] 53 | receivers: [filelog] 54 | -------------------------------------------------------------------------------- /operator/Dockerfile.ubi: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.24.5 AS builder 3 | 4 | WORKDIR /workspace 5 | 6 | # Copy the go source 7 | COPY go.mod go.sum ./ 8 | 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | COPY . . 14 | 15 | # Build 16 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go config.go 17 | 18 | FROM registry.access.redhat.com/ubi9/ubi:9.5 19 | 20 | ARG VERSION=${VERSION} 21 | ARG RELEASE_NUMBER=${RELEASE_NUMBER} 22 | 23 | ENV SUMMARY="UBI based Tailing Sidecar Operator" \ 24 | DESCRIPTION="Tailing Sidecar Operator adds streaming sidecar containers which use tailing sidecar image to Pods." 25 | 26 | LABEL name="Tailing Sidecar Operator" \ 27 | maintainer="collection@sumologic.com" \ 28 | vendor="Sumo Logic" \ 29 | version=${VERSION} \ 30 | release=${RELEASE_NUMBER} \ 31 | summary="$SUMMARY" \ 32 | description="$DESCRIPTION" \ 33 | io.k8s.description="$DESCRIPTION" 34 | 35 | ADD https://raw.githubusercontent.com/SumoLogic/tailing-sidecar/release-v0.3/LICENSE /licenses/LICENSE 36 | 37 | WORKDIR / 38 | COPY --from=builder /workspace/manager . 39 | 40 | RUN useradd -m nonroot 41 | USER nonroot 42 | 43 | ENTRYPOINT ["/manager"] 44 | -------------------------------------------------------------------------------- /operator/api/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1 contains API Schema definitions for the tailing-sidecar v1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=tailing-sidecar.sumologic.com 20 | package v1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "tailing-sidecar.sumologic.com", Version: "v1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /operator/config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.2.0 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.2.0 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.2.0 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.2.0 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.2.0 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /operator/tests/test-update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | readonly ROOT_DIR="$(dirname "$(dirname "${0}")")" 6 | source "${ROOT_DIR}"/tests/functions.sh 7 | 8 | readonly NAMESPACE="tailing-sidecar-system" 9 | readonly TIME=300 10 | 11 | wait_for_all_pods_running ${NAMESPACE} ${TIME} 12 | kubectl describe pods -n ${NAMESPACE} 13 | 14 | # Check Pod logs 15 | readonly POD="pod-with-annotations" 16 | wait_for_pod ${NAMESPACE} ${POD} ${TIME} 17 | [[ $(kubectl logs ${POD} tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 18 | [[ $(kubectl logs ${POD} named-sidecar -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 19 | [[ $(kubectl logs ${POD} tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 20 | 21 | # Check Deployment logs 22 | readonly DEPLOYMENT_POD_NAME="$(kubectl get pod -l app=deployment-with-annotations -n ${NAMESPACE} -o jsonpath="{.items[0].metadata.name}")" 23 | wait_for_pod ${NAMESPACE} ${DEPLOYMENT_POD_NAME} ${TIME} 24 | [[ $(kubectl logs ${DEPLOYMENT_POD_NAME} tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 25 | 26 | # Test Pod with configuration in CR 27 | readonly POD_WITH_CR="pod-with-tailing-sidecar-config" 28 | wait_for_pod ${NAMESPACE} ${POD_WITH_CR} ${TIME} 29 | [[ $(kubectl logs ${POD_WITH_CR} sidecar-2 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 30 | 31 | echo "ok" 32 | exit 0 33 | -------------------------------------------------------------------------------- /tests/sidecar/pod-with-sidecar/00-install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: example-with-tailling-sidecars 5 | spec: 6 | containers: 7 | - name: count 8 | image: busybox 9 | args: 10 | - /bin/sh 11 | - -c 12 | - > 13 | i=0; 14 | while true; 15 | do 16 | echo "example1: $i $(date)" >> /var/log/example1.log; 17 | echo "example2: $i $(date)" >> /var/log/example2.log; 18 | i=$((i+1)); 19 | sleep 1; 20 | done 21 | volumeMounts: 22 | - name: varlog 23 | mountPath: /var/log 24 | - name: sidecar1 25 | image: ghcr.io/sumologic/tailing-sidecar:latest 26 | env: 27 | - name: PATH_TO_TAIL 28 | value: /var/log/example1.log 29 | volumeMounts: 30 | - name: varlog 31 | mountPath: /var/log 32 | - name: volume-sidecar-1 33 | mountPath: /tailing-sidecar/var 34 | - name: sidecar2 35 | image: ghcr.io/sumologic/tailing-sidecar:latest 36 | env: 37 | - name: PATH_TO_TAIL 38 | value: /var/log/example2.log 39 | volumeMounts: 40 | - name: varlog 41 | mountPath: /var/log 42 | - name: volume-sidecar-2 43 | mountPath: /tailing-sidecar/var 44 | volumes: 45 | - name: varlog 46 | emptyDir: {} 47 | - name: volume-sidecar-1 48 | hostPath: 49 | path: /var/log/sidecar1 50 | type: DirectoryOrCreate 51 | - name: volume-sidecar-2 52 | hostPath: 53 | path: /var/log/sidecar2 54 | type: DirectoryOrCreate 55 | -------------------------------------------------------------------------------- /sidecar/fluentbit/examples/pod_with_tailing_sidecars.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: example-with-tailling-sidecars 5 | spec: 6 | containers: 7 | - name: count 8 | image: busybox 9 | args: 10 | - /bin/sh 11 | - -c 12 | - > 13 | i=0; 14 | while true; 15 | do 16 | echo "example1: $i $(date)" >> /var/log/example1.log; 17 | echo "example2: $i $(date)" >> /var/log/example2.log; 18 | i=$((i+1)); 19 | sleep 1; 20 | done 21 | volumeMounts: 22 | - name: varlog 23 | mountPath: /var/log 24 | - name: sidecar1 25 | image: ghcr.io/sumologic/tailing-sidecar:latest 26 | env: 27 | - name: PATH_TO_TAIL 28 | value: /var/log/example1.log 29 | volumeMounts: 30 | - name: varlog 31 | mountPath: /var/log 32 | - name: volume-sidecar-1 33 | mountPath: /tailing-sidecar/var 34 | - name: sidecar2 35 | image: ghcr.io/sumologic/tailing-sidecar:latest 36 | env: 37 | - name: PATH_TO_TAIL 38 | value: /var/log/example2.log 39 | volumeMounts: 40 | - name: varlog 41 | mountPath: /var/log 42 | - name: volume-sidecar-2 43 | mountPath: /tailing-sidecar/var 44 | volumes: 45 | - name: varlog 46 | emptyDir: {} 47 | - name: volume-sidecar-1 48 | hostPath: 49 | path: /var/log/sidecar1 50 | type: DirectoryOrCreate 51 | - name: volume-sidecar-2 52 | hostPath: 53 | path: /var/log/sidecar2 54 | type: DirectoryOrCreate 55 | -------------------------------------------------------------------------------- /tests/operator/statefulset-with-annotations/00-install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: statefulset-with-annotations 5 | labels: 6 | app: statefulset-with-annotations 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: statefulset-with-annotations 11 | --- 12 | apiVersion: apps/v1 13 | kind: StatefulSet 14 | metadata: 15 | name: statefulset-with-annotations 16 | spec: 17 | replicas: 1 18 | serviceName: statefulset-with-annotations 19 | selector: 20 | matchLabels: 21 | app: statefulset-with-annotations 22 | template: 23 | metadata: 24 | labels: 25 | app: statefulset-with-annotations 26 | annotations: 27 | tailing-sidecar: my-named-sidecar:varlog:/var/log/example0.log;varlog:/var/log/example1.log 28 | spec: 29 | containers: 30 | - name: count 31 | image: busybox 32 | args: 33 | - /bin/sh 34 | - -c 35 | - > 36 | i=0; 37 | while true; 38 | do 39 | echo "example0: $i $(date)" >> /var/log/example0.log; 40 | echo "example1: $i $(date)" >> /var/log/example1.log; 41 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 42 | i=$((i+1)); 43 | sleep 1; 44 | done 45 | volumeMounts: 46 | - name: varlog 47 | mountPath: /var/log 48 | - name: varlogconfig 49 | mountPath: /varconfig/log 50 | volumes: 51 | - name: varlog 52 | emptyDir: {} 53 | - name: varlogconfig 54 | emptyDir: {} 55 | -------------------------------------------------------------------------------- /sidecar/fluentbit/Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # mkfile_path is absolute path of this file 4 | # The intention is to be able to run this file from any location 5 | mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) 6 | 7 | # root_dir is a root directory of the project (github repo) 8 | root_dir := $(dir $(abspath $(mkfile_path)/..)) 9 | 10 | TAG ?= "localhost:32000/sumologic/tailing-sidecar:latest" 11 | DOCKERFILE ?= Dockerfile 12 | RELEASE_NUMBER ?= 1 13 | VERSION ?= "" 14 | 15 | all: build push 16 | 17 | build: 18 | docker build \ 19 | --build-arg RELEASE_NUMBER=$(RELEASE_NUMBER) \ 20 | --build-arg VERSION=$(VERSION) \ 21 | --tag $(TAG) \ 22 | --file ${DOCKERFILE} . 23 | 24 | build-test-image: build 25 | 26 | run: build 27 | docker run --rm -it \ 28 | -v $(DIR_TO_TAIL):/tmp/host \ 29 | -v $(FLUENT_BIT_DB_DIR):/tailing-sidecar/var \ 30 | --env "PATH_TO_TAIL=/tmp/host/$(FILES_PATTERN)" \ 31 | --env "LOG_LEVEL=${LOG_LEVEL}" $(TAG) 32 | 33 | build-push-multiplatform: 34 | docker buildx build \ 35 | --push \ 36 | --platform linux/amd64,linux/arm/v7,linux/arm64 \ 37 | --tag ${TAG} \ 38 | . 39 | 40 | build-push-ubi: 41 | $(MAKE) build DOCKERFILE=${DOCKERFILE}.ubi TAG=${TAG}-ubi 42 | $(MAKE) push DOCKERFILE=${DOCKERFILE}.ubi TAG=${TAG}-ubi 43 | 44 | push: 45 | docker push $(TAG) 46 | 47 | deploy-examples: 48 | kubectl apply -f examples/pod_with_tailing_sidecars.yaml 49 | kubectl wait --for=condition=ready --timeout 60s pod example-with-tailling-sidecars 50 | 51 | test-examples: 52 | tests/test.sh 53 | 54 | teardown-examples: 55 | kubectl delete pod example-with-tailling-sidecars 56 | -------------------------------------------------------------------------------- /operator/examples/statefulset_with_annotations.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: statefulset-with-annotations 5 | labels: 6 | app: statefulset-with-annotations 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: statefulset-with-annotations 11 | --- 12 | apiVersion: apps/v1 13 | kind: StatefulSet 14 | metadata: 15 | name: statefulset-with-annotations 16 | namespace: tailing-sidecar-system 17 | spec: 18 | replicas: 3 19 | serviceName: statefulset-with-annotations 20 | selector: 21 | matchLabels: 22 | app: statefulset-with-annotations 23 | template: 24 | metadata: 25 | labels: 26 | app: statefulset-with-annotations 27 | annotations: 28 | tailing-sidecar: my-named-sidecar:varlog:/var/log/example0.log;varlog:/var/log/example1.log 29 | spec: 30 | containers: 31 | - name: count 32 | image: busybox 33 | args: 34 | - /bin/sh 35 | - -c 36 | - > 37 | i=0; 38 | while true; 39 | do 40 | echo "example0: $i $(date)" >> /var/log/example0.log; 41 | echo "example1: $i $(date)" >> /var/log/example1.log; 42 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 43 | i=$((i+1)); 44 | sleep 1; 45 | done 46 | volumeMounts: 47 | - name: varlog 48 | mountPath: /var/log 49 | - name: varlogconfig 50 | mountPath: /varconfig/log 51 | volumes: 52 | - name: varlog 53 | emptyDir: {} 54 | - name: varlogconfig 55 | emptyDir: {} 56 | -------------------------------------------------------------------------------- /sidecar/fluentbit/out_gstdout/out_gstdout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "C" 5 | "fmt" 6 | "unsafe" 7 | 8 | "github.com/fluent/fluent-bit-go/output" 9 | ) 10 | 11 | //export FLBPluginRegister 12 | func FLBPluginRegister(def unsafe.Pointer) int { 13 | return output.FLBPluginRegister(def, "gstdout", "Stdout GO!") 14 | } 15 | 16 | //export FLBPluginInit 17 | // (fluentbit will call this) 18 | // plugin (context) pointer to fluentbit context (state/ c code) 19 | func FLBPluginInit(plugin unsafe.Pointer) int { 20 | // Example to retrieve an optional configuration parameter 21 | // param := output.FLBPluginConfigKey(plugin, "param") 22 | // fmt.Printf("[flb-go] plugin parameter = '%s'\n", param) 23 | return output.FLB_OK 24 | } 25 | 26 | //export FLBPluginFlush 27 | func FLBPluginFlush(data unsafe.Pointer, length C.int, tag *C.char) int { 28 | var ret int 29 | var record map[interface{}]interface{} 30 | 31 | // Create Fluent Bit decoder 32 | dec := output.NewDecoder(data, int(length)) 33 | 34 | // Iterate Records 35 | for { 36 | // Extract Record 37 | ret, _, record = output.GetRecord(dec) 38 | if ret != 0 { 39 | break 40 | } 41 | 42 | // Print values 43 | for _, v := range record { 44 | fmt.Printf("%s\n", v) 45 | } 46 | } 47 | 48 | // Return options: 49 | // 50 | // output.FLB_OK = data have been processed. 51 | // output.FLB_ERROR = unrecoverable error, do not try this again. 52 | // output.FLB_RETRY = retry to flush later. 53 | return output.FLB_OK 54 | } 55 | 56 | //export FLBPluginExit 57 | func FLBPluginExit() int { 58 | return output.FLB_OK 59 | } 60 | 61 | func main() { 62 | } 63 | -------------------------------------------------------------------------------- /sidecar/fluentbit/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.24.5 AS go-builder 2 | RUN mkdir /build 3 | ADD ./out_gstdout /build/ 4 | WORKDIR /build 5 | RUN make all 6 | 7 | # Manually upgrade libc and zlib to address https://www.cve.org/CVERecord?id=CVE-2022-37434 and https://www.cve.org/CVERecord?id=CVE-2021-3999 8 | # TODO: Revert this after fluent-bit 1.9.9 is released 9 | FROM debian:bookworm-slim AS deb-extractor 10 | 11 | # We download all debs locally then extract them into a directory we can use as the root for distroless. 12 | # This is directly copied from Fluent Bit's upstream Dockerfile 13 | WORKDIR /tmp 14 | RUN apt-get update && \ 15 | apt-get download \ 16 | zlib1g \ 17 | libc6 && \ 18 | mkdir -p /dpkg/var/lib/dpkg/status.d/ && \ 19 | for deb in *.deb; do \ 20 | package_name=$(dpkg-deb -I ${deb} | awk '/^ Package: .*$/ {print $2}'); \ 21 | echo "Processing: ${package_name}"; \ 22 | dpkg --ctrl-tarfile $deb | tar -Oxf - ./control > /dpkg/var/lib/dpkg/status.d/${package_name}; \ 23 | dpkg --extract $deb /dpkg || exit 10; \ 24 | done 25 | 26 | # Remove unnecessary files extracted from deb packages like man pages and docs etc. 27 | RUN find /dpkg/ -type d -empty -delete && \ 28 | rm -r /dpkg/usr/share/doc/ 29 | 30 | FROM fluent/fluent-bit:4.0.5 31 | ENV LOG_LEVEL=warning 32 | 33 | # Copy the libraries from the extractor stage into root 34 | COPY --from=deb-extractor /dpkg / 35 | 36 | COPY --from=go-builder \ 37 | /build/out_gstdout.so \ 38 | /tailing-sidecar/lib/ 39 | 40 | COPY conf/fluent-bit.conf \ 41 | conf/plugins.conf \ 42 | /fluent-bit/etc/ 43 | 44 | CMD ["/fluent-bit/bin/fluent-bit", "-c", "/fluent-bit/etc/fluent-bit.conf", "--quiet"] 45 | -------------------------------------------------------------------------------- /tests/operator/pod-with-cr/01-update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - command: kubectl delete pod pod-with-tailing-sidecar-config -n $NAMESPACE 5 | - command: kubectl delete tailingsidecarconfig tailingsidecar-sample -n $NAMESPACE 6 | --- 7 | apiVersion: tailing-sidecar.sumologic.com/v1 8 | kind: TailingSidecarConfig 9 | metadata: 10 | name: tailingsidecar-sample 11 | spec: 12 | annotationsPrefix: tailing-sidecar.sumologic.com 13 | podSelector: 14 | matchLabels: 15 | tailing-sidecar: "true" 16 | configs: 17 | sidecar-2: 18 | volumeMount: 19 | name: varlogconfig 20 | mountPath: /varconfig-new-dir/log 21 | path: /varconfig-new-dir/log/example2.log 22 | annotations: 23 | sourceCategory: sourceCategory-2 24 | annotation-2: "true" 25 | --- 26 | apiVersion: v1 27 | kind: Pod 28 | metadata: 29 | name: pod-with-tailing-sidecar-config 30 | labels: 31 | app: pod-with-tailing-sidecar-config 32 | tailing-sidecar: "true" 33 | spec: 34 | containers: 35 | - name: count 36 | image: busybox 37 | args: 38 | - /bin/sh 39 | - -c 40 | - > 41 | i=0; 42 | while true; 43 | do 44 | echo "example0: $i $(date)" >> /var/log/example0.log; 45 | echo "example1: $i $(date)" >> /var/log/example1.log; 46 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 47 | i=$((i+1)); 48 | sleep 1; 49 | done 50 | volumeMounts: 51 | - name: varlog 52 | mountPath: /var/log 53 | - name: varlogconfig 54 | mountPath: /varconfig/log 55 | volumes: 56 | - name: varlog 57 | emptyDir: {} 58 | - name: varlogconfig 59 | emptyDir: {} 60 | 61 | -------------------------------------------------------------------------------- /operator/handler/annotations.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package handler 18 | 19 | import ( 20 | "fmt" 21 | "regexp" 22 | ) 23 | 24 | const defaultAnnotationKeyPrefix = "tailing-sidecar.sumologic.com" 25 | 26 | var whiteSpaces = regexp.MustCompile(`\s+`) 27 | 28 | // addAnnotations adds per tailing sidecar container annotations to Pod specification 29 | // according to configuration defined in TailingSidecarConfig 30 | // format of annotation: /.: 31 | func addAnnotations(annotations map[string]string, config sidecarConfig) map[string]string { 32 | if annotations == nil { 33 | annotations = make(map[string]string, 0) 34 | } 35 | 36 | if config.name == "" { 37 | handlerLog.Info( 38 | "Missing tailing sidecar container name, cannot create per sidecar annotations", 39 | "config", config, 40 | ) 41 | return annotations 42 | } 43 | 44 | if config.annotationsPrefix == "" { 45 | config.annotationsPrefix = defaultAnnotationKeyPrefix 46 | } 47 | 48 | keyPrefix := fmt.Sprintf("%s/%s.", config.annotationsPrefix, config.name) 49 | 50 | for k, v := range config.spec.Annotations { 51 | annotations[keyPrefix+k] = v 52 | } 53 | return annotations 54 | } 55 | -------------------------------------------------------------------------------- /docs/dev.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | This document contains information helpful for developers. 4 | 5 | ## Development Builds 6 | 7 | Development builds are created on each merge to `main` branch. 8 | 9 | ### Container Images 10 | 11 | Container images for [tailing sidecar](../sidecar) and [tailing sidecar operator](../operator) are pushed to 12 | Github Container Registry. The latest development images have `main` tag. 13 | 14 | To pull the latest tailing sidecar image use: 15 | 16 | ```sh 17 | docker pull ghcr.io/sumologic/tailing-sidecar:main 18 | ``` 19 | 20 | To pull the latest tailing sidecar operator image use: 21 | 22 | ```sh 23 | docker pull ghcr.io/sumologic/tailing-sidecar-operator:main 24 | ``` 25 | 26 | ### Helm Charts 27 | 28 | Helm Charts are available on [gh-pages](https://github.com/SumoLogic/tailing-sidecar/tree/gh-pages) branch. 29 | Development Helm Charts are stored in [dev](https://github.com/SumoLogic/tailing-sidecar/tree/gh-pages/dev) directory. 30 | 31 | To add development repository: 32 | 33 | ```sh 34 | helm repo add tailing-sidecar-dev https://sumologic.github.io/tailing-sidecar/dev 35 | helm repo update 36 | ``` 37 | 38 | To install development Helm chart with the latest development container images: 39 | 40 | ```sh 41 | helm upgrade --install tailing-sidecar tailing-sidecar-dev/tailing-sidecar-operator \ 42 | --namespace tailing-sidecar-system \ 43 | --create-namespace \ 44 | --set operator.image.tag=main \ 45 | --set sidecar.image.tag=main \ 46 | --version 47 | ``` 48 | 49 | e.g. 50 | 51 | ```sh 52 | helm upgrade --install tailing-sidecar tailing-sidecar-dev/tailing-sidecar-operator \ 53 | --namespace tailing-sidecar-system \ 54 | --create-namespace \ 55 | --set operator.image.tag=main \ 56 | --set sidecar.image.tag=main \ 57 | --version 0.1.0-13-g177189e057df0180b46232ebea53f60fa93d242f 58 | ``` 59 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/_operator-webhook.tpl: -------------------------------------------------------------------------------- 1 | {{- define "tailing-sidecar-operator.webhook" -}} 2 | {{- $altNames := list ( printf "%s.%s" (include "tailing-sidecar-operator.fullname" .) .Release.Namespace ) ( printf "%s.%s.svc" (include "tailing-sidecar-operator.fullname" .) .Release.Namespace ) -}} 3 | {{- $ca := genCA "tailing-sidecar-operator-ca" 365 -}} 4 | {{- $cert := genSignedCert ( include "tailing-sidecar-operator.fullname" . ) nil $altNames 365 $ca -}} 5 | apiVersion: admissionregistration.k8s.io/v1 6 | kind: MutatingWebhookConfiguration 7 | metadata: 8 | name: tailing-sidecar-mutating-webhook-configuration 9 | namespace: {{ .Release.Namespace }} 10 | webhooks: 11 | - admissionReviewVersions: 12 | - v1 13 | clientConfig: 14 | caBundle: {{ $ca.Cert | b64enc }} 15 | service: 16 | name: {{ include "tailing-sidecar-operator.fullname" . }} 17 | namespace: {{ .Release.Namespace }} 18 | path: /add-tailing-sidecars-v1-pod 19 | failurePolicy: {{ .Values.webhook.failurePolicy }} 20 | reinvocationPolicy: {{ .Values.webhook.reinvocationPolicy }} 21 | objectSelector: 22 | {{- toYaml .Values.webhook.objectSelector | nindent 4 }} 23 | namespaceSelector: 24 | {{- toYaml .Values.webhook.namespaceSelector | nindent 4 }} 25 | name: tailing-sidecar.sumologic.com 26 | rules: 27 | - apiGroups: 28 | - "" 29 | apiVersions: 30 | - v1 31 | - v1beta1 32 | operations: 33 | - CREATE 34 | - DELETE 35 | resources: 36 | - pods 37 | sideEffects: None 38 | --- 39 | apiVersion: v1 40 | kind: Secret 41 | type: kubernetes.io/tls 42 | metadata: 43 | annotations: 44 | "helm.sh/hook": "pre-install,pre-upgrade" 45 | "helm.sh/hook-delete-policy": "before-hook-creation" 46 | labels: 47 | {{- include "tailing-sidecar-operator.labels" . | nindent 4 }} 48 | name: webhook-server-cert 49 | namespace: {{ .Release.Namespace }} 50 | data: 51 | tls.crt: {{ $cert.Cert | b64enc }} 52 | tls.key: {{ $cert.Key | b64enc }} 53 | {{- end }} 54 | -------------------------------------------------------------------------------- /tests/operator/pod-with-cr/00-install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tailing-sidecar.sumologic.com/v1 2 | kind: TailingSidecarConfig 3 | metadata: 4 | name: tailingsidecar-sample 5 | spec: 6 | annotationsPrefix: tailing-sidecar.sumologic.com 7 | podSelector: 8 | matchLabels: 9 | tailing-sidecar: "true" 10 | configs: 11 | sidecar-0: 12 | volumeMount: 13 | name: varlog 14 | mountPath: /var/log 15 | path: /var/log/example0.log 16 | annotations: 17 | sourceCategory: sourceCategory-0 18 | annotation-0: "true" 19 | sidecar-1: 20 | volumeMount: 21 | name: varlog 22 | mountPath: /var/log 23 | path: /var/log/example1.log 24 | annotations: 25 | sourceCategory: sourceCategory-1 26 | annotation-1: "true" 27 | sidecar-2: 28 | volumeMount: 29 | name: varlogconfig 30 | mountPath: /varconfig-new-dir/log 31 | readOnly: true 32 | mountPropagation: HostToContainer 33 | path: /varconfig-new-dir/log/example2.log 34 | annotations: 35 | sourceCategory: sourceCategory-2 36 | annotation-2: "true" 37 | --- 38 | apiVersion: v1 39 | kind: Pod 40 | metadata: 41 | name: pod-with-tailing-sidecar-config 42 | labels: 43 | app: pod-with-tailing-sidecar-config 44 | tailing-sidecar: "true" 45 | spec: 46 | containers: 47 | - name: count 48 | image: busybox 49 | args: 50 | - /bin/sh 51 | - -c 52 | - > 53 | i=0; 54 | while true; 55 | do 56 | echo "example0: $i $(date)" >> /var/log/example0.log; 57 | echo "example1: $i $(date)" >> /var/log/example1.log; 58 | echo "example2: $i $(date)" >> /varconfig/log/example2.log; 59 | i=$((i+1)); 60 | sleep 1; 61 | done 62 | volumeMounts: 63 | - name: varlog 64 | mountPath: /var/log 65 | - name: varlogconfig 66 | mountPath: /varconfig/log 67 | volumes: 68 | - name: varlog 69 | emptyDir: {} 70 | - name: varlogconfig 71 | emptyDir: {} 72 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/_operator-webhook-with-cert-manager.tpl: -------------------------------------------------------------------------------- 1 | {{- define "tailing-sidecar-operator.webhookWithCertManager" }} 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/tailing-sidecar-serving-cert 7 | name: tailing-sidecar-mutating-webhook-configuration 8 | namespace: {{ .Release.Namespace }} 9 | webhooks: 10 | - admissionReviewVersions: 11 | - v1 12 | - v1beta1 13 | clientConfig: 14 | caBundle: Cg== 15 | service: 16 | name: {{ include "tailing-sidecar-operator.fullname" . }} 17 | namespace: {{ .Release.Namespace }} 18 | path: /add-tailing-sidecars-v1-pod 19 | failurePolicy: {{ .Values.webhook.failurePolicy }} 20 | reinvocationPolicy: {{ .Values.webhook.reinvocationPolicy }} 21 | objectSelector: 22 | {{- toYaml .Values.webhook.objectSelector | nindent 4 }} 23 | namespaceSelector: 24 | {{- toYaml .Values.webhook.namespaceSelector | nindent 4 }} 25 | name: tailing-sidecar.sumologic.com 26 | rules: 27 | - apiGroups: 28 | - "" 29 | apiVersions: 30 | - v1 31 | operations: 32 | - CREATE 33 | - DELETE 34 | resources: 35 | - pods 36 | sideEffects: None 37 | --- 38 | apiVersion: cert-manager.io/v1 39 | kind: Certificate 40 | metadata: 41 | labels: 42 | {{- include "tailing-sidecar-operator.labels" . | nindent 4 }} 43 | name: tailing-sidecar-serving-cert 44 | namespace: {{ .Release.Namespace }} 45 | spec: 46 | dnsNames: 47 | - {{ include "tailing-sidecar-operator.fullname" . }}.{{ .Release.Namespace }}.svc 48 | - {{ include "tailing-sidecar-operator.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local 49 | issuerRef: 50 | kind: Issuer 51 | name: tailing-sidecar-selfsigned-issuer 52 | secretName: webhook-server-cert 53 | --- 54 | apiVersion: cert-manager.io/v1 55 | kind: Issuer 56 | metadata: 57 | labels: 58 | {{- include "tailing-sidecar-operator.labels" . | nindent 4 }} 59 | name: tailing-sidecar-selfsigned-issuer 60 | namespace: {{ .Release.Namespace }} 61 | spec: 62 | selfSigned: {} 63 | {{- end }} 64 | -------------------------------------------------------------------------------- /sidecar/otelcol/.otelcol-builder.yaml: -------------------------------------------------------------------------------- 1 | dist: 2 | name: otelcol-sidecar 3 | description: Sumo Logic OpenTelemetry Collector Sidecar distribution 4 | # the module name for the new distribution, following Go mod conventions. Optional, but recommended. 5 | module: github.com/SumoLogic/tailing-sidecar/sidecar 6 | # the OpenTelemetry Collector version to use as base for the distribution. 7 | otelcol_version: 0.90.1 8 | # the path to write the output (sources and binary). 9 | output_path: ./cmd 10 | 11 | exporters: 12 | - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.90.1 13 | 14 | # Note: These components aren't strictly necessary, but they don't measurably increase the binary size 15 | processors: 16 | - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.90.1 17 | - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.90.1 18 | - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/groupbyattrsprocessor v0.90.1 19 | 20 | receivers: 21 | - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.90.1 22 | 23 | extensions: 24 | - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.90.1 25 | - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.90.1 26 | import: github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage 27 | - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding v0.90.1 28 | import: github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/textencodingextension 29 | 30 | # Replacement paths are relative to the output_path (location of source files) 31 | replaces: 32 | - github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter => github.com/SumoLogic/opentelemetry-collector-contrib/exporter/fileexporter 687035f9f64c57e96d74d523b398f526e698f9e4 33 | - github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/textencodingextension => github.com/SumoLogic/opentelemetry-collector-contrib/extension/encoding/textencodingextension 687035f9f64c57e96d74d523b398f526e698f9e4 34 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "tailing-sidecar-operator.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "tailing-sidecar-operator.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "tailing-sidecar-operator.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "tailing-sidecar-operator.labels" -}} 37 | helm.sh/chart: {{ include "tailing-sidecar-operator.chart" . }} 38 | {{ include "tailing-sidecar-operator.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "tailing-sidecar-operator.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "tailing-sidecar-operator.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Configmap name 55 | */}} 56 | {{- define "tailing-sidecar-operator.configMap.name" -}} 57 | {{- printf "%s-%s" .Release.Name "operator-config" | trunc 63 | trimSuffix "-" }} 58 | {{- end }} 59 | 60 | {{/* 61 | Tailing sidecar configmap name 62 | */}} 63 | {{- define "tailing-sidecar.configMap.name" -}} 64 | {{- printf "%s-%s" .Release.Name "sidecar-config" | trunc 63 | trimSuffix "-" }} 65 | {{- end }} 66 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_with_2_tailing_sidecars.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/spec/containers/1", 5 | "value": { 6 | "env": [ 7 | { 8 | "name": "PATH_TO_TAIL", 9 | "value": "/var/log/example0.log" 10 | }, 11 | { 12 | "name": "TAILING_SIDECAR", 13 | "value": "true" 14 | } 15 | ], 16 | "image": "tailing-sidecar-image:test", 17 | "name": "tailing-sidecar-0", 18 | "resources": {}, 19 | "volumeMounts": [ 20 | { 21 | "mountPath": "/var/log", 22 | "name": "varlog" 23 | }, 24 | { 25 | "mountPath": "/tailing-sidecar/var", 26 | "name": "volume-sidecar-0" 27 | } 28 | ] 29 | } 30 | }, 31 | { 32 | "op": "add", 33 | "path": "/spec/containers/2", 34 | "value": { 35 | "env": [ 36 | { 37 | "name": "PATH_TO_TAIL", 38 | "value": "/var/log/example1.log" 39 | }, 40 | { 41 | "name": "TAILING_SIDECAR", 42 | "value": "true" 43 | } 44 | ], 45 | "image": "tailing-sidecar-image:test", 46 | "name": "tailing-sidecar-1", 47 | "resources": {}, 48 | "volumeMounts": [ 49 | { 50 | "mountPath": "/var/log", 51 | "name": "varlog" 52 | }, 53 | { 54 | "mountPath": "/tailing-sidecar/var", 55 | "name": "volume-sidecar-1" 56 | } 57 | ] 58 | } 59 | }, 60 | { 61 | "op": "add", 62 | "path": "/spec/volumes/2", 63 | "value": { 64 | "emptyDir": {}, 65 | "name": "volume-sidecar-0" 66 | } 67 | }, 68 | { 69 | "op": "add", 70 | "path": "/spec/volumes/3", 71 | "value": { 72 | "emptyDir": {}, 73 | "name": "volume-sidecar-1" 74 | } 75 | } 76 | ] 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tailing-sidecar 2 | 3 | ![Project Status](https://img.shields.io/badge/status-alpha-important?style=for-the-badge) 4 | 5 | ## TL;DR 6 | 7 | ```sh 8 | helm repo add tailing-sidecar https://sumologic.github.io/tailing-sidecar 9 | helm repo update 10 | ``` 11 | 12 | ```sh 13 | helm upgrade --install tailing-sidecar tailing-sidecar/tailing-sidecar-operator \ 14 | -n tailing-sidecar-system \ 15 | --create-namespace 16 | ``` 17 | 18 | Add `tailing-sidecar` annotation to Pod: 19 | 20 | ```yaml 21 | metadata: 22 | annotations: 23 | tailing-sidecar: ::;:: 24 | ``` 25 | 26 | Tailing Sidecar Operator configuration is described [here](operator/docs/configuration.md). 27 | 28 | ## Tailing Sidecar 29 | 30 | **tailing sidecar** is a [streaming sidecar container](https://kubernetes.io/docs/concepts/cluster-administration/logging/#streaming-sidecar-container), 31 | the cluster-level logging agent for Kubernetes. 32 | 33 | It helps when your application inside the Pod cannot write to standard output and/or standard error stream 34 | or when it outputs additional logs to a file instead (eg. the gc.log). 35 | 36 | It [tails](https://en.wikipedia.org/wiki/Tail_(Unix)) the files inside Kubernetes Pods, 37 | handling situations like the file not being there when tailing starts, tailing multiple files, rotating files, etc. 38 | 39 | It uses [Fluent Bit](https://fluentbit.io/) under the hood, benefiting from its performance. 40 | 41 | For more information about cluster-level logging architecture please read Kubernetes 42 | [documentation](https://kubernetes.io/docs/concepts/cluster-administration/logging/#cluster-level-logging-architectures). 43 | 44 | The project consists of two parts: 45 | 46 | - [tailing sidecar container image](sidecar/) which can be used to manually extend Pods by tailing sidecars 47 | - [tailing sidecar operator](operator/) which automatically adds tailing sidecars to Pods based on configuration 48 | provided in annotation 49 | 50 | ## License 51 | 52 | This project is released under the [Apache 2.0 License](LICENSE). 53 | 54 | ## Contributing 55 | 56 | Please share your thoughts about tailing sidecar by opening an [issue](https://github.com/SumoLogic/tailing-sidecar/issues/new). 57 | 58 | To get started contributing, please refer to our [Contributing](CONTRIBUTING.md) documentation. 59 | -------------------------------------------------------------------------------- /operator/controllers/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "path/filepath" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo" 24 | . "github.com/onsi/gomega" 25 | "k8s.io/client-go/kubernetes/scheme" 26 | "k8s.io/client-go/rest" 27 | "sigs.k8s.io/controller-runtime/pkg/client" 28 | "sigs.k8s.io/controller-runtime/pkg/envtest" 29 | logf "sigs.k8s.io/controller-runtime/pkg/log" 30 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 31 | 32 | tailingsidecarv1 "github.com/SumoLogic/tailing-sidecar/operator/api/v1" 33 | // +kubebuilder:scaffold:imports 34 | ) 35 | 36 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 37 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 38 | 39 | var cfg *rest.Config 40 | var k8sClient client.Client 41 | var testEnv *envtest.Environment 42 | 43 | func TestAPIs(t *testing.T) { 44 | RegisterFailHandler(Fail) 45 | 46 | RunSpecs(t, "Controller Suite") 47 | } 48 | 49 | var _ = BeforeSuite(func(done Done) { 50 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 51 | 52 | By("bootstrapping test environment") 53 | testEnv = &envtest.Environment{ 54 | CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, 55 | } 56 | 57 | var err error 58 | cfg, err = testEnv.Start() 59 | Expect(err).ToNot(HaveOccurred()) 60 | Expect(cfg).ToNot(BeNil()) 61 | 62 | err = tailingsidecarv1.AddToScheme(scheme.Scheme) 63 | Expect(err).NotTo(HaveOccurred()) 64 | 65 | // +kubebuilder:scaffold:scheme 66 | 67 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 68 | Expect(err).ToNot(HaveOccurred()) 69 | Expect(k8sClient).ToNot(BeNil()) 70 | 71 | close(done) 72 | }, 60) 73 | 74 | var _ = AfterSuite(func() { 75 | By("tearing down the test environment") 76 | err := testEnv.Stop() 77 | Expect(err).ToNot(HaveOccurred()) 78 | }) 79 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/README.md: -------------------------------------------------------------------------------- 1 | # Tailing Sidecar Operator 2 | 3 | ![Project Status](https://img.shields.io/badge/status-alpha-important?style=for-the-badge) 4 | 5 | [Tailing Sidecar Operator](../../operator/README.md) makes it easy to add 6 | [streaming sidecar containers](https://kubernetes.io/docs/concepts/cluster-administration/logging/#streaming-sidecar-container) 7 | to pods in your cluster by adding annotations on the pods. 8 | 9 | ## Prerequisites 10 | 11 | Before installing this chart, ensure the following prerequisites are satisfied in your cluster: 12 | 13 | - [admission webhooks](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites) 14 | are enabled 15 | 16 | ## Installing 17 | 18 | Having satisfied the [Prerequisites](#prerequisites), run the following to add Helm repository: 19 | 20 | ```sh 21 | helm repo add tailing-sidecar https://sumologic.github.io/tailing-sidecar 22 | helm repo update 23 | ``` 24 | 25 | and install Helm chart: 26 | 27 | ```sh 28 | helm upgrade --install tailing-sidecar tailing-sidecar/tailing-sidecar-operator \ 29 | -n tailing-sidecar-system \ 30 | --create-namespace 31 | ``` 32 | 33 | ## Uninstalling 34 | 35 | ```sh 36 | helm uninstall tailing-sidecar-operator 37 | ``` 38 | 39 | ## Configuration 40 | 41 | See [values.yaml](./values.yaml) file for the available configuration options. 42 | 43 | ### Using `cert-manager` to manage operator's certificates 44 | 45 | By default, TLS certificates for the Tailing Sidecar Operator's API webhook 46 | are created using Helm's functions `genCA` and `genSignedCert`. 47 | The generated certificate is valid for 365 days after issuing, i.e. after chart installation. 48 | 49 | If you have [cert-manager](https://cert-manager.io/) installed in your cluster, 50 | you can make the chart use it for certificate management by setting the property `certManager.enabled` to `true`. 51 | 52 | ### Overriding Tailing Sidecar configuration 53 | 54 | In order to override tailing sidecar configuration, the following properties may be used: 55 | 56 | ```yaml 57 | sidecar: 58 | config: 59 | mountPath: /fluent-bit/etc/ 60 | content: 61 | file-1.conf: | 62 | content of file-1.conf 63 | file-2.conf: | 64 | content of file-2.conf 65 | ``` 66 | 67 | The above configuration is going to create `file-1.conf` and `file-2.conf` in `/fluent-bit/etc/` directory. 68 | 69 | **All existing content of `/fluent-bit/etc/` directory will be replaced with the `sidecar.config.content`.** 70 | -------------------------------------------------------------------------------- /ci/_build_functions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # shellcheck disable=SC2154 4 | 5 | err_report() { 6 | echo "Script error on line $1" 7 | exit 1 8 | } 9 | trap 'err_report $LINENO' ERR 10 | 11 | function helm() { 12 | docker run --rm \ 13 | -v "$(pwd):/chart" \ 14 | -w /chart \ 15 | sumologic/kubernetes-tools:2.2.3 \ 16 | helm "$@" 17 | } 18 | 19 | function set_up_github() { 20 | git config --global user.email "continuous-integration@sumologic.com" 21 | git config --global user.name "Continuous Integration [bot]" 22 | } 23 | 24 | function push_helm_chart() { 25 | local version="$1" 26 | local chart_dir="$2" 27 | local sync_dir="./tmp-helm-sync" 28 | 29 | echo "Pushing new Helm Chart release ${version}" 30 | 31 | # due to helm repo index issue: https://github.com/helm/helm/issues/7363 32 | # we need to create new package in a different dir, merge the index and move the package back 33 | mkdir -p "${sync_dir}" 34 | set -ex 35 | helm package helm/tailing-sidecar-operator --dependency-update --version="${version}" --app-version="${version}" --destination "${sync_dir}" 36 | 37 | git fetch origin gh-pages 38 | git reset --hard HEAD 39 | git checkout gh-pages 40 | 41 | helm repo index --url "https://sumologic.github.io/tailing-sidecar${chart_dir:1}/" --merge "${chart_dir}/index.yaml" "${sync_dir}" 42 | 43 | mv -f "${sync_dir}"/* "${chart_dir}" 44 | rmdir "${sync_dir}" 45 | 46 | git add -A 47 | git status 48 | git commit -m "Push new Helm Chart release ${version}" 49 | git push origin gh-pages 50 | set +ex 51 | } 52 | 53 | function is_checkout_on_tag() { 54 | git describe --exact-match --tags HEAD 2>/dev/null 55 | } 56 | 57 | function fetch_current_branch() { 58 | # No need to fetch when we can already do 'git describe ...' 59 | git describe --tags >/dev/null && return 60 | 61 | # No need to fetch full history with: 62 | # git fetch --tags --unshallow 63 | # Just fetch the current branch and its tags so that git describe works. 64 | local BRANCH 65 | BRANCH="$(git rev-parse --abbrev-ref HEAD)" 66 | 67 | # Need to check if repo is shallow because: 68 | # "fatal: --unshallow on a complete repository does not make sense" 69 | # and we need to unshallow the repository because otherwise we'd get: 70 | # fatal: No tags can describe ''. 71 | # Try --always, or create some tags. 72 | if [[ "true" == "$(git rev-parse --is-shallow-repository)" ]]; then 73 | git fetch -v --tags --unshallow origin "${BRANCH}" 74 | else 75 | git fetch -v --tags origin "${BRANCH}" 76 | fi 77 | } 78 | -------------------------------------------------------------------------------- /operator/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | readonly ROOT_DIR="$(dirname "$(dirname "${0}")")" 6 | source "${ROOT_DIR}"/tests/functions.sh 7 | 8 | readonly NAMESPACE="tailing-sidecar-system" 9 | readonly TIME=60 10 | 11 | wait_for_all_pods_running ${NAMESPACE} ${TIME} 12 | kubectl describe pods -n ${NAMESPACE} 13 | 14 | # Check Pod logs 15 | readonly POD="pod-with-annotations" 16 | wait_for_pod ${NAMESPACE} ${POD} ${TIME} 17 | [[ $(kubectl logs ${POD} tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 18 | [[ $(kubectl logs ${POD} named-container -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 19 | 20 | # Check StatefulSet logs 21 | readonly STATEFULSET_POD_NAME="statefulset-with-annotations-0" 22 | wait_for_pod ${NAMESPACE} ${STATEFULSET_POD_NAME} ${TIME} 23 | [[ $(kubectl logs ${STATEFULSET_POD_NAME} my-named-sidecar -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 24 | [[ $(kubectl logs ${STATEFULSET_POD_NAME} tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 25 | 26 | # Check Deployment logs 27 | readonly DEPLOYMENT_POD_NAME="$(kubectl get pod -l app=deployment-with-annotations -n ${NAMESPACE} -o jsonpath="{.items[0].metadata.name}")" 28 | wait_for_pod ${NAMESPACE} ${DEPLOYMENT_POD_NAME} ${TIME} 29 | [[ $(kubectl logs ${DEPLOYMENT_POD_NAME} tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 30 | [[ $(kubectl logs ${DEPLOYMENT_POD_NAME} tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 31 | 32 | # Check Daemonset logs 33 | readonly DAEMONSET_POD_NAME="$(kubectl get pod -l app=daemonset-with-annotations -n ${NAMESPACE} -o jsonpath="{.items[0].metadata.name}")" 34 | wait_for_pod ${NAMESPACE} ${DAEMONSET_POD_NAME} ${TIME} 35 | [[ $(kubectl logs ${DAEMONSET_POD_NAME} tailing-sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 36 | [[ $(kubectl logs ${DAEMONSET_POD_NAME} tailing-sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 37 | 38 | # Test Pod with configuration in CR 39 | readonly POD_WITH_CR="pod-with-tailing-sidecar-config" 40 | wait_for_pod ${NAMESPACE} ${POD_WITH_CR} ${TIME} 41 | [[ $(kubectl logs ${POD_WITH_CR} sidecar-0 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 42 | [[ $(kubectl logs ${POD_WITH_CR} sidecar-1 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 43 | [[ $(kubectl logs ${POD_WITH_CR} sidecar-2 -n ${NAMESPACE} --tail 5 | grep example | wc -l) -ne 5 ]] && exit 1 44 | 45 | echo "ok" 46 | exit 0 47 | -------------------------------------------------------------------------------- /sidecar/fluentbit/docker-bake.hcl: -------------------------------------------------------------------------------- 1 | ################################################################################# 2 | # NOTE: This bake file was added to make it easier to test variations of the 3 | # docker images locally without having to update the Makefile. It isn't used in 4 | # any part of the release process. 5 | ################################################################################# 6 | 7 | ################################################################################# 8 | # Variables 9 | ################################################################################# 10 | 11 | variable "RELEASE_NUMBER" { 12 | type = string 13 | default = "1" 14 | } 15 | 16 | variable "TAG" { 17 | type = string 18 | default = "localhost:32000/sumologic/tailing-sidecar:latest" 19 | } 20 | 21 | variable "VERSION" { 22 | type = string 23 | default = "" 24 | } 25 | 26 | ################################################################################# 27 | # Groups 28 | ################################################################################# 29 | 30 | group "default" { 31 | targets = [ 32 | "standard", 33 | "ubi" 34 | ] 35 | } 36 | 37 | ################################################################################# 38 | # Base targets 39 | ################################################################################# 40 | 41 | target "_common" { 42 | context = "./" 43 | attest = [ 44 | { 45 | type = "provenance", 46 | disabled = true, 47 | }, 48 | { 49 | type = "sbom", 50 | disabled = true, 51 | }, 52 | ] 53 | args = { 54 | RELEASE_NUMBER = "${RELEASE_NUMBER}" 55 | VERSION = "${VERSION}" 56 | } 57 | output = [{ type = "docker" }] 58 | } 59 | 60 | target "_common-standard" { 61 | inherits = ["_common"] 62 | dockerfile = "./Dockerfile" 63 | } 64 | 65 | target "_common-ubi" { 66 | inherits = ["_common"] 67 | dockerfile = "./Dockerfile.ubi" 68 | } 69 | 70 | ################################################################################# 71 | # Composite targets 72 | ################################################################################# 73 | 74 | target "standard" { 75 | inherits = ["_common-standard"] 76 | tags = ["${TAG}"] 77 | } 78 | 79 | # NOTE: Only linux/amd64 is supported as our fluent-bit base image was not 80 | # pushed with support for other platforms. This may be something we can change 81 | # but it may not make sense as we're moving away from fluent-bit. 82 | target "ubi" { 83 | inherits = ["_common-ubi"] 84 | tags = ["${TAG}-ubi"] 85 | platforms = ["linux/amd64"] 86 | } 87 | -------------------------------------------------------------------------------- /operator/controllers/tailingsidecar_controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-logr/logr" 23 | "k8s.io/apimachinery/pkg/runtime" 24 | ctrl "sigs.k8s.io/controller-runtime" 25 | "sigs.k8s.io/controller-runtime/pkg/client" 26 | 27 | tailingsidecarv1 "github.com/SumoLogic/tailing-sidecar/operator/api/v1" 28 | ) 29 | 30 | // TailingSidecarConfigReconciler reconciles a TailingSidecarConfig object 31 | type TailingSidecarConfigReconciler struct { 32 | client.Client 33 | Log logr.Logger 34 | Scheme *runtime.Scheme 35 | } 36 | 37 | // +kubebuilder:rbac:groups=tailing-sidecar.sumologic.com,resources=tailingsidecarconfigs,verbs=get;list;watch;create;update;patch;delete 38 | // +kubebuilder:rbac:groups=tailing-sidecar.sumologic.com,resources=tailingsidecarconfigs/status,verbs=get;update;patch 39 | // +kubebuilder:rbac:groups=tailing-sidecar.sumologic.com,resources=tailingsidecars/finalizers,verbs=update 40 | 41 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 42 | // move the current state of the cluster closer to the desired state. 43 | // TODO(user): Modify the Reconcile function to compare the state specified by 44 | // the TailingSidecar object against the actual cluster state, and then 45 | // perform operations to make the cluster state reflect the state specified by 46 | // the user. 47 | // 48 | // For more details, check Reconcile and its Result here: 49 | // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile 50 | func (r *TailingSidecarConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 51 | _ = context.Background() 52 | _ = r.Log.WithValues("tailingsidecarconfigs", req.NamespacedName) 53 | 54 | // your logic here 55 | 56 | return ctrl.Result{}, nil 57 | } 58 | 59 | func (r *TailingSidecarConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { 60 | return ctrl.NewControllerManagedBy(mgr). 61 | For(&tailingsidecarv1.TailingSidecarConfig{}). 62 | Complete(r) 63 | } 64 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NAMESPACE ?= tailing-sidecar-system 2 | RELEASE ?= tailing-sidecar 3 | HELM_CHART ?= helm/tailing-sidecar-operator 4 | KUTTL_CONFIG ?= kuttl-test.yaml 5 | TAILING_SIDECAR ?= fluentbit 6 | 7 | all: markdownlint yamllint 8 | 9 | markdownlint: mdl 10 | 11 | mdl: 12 | mdl --style .markdownlint/style.rb \ 13 | README.md \ 14 | sidecar/fluentbit/README.md \ 15 | operator/README.md \ 16 | docs/*.md 17 | 18 | yamllint: 19 | yamllint -c .yamllint.yaml \ 20 | operator/examples/ 21 | 22 | login-ecr: 23 | aws ecr-public get-login-password --region us-east-1 \ 24 | | docker login --username AWS --password-stdin $(ECR_URL) 25 | 26 | .PHONY: e2e 27 | e2e: IMG="registry.localhost:5000/sumologic/tailing-sidecar-operator:test" 28 | e2e: TAILING_SIDECAR_IMG = "registry.localhost:5000/sumologic/sidecar:test" 29 | e2e: 30 | $(MAKE) -C ./sidecar/$(TAILING_SIDECAR) build-test-image TAG=$(TAILING_SIDECAR_IMG) 31 | $(MAKE) -C ./operator docker-build IMG=$(IMG) TAILING_SIDECAR_IMG=$(TAILING_SIDECAR_IMG) 32 | kubectl-kuttl test --config $(KUTTL_CONFIG) 33 | 34 | .PHONY: e2e-helm 35 | e2e-helm: KUTTL_CONFIG = kuttl-test-helm.yaml 36 | e2e-helm: e2e 37 | 38 | .PHONY: e2e-helm-certmanager 39 | e2e-helm-certmanager: KUTTL_CONFIG = kuttl-test-helm-certmanager.yaml 40 | e2e-helm-certmanager: e2e 41 | 42 | .PHONY: e2e-helm-custom-configuration 43 | e2e-helm-custom-configuration: KUTTL_CONFIG = kuttl-test-helm-$(TAILING_SIDECAR)-custom-configuration.yaml 44 | e2e-helm-custom-configuration: e2e 45 | 46 | # We sleep for 10 seconds here because webhooks can mysteriously be unavailable even though the readiness check passes 47 | .PHONY: e2e-wait-until-operator-ready 48 | e2e-wait-until-operator-ready: 49 | kubectl wait --for=condition=available --timeout 300s deploy --all -n tailing-sidecar-system 50 | kubectl wait --for=condition=ready --timeout 300s pod --all -n tailing-sidecar-system 51 | sleep 10 52 | 53 | build-push-deploy: build-push-sidecar build-push-deploy-operator 54 | 55 | build-push-sidecar: 56 | $(MAKE) -C sidecar all 57 | 58 | build-push-deploy-operator: 59 | $(MAKE) -C operator all 60 | 61 | push-helm-chart: 62 | ./ci/push-helm-chart.sh 63 | 64 | helm-upgrade: 65 | helm upgrade --install $(RELEASE) \ 66 | --namespace $(NAMESPACE) \ 67 | --create-namespace \ 68 | $(HELM_CHART) 69 | 70 | helm-dry-run: 71 | helm install --dry-run $(RELEASE) \ 72 | --namespace $(NAMESPACE) \ 73 | $(HELM_CHART) 74 | 75 | helm-delete: 76 | helm delete $(RELEASE) --namespace $(NAMESPACE) 77 | 78 | deploy-examples: 79 | $(MAKE) -C operator deploy-examples 80 | 81 | check-examples: 82 | $(MAKE) -C operator check-examples 83 | 84 | teardown-examples: 85 | $(MAKE) -C operator teardown-examples 86 | -------------------------------------------------------------------------------- /helm/tailing-sidecar-operator/values.yaml: -------------------------------------------------------------------------------- 1 | fullnameOverride: "" 2 | nameOverride: "" 3 | 4 | operator: 5 | image: 6 | pullPolicy: IfNotPresent 7 | repository: public.ecr.aws/sumologic/tailing-sidecar-operator 8 | # Overrides the image tag whose default is the Helm Chart appVersion. 9 | tag: "" 10 | resources: 11 | limits: 12 | cpu: 100m 13 | memory: 30Mi 14 | requests: 15 | cpu: 100m 16 | memory: 20Mi 17 | 18 | ## Enable leader election mechanism for protecting against split brain if multiple operator pods/replicas are started. 19 | ## See more at https://docs.openshift.com/container-platform/4.10/operators/operator_sdk/osdk-leader-election.html 20 | leaderElection: 21 | enabled: true 22 | leaseDuration: "137s" 23 | renewDeadline: "107s" 24 | retryPeriod: "26s" 25 | 26 | # Number of sidecar operator Pods to run (requires enable leader election if replicaCount > 1) 27 | replicaCount: 1 28 | 29 | livenessProbe: {} 30 | # initialDelaySeconds: 1 31 | # periodSeconds: 20 32 | startupProbe: {} 33 | # periodSeconds: 3 34 | 35 | affinity: {} 36 | 37 | tolerations: [] 38 | 39 | sidecar: 40 | image: 41 | repository: public.ecr.aws/sumologic/tailing-sidecar 42 | # Overrides the image tag whose default is the Helm Chart appVersion. 43 | tag: "" 44 | # Configuration for sidecar compute resource requirements. 45 | # Those are the default resources settings and can be overrides by TailingSidecarConfig 46 | resources: 47 | limits: 48 | cpu: 500m 49 | memory: 500Mi 50 | requests: 51 | cpu: 100m 52 | memory: 200Mi 53 | 54 | # Overrides the sidecar configuration 55 | config: 56 | mountPath: /fluent-bit/etc/ 57 | # map of files which are going to be created in mountPath 58 | # for example to create three empty files: 59 | # 60 | # content: 61 | # fluent-bit.conf: | 62 | # parsers.conf: | 63 | # plugins.conf 64 | content: {} 65 | 66 | kubeRbacProxy: 67 | image: 68 | pullPolicy: IfNotPresent 69 | repository: quay.io/brancz/kube-rbac-proxy 70 | tag: v0.18.0 71 | resources: 72 | limits: 73 | cpu: 500m 74 | memory: 128Mi 75 | requests: 76 | cpu: 5m 77 | memory: 64Mi 78 | 79 | # Configuration for MutatingWebhook which is used by tailing sidecar operator 80 | # for details please see Kubernetes API Reference Docs 81 | # e.g. https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#mutatingwebhookconfiguration-v1-admissionregistration-k8s-io 82 | webhook: 83 | failurePolicy: Ignore 84 | reinvocationPolicy: Never 85 | 86 | objectSelector: {} 87 | # matchLabels: 88 | # tailing-sidecar: "true" 89 | 90 | namespaceSelector: {} 91 | # matchLabels: 92 | # tailing-sidecar: "true" 93 | 94 | certManager: 95 | enabled: false 96 | 97 | scc: 98 | create: true 99 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_with_2_tailing_sidecars_with_configuration.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/spec/containers/1", 5 | "value": { 6 | "env": [ 7 | { 8 | "name": "PATH_TO_TAIL", 9 | "value": "/var/log/example0.log" 10 | }, 11 | { 12 | "name": "TAILING_SIDECAR", 13 | "value": "true" 14 | } 15 | ], 16 | "image": "tailing-sidecar-image:test", 17 | "name": "tailing-sidecar-0", 18 | "resources": {}, 19 | "volumeMounts": [ 20 | { 21 | "mountPath": "/var/log", 22 | "name": "varlog" 23 | }, 24 | { 25 | "mountPath": "/tailing-sidecar/var", 26 | "name": "volume-sidecar-0" 27 | }, 28 | { 29 | "mountPath": "my-custom-path", 30 | "name": "tailing-sidecar-configuration" 31 | } 32 | ] 33 | } 34 | }, 35 | { 36 | "op": "add", 37 | "path": "/spec/containers/2", 38 | "value": { 39 | "env": [ 40 | { 41 | "name": "PATH_TO_TAIL", 42 | "value": "/var/log/example1.log" 43 | }, 44 | { 45 | "name": "TAILING_SIDECAR", 46 | "value": "true" 47 | } 48 | ], 49 | "image": "tailing-sidecar-image:test", 50 | "name": "tailing-sidecar-1", 51 | "resources": {}, 52 | "volumeMounts": [ 53 | { 54 | "mountPath": "/var/log", 55 | "name": "varlog" 56 | }, 57 | { 58 | "mountPath": "/tailing-sidecar/var", 59 | "name": "volume-sidecar-1" 60 | }, 61 | { 62 | "mountPath": "my-custom-path", 63 | "name": "tailing-sidecar-configuration" 64 | } 65 | ] 66 | } 67 | }, 68 | { 69 | "op": "add", 70 | "path": "/spec/volumes/2", 71 | "value": { 72 | "emptyDir": {}, 73 | "name": "volume-sidecar-0" 74 | } 75 | }, 76 | { 77 | "op": "add", 78 | "path": "/spec/volumes/3", 79 | "value": { 80 | "emptyDir": {}, 81 | "name": "volume-sidecar-1" 82 | } 83 | }, 84 | { 85 | "op": "add", 86 | "path": "/spec/volumes/4", 87 | "value": { 88 | "configMap": { 89 | "name": "my-config-map" 90 | }, 91 | "name": "tailing-sidecar-configuration" 92 | } 93 | } 94 | ] 95 | -------------------------------------------------------------------------------- /sidecar/fluentbit/conf/fluent-bit.conf: -------------------------------------------------------------------------------- 1 | [SERVICE] 2 | # Flush 3 | # ===== 4 | # set an interval of seconds before to flush records to a destination 5 | flush 1 6 | 7 | # Daemon 8 | # ====== 9 | # instruct Fluent Bit to run in foreground or background mode. 10 | daemon Off 11 | 12 | # Log_Level 13 | # ========= 14 | # Set the verbosity level of the service, values can be: 15 | # 16 | # - error 17 | # - warning 18 | # - info 19 | # - debug 20 | # - trace 21 | # 22 | # e.g. when 'info' is set, that means it includes 'error' and 'warning'. 23 | log_level ${LOG_LEVEL} 24 | 25 | # Parsers File 26 | # ============ 27 | # specify an optional 'Parsers' configuration file 28 | parsers_file parsers.conf 29 | 30 | # Plugins File 31 | # ============ 32 | # specify an optional 'Plugins' configuration file to load external plugins. 33 | plugins_file plugins.conf 34 | 35 | # HTTP Server 36 | # =========== 37 | # Enable/Disable the built-in HTTP Server for metrics 38 | http_server Off 39 | http_listen 0.0.0.0 40 | http_port 2020 41 | 42 | # Storage 43 | # ======= 44 | # Fluent Bit can use memory and filesystem buffering based mechanisms 45 | # 46 | # - https://docs.fluentbit.io/manual/administration/buffering-and-storage 47 | # 48 | # storage metrics 49 | # --------------- 50 | # publish storage pipeline metrics in '/api/v1/storage'. The metrics are 51 | # exported only if the 'http_server' option is enabled. 52 | # 53 | storage.metrics on 54 | 55 | # storage.path 56 | # ------------ 57 | # absolute file system path to store filesystem data buffers (chunks). 58 | # 59 | # storage.path /tmp/storage 60 | 61 | # storage.sync 62 | # ------------ 63 | # configure the synchronization mode used to store the data into the 64 | # filesystem. It can take the values normal or full. 65 | # 66 | # storage.sync normal 67 | 68 | # storage.checksum 69 | # ---------------- 70 | # enable the data integrity check when writing and reading data from the 71 | # filesystem. The storage layer uses the CRC32 algorithm. 72 | # 73 | # storage.checksum off 74 | 75 | # storage.backlog.mem_limit 76 | # ------------------------- 77 | # if storage.path is set, Fluent Bit will look for data chunks that were 78 | # not delivered and are still in the storage layer, these are called 79 | # backlog data. This option configure a hint of maximum value of memory 80 | # to use when processing these records. 81 | # 82 | # storage.backlog.mem_limit 5M 83 | 84 | [INPUT] 85 | name tail 86 | path ${PATH_TO_TAIL} 87 | Read_from_Head On 88 | Refresh_Interval 1 89 | Rotate_Wait 60 90 | Mem_Buf_Limit 5MB 91 | DB /tailing-sidecar/var/fluent-bit-state.db 92 | DB.Sync Normal 93 | 94 | [OUTPUT] 95 | name gstdout 96 | -------------------------------------------------------------------------------- /operator/config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: tailing-sidecar-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: tailing-sidecar- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 20 | # crd/kustomization.yaml 21 | - ../webhook 22 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 23 | - ../certmanager 24 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 25 | #- ../prometheus 26 | 27 | patchesStrategicMerge: 28 | # Patches for tailing sidecar operator manager 29 | - manager_patch.yaml 30 | # Protect the /metrics endpoint by putting it behind auth. 31 | # If you want your operator to expose the /metrics 32 | # endpoint w/o any authn/z, please comment the following line. 33 | - manager_auth_proxy_patch.yaml 34 | 35 | # Patches for ClusterRoleBindings 36 | - cluster_roles_binding_patches.yaml 37 | 38 | # Patch for RoleBinding 39 | - role_binding_patch.yaml 40 | 41 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 42 | # crd/kustomization.yaml 43 | - manager_webhook_patch.yaml 44 | 45 | # [WEBHOOK] To add reinvocationPolicy, namespaceSelector, objectSelector, adjust it if needed 46 | #- webhook_patch.yaml 47 | 48 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 49 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 50 | # 'CERTMANAGER' needs to be enabled to use ca injection 51 | - webhook_admission_ca_injection_patch.yaml 52 | #- webhook_validating_ca_injection_patch.yaml 53 | # the following config is for teaching kustomize how to do var substitution 54 | vars: 55 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 56 | - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 57 | objref: 58 | kind: Certificate 59 | group: cert-manager.io 60 | version: v1 61 | name: serving-cert # this name should match the one in certificate.yaml 62 | fieldref: 63 | fieldpath: metadata.namespace 64 | - name: CERTIFICATE_NAME 65 | objref: 66 | kind: Certificate 67 | group: cert-manager.io 68 | version: v1 69 | name: serving-cert # this name should match the one in certificate.yaml 70 | - name: SERVICE_NAMESPACE # namespace of the service 71 | objref: 72 | kind: Service 73 | version: v1 74 | name: webhook-service 75 | fieldref: 76 | fieldpath: metadata.namespace 77 | - name: SERVICE_NAME 78 | objref: 79 | kind: Service 80 | version: v1 81 | name: webhook-service 82 | -------------------------------------------------------------------------------- /sidecar/otelcol/Makefile: -------------------------------------------------------------------------------- 1 | BINARY_NAME ?= otelcol-sidecar 2 | OTELCOL_VERSION ?= 0.90.1 3 | BUILDER_REPO ?= github.com/open-telemetry/opentelemetry-collector 4 | GO ?= go 5 | 6 | OS ?= $(shell uname -s | tr A-Z a-z) 7 | ARCH ?= $(shell uname -m | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) 8 | LOCALBIN ?= $(shell pwd)/bin 9 | 10 | GORELEASER ?= $(LOCALBIN)/goreleaser 11 | 12 | BUILDER_BIN_NAME ?= opentelemetry-collector-builder$(BUILDER_BIN_EXT) 13 | BUILDER_BIN_PATH ?= $(LOCALBIN) 14 | BUILDER=$(BUILDER_BIN_PATH)/$(BUILDER_BIN_NAME) 15 | 16 | INSTALLED_VERSION := $(shell $(BUILDER) version 2>&1) 17 | 18 | # go-get-tool will 'go get' any package $2 and install it to $1. 19 | PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) 20 | define go-get-tool 21 | @[ -f $(1) ] || { \ 22 | set -e ;\ 23 | TMP_DIR=$$(mktemp -d) ;\ 24 | cd $$TMP_DIR ;\ 25 | go mod init tmp ;\ 26 | echo "Downloading $(2)" ;\ 27 | go get -d $(2)@$(3) ;\ 28 | GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\ 29 | rm -rf $$TMP_DIR ;\ 30 | } 31 | endef 32 | 33 | .PHONY: install-builder 34 | install-builder: 35 | @mkdir -p "$(BUILDER_BIN_PATH)" 36 | curl -L -o "$(BUILDER_BIN_PATH)/$(BUILDER_BIN_NAME)" https://$(BUILDER_REPO)/releases/download/cmd/builder/v$(OTELCOL_VERSION)/ocb_$(OTELCOL_VERSION)_$(OS)_$(ARCH)$(BUILDER_BIN_EXT) 37 | @chmod +x "$(BUILDER_BIN_PATH)/$(BUILDER_BIN_NAME)" 38 | @$(MAKE) ensure-correct-builder-version 39 | 40 | .PHONY: install-goreleaser 41 | install-goreleaser: 42 | $(call go-get-tool,$(GORELEASER),github.com/goreleaser/goreleaser,latest) 43 | 44 | 45 | .PHONY: ensure-correct-builder-version 46 | ensure-correct-builder-version: 47 | ifneq ($(lastword $(INSTALLED_VERSION)),$(OTELCOL_VERSION)) 48 | @$(error Installed opentelemetry-collector-builder version \ 49 | "$(INSTALLED_VERSION)" \ 50 | does not match the requested "$(OTELCOL_VERSION)" \ 51 | Please check if "$(BUILDER_BIN_PATH)" can be found in your PATH \ 52 | and if not, then install it using 'make install-builder' from otelcolbuilder's directory\ 53 | ) 54 | endif 55 | 56 | .PHONY: build 57 | build: ensure-correct-builder-version install-goreleaser 58 | @$(GORELEASER) release --snapshot --clean 59 | 60 | .PHONY: release-dev 61 | release-dev: TAG = $(shell git describe --tags --always) 62 | release-dev: ensure-correct-builder-version install-goreleaser 63 | git tag "$(TAG)" 64 | GORELEASER_CURRENT_TAG=$(TAG) \ 65 | ECR_IMAGE=public.ecr.aws/sumologic/tailing-sidecar-otel-dev \ 66 | GHCR_IMAGE=ghcr.io/sumologic/tailing-sidecar-otel \ 67 | DOCKERHUB_IMAGE=sumologic/tailing-sidecar-otel-dev \ 68 | make release 69 | git tag -d "$(TAG)" 70 | 71 | .PHONY: release 72 | release: ensure-correct-builder-version install-goreleaser 73 | @$(GORELEASER) release --clean 74 | 75 | .PHONY: build-test-image 76 | build-test-image: GHCR_IMAGE = ghcr.io/sumologic/tailing-sidecar-otel 77 | build-test-image: build 78 | docker tag $(GHCR_IMAGE):main-$(ARCH) $(TAG) 79 | 80 | .PHONY: generate-sources 81 | generate-sources: 82 | $(BUILDER) \ 83 | --go $(GO) \ 84 | --version "$(VERSION)" \ 85 | --config .otelcol-builder.yaml \ 86 | --skip-compilation=true 87 | 88 | -------------------------------------------------------------------------------- /operator/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "os" 7 | "time" 8 | 9 | corev1 "k8s.io/api/core/v1" 10 | "k8s.io/apimachinery/pkg/api/resource" 11 | "sigs.k8s.io/yaml" 12 | ) 13 | 14 | type Config struct { 15 | Sidecar SidecarConfig `yaml:"sidecar,omitempty"` 16 | LeaderElection LeaderElectionConfig `yaml:"leaderElection,omitempty"` 17 | } 18 | 19 | type SidecarConfig struct { 20 | Image string `yaml:"image,omitempty"` 21 | Resources corev1.ResourceRequirements `yaml:"resources,omitempty"` 22 | Config SidecarConfigConfig `yaml:"config,omitempty"` 23 | } 24 | 25 | type LeaderElectionConfig struct { 26 | LeaseDuration Duration `yaml:"leaseDuration,omitempty"` 27 | RenewDeadline Duration `yaml:"renewDeadline,omitempty"` 28 | RetryPeriod Duration `yaml:"retryPeriod,omitempty"` 29 | } 30 | 31 | type SidecarConfigConfig struct { 32 | Name string `yaml:"name,omitempty"` 33 | MountPath string `yaml:"mountPath,omitempty"` 34 | Namespace string `yaml:"namespace,omitempty"` 35 | } 36 | 37 | // Duration sigs.k8s.io/yaml not support time.Duration:https://github.com/kubernetes-sigs/yaml/issues/64 38 | type Duration time.Duration 39 | 40 | func (d Duration) MarshalJSON() ([]byte, error) { 41 | return json.Marshal(time.Duration(d).String()) 42 | } 43 | 44 | func (d *Duration) UnmarshalJSON(b []byte) error { 45 | var v interface{} 46 | if err := json.Unmarshal(b, &v); err != nil { 47 | return err 48 | } 49 | switch value := v.(type) { 50 | case float64: 51 | *d = Duration(time.Duration(value)) 52 | return nil 53 | case string: 54 | tmp, err := time.ParseDuration(value) 55 | if err != nil { 56 | return err 57 | } 58 | *d = Duration(tmp) 59 | return nil 60 | default: 61 | return errors.New("invalid duration") 62 | } 63 | } 64 | 65 | func ReadConfig(configPath string, config *Config) error { 66 | content, err := os.ReadFile(configPath) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | err = yaml.Unmarshal(content, config) 72 | if err != nil { 73 | return err 74 | } 75 | return err 76 | } 77 | 78 | func (c *Config) Validate() error { 79 | return nil 80 | } 81 | 82 | func GetDefaultConfig() Config { 83 | return Config{ 84 | Sidecar: SidecarConfig{ 85 | Image: "sumologic/tailing-sidecar:latest", 86 | Resources: corev1.ResourceRequirements{ 87 | Limits: corev1.ResourceList{ 88 | corev1.ResourceCPU: resource.MustParse("500m"), 89 | corev1.ResourceMemory: resource.MustParse("500Mi"), 90 | }, 91 | Requests: corev1.ResourceList{ 92 | corev1.ResourceCPU: resource.MustParse("100m"), 93 | corev1.ResourceMemory: resource.MustParse("200Mi"), 94 | }, 95 | }, 96 | }, 97 | // reference for values: https://github.com/open-telemetry/opentelemetry-operator/blob/a8653601cd6a6e2b35fd7f3e1a28b4e9608fb794/main.go#L181 98 | LeaderElection: LeaderElectionConfig{ 99 | LeaseDuration: Duration(time.Second * 137), 100 | RenewDeadline: Duration(time.Second * 107), 101 | RetryPeriod: Duration(time.Second * 26), 102 | }, 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /vagrant/provision.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | export DEBIAN_FRONTEND=noninteractive 6 | GO_VERSION="1.21.5" 7 | HELM_VERSION=v3.5.2 8 | KUTTL_VERSION=0.15.0 9 | MICROK8S_VERSION=1.27 10 | 11 | apt-get update 12 | apt-get --yes upgrade 13 | 14 | 15 | apt-get install --yes make gcc 16 | 17 | # Install docker 18 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - 19 | add-apt-repository \ 20 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 21 | $(lsb_release -cs) \ 22 | stable" 23 | apt-get install --yes docker-ce docker-ce-cli containerd.io 24 | usermod -aG docker vagrant 25 | 26 | # Install k8s 27 | snap install microk8s --classic --channel=${MICROK8S_VERSION}/stable 28 | microk8s.status --wait-ready 29 | ufw allow in on cbr0 30 | ufw allow out on cbr0 31 | ufw default allow routed 32 | 33 | microk8s enable registry 34 | microk8s enable storage 35 | microk8s enable dns 36 | 37 | microk8s.kubectl config view --raw > /tailing-sidecar/.kube-config 38 | 39 | snap alias microk8s.kubectl kubectl 40 | 41 | usermod -a -G microk8s vagrant 42 | 43 | echo "export KUBECONFIG=/var/snap/microk8s/current/credentials/kubelet.config" >> /home/vagrant/.bashrc 44 | 45 | # Install go 46 | wget "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" 47 | tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz 48 | rm go${GO_VERSION}.linux-amd64.tar.gz 49 | echo "export PATH=$PATH:/usr/local/go/bin" >> /home/vagrant/.bashrc 50 | 51 | # Install operator SDK 52 | curl -LO "https://github.com/operator-framework/operator-sdk/releases/latest/download/operator-sdk_linux_amd64" 53 | chmod +x operator-sdk_linux_amd64 54 | mv operator-sdk_linux_amd64 /usr/local/bin/operator-sdk 55 | 56 | # Install kustomize 57 | curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash 58 | mv kustomize /usr/local/bin/ 59 | 60 | # Install Helm 61 | mkdir /opt/helm3 62 | curl "https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz" | tar -xz -C /opt/helm3 63 | ln -s /opt/helm3/linux-amd64/helm /usr/bin/helm3 64 | ln -s /usr/bin/helm3 /usr/bin/helm 65 | 66 | # Check if k8s is ready 67 | while true; do 68 | kubectl -n kube-system get services 1>/dev/null 2>&1 && break 69 | echo 'Waiting for k8s server' 70 | sleep 1 71 | done 72 | 73 | # Deploy cert-manager 74 | kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.11.0/cert-manager.yaml 75 | 76 | # Check if cert-manager is ready 77 | # NOTICE: kubectl wait is not used due to unexpected errors 78 | # https://github.com/ubuntu/microk8s/issues/1710 79 | while true; do 80 | if [ $( kubectl get pods -n cert-manager | grep Running | wc -l ) -eq 3 ]; then 81 | echo 'cert-manager is ready' 82 | break 83 | else 84 | echo 'Waiting for cert-manager' 85 | fi 86 | sleep 5 87 | done 88 | 89 | # Install kuttl 90 | curl -L "https://github.com/kudobuilder/kuttl/releases/latest/download/kubectl-kuttl_${KUTTL_VERSION}_linux_x86_64" --output kubectl-kuttl 91 | chmod +x kubectl-kuttl 92 | mv kubectl-kuttl /usr/local/bin/kubectl-kuttl 93 | 94 | # For AMD64 / x86_64 95 | curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 96 | chmod +x kind 97 | mv kind /usr/local/bin/kind 98 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_with_2_tailing_sidecars_different_namespace.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/spec/volumes/2", 5 | "value": { 6 | "emptyDir": {}, 7 | "name": "volume-sidecar-0" 8 | } 9 | }, 10 | { 11 | "op": "add", 12 | "path": "/spec/volumes/3", 13 | "value": { 14 | "emptyDir": {}, 15 | "name": "volume-sidecar-1" 16 | } 17 | }, 18 | { 19 | "op": "add", 20 | "path": "/spec/containers/1", 21 | "value": { 22 | "env": [ 23 | { 24 | "name": "PATH_TO_TAIL", 25 | "value": "/varconfig/log/example2.log" 26 | }, 27 | { 28 | "name": "TAILING_SIDECAR", 29 | "value": "true" 30 | } 31 | ], 32 | "image": "tailing-sidecar-image:test", 33 | "name": "sidecar-1", 34 | "resources": {}, 35 | "volumeMounts": [ 36 | { 37 | "mountPath": "/varconfig/log", 38 | "name": "varlogconfig", 39 | "readOnly": true 40 | }, 41 | { 42 | "mountPath": "/tailing-sidecar/var", 43 | "name": "volume-sidecar-0" 44 | } 45 | ] 46 | } 47 | }, 48 | { 49 | "op": "add", 50 | "path": "/spec/containers/2", 51 | "value": { 52 | "env": [ 53 | { 54 | "name": "PATH_TO_TAIL", 55 | "value": "/var/log/example1.log" 56 | }, 57 | { 58 | "name": "TAILING_SIDECAR", 59 | "value": "true" 60 | } 61 | ], 62 | "image": "tailing-sidecar-image:test", 63 | "name": "sidecar-2", 64 | "resources": {}, 65 | "volumeMounts": [ 66 | { 67 | "mountPath": "/var/log", 68 | "name": "varlog" 69 | }, 70 | { 71 | "mountPath": "/tailing-sidecar/var", 72 | "name": "volume-sidecar-1" 73 | } 74 | ] 75 | } 76 | } 77 | ] 78 | -------------------------------------------------------------------------------- /operator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/SumoLogic/tailing-sidecar/operator 2 | 3 | go 1.24.0 4 | 5 | toolchain go1.24.3 6 | 7 | require ( 8 | github.com/go-logr/logr v1.4.2 9 | github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce 10 | github.com/onsi/ginkgo v1.16.5 11 | github.com/onsi/gomega v1.36.1 12 | github.com/stretchr/testify v1.10.0 13 | gomodules.xyz/jsonpatch/v2 v2.4.0 14 | k8s.io/api v0.33.3 15 | k8s.io/apimachinery v0.33.3 16 | k8s.io/client-go v0.33.3 17 | sigs.k8s.io/controller-runtime v0.21.0 18 | sigs.k8s.io/yaml v1.4.0 19 | ) 20 | 21 | require github.com/pmezard/go-difflib v1.0.0 // indirect 22 | 23 | require ( 24 | github.com/beorn7/perks v1.0.1 // indirect 25 | github.com/blang/semver/v4 v4.0.0 // indirect 26 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 27 | github.com/davecgh/go-spew v1.1.1 // indirect 28 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 29 | github.com/evanphx/json-patch/v5 v5.9.11 // indirect 30 | github.com/fsnotify/fsnotify v1.7.0 // indirect 31 | github.com/fxamacker/cbor/v2 v2.7.0 // indirect 32 | github.com/go-logr/zapr v1.3.0 // indirect 33 | github.com/go-openapi/jsonpointer v0.21.0 // indirect 34 | github.com/go-openapi/jsonreference v0.20.2 // indirect 35 | github.com/go-openapi/swag v0.23.0 // indirect 36 | github.com/gogo/protobuf v1.3.2 // indirect 37 | github.com/google/btree v1.1.3 // indirect 38 | github.com/google/gnostic-models v0.6.9 // indirect 39 | github.com/google/go-cmp v0.7.0 // indirect 40 | github.com/google/uuid v1.6.0 // indirect 41 | github.com/josharian/intern v1.0.0 // indirect 42 | github.com/json-iterator/go v1.1.12 // indirect 43 | github.com/mailru/easyjson v0.7.7 // indirect 44 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 45 | github.com/modern-go/reflect2 v1.0.2 // indirect 46 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 47 | github.com/nxadm/tail v1.4.8 // indirect 48 | github.com/pkg/errors v0.9.1 // indirect 49 | github.com/prometheus/client_golang v1.22.0 // indirect 50 | github.com/prometheus/client_model v0.6.1 // indirect 51 | github.com/prometheus/common v0.62.0 // indirect 52 | github.com/prometheus/procfs v0.15.1 // indirect 53 | github.com/spf13/pflag v1.0.5 // indirect 54 | github.com/x448/float16 v0.8.4 // indirect 55 | go.uber.org/multierr v1.11.0 // indirect 56 | go.uber.org/zap v1.27.0 // indirect 57 | golang.org/x/net v0.38.0 // indirect 58 | golang.org/x/oauth2 v0.27.0 // indirect 59 | golang.org/x/sync v0.12.0 // indirect 60 | golang.org/x/sys v0.31.0 // indirect 61 | golang.org/x/term v0.30.0 // indirect 62 | golang.org/x/text v0.23.0 // indirect 63 | golang.org/x/time v0.9.0 // indirect 64 | google.golang.org/protobuf v1.36.5 // indirect 65 | gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect 66 | gopkg.in/inf.v0 v0.9.1 // indirect 67 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 68 | gopkg.in/yaml.v3 v3.0.1 // indirect 69 | k8s.io/apiextensions-apiserver v0.33.0 // indirect 70 | k8s.io/klog/v2 v2.130.1 // indirect 71 | k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect 72 | k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect 73 | sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect 74 | sigs.k8s.io/randfill v1.0.0 // indirect 75 | sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect 76 | ) 77 | -------------------------------------------------------------------------------- /operator/README.md: -------------------------------------------------------------------------------- 1 | # Tailing sidecar operator 2 | 3 | *Tailing sidecar operator* automatically adds 4 | [streaming sidecar containers](https://kubernetes.io/docs/concepts/cluster-administration/logging/#streaming-sidecar-container) 5 | which use [tailing sidecar image](../sidecar/) to Pods based on configuration provided in annotation. 6 | 7 | Configuration for tailing sidecar operator is described [here](docs/configuration.md). 8 | 9 | To quickly see benefits of using tailing sidecar operator try it in prepared [Vagrant environment](#testing-in-Vagrant-environment). 10 | 11 | ## Deploy tailing sidecar operator 12 | 13 | ### Prerequisities 14 | 15 | - [cert-manager](https://cert-manager.io/docs/installation/) 16 | - [admission webhooks](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites) 17 | enabled 18 | - [kustomize](https://kustomize.io/) 19 | 20 | ### Set images (optional) 21 | 22 | Set tailing sidecar image: 23 | 24 | ```bash 25 | export TAILING_SIDECAR_IMG="/:tag" 26 | sed -i.backup "s#sumologic/tailing-sidecar:latest#${TAILING_SIDECAR_IMG}#g" config/default/manager_patch.yaml 27 | ``` 28 | 29 | Set tailing-sidecar operator image: 30 | 31 | ```bash 32 | export TAILING_SIDECAR_OPERATOR_IMG="/:tag" 33 | (cd config/manager && kustomize edit set image controller="${TAILING_SIDECAR_OPERATOR_IMG}") 34 | ``` 35 | 36 | ### Deploy operator 37 | 38 | ```bash 39 | kustomize build config/default | kubectl apply -f - 40 | ``` 41 | 42 | ### Test operator 43 | 44 | Add annotation to Pod in following form: 45 | 46 | ```yaml 47 | metadata: 48 | annotations: 49 | tailing-sidecar: ::;:: 50 | ``` 51 | 52 | to learn more about configuration see [this](docs/configuration.md). 53 | 54 | Deploy Pod with `tailing-sidecar` annotation e.g. 55 | 56 | ```bash 57 | kubectl apply -f examples/pod_with_annotations.yaml 58 | ``` 59 | 60 | Check logs from tailing sidecar e.g. 61 | 62 | ```bash 63 | kubectl logs pod-with-annotations tailing-sidecar-0 --tail 5 -n tailing-sidecar-system 64 | ``` 65 | 66 | ## Build and push tailing sidecar operator image to container registry 67 | 68 | To build tailing sidecar operator image: 69 | 70 | ```bash 71 | make docker-build IMG="/:tag" 72 | ``` 73 | 74 | To push tailing sidecar operator image to container registry: 75 | 76 | ```bash 77 | make docker-push IMG="/:tag" 78 | ``` 79 | 80 | ## Testing in Vagrant environment 81 | 82 | Start and provision the Vagrant environment: 83 | 84 | ```bash 85 | vagrant up 86 | ``` 87 | 88 | Connect to virtual machine: 89 | 90 | ```bash 91 | vagrant ssh 92 | ``` 93 | 94 | Build and push tailing sidecar image to local container registry: 95 | 96 | ```bash 97 | /tailing-sidecasidecar/fluentbit/akefile 98 | ``` 99 | 100 | Go to operator directory: 101 | 102 | ```bash 103 | cd /tailing-sidecar/operator 104 | ``` 105 | 106 | Deploy operator: 107 | 108 | ```bash 109 | make 110 | ``` 111 | 112 | Deploy examples: 113 | 114 | ```bash 115 | make deploy-examples 116 | ``` 117 | 118 | Check that operator added tailing sidecars to example resources: 119 | 120 | ```bash 121 | make check-examples 122 | ``` 123 | -------------------------------------------------------------------------------- /operator/api/v1/tailingsidecar_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | ) 23 | 24 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 25 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 26 | 27 | type SidecarSpec struct { 28 | // Annotations defines tailing sidecar container annotations. 29 | Annotations map[string]string `json:"annotations,omitempty"` 30 | 31 | // Path defines path to a file containing logs to tail within a tailing sidecar container. 32 | Path string `json:"path,omitempty"` 33 | 34 | // VolumeMount describes a mounting of a volume within a tailing sidecar container. 35 | VolumeMount corev1.VolumeMount `json:"volumeMount,omitempty"` 36 | 37 | // Resources describes the compute resource requirements. 38 | Resources corev1.ResourceRequirements `json:"resources,omitempty"` 39 | } 40 | 41 | // TailingSidecarConfigSpec defines the desired state of TailingSidecarConfig 42 | type TailingSidecarConfigSpec struct { 43 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 44 | // Important: Run "make" to regenerate code after modifying this file 45 | 46 | // AnnotationsPrefix defines prefix for per container annotations. 47 | AnnotationsPrefix string `json:"annotationsPrefix,omitempty"` 48 | 49 | // SidecarSpecs defines specifications for tailing sidecar containers, 50 | // map key indicates name of tailing sidecar container 51 | SidecarSpecs map[string]SidecarSpec `json:"configs,omitempty"` 52 | 53 | // PodSelector selects Pods to which this tailing sidecar configuration applies. 54 | PodSelector *metav1.LabelSelector `json:"podSelector,omitempty"` 55 | } 56 | 57 | // TailingSidecarConfigStatus defines the observed state of TailingSidecarConfig 58 | type TailingSidecarConfigStatus struct { 59 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 60 | // Important: Run "make" to regenerate code after modifying this file 61 | } 62 | 63 | // +kubebuilder:object:root=true 64 | // +kubebuilder:subresource:status 65 | 66 | // TailingSidecarConfig is the Schema for the tailingsidecars API 67 | type TailingSidecarConfig struct { 68 | metav1.TypeMeta `json:",inline"` 69 | metav1.ObjectMeta `json:"metadata,omitempty"` 70 | 71 | Spec TailingSidecarConfigSpec `json:"spec,omitempty"` 72 | Status TailingSidecarConfigStatus `json:"status,omitempty"` 73 | } 74 | 75 | // +kubebuilder:object:root=true 76 | 77 | // TailingSidecarConfigList contains a list of TailingSidecarConfig 78 | type TailingSidecarConfigList struct { 79 | metav1.TypeMeta `json:",inline"` 80 | metav1.ListMeta `json:"metadata,omitempty"` 81 | Items []TailingSidecarConfig `json:"items"` 82 | } 83 | 84 | func init() { 85 | SchemeBuilder.Register(&TailingSidecarConfig{}, &TailingSidecarConfigList{}) 86 | } 87 | -------------------------------------------------------------------------------- /sidecar/otelcol/.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | # This is an example .goreleaser.yml file with some sensible defaults. 2 | # Make sure to check the documentation at https://goreleaser.com 3 | 4 | # The lines below are called `modelines`. See `:help modeline` 5 | # Feel free to remove those if you don't want/need to use them. 6 | # yaml-language-server: $schema=https://goreleaser.com/static/schema.json 7 | # vim: set ts=2 sw=2 tw=0 fo=cnqoj 8 | 9 | version: 1 10 | 11 | project_name: otelcol-sidecar 12 | 13 | env: 14 | - GHCR_IMAGE={{ if index .Env "GHCR_IMAGE" }}{{ .Env.GHCR_IMAGE }}{{ else }}ghcr.io/sumologic/tailing-sidecar-otel{{ end }} 15 | - ECR_IMAGE={{ if index .Env "ECR_IMAGE" }}{{ .Env.ECR_IMAGE }}{{ else }}public.ecr.aws/sumologic/tailing-sidecar-otel{{ end }} 16 | - DOCKERHUB_IMAGE={{ if index .Env "DOCKERHUB_IMAGE" }}{{ .Env.DOCKERHUB_IMAGE }}{{ else }}sumologic/tailing-sidecar-otel{{ end }} 17 | 18 | before: 19 | hooks: 20 | - make generate-sources VERSION={{ .Version }} 21 | 22 | builds: 23 | - dir: ./cmd 24 | env: 25 | - CGO_ENABLED=0 26 | goos: 27 | - linux 28 | goarch: 29 | - amd64 30 | - arm64 31 | 32 | # disable archiving 33 | archives: 34 | - format: binary 35 | 36 | dockers: 37 | - image_templates: 38 | - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-amd64" 39 | - "{{ .Env.ECR_IMAGE }}:main-amd64" 40 | - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-amd64" 41 | - "{{ .Env.GHCR_IMAGE }}:main-amd64" 42 | - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-amd64" 43 | - "{{ .Env.DOCKERHUB_IMAGE }}:main-amd64" 44 | use: buildx 45 | goarch: amd64 46 | build_flag_templates: 47 | - "--platform=linux/amd64" 48 | extra_files: 49 | - "config.yaml" 50 | - image_templates: 51 | - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-arm64" 52 | - "{{ .Env.ECR_IMAGE }}:main-arm64" 53 | - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-arm64" 54 | - "{{ .Env.GHCR_IMAGE }}:main-arm64" 55 | - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-arm64" 56 | - "{{ .Env.DOCKERHUB_IMAGE }}:main-arm64" 57 | use: buildx 58 | goarch: arm64 59 | build_flag_templates: 60 | - "--platform=linux/arm64" 61 | extra_files: 62 | - "config.yaml" 63 | 64 | docker_manifests: 65 | - name_template: "{{ .Env.GHCR_IMAGE }}:{{ .Version }}" 66 | image_templates: 67 | - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-amd64" 68 | - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-arm64" 69 | - name_template: "{{ .Env.GHCR_IMAGE }}:main" 70 | image_templates: 71 | - "{{ .Env.GHCR_IMAGE }}:main-amd64" 72 | - "{{ .Env.GHCR_IMAGE }}:main-arm64" 73 | - name_template: "{{ .Env.ECR_IMAGE }}:{{ .Version }}" 74 | image_templates: 75 | - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-amd64" 76 | - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-arm64" 77 | - name_template: "{{ .Env.ECR_IMAGE }}:main" 78 | image_templates: 79 | - "{{ .Env.ECR_IMAGE }}:main-amd64" 80 | - "{{ .Env.ECR_IMAGE }}:main-arm64" 81 | - name_template: "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}" 82 | image_templates: 83 | - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-amd64" 84 | - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-arm64" 85 | - name_template: "{{ .Env.DOCKERHUB_IMAGE }}:main" 86 | image_templates: 87 | - "{{ .Env.DOCKERHUB_IMAGE }}:main-amd64" 88 | - "{{ .Env.DOCKERHUB_IMAGE }}:main-arm64" 89 | 90 | # we only want to build and publish docker images 91 | release: 92 | disable: true 93 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_with_3_named_not_named_tailing_sidecars.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/spec/volumes/2", 5 | "value": { 6 | "emptyDir": {}, 7 | "name": "volume-sidecar-0" 8 | } 9 | }, 10 | { 11 | "op": "add", 12 | "path": "/spec/volumes/3", 13 | "value": { 14 | "emptyDir": {}, 15 | "name": "volume-sidecar-1" 16 | } 17 | }, 18 | { 19 | "op": "add", 20 | "path": "/spec/volumes/4", 21 | "value": { 22 | "emptyDir": {}, 23 | "name": "volume-sidecar-2" 24 | } 25 | }, 26 | { 27 | "op": "add", 28 | "path": "/spec/containers/1", 29 | "value": { 30 | "env": [ 31 | { 32 | "name": "PATH_TO_TAIL", 33 | "value": "/var/log/example0.log" 34 | }, 35 | { 36 | "name": "TAILING_SIDECAR", 37 | "value": "true" 38 | } 39 | ], 40 | "image": "tailing-sidecar-image:test", 41 | "name": "test-container-0", 42 | "resources": {}, 43 | "volumeMounts": [ 44 | { 45 | "mountPath": "/var/log", 46 | "name": "varlog" 47 | }, 48 | { 49 | "mountPath": "/tailing-sidecar/var", 50 | "name": "volume-sidecar-0" 51 | } 52 | ] 53 | } 54 | }, 55 | { 56 | "op": "add", 57 | "path": "/spec/containers/2", 58 | "value": { 59 | "env": [ 60 | { 61 | "name": "PATH_TO_TAIL", 62 | "value": "/var/log/example1.log" 63 | }, 64 | { 65 | "name": "TAILING_SIDECAR", 66 | "value": "true" 67 | } 68 | ], 69 | "image": "tailing-sidecar-image:test", 70 | "name": "tailing-sidecar-1", 71 | "resources": {}, 72 | "volumeMounts": [ 73 | { 74 | "mountPath": "/var/log", 75 | "name": "varlog" 76 | }, 77 | { 78 | "mountPath": "/tailing-sidecar/var", 79 | "name": "volume-sidecar-1" 80 | } 81 | ] 82 | } 83 | }, 84 | { 85 | "op": "add", 86 | "path": "/spec/containers/3", 87 | "value": { 88 | "env": [ 89 | { 90 | "name": "PATH_TO_TAIL", 91 | "value": "/varconfig/log/example2.log" 92 | }, 93 | { 94 | "name": "TAILING_SIDECAR", 95 | "value": "true" 96 | } 97 | ], 98 | "image": "tailing-sidecar-image:test", 99 | "name": "test-container-2", 100 | "resources": {}, 101 | "volumeMounts": [ 102 | { 103 | "mountPath": "/varconfig/log", 104 | "name": "varlogconfig" 105 | }, 106 | { 107 | "mountPath": "/tailing-sidecar/var", 108 | "name": "volume-sidecar-2" 109 | } 110 | ] 111 | } 112 | } 113 | ] 114 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_with_3_named_tailing_sidecars.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/metadata/annotations/tailing-sidecar.sumologic.com~1test-container-2.annotation-1", 5 | "value": "annotation-1" 6 | }, 7 | { 8 | "op": "add", 9 | "path": "/metadata/annotations/tailing-sidecar.sumologic.com~1test-container-2.sourceCategory", 10 | "value": "sourceCategory-1" 11 | }, 12 | { 13 | "op": "add", 14 | "path": "/spec/containers/1", 15 | "value": { 16 | "env": [ 17 | { 18 | "name": "PATH_TO_TAIL", 19 | "value": "/var/log/example0.log" 20 | }, 21 | { 22 | "name": "TAILING_SIDECAR", 23 | "value": "true" 24 | } 25 | ], 26 | "image": "tailing-sidecar-image:test", 27 | "name": "test-container-3", 28 | "resources": {}, 29 | "volumeMounts": [ 30 | { 31 | "mountPath": "/var/log", 32 | "name": "varlog" 33 | }, 34 | { 35 | "mountPath": "/tailing-sidecar/var", 36 | "name": "volume-sidecar-0" 37 | } 38 | ] 39 | } 40 | }, 41 | { 42 | "op": "add", 43 | "path": "/spec/containers/2", 44 | "value": { 45 | "env": [ 46 | { 47 | "name": "PATH_TO_TAIL", 48 | "value": "/var/log/example1.log" 49 | }, 50 | { 51 | "name": "TAILING_SIDECAR", 52 | "value": "true" 53 | } 54 | ], 55 | "image": "tailing-sidecar-image:test", 56 | "name": "test-container-1", 57 | "resources": {}, 58 | "volumeMounts": [ 59 | { 60 | "mountPath": "/var/log", 61 | "name": "varlog" 62 | }, 63 | { 64 | "mountPath": "/tailing-sidecar/var", 65 | "name": "volume-sidecar-1" 66 | } 67 | ] 68 | } 69 | }, 70 | { 71 | "op": "add", 72 | "path": "/spec/containers/3", 73 | "value": { 74 | "env": [ 75 | { 76 | "name": "PATH_TO_TAIL", 77 | "value": "/varconfig/log/example2.log" 78 | }, 79 | { 80 | "name": "TAILING_SIDECAR", 81 | "value": "true" 82 | } 83 | ], 84 | "image": "tailing-sidecar-image:test", 85 | "name": "test-container-2", 86 | "resources": {}, 87 | "volumeMounts": [ 88 | { 89 | "mountPath": "/varconfig/log", 90 | "name": "varlogconfig" 91 | }, 92 | { 93 | "mountPath": "/tailing-sidecar/var", 94 | "name": "volume-sidecar-2" 95 | } 96 | ] 97 | } 98 | }, 99 | { 100 | "op": "add", 101 | "path": "/spec/volumes/2", 102 | "value": { 103 | "emptyDir": {}, 104 | "name": "volume-sidecar-0" 105 | } 106 | }, 107 | { 108 | "op": "add", 109 | "path": "/spec/volumes/3", 110 | "value": { 111 | "emptyDir": {}, 112 | "name": "volume-sidecar-1" 113 | } 114 | }, 115 | { 116 | "op": "add", 117 | "path": "/spec/volumes/4", 118 | "value": { 119 | "emptyDir": {}, 120 | "name": "volume-sidecar-2" 121 | } 122 | } 123 | ] 124 | -------------------------------------------------------------------------------- /operator/config_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/require" 10 | corev1 "k8s.io/api/core/v1" 11 | "k8s.io/apimachinery/pkg/api/resource" 12 | ) 13 | 14 | func TestReadConfig(t *testing.T) { 15 | testCases := []struct { 16 | name string 17 | content string 18 | expected Config 19 | expectedError error 20 | }{ 21 | { 22 | name: "empty file", 23 | content: ``, 24 | expected: Config{ 25 | Sidecar: SidecarConfig{ 26 | Image: "sumologic/tailing-sidecar:latest", 27 | Resources: corev1.ResourceRequirements{ 28 | Limits: corev1.ResourceList{ 29 | corev1.ResourceCPU: resource.MustParse("500m"), 30 | corev1.ResourceMemory: resource.MustParse("500Mi"), 31 | }, 32 | Requests: corev1.ResourceList{ 33 | corev1.ResourceCPU: resource.MustParse("100m"), 34 | corev1.ResourceMemory: resource.MustParse("200Mi"), 35 | }, 36 | }, 37 | }, 38 | LeaderElection: LeaderElectionConfig{ 39 | LeaseDuration: Duration(time.Second * 137), 40 | RenewDeadline: Duration(time.Second * 107), 41 | RetryPeriod: Duration(time.Second * 26), 42 | }, 43 | }, 44 | expectedError: nil, 45 | }, 46 | { 47 | name: "defaults", 48 | content: ` 49 | sidecar: 50 | commands: 51 | - test 52 | - command`, 53 | expected: Config{ 54 | Sidecar: SidecarConfig{ 55 | Image: "sumologic/tailing-sidecar:latest", 56 | Resources: corev1.ResourceRequirements{ 57 | Limits: corev1.ResourceList{ 58 | corev1.ResourceCPU: resource.MustParse("500m"), 59 | corev1.ResourceMemory: resource.MustParse("500Mi"), 60 | }, 61 | Requests: corev1.ResourceList{ 62 | corev1.ResourceCPU: resource.MustParse("100m"), 63 | corev1.ResourceMemory: resource.MustParse("200Mi"), 64 | }, 65 | }, 66 | }, 67 | LeaderElection: LeaderElectionConfig{ 68 | LeaseDuration: Duration(time.Second * 137), 69 | RenewDeadline: Duration(time.Second * 107), 70 | RetryPeriod: Duration(time.Second * 26), 71 | }, 72 | }, 73 | expectedError: nil, 74 | }, 75 | { 76 | name: "overwrite defaults", 77 | content: ` 78 | sidecar: 79 | image: my-new-image 80 | resources: 81 | limits: 82 | cpu: 400m 83 | memory: 400Mi 84 | requests: 85 | cpu: 20m 86 | memory: 20Mi 87 | leaderElection: 88 | leaseDuration: 10s 89 | renewDeadline: 10s 90 | retryPeriod: 10s`, 91 | expected: Config{ 92 | Sidecar: SidecarConfig{ 93 | Image: "my-new-image", 94 | Resources: corev1.ResourceRequirements{ 95 | Limits: corev1.ResourceList{ 96 | corev1.ResourceCPU: resource.MustParse("400m"), 97 | corev1.ResourceMemory: resource.MustParse("400Mi"), 98 | }, 99 | Requests: corev1.ResourceList{ 100 | corev1.ResourceCPU: resource.MustParse("20m"), 101 | corev1.ResourceMemory: resource.MustParse("20Mi"), 102 | }, 103 | }, 104 | }, 105 | LeaderElection: LeaderElectionConfig{ 106 | LeaseDuration: Duration(time.Second * 10), 107 | RenewDeadline: Duration(time.Second * 10), 108 | RetryPeriod: Duration(time.Second * 10), 109 | }, 110 | }, 111 | expectedError: nil, 112 | }, 113 | } 114 | 115 | for _, tt := range testCases { 116 | t.Run(tt.name, func(t *testing.T) { 117 | file, err := ioutil.TempFile(".", "prefix") 118 | require.NoError(t, err) 119 | defer os.Remove(file.Name()) 120 | 121 | _, err = file.WriteString(tt.content) 122 | require.NoError(t, err) 123 | config := GetDefaultConfig() 124 | err = ReadConfig(file.Name(), &config) 125 | require.NoError(t, err) 126 | 127 | if tt.expectedError != nil { 128 | require.Error(t, tt.expectedError, err) 129 | return 130 | } 131 | 132 | require.NoError(t, err) 133 | require.Equal(t, tt.expected, config) 134 | }) 135 | } 136 | } 137 | 138 | func TestReadConfigInvalidFile(t *testing.T) { 139 | config := GetDefaultConfig() 140 | err := ReadConfig("non-existing-file", &config) 141 | require.Error(t, err) 142 | require.EqualError(t, err, "open non-existing-file: no such file or directory") 143 | } 144 | -------------------------------------------------------------------------------- /helm/tests/values.withFluentBitCustomConfiguration.yaml: -------------------------------------------------------------------------------- 1 | operator: 2 | image: 3 | repository: registry.localhost:5000/sumologic/tailing-sidecar-operator 4 | tag: test 5 | 6 | sidecar: 7 | image: 8 | repository: registry.localhost:5000/sumologic/sidecar 9 | tag: test 10 | 11 | resources: 12 | limits: 13 | cpu: "0" 14 | memory: "0" 15 | requests: 16 | cpu: "0" 17 | memory: "0" 18 | 19 | config: 20 | content: 21 | fluent-bit.conf: | 22 | [SERVICE] 23 | # Flush 24 | # ===== 25 | # set an interval of seconds before to flush records to a destination 26 | flush 1 27 | 28 | # Daemon 29 | # ====== 30 | # instruct Fluent Bit to run in foreground or background mode. 31 | daemon Off 32 | 33 | # Log_Level 34 | # ========= 35 | # Set the verbosity level of the service, values can be: 36 | # 37 | # - error 38 | # - warning 39 | # - info 40 | # - debug 41 | # - trace 42 | # 43 | # e.g. when 'info' is set, that means it includes 'error' and 'warning'. 44 | log_level ${LOG_LEVEL} 45 | 46 | # Parsers File 47 | # ============ 48 | # specify an optional 'Parsers' configuration file 49 | parsers_file parsers.conf 50 | 51 | # Plugins File 52 | # ============ 53 | # specify an optional 'Plugins' configuration file to load external plugins. 54 | plugins_file plugins.conf 55 | 56 | # HTTP Server 57 | # =========== 58 | # Enable/Disable the built-in HTTP Server for metrics 59 | http_server Off 60 | http_listen 0.0.0.0 61 | http_port 2020 62 | 63 | # Storage 64 | # ======= 65 | # Fluent Bit can use memory and filesystem buffering based mechanisms 66 | # 67 | # - https://docs.fluentbit.io/manual/administration/buffering-and-storage 68 | # 69 | # storage metrics 70 | # --------------- 71 | # publish storage pipeline metrics in '/api/v1/storage'. The metrics are 72 | # exported only if the 'http_server' option is enabled. 73 | # 74 | storage.metrics on 75 | 76 | # storage.path 77 | # ------------ 78 | # absolute file system path to store filesystem data buffers (chunks). 79 | # 80 | # storage.path /tmp/storage 81 | 82 | # storage.sync 83 | # ------------ 84 | # configure the synchronization mode used to store the data into the 85 | # filesystem. It can take the values normal or full. 86 | # 87 | # storage.sync normal 88 | 89 | # storage.checksum 90 | # ---------------- 91 | # enable the data integrity check when writing and reading data from the 92 | # filesystem. The storage layer uses the CRC32 algorithm. 93 | # 94 | # storage.checksum off 95 | 96 | # storage.backlog.mem_limit 97 | # ------------------------- 98 | # if storage.path is set, Fluent Bit will look for data chunks that were 99 | # not delivered and are still in the storage layer, these are called 100 | # backlog data. This option configure a hint of maximum value of memory 101 | # to use when processing these records. 102 | # 103 | # storage.backlog.mem_limit 5M 104 | 105 | [INPUT] 106 | name tail 107 | path ${PATH_TO_TAIL} 108 | Read_from_Head On 109 | Refresh_Interval 1 110 | Rotate_Wait 60 111 | Mem_Buf_Limit 5MB 112 | DB /tailing-sidecar/var/fluent-bit-state.db 113 | DB.Sync Normal 114 | 115 | [FILTER] 116 | Name modify 117 | Match * 118 | Set log modified 119 | 120 | [OUTPUT] 121 | name gstdout 122 | 123 | plugins.conf: | 124 | [PLUGINS] 125 | Path /tailing-sidecar/lib/out_gstdout.so 126 | 127 | parsers.conf: | 128 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_with_3_tailing_sidecars.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/spec/volumes/2", 5 | "value": { 6 | "emptyDir": {}, 7 | "name": "volume-sidecar-0" 8 | } 9 | }, 10 | { 11 | "op": "add", 12 | "path": "/spec/volumes/3", 13 | "value": { 14 | "emptyDir": {}, 15 | "name": "volume-sidecar-1" 16 | } 17 | }, 18 | { 19 | "op": "add", 20 | "path": "/spec/volumes/4", 21 | "value": { 22 | "emptyDir": {}, 23 | "name": "volume-sidecar-2" 24 | } 25 | }, 26 | { 27 | "op": "add", 28 | "path": "/spec/containers/1", 29 | "value": { 30 | "env": [ 31 | { 32 | "name": "PATH_TO_TAIL", 33 | "value": "/varconfig/log/example2.log" 34 | }, 35 | { 36 | "name": "TAILING_SIDECAR", 37 | "value": "true" 38 | } 39 | ], 40 | "image": "tailing-sidecar-image:test", 41 | "name": "tailing-sidecar-0", 42 | "resources": {}, 43 | "volumeMounts": [ 44 | { 45 | "mountPath": "/varconfig/log", 46 | "name": "varlogconfig", 47 | "readOnly": true 48 | }, 49 | { 50 | "mountPath": "/tailing-sidecar/var", 51 | "name": "volume-sidecar-0" 52 | } 53 | ] 54 | } 55 | }, 56 | { 57 | "op": "add", 58 | "path": "/spec/containers/2", 59 | "value": { 60 | "env": [ 61 | { 62 | "name": "PATH_TO_TAIL", 63 | "value": "/var/log/example0.log" 64 | }, 65 | { 66 | "name": "TAILING_SIDECAR", 67 | "value": "true" 68 | } 69 | ], 70 | "image": "tailing-sidecar-image:test", 71 | "name": "tailing-sidecar-1", 72 | "resources": {}, 73 | "volumeMounts": [ 74 | { 75 | "mountPath": "/var/log", 76 | "name": "varlog" 77 | }, 78 | { 79 | "mountPath": "/tailing-sidecar/var", 80 | "name": "volume-sidecar-1" 81 | } 82 | ] 83 | } 84 | }, 85 | { 86 | "op": "add", 87 | "path": "/spec/containers/3", 88 | "value": { 89 | "env": [ 90 | { 91 | "name": "PATH_TO_TAIL", 92 | "value": "/var/log/example1.log" 93 | }, 94 | { 95 | "name": "TAILING_SIDECAR", 96 | "value": "true" 97 | } 98 | ], 99 | "image": "tailing-sidecar-image:test", 100 | "name": "tailing-sidecar-2", 101 | "resources": {}, 102 | "volumeMounts": [ 103 | { 104 | "mountPath": "/var/log", 105 | "name": "varlog" 106 | }, 107 | { 108 | "mountPath": "/tailing-sidecar/var", 109 | "name": "volume-sidecar-2" 110 | } 111 | ] 112 | } 113 | } 114 | ] 115 | -------------------------------------------------------------------------------- /operator/handler/testdata/patch_with_3_tailing_sidecars_raw_and_predefined.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "add", 4 | "path": "/spec/volumes/2", 5 | "value": { 6 | "emptyDir": {}, 7 | "name": "volume-sidecar-0" 8 | } 9 | }, 10 | { 11 | "op": "add", 12 | "path": "/spec/volumes/3", 13 | "value": { 14 | "emptyDir": {}, 15 | "name": "volume-sidecar-1" 16 | } 17 | }, 18 | { 19 | "op": "add", 20 | "path": "/spec/volumes/4", 21 | "value": { 22 | "emptyDir": {}, 23 | "name": "volume-sidecar-2" 24 | } 25 | }, 26 | { 27 | "op": "add", 28 | "path": "/spec/containers/1", 29 | "value": { 30 | "env": [ 31 | { 32 | "name": "PATH_TO_TAIL", 33 | "value": "/var/log/example0.log" 34 | }, 35 | { 36 | "name": "TAILING_SIDECAR", 37 | "value": "true" 38 | } 39 | ], 40 | "image": "tailing-sidecar-image:test", 41 | "name": "tailing-sidecar-0", 42 | "resources": {}, 43 | "volumeMounts": [ 44 | { 45 | "mountPath": "/var/log", 46 | "name": "varlog" 47 | }, 48 | { 49 | "mountPath": "/tailing-sidecar/var", 50 | "name": "volume-sidecar-0" 51 | } 52 | ] 53 | } 54 | }, 55 | { 56 | "op": "add", 57 | "path": "/spec/containers/2", 58 | "value": { 59 | "env": [ 60 | { 61 | "name": "PATH_TO_TAIL", 62 | "value": "/var/log/example1.log" 63 | }, 64 | { 65 | "name": "TAILING_SIDECAR", 66 | "value": "true" 67 | } 68 | ], 69 | "image": "tailing-sidecar-image:test", 70 | "name": "tailing-sidecar-1", 71 | "resources": {}, 72 | "volumeMounts": [ 73 | { 74 | "mountPath": "/var/log", 75 | "name": "varlog" 76 | }, 77 | { 78 | "mountPath": "/tailing-sidecar/var", 79 | "name": "volume-sidecar-1" 80 | } 81 | ] 82 | } 83 | }, 84 | { 85 | "op": "add", 86 | "path": "/spec/containers/3", 87 | "value": { 88 | "env": [ 89 | { 90 | "name": "PATH_TO_TAIL", 91 | "value": "/varconfig/log/example2.log" 92 | }, 93 | { 94 | "name": "TAILING_SIDECAR", 95 | "value": "true" 96 | } 97 | ], 98 | "image": "tailing-sidecar-image:test", 99 | "name": "sidecar-0", 100 | "resources": {}, 101 | "volumeMounts": [ 102 | { 103 | "mountPath": "/varconfig/log", 104 | "name": "varlogconfig", 105 | "readOnly": true 106 | }, 107 | { 108 | "mountPath": "/tailing-sidecar/var", 109 | "name": "volume-sidecar-2" 110 | } 111 | ] 112 | } 113 | } 114 | ] 115 | -------------------------------------------------------------------------------- /operator/docs/configuration.md: -------------------------------------------------------------------------------- 1 | # Tailing Sidecar Operator configuration 2 | 3 | ## Configuration in annotation 4 | 5 | Configuration for Tailing Sidecar Operator can be provided through `tailing-sidecar` annotation added to Pod metadata 6 | 7 | ```yaml 8 | metadata: 9 | annotations: 10 | tailing-sidecar: 11 | ``` 12 | 13 | Tailing sidecar container is joined with container containing logs by Volume. 14 | 15 | Configuration for single tailing sidecar consists of: 16 | 17 | - tailing sidecar container name (optional, if not specified container name will be automatically created and 18 | it will start with "tailing-sidecar" prefix) 19 | - volume name 20 | - path to file containing logs to tail 21 | 22 | Configuration for single tailing sidecar is separated by `;`. 23 | 24 | Configuration in annotations allows to define configurations for multiple tailing sidecars in following form: 25 | 26 | ```yaml 27 | metadata: 28 | annotations: 29 | tailing-sidecar: ::;:;: 30 | ``` 31 | 32 | Example configurations in annotations for Kubernetes resources can be found in [examples](../examples) directory. 33 | 34 | **Notice**: Only basic options can be configured in annotations, for extended configuration options please 35 | see [Configuration in TailingSidecarConfig](#configuration-in-tailingsidecarconfig). 36 | 37 | ## Configuration in TailingSidecarConfig 38 | 39 | Configuration for Tailing Sidecar Operator can be provided through `TailingSidecarConfig` which is a Custom Resource 40 | used by the operator. 41 | 42 | Example definitions of `TailingSidecarConfig` are available in [samples](../config/samples) directory and Pod adjusted to this configuration 43 | in available [pod-with-tailing-sidecar-config.yaml](../examples/pod_with_tailing_sidecar_config.yaml). 44 | 45 | To try example configuration use following commands: 46 | 47 | ```bash 48 | kubectl apply -f https://raw.githubusercontent.com/SumoLogic/tailing-sidecar/release-v0.5/operator/config/samples/tailing-sidecar_v1_tailingsidecar.yaml 49 | kubectl apply -f https://raw.githubusercontent.com/SumoLogic/tailing-sidecar/release-v0.5/operator/examples/pod_with_tailing_sidecar_config.yaml 50 | ``` 51 | 52 | For details related to `TailingSidecarConfig` definition please see subsections below. 53 | 54 | ### TailingSidecarConfig 55 | 56 | | Field | Description | Scheme | 57 | | ----- | ----------- | ------ | 58 | | metadata | Metadata for TailingSidecarConfig | [metav1.ObjectMeta][metav1.ObjectMeta] | 59 | | spec | Spec defines specification of TailingSidecarConfig | [tailingsidecarv1.TailingSidecarConfigSpec](#tailingSidecarConfigSpec) | 60 | 61 | [metav1.ObjectMeta]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#objectmeta-v1-meta 62 | 63 | ### TailingSidecarConfigSpec 64 | 65 | | Field | Description | Scheme | 66 | | ----- | ----------- | ------ | 67 | | annotationsPrefix | AnnotationsPrefix defines prefix for per container annotations. | [metav1.LabelSelector][metav1.LabelSelector] | 68 | | podSelector | PodSelector selects Pods to which this tailing sidecar configuration applies. | [metav1.LabelSelector][metav1.LabelSelector] | 69 | | SidecarSpecs | SidecarSpecs defines specifications for tailing sidecar containers, map key indicates name of tailing sidecar container. | [map\[string\]tailingsidecarv1.SidecarSpec](#sidecarspec) | 70 | 71 | [metav1.LabelSelector]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta 72 | 73 | ### SidecarSpec 74 | 75 | | Field | Description | Scheme | 76 | |-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------ | 77 | | annotations | Annotations defines tailing sidecar container annotations. Tailing sidecar annotations are added in following form `/.:` | map\[string\]string | 78 | | path | Path defines path to a file containing logs to tail within a tailing sidecar container. | string | 79 | | volumeMount | VolumeMount describes a mounting of a volume within a tailing sidecar container. This volume joins tailing sidecar container with container containing logs to tail and provide access to file with logs. | [corev1.VolumeMount][corev1.VolumeMount] | 80 | | resources | resources describes the compute resource requirements for a tailing sidecar container. | [corev1.ResourceRequirements][corev1.ResourceRequirements] | 81 | [corev1.VolumeMount]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#volumemount-v1-core 82 | [corev1.ResourceRequirements]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core 83 | 84 | --------------------------------------------------------------------------------