Skip to content

Commit 03c1a99

Browse files
authored
Merge pull request #48 from dalehamel/cos-header-install
feat: Automatically fetch headers for Google's Container OS linux header install via initContainer
2 parents 0510804 + c934736 commit 03c1a99

File tree

4 files changed

+222
-7
lines changed

4 files changed

+222
-7
lines changed

Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ image/build:
5555
-f Dockerfile.tracerunner .
5656
$(DOCKER) tag $(IMAGE_TRACERUNNER_BRANCH) $(IMAGE_TRACERUNNER_COMMIT)
5757

58+
.PHONY: image/build-init
59+
image/build-init:
60+
$(DOCKER) build \
61+
$(IMAGE_BUILD_FLAGS) \
62+
-t $(IMAGE_INITCONTAINER_BRANCH) \
63+
-f ./init/Dockerfile.initcontainer ./init
64+
$(DOCKER) tag $(IMAGE_INITCONTAINER_BRANCH) $(IMAGE_INITCONTAINER_COMMIT)
65+
5866
.PHONY: image/push
5967
image/push:
6068
$(DOCKER) push $(IMAGE_TRACERUNNER_BRANCH)

init/Dockerfile.initcontainer

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM alpine:3.8
2+
RUN apk add --update \
3+
bash \
4+
bc \
5+
build-base \
6+
curl \
7+
libelf-dev \
8+
linux-headers \
9+
make
10+
11+
WORKDIR /
12+
13+
COPY /fetch-linux-headers.sh /
14+
15+
ENTRYPOINT [ "/fetch-linux-headers.sh" ]

init/fetch-linux-headers.sh

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/bash
2+
3+
set -x
4+
5+
LSB_FILE="/etc/lsb-release.host"
6+
OS_RELEASE_FILE="/etc/os-release.host"
7+
TARGET_DIR="/usr/src"
8+
HOST_MODULES_DIR="/lib/modules.host"
9+
10+
generate_headers()
11+
{
12+
echo "Generating kernel headers"
13+
cd ${BUILD_DIR}
14+
zcat /proc/config.gz > .config
15+
make ARCH=x86 oldconfig > /dev/null
16+
make ARCH=x86 prepare > /dev/null
17+
}
18+
19+
fetch_cos_linux_sources()
20+
{
21+
echo "Fetching upstream kernel sources."
22+
mkdir -p ${BUILD_DIR}
23+
curl -s "https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-src.tar.gz" | tar -xzf - -C ${BUILD_DIR}
24+
}
25+
26+
install_cos_linux_headers()
27+
{
28+
if grep -q CHROMEOS_RELEASE_VERSION ${LSB_FILE};then
29+
BUILD_ID=$(grep CHROMEOS_RELEASE_VERSION ${LSB_FILE} | cut -d = -f 2)
30+
BUILD_DIR="/linux-lakitu-${BUILD_ID}"
31+
SOURCES_DIR="${TARGET_DIR}/linux-lakitu-${BUILD_ID}"
32+
33+
if [ ! -e "${SOURCES_DIR}/.installed" ];then
34+
echo "Installing kernel headers for for COS build ${BUILD_ID}"
35+
fetch_cos_linux_sources
36+
generate_headers
37+
mv ${BUILD_DIR} ${TARGET_DIR}
38+
touch "${SOURCES_DIR}/.installed"
39+
fi
40+
fi
41+
}
42+
43+
install_headers()
44+
{
45+
distro=$(grep ^NAME ${OS_RELEASE_FILE} | cut -d = -f 2)
46+
47+
case $distro in
48+
*"Container-Optimized OS"*)
49+
install_cos_linux_headers
50+
HEADERS_TARGET=${SOURCES_DIR}
51+
;;
52+
*)
53+
echo "WARNING: ${distro} is not a supported distro, cannot install headers, ensure they are installed to /lib/modules"
54+
esac
55+
}
56+
57+
check_headers()
58+
{
59+
modules_path=$1
60+
utsname=$(uname -r)
61+
arch=$(uname -m)
62+
kdir="${modules_path}/${utsname}"
63+
64+
[ "${arch}" == "x86_64" ] && arch="x86"
65+
66+
[ ! -e ${kdir} ] && return 1
67+
[ ! -e "${kdir}/source" ] && [ ! -e "${kdir}/build" ] && return 1
68+
69+
header_dir=$([ -e "${kdir}/source" ] && echo "${kdir}/source" || echo "${kdir}/build")
70+
71+
[ ! -e "${header_dir}/include/linux/kconfig.h" ] && return 1
72+
[ ! -e "${header_dir}/include/generated/uapi" ] && return 1
73+
[ ! -e "${header_dir}/arch/${arch}/include/generated/uapi" ] && return 1
74+
75+
return 0
76+
}
77+
78+
if [ ! -e /lib/modules/.installed ];then
79+
if ! check_headers ${HOST_MODULES_DIR}; then
80+
install_headers
81+
else
82+
HEADERS_TARGET=${HOST_MODULES_DIR}/source
83+
fi
84+
85+
mkdir -p "/lib/modules/$(uname -r)"
86+
ln -sf ${HEADERS_TARGET} "/lib/modules/$(uname -r)/source"
87+
ln -sf ${HEADERS_TARGET} "/lib/modules/$(uname -r)/build"
88+
touch /lib/modules/.installed
89+
exit 0
90+
else
91+
echo "Headers already installed"
92+
exit 0
93+
fi

