Skip to content

Commit 2df7710

Browse files
authored
T-8952: Reload Vector when enrichment table changes (#18)
1 parent 6c295f5 commit 2df7710

15 files changed

+332
-45
lines changed

Dockerfile

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ RUN apt-get update && apt-get install -y \
2626
&& rm -rf /var/lib/apt/lists/*
2727

2828
# Copy Vector from vector image
29-
COPY --from=vector /usr/bin/vector /usr/local/bin/vector
29+
COPY --from=vector --chmod=755 /usr/bin/vector /usr/local/bin/vector
3030
COPY --from=vector /etc/vector /etc/vector
3131

3232
# Copy Cluster Agent
33-
COPY --from=cluster-agent /usr/bin/coroot-cluster-agent /usr/local/bin/cluster-agent
33+
COPY --from=cluster-agent --chmod=755 /usr/bin/coroot-cluster-agent /usr/local/bin/cluster-agent
3434

3535
# Copy mdprobe
36-
COPY --from=mdprobe-builder /bin/mdprobe /usr/local/bin/mdprobe
36+
COPY --from=mdprobe-builder --chmod=755 /bin/mdprobe /usr/local/bin/mdprobe
3737

3838
# Create necessary directories
3939
RUN mkdir -p /versions/0-default \
@@ -46,7 +46,7 @@ RUN mkdir -p /versions/0-default \
4646
# Set environment variables
4747
ENV BASE_URL=https://telemetry.betterstack.com
4848
ENV CLUSTER_COLLECTOR=false
49-
ENV COLLECTOR_VERSION=1.0.6
49+
ENV COLLECTOR_VERSION=1.0.7
5050
ENV VECTOR_VERSION=0.47.0
5151
ENV BEYLA_VERSION=2.2.4
5252
ENV CLUSTER_AGENT_VERSION=1.2.4
@@ -68,16 +68,17 @@ ENV TINI_SUBREAPER=true
6868
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
6969

7070
# Copy Ruby scripts
71-
COPY updater.rb /updater.rb
72-
COPY proxy.rb /proxy.rb
73-
COPY vector.sh /vector.sh
71+
COPY --chmod=755 updater.rb /updater.rb
72+
COPY --chmod=755 proxy.rb /proxy.rb
73+
COPY --chmod=755 vector.sh /vector.sh
7474
COPY versions/0-default/vector.yaml /versions/0-default/vector.yaml
7575
COPY versions/0-default/databases.json /versions/0-default/databases.json
7676
COPY kubernetes-discovery/0-default/discovered_pods.yaml /kubernetes-discovery/0-default/discovered_pods.yaml
7777
COPY engine /engine
7878
COPY should_run_cluster_collector.rb /should_run_cluster_collector.rb
79-
COPY cluster-collector.sh /cluster-collector.sh
80-
COPY ebpf.sh /ebpf.sh
79+
COPY --chmod=755 cluster-collector.sh /cluster-collector.sh
80+
COPY --chmod=755 ebpf.sh /ebpf.sh
81+
COPY dockerprobe/docker-mappings.default.csv /enrichment/docker-mappings.csv
8182

8283
# Create initial vector-config with symlinks to defaults
8384
RUN mkdir -p /vector-config/0-default \
@@ -87,16 +88,6 @@ RUN mkdir -p /vector-config/0-default \
8788
&& ln -s /vector-config/0-default /vector-config/current \
8889
&& cp /versions/0-default/vector.yaml /vector-config/latest-valid-upstream/vector.yaml
8990

90-
# Set permissions
91-
RUN chmod +x /usr/local/bin/vector \
92-
&& chmod +x /usr/local/bin/cluster-agent \
93-
&& chmod +x /usr/local/bin/mdprobe \
94-
&& chmod +x /cluster-collector.sh \
95-
&& chmod +x /vector.sh \
96-
&& chmod +x /updater.rb \
97-
&& chmod +x /proxy.rb \
98-
&& chmod +x /ebpf.sh
99-
10091
# Install tini and use it as init to handle signals properly
10192
ENTRYPOINT ["/usr/bin/tini", "-s", "--"]
10293

beyla/entrypoint.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ if [ "${ENABLE_DOCKERPROBE}" = "true" ] || [ "${ENABLE_DOCKERPROBE}" = "1" ]; th
55
echo "Enabling dockerprobe (ENABLE_DOCKERPROBE=${ENABLE_DOCKERPROBE})"
66
# Replace autostart=false with autostart=true for dockerprobe
77
sed -i '/\[program:dockerprobe\]/,/^\[/ s/autostart=false/autostart=true/' /etc/supervisor/conf.d/supervisord.conf
8-
else
9-
echo "Dockerprobe disabled (ENABLE_DOCKERPROBE=${ENABLE_DOCKERPROBE})"
108
fi
119

1210
# Start supervisord

beyla/supervisord.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ command=/usr/local/bin/dockerprobe
2323
autorestart=true
2424
stdout_logfile=/var/log/supervisor/dockerprobe.out.log
2525
stderr_logfile=/var/log/supervisor/dockerprobe.err.log
26-
environment=DOCKER_HOST="unix:///var/run/docker.sock",DOCKERPROBE_OUTPUT_PATH="/enrichment/docker-mappings.csv",DOCKERPROBE_INTERVAL="15"
26+
environment=DOCKER_HOST="unix:///var/run/docker.sock",DOCKERPROBE_OUTPUT_PATH="/enrichment/docker-mappings.incoming.csv",DOCKERPROBE_INTERVAL="15"

docker-compose.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ services:
33
build:
44
context: .
55
dockerfile: Dockerfile
6-
image: betterstack/collector:latest
6+
# image: betterstack/collector:latest
77
container_name: better-stack-collector
88
restart: always
99
environment:
@@ -23,7 +23,7 @@ services:
2323
- /var/lib/docker/containers:/host/var/lib/docker/containers:ro
2424
# dockerprobe running in the beyla container writes a map of PIDs->container IDs and names to this volume
2525
# Vector uses this file as an enrichment table to tag logs, metrics, and traces with container metadata.
26-
- docker-metadata:/enrichment:ro
26+
- docker-metadata:/enrichment:rw
2727
ports:
2828
# Bind to localhost only for security - Beyla will connect via host network
2929
- "127.0.0.1:34320:34320"
@@ -32,7 +32,7 @@ services:
3232
build:
3333
context: .
3434
dockerfile: Dockerfile.beyla
35-
image: betterstack/collector-beyla:latest
35+
# image: betterstack/collector-beyla:latest
3636
container_name: better-stack-beyla
3737
restart: always
3838
privileged: true
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pid,container_name,container_id,image_name

dockerprobe/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
)
2828

2929
const (
30-
defaultOutputPath = "/enrichment/docker-mappings.csv"
30+
defaultOutputPath = "/enrichment/docker-mappings.incoming.csv"
3131
defaultInterval = 15 // seconds; in line with default tickrate of Beyla collection
3232
defaultTimeout = 15 // seconds
3333
debugLogLimit = 5

engine/better_stack_client.rb

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22
require_relative 'kubernetes_discovery'
33
require_relative 'vector_config'
44
require_relative 'ebpf_compatibility_checker'
5+
require_relative 'vector_enrichment_table'
56
require 'net/http'
67
require 'fileutils'
78
require 'time'
9+
require 'forwardable'
810

911
class BetterStackClient
12+
extend Forwardable
1013
include Utils
1114

15+
def_delegator :@vector_config, :reload_vector
16+
1217
def initialize(working_dir)
1318
@base_url = (ENV['BASE_URL'] || 'https://telemetry.betterstack.com').chomp('/')
1419
@collector_secret = ENV['COLLECTOR_SECRET']
@@ -22,6 +27,7 @@ def initialize(working_dir)
2227
@kubernetes_discovery = KubernetesDiscovery.new(working_dir)
2328
@vector_config = VectorConfig.new(working_dir)
2429
@ebpf_compatibility_checker = EbpfCompatibilityChecker.new(working_dir)
30+
@vector_enrichment_table = VectorEnrichmentTable.new(ENRICHMENT_TABLE_PATH, ENRICHMENT_TABLE_INCOMING_PATH)
2531
end
2632

2733
def make_post_request(path, params)
@@ -98,14 +104,32 @@ def ping
98104
validate_output = @vector_config.validate_dir(new_config_dir)
99105
unless validate_output.nil?
100106
write_error("Validation failed for vector config with kubernetes_discovery\n\n#{validate_output}")
101-
return
107+
return false
102108
end
103109

104-
@vector_config.promote_dir(new_config_dir)
110+
result = @vector_config.promote_dir(new_config_dir)
105111
clear_error
112+
113+
return result
106114
end
115+
116+
false
107117
end
108118

119+
def enrichment_table_changed? = @vector_enrichment_table.different?
120+
121+
def validate_enrichment_table
122+
output = @vector_enrichment_table.validate
123+
unless output.nil?
124+
write_error("Validation failed for enrichment table\n\n#{output}")
125+
return output
126+
end
127+
128+
nil
129+
end
130+
131+
def promote_enrichment_table = @vector_enrichment_table.promote
132+
109133
def process_ping(code, body)
110134
case code
111135
when '204'

engine/utils.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
require 'socket'
55

66
module Utils
7+
ENRICHMENT_TABLE_PATH = "/enrichment/docker-mappings.csv"
8+
ENRICHMENT_TABLE_INCOMING_PATH = "/enrichment/docker-mappings.incoming.csv"
9+
710
# Shared and main.rb specific functions
811
def latest_version
912
# Assuming version directories are named like 'YYYY-MM-DDTHH:MM:SS'

engine/vector_config.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ def promote_dir(config_dir)
193193
# Move new config to current
194194
FileUtils.mv(config_dir, current_dir)
195195

196+
true
197+
end
198+
199+
def reload_vector
196200
puts "Reloading vector..."
197201
system("supervisorctl signal HUP vector")
198202

engine/vector_enrichment_table.rb

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
require 'digest'
2+
3+
# Checks whether the enrichment table has changed
4+
# Returns a hash of the file if it exists, otherwise nil
5+
# Used by enrichment_table_watcher.rb to reload vector if the enrichment table has changed
6+
class VectorEnrichmentTable
7+
def initialize(target_path, incoming_path)
8+
@target_path = target_path
9+
@incoming_path = incoming_path
10+
end
11+
12+
def different?
13+
directory = File.dirname(incoming_path)
14+
return false unless File.exist?(directory) && File.directory?(directory)
15+
return false unless File.exist?(incoming_path)
16+
17+
current_hash = calculate_file_hash(target_path)
18+
new_hash = calculate_file_hash(incoming_path)
19+
20+
current_hash != new_hash
21+
end
22+
23+
def validate
24+
puts "Validating enrichment table at #{incoming_path}"
25+
26+
if !File.exist?(incoming_path)
27+
puts "Enrichment table not found at #{incoming_path}"
28+
return "Enrichment table not found at #{incoming_path}"
29+
end
30+
31+
if File.size(incoming_path) == 0
32+
puts "Enrichment table is empty at #{incoming_path}"
33+
return "Enrichment table is empty at #{incoming_path}"
34+
end
35+
36+
if File.readlines(incoming_path).first.strip != "pid,container_name,container_id,image_name"
37+
puts "Enrichment table is not valid at #{incoming_path}"
38+
return "Enrichment table is not valid at #{incoming_path}"
39+
end
40+
41+
nil
42+
end
43+
44+
def promote
45+
FileUtils.mv(incoming_path, target_path)
46+
end
47+
48+
private
49+
50+
attr_reader :target_path, :incoming_path
51+
52+
def calculate_file_hash(file_path)
53+
Digest::MD5.file(file_path).hexdigest
54+
end
55+
end

0 commit comments

Comments
 (0)