Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distribute mountpoint binary instead of package #48

Merged
merged 7 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 23 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,53 @@

ARG MOUNTPOINT_VERSION=1.1.0

# Download and verify the mountpoint's RPM and DEB in this container
FROM --platform=$BUILDPLATFORM public.ecr.aws/amazonlinux/amazonlinux:2023 as mp_builder
# Download the mountpoint tarball and produce an installable directory
# Building on Amazon Linux 2 because it has an old libc version. libfuse from the os
# is being packaged up in the container and a newer version linking to a too new glibc
# can cause portability issues
FROM --platform=$TARGETPLATFORM public.ecr.aws/amazonlinux/amazonlinux:2 as mp_builder
ARG MOUNTPOINT_VERSION
ARG TARGETARCH
ARG TARGETPLATFORM
# We need the full version of GnuPG
RUN dnf install -y --allowerasing wget gnupg2
RUN yum install -y gzip wget gnupg2 tar fuse-libs binutils patchelf

RUN MP_ARCH=`echo ${TARGETARCH} | sed s/amd64/x86_64/` && \
wget -q "https://s3.amazonaws.com/mountpoint-s3-release/${MOUNTPOINT_VERSION}/$MP_ARCH/mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.rpm" && \
wget -q "https://s3.amazonaws.com/mountpoint-s3-release/${MOUNTPOINT_VERSION}/$MP_ARCH/mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.rpm.asc" && \
wget -q "https://s3.amazonaws.com/mountpoint-s3-release/${MOUNTPOINT_VERSION}/$MP_ARCH/mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.deb" && \
wget -q "https://s3.amazonaws.com/mountpoint-s3-release/${MOUNTPOINT_VERSION}/$MP_ARCH/mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.deb.asc" && \
wget -q "https://s3.amazonaws.com/mountpoint-s3-release/${MOUNTPOINT_VERSION}/$MP_ARCH/mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.tar.gz" && \
wget -q "https://s3.amazonaws.com/mountpoint-s3-release/${MOUNTPOINT_VERSION}/$MP_ARCH/mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.tar.gz.asc" && \
wget -q https://s3.amazonaws.com/mountpoint-s3-release/public_keys/KEYS

# Import the key and validate it has the fingerprint we expect
RUN gpg --import KEYS && \
(gpg --fingerprint [email protected] | grep "673F E406 1506 BB46 9A0E F857 BE39 7A52 B086 DA5A")

# Verify the downloaded binary
# Verify the downloaded tarball, extract it, and fixup the binary
RUN MP_ARCH=`echo ${TARGETARCH} | sed s/amd64/x86_64/` && \
gpg --verify mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.rpm.asc && \
gpg --verify mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.deb.asc && \
mv mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.rpm /mount-s3.rpm && \
mv mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.deb /mount-s3.deb
gpg --verify mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.tar.gz.asc && \
mkdir -p /mountpoint-s3 && \
tar -xvzf mount-s3-${MOUNTPOINT_VERSION}-$MP_ARCH.tar.gz -C /mountpoint-s3 && \
# strip debugging information to reduce binary size
strip --strip-debug /mountpoint-s3/bin/mount-s3 && \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how many MBs we're saving with that? is it a good trade-off? as I understand this will make MPs traces unreadable

Copy link
Contributor

@vladem vladem Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also taking into the account that MP operational runbooks may rely on this info

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The binary goes from 55 MB to 12, so it's not insignificant. I will double check with the mountpoint team though.

# set rpath for dynamic library loading
patchelf --set-rpath '$ORIGIN' /mountpoint-s3/bin/mount-s3

# Build driver
FROM --platform=$BUILDPLATFORM golang:1.21.1-bullseye as builder
# Build driver. Use BUILDPLATFORM not TARGETPLATFORM for cross compilation
FROM --platform=$BUILDPLATFORM public.ecr.aws/docker/library/golang:1.21-bullseye as builder
ARG TARGETARCH

