Remove s3ql
s3ql does not work very well in a dynamic environment like k8s. Also as it needs a ton of dependencies just to get it built makes it hard to maintain.
This commit is contained in:
parent
76fc704c31
commit
f80104f215
10 changed files with 35 additions and 211 deletions
7
Makefile
7
Makefile
|
@ -16,8 +16,9 @@
|
||||||
PROJECT_DIR=/app
|
PROJECT_DIR=/app
|
||||||
REGISTRY_NAME=ctrox
|
REGISTRY_NAME=ctrox
|
||||||
IMAGE_NAME=csi-s3
|
IMAGE_NAME=csi-s3
|
||||||
IMAGE_VERSION=1.0.1-alpha
|
VERSION ?= dev
|
||||||
IMAGE_TAG=$(REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_VERSION)
|
IMAGE_TAG=$(REGISTRY_NAME)/$(IMAGE_NAME):$(VERSION)
|
||||||
|
FULL_IMAGE_TAG=$(IMAGE_TAG)-full
|
||||||
TEST_IMAGE_TAG=$(REGISTRY_NAME)/$(IMAGE_NAME):test
|
TEST_IMAGE_TAG=$(REGISTRY_NAME)/$(IMAGE_NAME):test
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
@ -27,8 +28,10 @@ test:
|
||||||
docker run --rm --privileged -v $(PWD):$(PROJECT_DIR) --device /dev/fuse $(TEST_IMAGE_TAG)
|
docker run --rm --privileged -v $(PWD):$(PROJECT_DIR) --device /dev/fuse $(TEST_IMAGE_TAG)
|
||||||
container: build
|
container: build
|
||||||
docker build -t $(IMAGE_TAG) -f cmd/s3driver/Dockerfile .
|
docker build -t $(IMAGE_TAG) -f cmd/s3driver/Dockerfile .
|
||||||
|
docker build -t $(FULL_IMAGE_TAG) --build-arg VERSION=$(VERSION) -f cmd/s3driver/Dockerfile.full .
|
||||||
push: container
|
push: container
|
||||||
docker push $(IMAGE_TAG)
|
docker push $(IMAGE_TAG)
|
||||||
|
docker push $(FULL_IMAGE_TAG)
|
||||||
clean:
|
clean:
|
||||||
go clean -r -x
|
go clean -r -x
|
||||||
-rm -rf _output
|
-rm -rf _output
|
||||||
|
|
26
README.md
26
README.md
|
@ -10,14 +10,12 @@ This is still very experimental and should not be used in any production environ
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
* Kubernetes 1.13+
|
* Kubernetes 1.13+ (CSI v1.0.0 compatibility)
|
||||||
* Kubernetes has to allow privileged containers
|
* Kubernetes has to allow privileged containers
|
||||||
* Docker daemon must allow shared mounts (systemd flag `MountFlags=shared`)
|
* Docker daemon must allow shared mounts (systemd flag `MountFlags=shared`)
|
||||||
|
|
||||||
### 1. Create a secret with your S3 credentials
|
### 1. Create a secret with your S3 credentials
|
||||||
|
|
||||||
The endpoint is optional if you are using something else than AWS S3. Also the region can be empty if you are using some other S3 compatible storage.
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
|
@ -30,11 +28,10 @@ stringData:
|
||||||
endpoint: <S3_ENDPOINT_URL>
|
endpoint: <S3_ENDPOINT_URL>
|
||||||
# If not on S3, set it to ""
|
# If not on S3, set it to ""
|
||||||
region: <S3_REGION>
|
region: <S3_REGION>
|
||||||
# Currently only for s3ql
|
|
||||||
# If not using s3ql, set it to ""
|
|
||||||
encryptionKey: <FS_ENCRYPTION_KEY>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The region can be empty if you are using some other S3 compatible storage.
|
||||||
|
|
||||||
### 2. Deploy the driver
|
### 2. Deploy the driver
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -63,7 +60,7 @@ kubectl create -f pvc.yaml
|
||||||
```bash
|
```bash
|
||||||
$ kubectl get pvc csi-s3-pvc
|
$ kubectl get pvc csi-s3-pvc
|
||||||
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
|
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
|
||||||
csi-s3-pvc Bound pvc-c5d4634f-8507-11e8-9f33-0e243832354b 5Gi RWX csi-s3 9s
|
csi-s3-pvc Bound pvc-c5d4634f-8507-11e8-9f33-0e243832354b 5Gi RWO csi-s3 9s
|
||||||
```
|
```
|
||||||
|
|
||||||
* Create a test pod which mounts your volume:
|
* Create a test pod which mounts your volume:
|
||||||
|
@ -96,7 +93,6 @@ The driver can be configured to use one of these mounters to mount buckets:
|
||||||
* [rclone](https://rclone.org/commands/rclone_mount)
|
* [rclone](https://rclone.org/commands/rclone_mount)
|
||||||
* [s3fs](https://github.com/s3fs-fuse/s3fs-fuse)
|
* [s3fs](https://github.com/s3fs-fuse/s3fs-fuse)
|
||||||
* [goofys](https://github.com/kahing/goofys)
|
* [goofys](https://github.com/kahing/goofys)
|
||||||
* [s3ql](https://github.com/s3ql/s3ql)
|
|
||||||
* [s3backer](https://github.com/archiecobbs/s3backer)
|
* [s3backer](https://github.com/archiecobbs/s3backer)
|
||||||
|
|
||||||
The mounter can be set as a parameter in the storage class. You can also create multiple storage classes for each mounter if you like.
|
The mounter can be set as a parameter in the storage class. You can also create multiple storage classes for each mounter if you like.
|
||||||
|
@ -121,16 +117,7 @@ All mounters have different strengths and weaknesses depending on your use case.
|
||||||
* Files can be viewed normally with any S3 client
|
* Files can be viewed normally with any S3 client
|
||||||
* Does not support appends or random writes
|
* Does not support appends or random writes
|
||||||
|
|
||||||
#### s3ql (not recommended*)
|
#### s3backer (experimental*)
|
||||||
|
|
||||||
* (Almost) full POSIX compatibility
|
|
||||||
* Uses its own object format
|
|
||||||
* Files are not readable with other S3 clients
|
|
||||||
* Support appends
|
|
||||||
* Supports compression before upload
|
|
||||||
* Supports encryption before upload
|
|
||||||
|
|
||||||
#### s3backer (not recommended*)
|
|
||||||
|
|
||||||
* Represents a block device stored on S3
|
* Represents a block device stored on S3
|
||||||
* Allows to use a real filesystem
|
* Allows to use a real filesystem
|
||||||
|
@ -139,7 +126,8 @@ All mounters have different strengths and weaknesses depending on your use case.
|
||||||
* Supports compression before upload (Not yet implemented in this driver)
|
* Supports compression before upload (Not yet implemented in this driver)
|
||||||
* Supports encryption before upload (Not yet implemented in this driver)
|
* Supports encryption before upload (Not yet implemented in this driver)
|
||||||
|
|
||||||
*s3ql and s3backer are not recommended at this point because volume corruption can occur pretty quickly in case of an unexpected shutdown of a Kubernetes node or CSI pod.
|
*s3backer is experimental at this point because volume corruption can occur pretty quickly in case of an unexpected shutdown of a Kubernetes node or CSI pod.
|
||||||
|
The s3backer binary is not bundled with the normal docker image to keep that as small as possible. Use the `<version>-full` image tag for testing s3backer.
|
||||||
|
|
||||||
Fore more detailed limitations consult the documentation of the different projects.
|
Fore more detailed limitations consult the documentation of the different projects.
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,16 @@ FROM debian:stretch
|
||||||
LABEL maintainers="Cyrill Troxler <cyrilltroxler@gmail.com>"
|
LABEL maintainers="Cyrill Troxler <cyrilltroxler@gmail.com>"
|
||||||
LABEL description="csi-s3 slim image"
|
LABEL description="csi-s3 slim image"
|
||||||
|
|
||||||
|
# s3fs and some other dependencies
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
s3fs wget unzip && \
|
s3fs curl unzip && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# install rclone
|
# install rclone
|
||||||
ARG RCLONE_VERSION=v1.46
|
ARG RCLONE_VERSION=v1.47.0
|
||||||
RUN cd /tmp \
|
RUN cd /tmp \
|
||||||
&& wget -q https://downloads.rclone.org/${RCLONE_VERSION}/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
&& curl -O https://downloads.rclone.org/${RCLONE_VERSION}/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
||||||
&& unzip /tmp/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
&& unzip /tmp/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
||||||
&& mv /tmp/rclone-*-linux-amd64/rclone /usr/bin \
|
&& mv /tmp/rclone-*-linux-amd64/rclone /usr/bin \
|
||||||
&& rm -r /tmp/rclone*
|
&& rm -r /tmp/rclone*
|
||||||
|
|
|
@ -1,16 +1,3 @@
|
||||||
FROM python:3.6 as s3ql-deps
|
|
||||||
LABEL maintainers="Cyrill Troxler <cyrilltroxler@gmail.com>"
|
|
||||||
LABEL description="s3ql dependencies"
|
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y \
|
|
||||||
python3 python3-setuptools \
|
|
||||||
python3-dev python3-pip pkg-config cython \
|
|
||||||
libfuse-dev libattr1-dev && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN pip3 install llfuse apsw defusedxml dugong requests pycrypto
|
|
||||||
|
|
||||||
FROM debian:stretch as s3backer
|
FROM debian:stretch as s3backer
|
||||||
ARG S3BACKER_VERSION=1.5.0
|
ARG S3BACKER_VERSION=1.5.0
|
||||||
|
|
||||||
|
@ -33,36 +20,29 @@ WORKDIR /src/s3backer
|
||||||
RUN git checkout tags/${S3BACKER_VERSION}
|
RUN git checkout tags/${S3BACKER_VERSION}
|
||||||
|
|
||||||
RUN ./autogen.sh && \
|
RUN ./autogen.sh && \
|
||||||
./configure && \
|
./configure && \
|
||||||
make && \
|
make && \
|
||||||
make install
|
make install
|
||||||
|
|
||||||
FROM python:3.6-slim
|
FROM debian:stretch
|
||||||
LABEL maintainers="Cyrill Troxler <cyrilltroxler@gmail.com>"
|
LABEL maintainers="Cyrill Troxler <cyrilltroxler@gmail.com>"
|
||||||
LABEL description="csi-s3 full image"
|
LABEL description="csi-s3 image"
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y \
|
|
||||||
libfuse2 gcc sqlite3 libsqlite3-dev \
|
|
||||||
s3fs psmisc procps libcurl3 xfsprogs wget unzip && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
ARG S3QL_VERSION=2.29
|
|
||||||
ENV S3QL_URL=https://github.com/s3ql/s3ql/releases/download/release-${S3QL_VERSION}/s3ql-${S3QL_VERSION}.tar.bz2
|
|
||||||
|
|
||||||
COPY --from=s3ql-deps /root/.cache /root/.cache
|
|
||||||
COPY --from=s3ql-deps /usr/local/lib/python3.6/site-packages /usr/local/lib/python3.6/site-packages
|
|
||||||
RUN pip install ${S3QL_URL} && rm -rf /root/.cache
|
|
||||||
|
|
||||||
COPY --from=s3backer /usr/bin/s3backer /usr/bin/s3backer
|
COPY --from=s3backer /usr/bin/s3backer /usr/bin/s3backer
|
||||||
|
|
||||||
|
# s3fs and some other dependencies
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y \
|
||||||
|
libfuse2 gcc sqlite3 libsqlite3-dev \
|
||||||
|
s3fs psmisc procps libcurl3 xfsprogs curl unzip && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# install rclone
|
# install rclone
|
||||||
ARG RCLONE_VERSION=v1.46
|
ARG RCLONE_VERSION=v1.47.0
|
||||||
RUN cd /tmp \
|
RUN cd /tmp \
|
||||||
&& wget -q https://downloads.rclone.org/${RCLONE_VERSION}/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
&& curl -O https://downloads.rclone.org/${RCLONE_VERSION}/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
||||||
&& unzip /tmp/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
&& unzip /tmp/rclone-${RCLONE_VERSION}-linux-amd64.zip \
|
||||||
&& mv /tmp/rclone-*-linux-amd64/rclone /usr/bin \
|
&& mv /tmp/rclone-*-linux-amd64/rclone /usr/bin \
|
||||||
&& rm -r /tmp/rclone*
|
&& rm -r /tmp/rclone*
|
||||||
|
|
||||||
COPY ./_output/s3driver /s3driver
|
COPY ./_output/s3driver /s3driver
|
||||||
ENTRYPOINT ["/s3driver"]
|
ENTRYPOINT ["/s3driver"]
|
||||||
|
|
|
@ -9,6 +9,3 @@ stringData:
|
||||||
endpoint: https://s3.eu-central-1.amazonaws.com
|
endpoint: https://s3.eu-central-1.amazonaws.com
|
||||||
# If not on S3, set it to ""
|
# If not on S3, set it to ""
|
||||||
region: <S3_REGION>
|
region: <S3_REGION>
|
||||||
# Currently only for s3ql
|
|
||||||
# If not using s3ql, set it to ""
|
|
||||||
encryptionKey: ""
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ metadata:
|
||||||
provisioner: ch.ctrox.csi.s3-driver
|
provisioner: ch.ctrox.csi.s3-driver
|
||||||
parameters:
|
parameters:
|
||||||
# specify which mounter to use
|
# specify which mounter to use
|
||||||
# can be set to s3backer, s3ql, s3fs or goofys
|
# can be set to rclone, s3fs, goofys or s3backer
|
||||||
mounter: rclone
|
mounter: rclone
|
||||||
csi.storage.k8s.io/provisioner-secret-name: csi-s3-secret
|
csi.storage.k8s.io/provisioner-secret-name: csi-s3-secret
|
||||||
csi.storage.k8s.io/provisioner-secret-namespace: kube-system
|
csi.storage.k8s.io/provisioner-secret-namespace: kube-system
|
||||||
|
|
|
@ -20,7 +20,6 @@ type Mounter interface {
|
||||||
const (
|
const (
|
||||||
s3fsMounterType = "s3fs"
|
s3fsMounterType = "s3fs"
|
||||||
goofysMounterType = "goofys"
|
goofysMounterType = "goofys"
|
||||||
s3qlMounterType = "s3ql"
|
|
||||||
s3backerMounterType = "s3backer"
|
s3backerMounterType = "s3backer"
|
||||||
rcloneMounterType = "rclone"
|
rcloneMounterType = "rclone"
|
||||||
mounterTypeKey = "mounter"
|
mounterTypeKey = "mounter"
|
||||||
|
@ -40,9 +39,6 @@ func newMounter(bucket *bucket, cfg *Config) (Mounter, error) {
|
||||||
case goofysMounterType:
|
case goofysMounterType:
|
||||||
return newGoofysMounter(bucket, cfg)
|
return newGoofysMounter(bucket, cfg)
|
||||||
|
|
||||||
case s3qlMounterType:
|
|
||||||
return newS3qlMounter(bucket, cfg)
|
|
||||||
|
|
||||||
case s3backerMounterType:
|
case s3backerMounterType:
|
||||||
return newS3backerMounter(bucket, cfg)
|
return newS3backerMounter(bucket, cfg)
|
||||||
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
package s3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"gopkg.in/ini.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Implements Mounter
|
|
||||||
type s3qlMounter struct {
|
|
||||||
bucket *bucket
|
|
||||||
url string
|
|
||||||
bucketURL string
|
|
||||||
login string
|
|
||||||
password string
|
|
||||||
passphrase string
|
|
||||||
options []string
|
|
||||||
ssl bool
|
|
||||||
targetPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
s3qlCmdMkfs = "mkfs.s3ql"
|
|
||||||
s3qlCmdMount = "mount.s3ql"
|
|
||||||
s3qlCmdUnmount = "umount.s3ql"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newS3qlMounter(b *bucket, cfg *Config) (Mounter, error) {
|
|
||||||
url, err := url.Parse(cfg.Endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ssl := url.Scheme != "http"
|
|
||||||
if strings.Contains(url.Scheme, "http") {
|
|
||||||
url.Scheme = "s3c"
|
|
||||||
}
|
|
||||||
s3ql := &s3qlMounter{
|
|
||||||
bucket: b,
|
|
||||||
url: url.String(),
|
|
||||||
login: cfg.AccessKeyID,
|
|
||||||
password: cfg.SecretAccessKey,
|
|
||||||
passphrase: cfg.EncryptionKey,
|
|
||||||
ssl: ssl,
|
|
||||||
}
|
|
||||||
|
|
||||||
// s3ql requires a trailing slash or it will just
|
|
||||||
// prepend the fspath to the s3ql files
|
|
||||||
url.Path = path.Join(url.Path, b.Name, b.FSPath) + "/"
|
|
||||||
s3ql.bucketURL = url.String()
|
|
||||||
|
|
||||||
if !ssl {
|
|
||||||
s3ql.options = []string{"--backend-options", "no-ssl"}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s3ql, s3ql.writeConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s3ql *s3qlMounter) Stage(stagePath string) error {
|
|
||||||
// force creation to ignore existing data
|
|
||||||
args := []string{
|
|
||||||
s3ql.bucketURL,
|
|
||||||
"--force",
|
|
||||||
}
|
|
||||||
|
|
||||||
p := fmt.Sprintf("%s\n%s\n", s3ql.passphrase, s3ql.passphrase)
|
|
||||||
reader := bytes.NewReader([]byte(p))
|
|
||||||
cmd := exec.Command(s3qlCmdMkfs, append(args, s3ql.options...)...)
|
|
||||||
cmd.Stdin = reader
|
|
||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error running s3ql command: %s", out)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s3ql *s3qlMounter) Unstage(stagePath string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s3ql *s3qlMounter) Mount(source string, target string) error {
|
|
||||||
args := []string{
|
|
||||||
s3ql.bucketURL,
|
|
||||||
target,
|
|
||||||
"--allow-other",
|
|
||||||
}
|
|
||||||
return fuseMount(target, s3qlCmdMount, append(args, s3ql.options...))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s3ql *s3qlMounter) writeConfig() error {
|
|
||||||
s3qlIni := ini.Empty()
|
|
||||||
section, err := s3qlIni.NewSection("s3ql")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
section.NewKey("storage-url", s3ql.url)
|
|
||||||
section.NewKey("backend-login", s3ql.login)
|
|
||||||
section.NewKey("backend-password", s3ql.password)
|
|
||||||
section.NewKey("fs-passphrase", s3ql.passphrase)
|
|
||||||
|
|
||||||
authDir := os.Getenv("HOME") + "/.s3ql"
|
|
||||||
authFile := authDir + "/authinfo2"
|
|
||||||
os.Mkdir(authDir, 0700)
|
|
||||||
s3qlIni.SaveTo(authFile)
|
|
||||||
os.Chmod(authFile, 0600)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -65,33 +65,6 @@ var _ = Describe("S3Driver", func() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("s3ql", func() {
|
|
||||||
socket := "/tmp/csi-s3ql.sock"
|
|
||||||
csiEndpoint := "unix://" + socket
|
|
||||||
|
|
||||||
if err := os.Remove(socket); err != nil && !os.IsNotExist(err) {
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
}
|
|
||||||
driver, err := s3.NewS3("test-node", csiEndpoint)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
go driver.Run()
|
|
||||||
|
|
||||||
Describe("CSI sanity", func() {
|
|
||||||
sanityCfg := &sanity.Config{
|
|
||||||
TargetPath: os.TempDir() + "/s3ql-target",
|
|
||||||
StagingPath: os.TempDir() + "/s3ql-staging",
|
|
||||||
Address: csiEndpoint,
|
|
||||||
SecretsFile: "../../test/secret.yaml",
|
|
||||||
TestVolumeParameters: map[string]string{
|
|
||||||
"mounter": "s3ql",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
sanity.GinkgoTest(sanityCfg)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("s3backer", func() {
|
Context("s3backer", func() {
|
||||||
socket := "/tmp/csi-s3backer.sock"
|
socket := "/tmp/csi-s3backer.sock"
|
||||||
csiEndpoint := "unix://" + socket
|
csiEndpoint := "unix://" + socket
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM ctrox/csi-s3:dev
|
FROM ctrox/csi-s3:dev-full
|
||||||
LABEL maintainers="Cyrill Troxler <cyrilltroxler@gmail.com>"
|
LABEL maintainers="Cyrill Troxler <cyrilltroxler@gmail.com>"
|
||||||
LABEL description="csi-s3 testing image"
|
LABEL description="csi-s3 testing image"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue