From bfcc41723d40502219c02c9d4d2f4e76b381ca37 Mon Sep 17 00:00:00 2001 From: Thilo Fromm Date: Thu, 16 Oct 2025 09:51:14 +0200 Subject: [PATCH 1/3] feat: Add support for Flatcar Container Linux This change adds support for Flatcar to the blobfuse installer. Changes are minimal; we're re-using the rhcos installer script and the gardenlinux paths. As Flatcar currently does not ship libfuse, we install it alongside blobfuse2. Signed-off-by: Thilo Fromm --- .../templates/csi-blob-node.yaml | 4 +-- pkg/blobfuse-proxy/init.sh | 2 +- pkg/blobfuse-proxy/install-proxy-rhcos.sh | 33 ++++++++++++------- pkg/blobfuse-proxy/server/server.go | 5 +++ 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/charts/latest/blob-csi-driver/templates/csi-blob-node.yaml b/charts/latest/blob-csi-driver/templates/csi-blob-node.yaml index 57b01acaf..ab9e5414a 100644 --- a/charts/latest/blob-csi-driver/templates/csi-blob-node.yaml +++ b/charts/latest/blob-csi-driver/templates/csi-blob-node.yaml @@ -113,7 +113,7 @@ spec: - name: host-home-kubernetes-bin mountPath: /host/home/kubernetes/bin {{- end }} -{{- if eq .Values.linux.distro "gardenlinux" }} +{{- if or (eq .Values.linux.distro "gardenlinux") (eq .Values.linux.distro "flatcar") }} - name: host-var-bin mountPath: /host/var/bin {{- end }} @@ -302,7 +302,7 @@ spec: hostPath: path: /home/kubernetes/bin {{- end }} -{{- if eq .Values.linux.distro "gardenlinux" }} +{{- if or (eq .Values.linux.distro "gardenlinux") (eq .Values.linux.distro "flatcar") }} - name: host-var-bin hostPath: path: /var/bin diff --git a/pkg/blobfuse-proxy/init.sh b/pkg/blobfuse-proxy/init.sh index af4487c02..1e714fbe2 100755 --- a/pkg/blobfuse-proxy/init.sh +++ b/pkg/blobfuse-proxy/init.sh @@ -39,7 +39,7 @@ echo "Linux distribution: $DISTRIBUTION, Arch: $ARCH" # install blobfuse-proxy and blobfuse/blobfuse2 if needed case "${DISTRIBUTION}" in - "rhcos" | "rhel" | "cos" | "gardenlinux") + "rhcos" | "rhel" | "cos" | "gardenlinux" | "flatcar") . ./blobfuse-proxy/install-proxy-rhcos.sh ;; *) diff --git a/pkg/blobfuse-proxy/install-proxy-rhcos.sh b/pkg/blobfuse-proxy/install-proxy-rhcos.sh index 420542f5a..73a241f92 100644 --- a/pkg/blobfuse-proxy/install-proxy-rhcos.sh +++ b/pkg/blobfuse-proxy/install-proxy-rhcos.sh @@ -16,19 +16,19 @@ set -xe -BIN_PATH=${BIN_PATH:-/usr/local/bin} -if [ "${DISTRIBUTION}" = "cos" ]; then - echo "set BIN_PATH to /home/kubernetes/bin" - BIN_PATH="/home/kubernetes/bin" -fi -if [ "${DISTRIBUTION}" = "gardenlinux" ]; then - echo "set BIN_PATH to /var/bin" - BIN_PATH="/var/bin" -fi -if [ "${CUSTOM_BIN_PATH}" != "" ]; then - echo "set BIN_PATH to ${CUSTOM_BIN_PATH}" - BIN_PATH="${CUSTOM_BIN_PATH}" +if [ -z "${CUSTOM_BIN_PATH:-}" ] ; then + case "${DISTRIBUTION}" in + "cos") + BIN_PATH="/home/kubernetes/bin" ;; + "gardenlinux" | "flatcar") + BIN_PATH="/var/bin" ;; + *) + BIN_PATH=${BIN_PATH:-/usr/local/bin} ;; + esac +else + BIN_PATH="/${CUSTOM_BIN_PATH#/}" fi +echo "set BIN_PATH to ${BIN_PATH}" #copy blobfuse2 binary to BIN_PATH/blobfuse2 updateBlobfuse2="true" @@ -60,6 +60,15 @@ if [ "$updateBlobfuse2" = "true" ];then cp /usr/lib64/libfuse3.so.3* /host/usr/lib64/ fi chmod 755 /host${BIN_PATH}/blobfuse2 + if [ "$DISTRIBUTION" = "flatcar" ] ; then + find /usr/ -name 'libfuse.so.*' -exec cp '{}' /host${BIN_PATH} \; + mv /host${BIN_PATH}/blobfuse2 /host${BIN_PATH}/blobfuse2.bin + { + echo '#!/usr/bin/bash' + echo "LD_LIBRARY_PATH='${BIN_PATH}' exec ${BIN_PATH}/blobfuse2.bin \"\${@}\"" + } >/host${BIN_PATH}/blobfuse2 + chmod 755 /host${BIN_PATH}/blobfuse2 + fi fi if [ "${INSTALL_BLOBFUSE_PROXY}" = "true" ];then diff --git a/pkg/blobfuse-proxy/server/server.go b/pkg/blobfuse-proxy/server/server.go index 9730c83dd..ab7c4bf96 100644 --- a/pkg/blobfuse-proxy/server/server.go +++ b/pkg/blobfuse-proxy/server/server.go @@ -150,6 +150,11 @@ func getBlobfuseVersion() BlobfuseVersion { return BlobfuseV2 } + if strings.EqualFold(osinfo.Distro, "flatcar") { + klog.V(2).Info("proxy default using blobfuse V2 for mounting on Flatcar Container Linux") + return BlobfuseV2 + } + klog.V(2).Info("proxy default using blobfuse V1 for mounting") return BlobfuseV1 } From 7a882e2aeaa78bd5b973379ca0734df2fb6a8a47 Mon Sep 17 00:00:00 2001 From: Thilo Fromm Date: Fri, 17 Oct 2025 16:40:55 +0200 Subject: [PATCH 2/3] fix: correctly modify PATH in install-proxy-rhcos.sh The installer script wants to update the PATH variable to include $BIN_PATH in blobfuse-proxs's systemd unit by setting: Environment="PATH=:$PATH" BIN_PATH is evaluated in the installer script, and $PATH is escaped, to be evaluated when the service unit runs. However, environment variables like "$PATH" are NOT evaluated by systemd in Environment="...". Quoting the documentation: " Variable expansion is not performed inside the strings and the "$" character has no special meaning. " https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Environment This effectively removes all other paths and sets PATH to ONLY . The resulting environment variable PATH contains the actual contents of BIN_PATH and a literal '$PATH'. This commit fixes that by wrapping ExecStart in bash -c '...' and updating PATH there. --- pkg/blobfuse-proxy/install-proxy-rhcos.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/blobfuse-proxy/install-proxy-rhcos.sh b/pkg/blobfuse-proxy/install-proxy-rhcos.sh index 73a241f92..9a9ac238a 100644 --- a/pkg/blobfuse-proxy/install-proxy-rhcos.sh +++ b/pkg/blobfuse-proxy/install-proxy-rhcos.sh @@ -93,8 +93,9 @@ if [ "${INSTALL_BLOBFUSE_PROXY}" = "true" ];then echo "change from /usr/bin/blobfuse-proxy to ${BIN_PATH}/blobfuse-proxy in blobfuse-proxy.service" sed -i "s|/usr/bin/blobfuse-proxy|${BIN_PATH}/blobfuse-proxy|g" /blobfuse-proxy/blobfuse-proxy.service if [ "${BIN_PATH}" != "/usr/local/bin" ]; then - echo "add Environment=\"PATH=${BIN_PATH}:$PATH\" in blobfuse-proxy.service" - sed -i "/Delegate=yes/a Environment=\"PATH=${BIN_PATH}:\$PATH\"" /blobfuse-proxy/blobfuse-proxy.service + echo "add \"PATH=${BIN_PATH}:\$PATH\" in blobfuse-proxy.service ExecStart." + sed "s,^ExecStart[[:space:]]*=\\(.*\\)\$,ExecStart=/usr/bin/bash -c \"PATH=${BIN_PATH}:\$PATH \\1\"," \ + /blobfuse-proxy/blobfuse-proxy.service fi if [ -f "/host/etc/systemd/system/blobfuse-proxy.service" ];then old=$(sha256sum /host/etc/systemd/system/blobfuse-proxy.service | awk '{print $1}') From 2fe03cd191d67dda8ffc9c6fd204f2e797390b15 Mon Sep 17 00:00:00 2001 From: Thilo Fromm Date: Sun, 19 Oct 2025 11:02:30 +0200 Subject: [PATCH 3/3] chore: update helm charts Signed-off-by: Thilo Fromm --- charts/latest/blob-csi-driver-1.26.7.tgz | Bin 8035 -> 6610 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/charts/latest/blob-csi-driver-1.26.7.tgz b/charts/latest/blob-csi-driver-1.26.7.tgz index 28da7e69e5f92e5da86f52e13a57ab2b11cafc32..c5bbcc185fa9943ca59890f875cfd727e25bfa8d 100644 GIT binary patch delta 6609 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 P00960i>ay>0JZ=CiT?kP literal 8035 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 G=05;j{=_r@