WORKDIR /go/src/github.com/awslabs/mountpoint-s3-csi-driver
COPY . .
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg/mod \
TARGETARCH=${TARGETARCH} make bin

FROM --platform=$TARGETPLATFORM public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-csi:latest-al2 AS linux-amazon
FROM --platform=$TARGETPLATFORM public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-csi:latest AS linux-amazon
ARG MOUNTPOINT_VERSION
ENV MOUNTPOINT_VERSION=${MOUNTPOINT_VERSION}

# MP Installer
COPY --from=mp_builder /mount-s3.rpm /mount-s3.rpm
COPY --from=mp_builder /mount-s3.deb /mount-s3.deb
COPY --from=mp_builder /mountpoint-s3 /mountpoint-s3
COPY --from=mp_builder /lib64/libfuse.so.2 /mountpoint-s3/bin/
COPY --from=mp_builder /lib64/libgcc_s.so.1 /mountpoint-s3/bin/
COPY ./cmd/install-mp.sh /install-mp.sh

# Install driver
Expand Down
12 changes: 5 additions & 7 deletions charts/aws-s3-csi-driver/templates/node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ spec:
{{- end }}
initContainers:
- name: install-mountpoint
securityContext:
privileged: true
image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }}
imagePullPolicy: IfNotPresent
command:
Expand Down Expand Up @@ -81,8 +79,8 @@ spec:
mountPropagation: "Bidirectional"
- name: plugin-dir
mountPath: /csi
- name: host-dbus
mountPath: /var/run/dbus
- name: systemd-bus
mountPath: /run/systemd/private
- name: host-dev
mountPath: /hostdev
ports:
Expand Down Expand Up @@ -141,10 +139,10 @@ spec:
hostPath:
path: /dev/
type: Directory
- name: host-dbus
- name: systemd-bus
hostPath:
path: /var/run/dbus/
type: Directory
path: /run/systemd/private
type: Socket
- name: kubelet-dir
hostPath:
path: /var/lib/kubelet
Expand Down
72 changes: 1 addition & 71 deletions cmd/install-mp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,5 @@

set -euox pipefail

NSENTER_HOST="nsenter --target 1 --mount --net"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep glad to see this go. It was gross. And now we don't have to run with hostPID: true

CSI_DIR="/csi/"
HOST_CSI_DIR="/var/lib/kubelet/plugins/s3.csi.aws.com/"
RPM_FILE=mount-s3.rpm
DEB_FILE=mount-s3.deb