pkg/tracejob/job.go

+106-7
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func (t *TraceJobClient) CreateJob(nj TraceJob) (*batchv1.Job, error) {
238238
},
239239
},
240240
apiv1.Volume{
241-
Name: "modules",
241+
Name: "modules-host",
242242
VolumeSource: apiv1.VolumeSource{
243243
HostPath: &apiv1.HostPathVolumeSource{
244244
Path: "/lib/modules",
@@ -277,11 +277,6 @@ func (t *TraceJobClient) CreateJob(nj TraceJob) (*batchv1.Job, error) {
277277
MountPath: "/programs",
278278
ReadOnly: true,
279279
},
280-
apiv1.VolumeMount{
281-
Name: "modules",
282-
MountPath: "/lib/modules",
283-
ReadOnly: true,
284-
},
285280
apiv1.VolumeMount{
286281
Name: "sys",
287282
MountPath: "/sys",
@@ -316,6 +311,110 @@ func (t *TraceJobClient) CreateJob(nj TraceJob) (*batchv1.Job, error) {
316311
},
317312
}
318313

314+
if nj.FetchHeaders {
315+
// If we aren't downloading headers, add the initContainer and set up mounts
316+
job.Spec.Template.Spec.InitContainers = []apiv1.Container{
317+
apiv1.Container{
318+
Name: "kubectl-trace-init",
319+
Image: nj.InitImageNameTag,
320+
Resources: apiv1.ResourceRequirements{
321+
Requests: apiv1.ResourceList{
322+
apiv1.ResourceCPU: resource.MustParse("100m"),
323+
apiv1.ResourceMemory: resource.MustParse("100Mi"),
324+
},
325+
Limits: apiv1.ResourceList{
326+
apiv1.ResourceCPU: resource.MustParse("1"),
327+
apiv1.ResourceMemory: resource.MustParse("1G"),
328+
},
329+
},
330+
VolumeMounts: []apiv1.VolumeMount{
331+
apiv1.VolumeMount{
332+
Name: "lsb-release",
333+
MountPath: "/etc/lsb-release.host",
334+
ReadOnly: true,
335+
},
336+
apiv1.VolumeMount{
337+
Name: "os-release",
338+
MountPath: "/etc/os-release.host",
339+
ReadOnly: true,
340+
},
341+
apiv1.VolumeMount{
342+
Name: "modules-dir",
343+
MountPath: "/lib/modules",
344+
},
345+
apiv1.VolumeMount{
346+
Name: "modules-host",
347+
MountPath: "/lib/modules.host",
348+
ReadOnly: true,
349+
},
350+
apiv1.VolumeMount{
351+
Name: "linux-headers-generated",
352+
MountPath: "/usr/src/",
353+
},
354+
},
355+
},
356+
}
357+
358+
job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes,
359+
apiv1.Volume{
360+
Name: "lsb-release",
361+
VolumeSource: apiv1.VolumeSource{
362+
HostPath: &apiv1.HostPathVolumeSource{
363+
Path: "/etc/lsb-release",
364+
},
365+
},
366+
},
367+
apiv1.Volume{
368+
Name: "os-release",
369+
VolumeSource: apiv1.VolumeSource{
370+
HostPath: &apiv1.HostPathVolumeSource{
371+
Path: "/etc/os-release",
372+
},
373+
},
374+
},
375+
apiv1.Volume{
376+
Name: "modules-dir",
377+
VolumeSource: apiv1.VolumeSource{
378+
HostPath: &apiv1.HostPathVolumeSource{
379+
Path: "/var/cache/linux-headers/modules_dir",
380+
},
381+
},
382+
},
383+
apiv1.Volume{
384+
Name: "linux-headers-generated",
385+
VolumeSource: apiv1.VolumeSource{
386+
HostPath: &apiv1.HostPathVolumeSource{
387+
Path: "/var/cache/linux-headers/generated",
388+
},
389+
},
390+
})
391+
392+
job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts,
393+
apiv1.VolumeMount{
394+
Name: "modules-dir",
395+
MountPath: "/lib/modules",
396+
ReadOnly: true,
397+
},
398+
apiv1.VolumeMount{
399+
Name: "modules-host",
400+
MountPath: "/lib/modules.host",
401+
ReadOnly: true,
402+
},
403+
apiv1.VolumeMount{
404+
Name: "linux-headers-generated",
405+
MountPath: "/usr/src/",
406+
ReadOnly: true,
407+
})
408+
409+
} else {
410+
// If we aren't downloading headers, unconditionally used the ones linked in /lib/modules
411+
job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts,
412+
apiv1.VolumeMount{
413+
Name: "modules-host",
414+
MountPath: "/lib/modules",
415+
ReadOnly: true,
416+
})
417+
}
319418
if _, err := t.ConfigClient.Create(cm); err != nil {
320419
return nil, err
321420
}
@@ -393,4 +492,4 @@ func jobStatus(j batchv1.Job) TraceJobStatus {
393492
return TraceJobFailed
394493
}
395494
return TraceJobUnknown
396-
}
495+
}

0 commit comments

Comments
 (0)