get_os_info() {
local key=$1
local value=$($NSENTER_HOST cat /etc/os-release | grep "^$key=" | cut -d= -f2-)
# Remove potential quotes around the value
echo ${value//\"/}
}

# Determine the package manager based on the ID_LIKE or ID from os-release
determine_package_manager() {
local id_like=$(get_os_info ID_LIKE)
local id=$(get_os_info ID)

if [[ "$id_like" == *"debian"* || "$id" == "debian" || "$id" == "ubuntu" ]]; then
echo "apt"
elif [[ "$id_like" == *"fedora"* || "$id_like" == *"rhel"* || "$id" == "fedora" || "$id" == "centos" ]]; then
echo "yum"
else
echo "unknown"
fi
}

cleanup_rpm() {
rm -f "${CSI_DIR}${RPM_FILE}"
}

cleanup_deb() {
rm -f "${CSI_DIR}${DEB_FILE}"
}

install_mountpoint_rpm() {
echo "Using yum to install S3 Mountpoint..."
local rpm_package_name=$(rpm -qp --queryformat '%{NAME}\n' "/${RPM_FILE}")
local installed_mp_version=$($NSENTER_HOST rpm -q --queryformat '%{VERSION}-%{RELEASE}\n' "${rpm_package_name}" || true)
local package_mp_version=$(rpm -qp --queryformat '%{VERSION}-%{RELEASE}\n' "/${RPM_FILE}")
echo "Installed S3 Mountpoint version: ${installed_mp_version}"
echo "Package S3 Mountpoint version: ${package_mp_version}"

if [[ "${installed_mp_version}" != "${package_mp_version}" ]]; then
cp "/${RPM_FILE}" "${CSI_DIR}${RPM_FILE}"
trap cleanup_rpm EXIT SIGINT SIGTERM
# If install fails try downgrade
$NSENTER_HOST yum install -y "${HOST_CSI_DIR}${RPM_FILE}" || \
$NSENTER_HOST yum downgrade -y "${HOST_CSI_DIR}${RPM_FILE}"
else
echo "S3 Mountpoint already up to date"
fi
}

install_mountpoint_deb() {
echo "Using apt to install S3 Mountpoint..."
$NSENTER_HOST apt-get update
cp "/${DEB_FILE}" "${CSI_DIR}${DEB_FILE}"
trap cleanup_deb EXIT SIGINT SIGTERM
$NSENTER_HOST apt-get install -y --allow-downgrades "${HOST_CSI_DIR}${DEB_FILE}"
}

package_manager=$(determine_package_manager)

if [ "$package_manager" == "apt" ]; then
install_mountpoint_deb
elif [ "$package_manager" == "yum" ]; then
install_mountpoint_rpm
else
echo "Package manager not supported or not detected."
exit 1
fi
cp -rf "/mountpoint-s3" "${CSI_DIR}"
22 changes: 8 additions & 14 deletions deploy/kubernetes/base/node-daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ spec:
spec:
nodeSelector:
kubernetes.io/os: linux
hostPID: true
serviceAccountName: s3-csi-driver-sa
priorityClassName: system-node-critical
tolerations:
Expand All @@ -29,9 +28,8 @@ spec:
tolerationSeconds: 300
initContainers:
- name: install-mountpoint
securityContext:
privileged: true
image: csi-driver
imagePullPolicy: IfNotPresent
command:
- "/install-mp.sh"
volumeMounts:
Expand All @@ -42,6 +40,7 @@ spec:
securityContext:
privileged: true
image: csi-driver
imagePullPolicy: IfNotPresent
args:
- --endpoint=$(CSI_ENDPOINT)
- --logtostderr
Expand Down Expand Up @@ -71,10 +70,8 @@ spec:
mountPropagation: "Bidirectional"
- name: plugin-dir
mountPath: /csi
- name: aws-credentials
mountPath: /root/.aws
- name: host-dbus
mountPath: /var/run/dbus
- name: systemd-bus
mountPath: /run/systemd/private
- name: host-dev
mountPath: /hostdev
ports:
Expand Down Expand Up @@ -123,13 +120,13 @@ spec:
hostPath:
path: /dev/
type: Directory
- name: host-dbus
- name: systemd-bus
hostPath:
path: /var/run/dbus/
type: Directory
path: /run/systemd/private
type: Socket
- name: kubelet-dir
hostPath:
path: /var/lib/kubelet
path: /var/lib/kubelet/
type: Directory
- name: registration-dir
hostPath:
Expand All @@ -139,6 +136,3 @@ spec:
hostPath:
path: /var/lib/kubelet/plugins/s3.csi.aws.com/
type: DirectoryOrCreate
- name: aws-credentials
secret:
secretName: aws-credentials
6 changes: 4 additions & 2 deletions pkg/driver/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
const (
keyIdEnv = "AWS_ACCESS_KEY_ID"
accessKeyEnv = "AWS_SECRET_ACCESS_KEY"
pluginDir = "/var/lib/kubelet/plugins/s3.csi.aws.com"
)

// Mounter is an interface for mount operations
Expand Down Expand Up @@ -98,8 +99,9 @@ func (m *S3Mounter) Mount(source string, target string, _ string, options []stri
env = append(env, keyIdEnv+"="+keyId)
env = append(env, accessKeyEnv+"="+accessKey)
}
output, err := m.runner.Run(timeoutCtx, "/usr/bin/mount-s3", m.mpVersion+"-"+uuid.New().String(),
env, append([]string{source, target}, options...))

output, err := m.runner.Run(timeoutCtx, pluginDir+"/mountpoint-s3/bin/mount-s3",
m.mpVersion+"-"+uuid.New().String(), env, append([]string{source, target}, options...))
if err != nil {
return fmt.Errorf("Mount failed: %w mount-s3 output: %s", err, output)
}
Expand Down
8 changes: 5 additions & 3 deletions pkg/driver/systemd.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"unsafe"

systemd "github.com/coreos/go-systemd/v22/dbus"
unit "github.com/coreos/go-systemd/v22/unit"
dbus "github.com/godbus/dbus/v5"
"golang.org/x/sys/unix"
)
Expand All @@ -34,7 +35,7 @@ type SystemdConnector interface {
type osSystemdConnector struct{}

func (o *osSystemdConnector) Connect(ctx context.Context) (SystemdConnection, error) {
return systemd.NewSystemConnectionContext(ctx)
return systemd.NewSystemdConnectionContext(ctx)
}

func NewOsSystemd() SystemdConnector {
Expand Down Expand Up @@ -75,7 +76,7 @@ func (sr *SystemdRunner) Run(ctx context.Context, cmd string, serviceTag string,
defer ptsMaster.Close()

props := []systemd.Property{
systemd.PropDescription("Mountpoint for S3 CSI driver FUSE daemon"),
systemd.PropDescription("Mountpoint for S3 CSI driver"),
systemd.PropType("forking"),
// Use a tty to capture stdout/stderr. Older versions of systemd do not support options like named pipes
{Name: "StandardOutput", Value: dbus.MakeVariant("tty")},
Expand All @@ -88,7 +89,7 @@ func (sr *SystemdRunner) Run(ctx context.Context, cmd string, serviceTag string,
}

// Unit names must be unique in systemd, so include a tag
serviceName := filepath.Base(cmd) + "-" + serviceTag + ".service"
serviceName := unit.UnitNamePathEscape(filepath.Base(cmd) + "-" + serviceTag + ".service")

respChan := make(chan string, 1)
defer close(respChan)
Expand Down Expand Up @@ -131,6 +132,7 @@ func (sr *SystemdRunner) Run(ctx context.Context, cmd string, serviceTag string,
unitFound := false
for _, status := range statuses {
if status.Name == serviceName {
// Service is active, success
if status.ActiveState == "active" {
return readOutput(), nil
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/driver/systemd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import (
driver "github.com/awslabs/aws-s3-csi-driver/pkg/driver"
mock_driver "github.com/awslabs/aws-s3-csi-driver/pkg/driver/mocks"
systemd "github.com/coreos/go-systemd/v22/dbus"
"github.com/coreos/go-systemd/v22/unit"
dbus "github.com/godbus/dbus/v5"
"github.com/golang/mock/gomock"
)

const (
var (
testExe = "/usr/bin/testmount"
testTag = "1.0.0-abcd"
testServiceName = "testmount-1.0.0-abcd.service"
testServiceName = unit.UnitNamePathEscape("testmount-1.0.0-abcd.service")
)

type systemRunnerTestEnv struct {
Expand Down Expand Up @@ -149,7 +150,7 @@ func TestSystemdRunSuccess(t *testing.T) {
ctx := context.Background()

expectedProps := []systemd.Property{
systemd.PropDescription("Mountpoint for S3 CSI driver FUSE daemon"),
systemd.PropDescription("Mountpoint for S3 CSI driver"),
systemd.PropType("forking"),
{Name: "StandardOutput", Value: dbus.MakeVariant("tty")},
{Name: "StandardError", Value: dbus.MakeVariant("tty")},
Expand Down