Repository: fluid-cloudnative/fluid
Pull request #3779 (2024-04-03 04:23:32)

Add the tutotial about how to use vineyard runtime to accelerate the kubeflow pipelines.
### Ⅰ. Describe what this PR does

As titled.

fluid-e2e-bot[bot]: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
**Once this PR has been reviewed and has the lgtm label**, please assign trafalgarzzz for approval by writing `/assign @trafalgarzzz` in a comment. For more information see:[The Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=fluid-cloudnative%2Ffluid).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/fluid-cloudnative/fluid/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["trafalgarzzz"]} -->
fluid-e2e-bot[bot]: Hi @dashanji. Thanks for your PR.

I'm waiting for a [fluid-cloudnative](https://github.com/orgs/fluid-cloudnative/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/fluid-cloudnative/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=fluid-cloudnative%2Ffluid).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=fluid-cloudnative_fluid&pullRequest=3779) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [132 New issues](https://sonarcloud.io/project/issues?id=fluid-cloudnative_fluid&pullRequest=3779&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=fluid-cloudnative_fluid&pullRequest=3779&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [2 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=fluid-cloudnative_fluid&pullRequest=3779&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [23.6% Duplication on New Code](https://sonarcloud.io/component_measures?id=fluid-cloudnative_fluid&pullRequest=3779&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=fluid-cloudnative_fluid&pullRequest=3779)


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/fluid-cloudnative/fluid/pull/3779?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fluid-cloudnative) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 64.28%. Comparing base [(`569dd49`)](https://app.codecov.io/gh/fluid-cloudnative/fluid/commit/569dd49a5f1dbf35bc8b3f3975011305fc81cdac?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fluid-cloudnative) to head [(`ec2e0da`)](https://app.codecov.io/gh/fluid-cloudnative/fluid/pull/3779?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fluid-cloudnative).


<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #3779   +/-   ##
=======================================
  Coverage   64.28%   64.28%           
=======================================
  Files         476      476           
  Lines       28312    28312           
=======================================
+ Hits        18199    18201    +2     
+ Misses       7947     7946    -1     
+ Partials     2166     2165    -1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/fluid-cloudnative/fluid/pull/3779?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fluid-cloudnative).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fluid-cloudnative).


Patch:
diff --git a/api/v1alpha1/dataprocess_types.go b/api/v1alpha1/dataprocess_types.go
index 70b426ef..5f4b44f7 100644
--- a/api/v1alpha1/dataprocess_types.go
+++ b/api/v1alpha1/dataprocess_types.go
@@ -96,7 +96,7 @@ type ScriptProcessor struct {
 // DataProcessSpec defines the desired state of DataProcess
 type DataProcessSpec struct {
 	// Dataset specifies the target dataset and its mount path.
-	// +requried
+	// +required
 	Dataset TargetDatasetWithMountPath `json:"dataset"`
 
 	// Processor specify how to process data.
diff --git a/charts/fluid/fluid/Chart.yaml b/charts/fluid/fluid/Chart.yaml
index c53aa99d..a7548f75 100644
--- a/charts/fluid/fluid/Chart.yaml
+++ b/charts/fluid/fluid/Chart.yaml
@@ -18,7 +18,7 @@ version: 1.0.0
 
 # This is the version number of the application being deployed. This version number should be
 # incremented each time you make changes to the application.
-appVersion: 1.0.0-10382d2
+appVersion: 1.0.0-4a2b2b8
 home: https://github.com/fluid-cloudnative/fluid
 keywords:
   - category:data
diff --git a/charts/fluid/fluid/templates/controller/vineyardruntime_controller.yaml b/charts/fluid/fluid/templates/controller/vineyardruntime_controller.yaml
index efaab4f0..55b26d52 100644
--- a/charts/fluid/fluid/templates/controller/vineyardruntime_controller.yaml
+++ b/charts/fluid/fluid/templates/controller/vineyardruntime_controller.yaml
@@ -60,6 +60,18 @@ spec:
         - name: MOUNT_ROOT
           value: {{ .Values.runtime.mountRoot | quote }}
         {{- end }}
+        {{- if .Values.runtime.vineyard.master.image }}
+        - name: VINEYARD_MASTER_IMAGE_ENV
+          value: {{ .Values.runtime.vineyard.master.image | quote }}
+        {{- end }}
+        {{- if .Values.runtime.vineyard.worker.image }}
+        - name: VINEYARD_WORKER_IMAGE_ENV
+          value: {{ .Values.runtime.vineyard.worker.image | quote }}
+        {{- end }}
+        {{- if .Values.runtime.vineyard.fuse.image }}
+        - name: VINEYARD_FUSE_IMAGE_ENV
+          value: {{ .Values.runtime.vineyard.fuse.image | quote }}
+        {{- end }}
         {{- if .Values.runtime.syncRetryDuration }}
         - name: FLUID_SYNC_RETRY_DURATION
           value: {{ .Values.runtime.syncRetryDuration | quote }}
diff --git a/charts/fluid/fluid/values.yaml b/charts/fluid/fluid/values.yaml
index fcac8ff7..cd81d59d 100644
--- a/charts/fluid/fluid/values.yaml
+++ b/charts/fluid/fluid/values.yaml
@@ -12,7 +12,7 @@ crdUpgrade:
   enabled: true
   # This sets the time-to-live (TTL) for crd-upgrade jobs. Default is 259200 seconds (3 days).
   ttlSecondsAfterFinished: 259200 
-  image: fluidcloudnative/fluid-crd-upgrader:v1.0.0-10382d2
+  image: fluidcloudnative/fluid-crd-upgrader:v1.0.0-4a2b2b8
 
 ##  if unspecified, will use built-in variable `.Release.Namespace`.
 namespace: fluid-system
@@ -25,7 +25,7 @@ dataset:
   tolerations:
     - operator: Exists
   controller:
-    image: fluidcloudnative/dataset-controller:v1.0.0-10382d2
+    image: fluidcloudnative/dataset-controller:v1.0.0-4a2b2b8
 
 csi:
   tolerations:
@@ -36,7 +36,7 @@ csi:
   registrar:
     image: fluidcloudnative/csi-node-driver-registrar:v2.3.0
   plugins:
-    image: fluidcloudnative/fluid-csi:v1.0.0-10382d2
+    image: fluidcloudnative/fluid-csi:v1.0.0-4a2b2b8
   kubelet:
     kubeConfigFile: /etc/kubernetes/kubelet.conf
     certDir: /var/lib/kubelet/pki
@@ -63,7 +63,7 @@ runtime:
     init:
       image: fluidcloudnative/init-users:v0.9.0
     controller:
-      image: fluidcloudnative/alluxioruntime-controller:v1.0.0-10382d2
+      image: fluidcloudnative/alluxioruntime-controller:v1.0.0-4a2b2b8
     runtime:
       image: alluxio/alluxio-dev:2.9.0
     fuse:
@@ -84,7 +84,7 @@ runtime:
     fuse:
       image: registry.cn-shanghai.aliyuncs.com/jindofs/jindo-fuse:6.2.0
     controller:
-      image: fluidcloudnative/jindoruntime-controller:v1.0.0-10382d2
+      image: fluidcloudnative/jindoruntime-controller:v1.0.0-4a2b2b8
     init:
       portCheck:
         enabled: false
@@ -100,7 +100,7 @@ runtime:
     init:
       image: fluidcloudnative/init-users:v0.9.0
     controller:
-      image: fluidcloudnative/goosefsruntime-controller:v1.0.0-10382d2
+      image: fluidcloudnative/goosefsruntime-controller:v1.0.0-4a2b2b8
     runtime:
       image: ccr.ccs.tencentyun.com/qcloud/goosefs:v1.2.0
     fuse:
@@ -112,7 +112,7 @@ runtime:
     enabled: false
     runtimeWorkers: 3
     controller:
-      image: fluidcloudnative/juicefsruntime-controller:v1.0.0-10382d2
+      image: fluidcloudnative/juicefsruntime-controller:v1.0.0-4a2b2b8
     fuse:
       ceimage: juicedata/juicefs-fuse:ce-v1.1.0-rc1
       eeimage: juicedata/juicefs-fuse:ee-4.9.16
@@ -122,7 +122,7 @@ runtime:
       - operator: Exists
     enabled: false
     controller:
-      image: fluidcloudnative/thinruntime-controller:v1.0.0-10382d2
+      image: fluidcloudnative/thinruntime-controller:v1.0.0-4a2b2b8
     fuse:
       configStorage: configmap
   efc:
@@ -131,7 +131,7 @@ runtime:
       - operator: Exists
     enabled: false
     controller:
-      image: fluidcloudnative/efcruntime-controller:v1.0.0-10382d2
+      image: fluidcloudnative/efcruntime-controller:v1.0.0-4a2b2b8
       imagePullPolicy: Always
     init:
       image: registry.cn-zhangjiakou.aliyuncs.com/nascache/init-alifuse:v1.2.2-19dcee9
@@ -147,12 +147,18 @@ runtime:
       - operator: Exists
     enabled: false
     controller:
-      image: fluidcloudnative/vineyardruntime-controller:v1.0.0-10382d2
+      image: fluidcloudnative/vineyardruntime-controller:v1.0.0-4a2b2b8
       imagePullPolicy: Always
+    master:
+      image: bitnami/etcd:3.5.10
+    worker:
+      image: vineyardcloudnative/vineyardd:v0.21.5
+    fuse:
+      image: vineyardcloudnative/vineyard-fluid-fuse:v0.21.5
 
 webhook:
   enabled: true
-  image: fluidcloudnative/fluid-webhook:v1.0.0-10382d2
+  image: fluidcloudnative/fluid-webhook:v1.0.0-4a2b2b8
   replicas: 1
   timeoutSeconds: 15
   reinvocationPolicy: IfNeeded
@@ -202,4 +208,4 @@ fluidapp:
   tolerations:
     - operator: Exists
   controller:
-    image: fluidcloudnative/application-controller:v1.0.0-10382d2
+    image: fluidcloudnative/application-controller:v1.0.0-4a2b2b8
diff --git a/cmd/alluxio/app/init.go b/cmd/alluxio/app/init.go
index d129a318..f492a467 100644
--- a/cmd/alluxio/app/init.go
+++ b/cmd/alluxio/app/init.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2021 The Fluid Authors.
+Copyright 2022 The Fluid Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
diff --git a/cmd/alluxio/app/version.go b/cmd/alluxio/app/version.go
index c1003351..f2270e40 100644
--- a/cmd/alluxio/app/version.go
+++ b/cmd/alluxio/app/version.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2021 The Fluid Authors.
+Copyright 2022 The Fluid Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
diff --git a/docs/en/samples/vineyard/accelerate_kubeflow_pipelines.md b/docs/en/samples/vineyard/accelerate_kubeflow_pipelines.md
new file mode 100644
index 00000000..d760af93
--- /dev/null
+++ b/docs/en/samples/vineyard/accelerate_kubeflow_pipelines.md
@@ -0,0 +1,241 @@
+## Use vineyard runtime to accelerate kubeflow pipelines
+
+Vineyard can accelerate data sharing by utilizing shared memory compared to existing methods such as local files or S3 services. In this doc, we will show you how to use vineyard runtime to accelerate an existing kubeflow pipeline on the fluid platform.
+
+### Prerequisites
+
+- Install the argo CLI tool via the [official guide](https://github.com/argoproj/argo-workflows/releases/).
+
+
+### Overview of the pipeline
+
+The pipeline we use is a simple pipeline that trains a linear regression model on the dummy Boston Housing Dataset. It contains three steps: [preprocess](../../../../samples/vineyard/preprocess-data/preprocess-data.y), [train](../../../../samples/vineyard/train-data/train-data.py), and [test](../../../../samples/vineyard/test-data/test-data.py).
+
+
+### Prepare the environment
+
+- Prepare a kubernetes cluster. If you don't have a kubernetes cluster on hand, you can use the following command to create a kubernetes cluster via kind(v0.20.0+):
+
+```shell
+cat <<EOF | kind create cluster -v 5 --name=kind --config=-
+kind: Cluster
+apiVersion: kind.x-k8s.io/v1alpha4
+nodes:
+- role: control-plane
+  image: kindest/node:v1.23.0
+- role: worker
+  image: kindest/node:v1.23.0
+- role: worker
+  image: kindest/node:v1.23.0
+- role: worker
+  image: kindest/node:v1.23.0
+EOF
+```
+
+- Prepare the docker images of the kubeflow pipeline. You can use the following command to build the docker image:
+
+```shell
+$ make docker-build REGISTRY="test-registry"(Replace with your custom registry)
+```
+
+Then you can push these images to the registry that your kubernetes cluster can access or load these images to the cluster if your kubernetes cluster is created by kind.
+
+```shell
+$ make load-images REGISTRY="test-registry"(Replace with your custom registry)
+```
+
+or
+
+```shell
+$ make push-images REGISTRY="test-registry"(Replace with your custom registry)
+```
+
+### Install the fluid platform and kubeflow components
+
+- Refer to the [Installation Documentation](../../../userguide/install.md) to complete the installation.
+
+- Install the argo workflow controller, which can be used as the backend of kubeflow pipeline. You can use the following command to install the argo workflow controller:
+
+```shell
+$ kubectl create ns argo
+$ kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.4.8/install.yaml
+```
+
+- Install the vineyard runtime and dataset. You can use the following command to install the vineyard runtime and dataset:
+
+```shell
+$ cat <<EOF | kubectl apply -f -
+apiVersion: data.fluid.io/v1alpha1
+kind: VineyardRuntime
+metadata:
+  name: vineyard
+spec:
+  replicas: 2
+  tieredstore:
+    levels:
+    - mediumtype: MEM
+      quota: 20Gi
+---
+apiVersion: data.fluid.io/v1alpha1
+kind: Dataset
+metadata:
+  name: vineyard
+EOF
+```
+
+### Run the pipeline
+
+Please make sure the `samples/vineyard/pipeline.yaml` and `samples/vineyard/pipeline-with-vineyard.yaml` files are the original 
+ones as they have been modified to use the privileged 
+container to clear the page cache. Then you can follow
+the next steps to run the pipeline:
+
+**Notice** You need to mount a **NAS path** to the kubernetes node.
+Here we mount a NAS path to the `/mnt/csi-benchmark`(shown in the `prepare-data.yaml`) path of all kubernetes nodes.
+Next, we need to prepare the dataset by running the following command:
+
+```shell
+$ kubectl apply -f samples/vineyard/prepare-data.yaml
+```
+
+The dataset will be stored in the host path. Also, you may need to wait for a while for the dataset to be generated and you can use the following command to check the status:
+
+```shell
+$ while ! kubectl logs -l app=prepare-data | grep "preparing data time" >/dev/null; do echo "dataset unready, waiting..."; sleep 5; done && echo "dataset ready"
+```
+
+Before running the pipeline, we need to create the role and rolebinding for the pipeline as follows.
+
+```shell
+$ kubectl apply -f samples/vineyard/rbac.yaml
+```
+
+After that, you can run the pipeline via the following command:
+
+Without vineyard:
+
+```shell
+$ argo submit samples/vineyard/pipeline.yaml -p data_mu
+ltiplier=2000 -p registry="test-registry" 
+Name:                machine-learning-pipeline-z72gm
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Pending
+Created:             Wed Apr 03 11:46:43 +0800 (now)
+Progress:            
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+```
+
+The result is shown as follows:
+
+```shell
+$ argo get machine-learning-pipeline-z72gm                                           
+Name:                machine-learning-pipeline-z72gm
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Succeeded
+Conditions:          
+ PodRunning          False
+ Completed           True
+Created:             Wed Apr 03 11:46:43 +0800 (3 minutes ago)
+Started:             Wed Apr 03 11:46:43 +0800 (3 minutes ago)
+Finished:            Wed Apr 03 11:49:23 +0800 (49 seconds ago)
+Duration:            2 minutes 40 seconds
+Progress:            3/3
+ResourcesDuration:   4m8s*(1 cpu),4m8s*(100Mi memory)
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+
+STEP                                TEMPLATE                   PODNAME                                                     DURATION  MESSAGE
+ ✔ machine-learning-pipeline-z72gm  machine-learning-pipeline                                                                          
+ ├─✔ preprocess-data                preprocess-data            machine-learning-pipeline-z72gm-preprocess-data-4229626381  1m          
+ ├─✔ train-data                     train-data                 machine-learning-pipeline-z72gm-train-data-1389575193       45s         
+ └─✔ test-data                      test-data                  machine-learning-pipeline-z72gm-test-data-2535188255        13s
+```
+
+Before running the pipeline with vineyard, you need to enable the best effort scheduling for the vineyard runtime as follows:
+
+```shell
+# enable the fuse affinity scheduling
+$ kubectl edit configmap webhook-plugins -n fluid-system
+data:
+  pluginsProfile: |
+    pluginConfig:
+    - args: |
+        preferred:
+          - name: fluid.io/fuse
+            weight: 100
+    ...
+
+# Restart the fluid-webhook pod
+$ kubectl delete pod -lcontrol-plane=fluid-webhook -n fluid-system
+```
+
+Then you can run the pipeline with vineyard via the following command:
+
+```shell
+$ argo submit samples/vineyard/pipeline-with-vineyard.yaml -p data_multiplier=2000 -p registry="test-registry"
+Name:                machine-learning-pipeline-with-vineyard-q4tfr
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Pending
+Created:             Wed Apr 03 12:00:45 +0800 (now)
+Progress:            
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+```
+
+The result is shown as follows:
+
+```shell
+$ argo get machine-learning-pipeline-with-vineyard-q4tfr                               
+Name:                machine-learning-pipeline-with-vineyard-q4tfr
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Succeeded
+Conditions:          
+ PodRunning          False
+ Completed           True
+Created:             Wed Apr 03 12:00:45 +0800 (2 minutes ago)
+Started:             Wed Apr 03 12:00:45 +0800 (2 minutes ago)
+Finished:            Wed Apr 03 12:02:36 +0800 (34 seconds ago)
+Duration:            1 minute 51 seconds
+Progress:            3/3
+ResourcesDuration:   2m40s*(1 cpu),2m40s*(100Mi memory)
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+
+STEP                                              TEMPLATE                                 PODNAME                                                                  DURATION  MESSAGE
+ ✔ machine-learning-pipeline-with-vineyard-q4tfr  machine-learning-pipeline-with-vineyard                                                                                       
+ ├─✔ preprocess-data                              preprocess-data                          machine-learning-pipeline-with-vineyard-q4tfr-preprocess-data-869469459  55s         
+ ├─✔ train-data                                   train-data                               machine-learning-pipeline-with-vineyard-q4tfr-train-data-4177295571      26s         
+ └─✔ test-data                                    test-data                                machine-learning-pipeline-with-vineyard-q4tfr-test-data-1755965473       8s
+```
+
+From the results, it's evident that the pipeline utilizing vineyard reduces the running time by approximately 30% compared to the pipeline without vineyard. This improvement is due to vineyard's ability to accelerate data sharing by leveraging shared memory, which is more efficient than traditional methods such as NFS.
+
+### Modifications to use vineyard
+
+Compared to the original kubeflow pipeline, we could use the following command to check the differences:
+
+```shell
+$ git diff --no-index --unified=40 samples/vineyard/pipeline.py samples/vineyard/pipeline-with-vineyard.py
+```
+
+The main modifications are:
+- Add the vineyard persistent volume to the pipeline. This persistent volume is used to mount the vineyard client config file to the pipeline.
+
+Also, you can check the modifications of the source code as 
+follows.
+
+- [Save data to vineyard](../../../../samples/vineyard/preprocess-data/preprocess-data.py#L32-L35).
+- [Load data from vineyard](../../../../samples/vineyard/train-data/train-data.py#L15-L16).
+- [load data from vineyard](../../../../samples/vineyard/test-data/test-data.py#L14-L15).
+
+The main modification is to use vineyard to load and save data
+rather than using local files.
diff --git a/docs/en/samples/vineyard/vineyard_runtime.md b/docs/en/samples/vineyard/vineyard_runtime.md
index bc60cf8a..a73bb4c0 100644
--- a/docs/en/samples/vineyard/vineyard_runtime.md
+++ b/docs/en/samples/vineyard/vineyard_runtime.md
@@ -8,19 +8,7 @@ For more information on how to use Vineyard, see the [Vineyard Quick Start Guide
 
 ## Install Fluid
 
-You can download the latest Fluid installation package from [Fluid Releases](https://github.com/fluid-cloudnative/fluid/releases). Refer to the [Installation Documentation](../../userguide/install.md) to complete the installation. Check that all Fluid components are running properly:
-
-```shell
-$ kubectl get po -n fluid-system
-NAME                                         READY   STATUS              RESTARTS   AGE
-csi-nodeplugin-fluid-56d44                   2/2     Running             0          106s
-csi-nodeplugin-fluid-5l78j                   2/2     Running             0          106s
-csi-nodeplugin-fluid-5mghb                   2/2     Running             0          106s
-dataset-controller-5cd87f8b9b-t7dv2          1/1     Running             0          106s
-fluid-webhook-77d44f5fbc-wttzl               1/1     Running             0          106s
-```
-
-Ensure that the `dataset-controller`, `fluid-webhook` pods, and several `csi-nodeplugin` pods are running properly. The `vineyard-runtime-controller` will be dynamically created when using VineyardRuntime.
+Refer to the [Installation Documentation](../../userguide/install.md) to complete the installation.
 
 ## Create Vineyard Runtime and Dataset
 
@@ -35,7 +23,7 @@ spec:
   tieredstore:
     levels:
     - mediumtype: MEM
-    quota: 20Gi
+      quota: 20Gi
 ---
 apiVersion: data.fluid.io/v1alpha1
 kind: Dataset
diff --git a/docs/en/userguide/install.md b/docs/en/userguide/install.md
index bd06b838..f43273a5 100644
--- a/docs/en/userguide/install.md
+++ b/docs/en/userguide/install.md
@@ -111,7 +111,7 @@ csi-nodeplugin-fluid-2scs9               2/2     Running     0          50s
 csi-nodeplugin-fluid-7vflb               2/2     Running     0          20s
 csi-nodeplugin-fluid-f9xfv               2/2     Running     0          33s
 dataset-controller-686d9d9cd6-gk6m6      1/1     Running     0          50s
-fluid-crds-upgrade-0.9.0-37e17c6-fp4mm   0/1     Completed   0          74s
+fluid-crds-upgrade-1.0.0-37e17c6-fp4mm   0/1     Completed   0          74s
 fluid-webhook-5bc9dfb9d8-hdvhk           1/1     Running     0          50s
 fluidapp-controller-6d4cbdcd88-z7l4c     1/1     Running     0          50s
 ```
@@ -132,10 +132,10 @@ $ kubectl exec dataset-controller-558c5c7785-mtgfh -n fluid-system -- dataset-co
 
 The output should be like:
 ```
-  BuildDate: 2022-09-01_13:07:33
-  GitCommit: aa7fdca4c4306762280570b7dc0c2a7c649ff785
+  BuildDate: 2024-03-02_07:35:18
+  GitCommit: 50ee8887239f07592ba74af3e14379efc1487c0c
   GitTreeState: clean
-  GoVersion: go1.17.8
+  GoVersion: go1.18.10
   Compiler: gc
   Platform: linux/amd64
 ```
diff --git a/docs/zh/operation/monitoring.md b/docs/zh/operation/monitoring.md
index e0c358f4..0d2387d3 100644
--- a/docs/zh/operation/monitoring.md
+++ b/docs/zh/operation/monitoring.md
@@ -129,12 +129,12 @@ spec:
         quota: 1Gi
         high: "0.95"
         low: "0.7"
-  # 默认在v0.5.0版本之后，alluxio runtime已经开启了Prometheous数据，如果需要关闭可以主动设置disablePrometheus: true
+  # 默认在v0.5.0版本之后，alluxio runtime已经开启了Prometheus数据，如果需要关闭可以主动设置disablePrometheus: true
   # disablePrometheus: false  
 EOF
 ```
 
-> 注意：默认Prometheous是开启的。如果需要关闭Prometheous，可以设置 disablePrometheus: true, 默认为 false
+> 注意：默认Prometheus是开启的。如果需要关闭Prometheus，可以设置 disablePrometheus: true, 默认为 false
 
 6. 查看监控
 在 grafana HOME 中知道名为Fluid-Prometheus-Grafana-Monitor视图即可，如下所示:
diff --git a/docs/zh/samples/vineyard/accelerate_kubeflow_pipelines.md b/docs/zh/samples/vineyard/accelerate_kubeflow_pipelines.md
new file mode 100644
index 00000000..231b782e
--- /dev/null
+++ b/docs/zh/samples/vineyard/accelerate_kubeflow_pipelines.md
@@ -0,0 +1,231 @@
+## 使用Vineyard Runtime加速Kubeflow pipeline
+
+Vineyard相比现有方法如本地文件或S3服务, 可以通过利用共享内存加速数据共享。在本文中，我们将展示如何使用Vineyard Runtime来加速Fluid平台上现有的Kubeflow pipeline。
+
+### 前提条件
+
+- 安装 argo CLI 工具，参见[官方指南](https://github.com/argoproj/argo-workflows/releases/).
+
+### pipline概述
+
+目前我们使用的pipeline是一个简单的pipeline，它是在虚拟的波士顿房价数据集上训练一个线性回归模型。它包含三个步骤：[数据预处理](../../../../samples/vineyard/preprocess-data/preprocess-data.y), [模型训练](../../../../samples/vineyard/train-data/train-data.py), 和 [模型测试](../../../../samples/vineyard/test-data/test-data.py).
+
+
+### 准备环境
+
+- 准备一个kubernetes集群。如果您没有现成的kubernetes集群，您可以使用以下命令通过kind(v0.20.0+)创建一个kubernetes集群：
+
+```shell
+cat <<EOF | kind create cluster -v 5 --name=kind --config=-
+kind: Cluster
+apiVersion: kind.x-k8s.io/v1alpha4
+nodes:
+- role: control-plane
+  image: kindest/node:v1.23.0
+- role: worker
+  image: kindest/node:v1.23.0
+- role: worker
+  image: kindest/node:v1.23.0
+- role: worker
+  image: kindest/node:v1.23.0
+EOF
+```
+
+- 准备kubeflow pipeline的docker镜像。您可以使用以下命令构建docker镜像：
+
+```shell
+$ make docker-build REGISTRY="test-registry"(Replace with your custom registry)
+```
+
+接下来，您可以将这些镜像推送到您的kubernetes集群可以访问的镜像仓库，或者如果您的kubernetes集群是通过kind创建的，则可以将这些镜像加载到集群中。
+
+```shell
+$ make load-images REGISTRY="test-registry"(Replace with your custom registry)
+```
+
+or
+
+```shell
+$ make push-images REGISTRY="test-registry"(Replace with your custom registry)
+```
+
+### 安装fluid平台和kubeflow组件
+
+- 参考[安装文档](../../../userguide/install.md)完成安装。
+
+- 安装argo workflow控制器，它可以作为kubeflow pipeline的后端。您可以使用以下命令安装argo workflow控制器：
+
+```shell
+$ kubectl create ns argo
+$ kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.4.8/install.yaml
+```
+
+- 安装vineyard runtime和dataset。您可以使用以下命令安装vineyard runtime和dataset：
+
+```shell
+$ cat <<EOF | kubectl apply -f -
+apiVersion: data.fluid.io/v1alpha1
+kind: VineyardRuntime
+metadata:
+  name: vineyard
+spec:
+  replicas: 2
+  tieredstore:
+    levels:
+    - mediumtype: MEM
+      quota: 20Gi
+---
+apiVersion: data.fluid.io/v1alpha1
+kind: Dataset
+metadata:
+  name: vineyard
+EOF
+```
+
+### 运行pipeline
+
+请确保`pipeline.yaml`和`pipeline-with-vineyard.yaml`文件是原始的文件，因为它们已经被修改为使用特权容器来清除页面缓存。然后您可以按照下面的步骤运行pipeline：
+
+**注意** 您需要将**NAS路径**挂载到kubernetes节点。在这里，我们将NAS路径挂载到所有kubernetes节点的`/mnt/csi-benchmark`(在`prepare-data.yaml`中显示)路径上。接下来，我们需要通过运行以下命令来准备数据集：
+
+```shell
+$ kubectl apply -f samples/vineyard/prepare-data.yaml
+```
+
+数据集将存储在主机路径中。此外，您可能需要等待一段时间以生成数据集，您可以使用以下命令来检查状态：
+
+```shell
+$ while ! kubectl logs -l app=prepare-data | grep "preparing data time" >/dev/null; do echo "dataset unready, waiting..."; sleep 5; done && echo "dataset ready"
+```
+
+在运行pipeline之前，我们需要为pipeline创建一些rbac roles，如下所示。
+
+```shell
+$ kubectl apply -f samples/vineyard/rbac.yaml
+```
+
+之后，您可以通过以下命令运行不使用vineyard的pipeline：
+
+```shell
+$ argo submit samples/vineyard/pipeline.yaml -p data_mu
+ltiplier=2000 -p registry="test-registry" 
+Name:                machine-learning-pipeline-z72gm
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Pending
+Created:             Wed Apr 03 11:46:43 +0800 (now)
+Progress:            
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+```
+
+结果如下所示。
+
+```shell
+$ argo get machine-learning-pipeline-z72gm                                           
+Name:                machine-learning-pipeline-z72gm
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Succeeded
+Conditions:          
+ PodRunning          False
+ Completed           True
+Created:             Wed Apr 03 11:46:43 +0800 (3 minutes ago)
+Started:             Wed Apr 03 11:46:43 +0800 (3 minutes ago)
+Finished:            Wed Apr 03 11:49:23 +0800 (49 seconds ago)
+Duration:            2 minutes 40 seconds
+Progress:            3/3
+ResourcesDuration:   4m8s*(1 cpu),4m8s*(100Mi memory)
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+
+STEP                                TEMPLATE                   PODNAME                                                     DURATION  MESSAGE
+ ✔ machine-learning-pipeline-z72gm  machine-learning-pipeline                                                                          
+ ├─✔ preprocess-data                preprocess-data            machine-learning-pipeline-z72gm-preprocess-data-4229626381  1m          
+ ├─✔ train-data                     train-data                 machine-learning-pipeline-z72gm-train-data-1389575193       45s         
+ └─✔ test-data                      test-data                  machine-learning-pipeline-z72gm-test-data-2535188255        13s
+```
+
+在运行使用vineyard的pipeline之前，您需要为vineyard runtime启用最佳调度策略，如下所示：
+
+```shell
+# 开启fuse亲和性调度
+$ kubectl edit configmap webhook-plugins -n fluid-system
+data:
+  pluginsProfile: |
+    pluginConfig:
+    - args: |
+        preferred:
+          - name: fluid.io/fuse
+            weight: 100
+    ...
+
+# 重启fluid-webhook pod
+$ kubectl delete pod -lcontrol-plane=fluid-webhook -n fluid-system
+```
+
+接下来，您可以通过以下命令运行使用vineyard的pipeline：
+
+```shell
+$ argo submit samples/vineyard/pipeline-with-vineyard.yaml -p data_multiplier=2000 -p registry="test-registry"
+Name:                machine-learning-pipeline-with-vineyard-q4tfr
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Pending
+Created:             Wed Apr 03 12:00:45 +0800 (now)
+Progress:            
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+```
+
+结果如下所示。
+
+```shell
+$ argo get machine-learning-pipeline-with-vineyard-q4tfr                               
+Name:                machine-learning-pipeline-with-vineyard-q4tfr
+Namespace:           default
+ServiceAccount:      pipeline-runner
+Status:              Succeeded
+Conditions:          
+ PodRunning          False
+ Completed           True
+Created:             Wed Apr 03 12:00:45 +0800 (2 minutes ago)
+Started:             Wed Apr 03 12:00:45 +0800 (2 minutes ago)
+Finished:            Wed Apr 03 12:02:36 +0800 (34 seconds ago)
+Duration:            1 minute 51 seconds
+Progress:            3/3
+ResourcesDuration:   2m40s*(1 cpu),2m40s*(100Mi memory)
+Parameters:          
+  data_multiplier:   2000
+  registry:          test-registry
+
+STEP                                              TEMPLATE                                 PODNAME                                                                  DURATION  MESSAGE
+ ✔ machine-learning-pipeline-with-vineyard-q4tfr  machine-learning-pipeline-with-vineyard                                                                                       
+ ├─✔ preprocess-data                              preprocess-data                          machine-learning-pipeline-with-vineyard-q4tfr-preprocess-data-869469459  55s         
+ ├─✔ train-data                                   train-data                               machine-learning-pipeline-with-vineyard-q4tfr-train-data-4177295571      26s         
+ └─✔ test-data                                    test-data                                machine-learning-pipeline-with-vineyard-q4tfr-test-data-1755965473       8s
+```
+
+从结果中可以看出，使用vineyard的pipeline比不使用vineyard的pipeline减少了大约30%的运行时间。这种改进是由于vineyard利用共享内存加速数据共享，比传统方法如NFS更有效。
+
+### Modifications to use vineyard
+
+相比原始的kubeflow pipeline，您可以使用以下命令来查看使用Vineyard需要的修改：
+
+```shell
+$ git diff --no-index --unified=40 samples/vineyard/pipeline.py samples/vineyard/pipeline-with-vineyard.py
+```
+
+主要的修改如下：
+- 为pipeline添加vineyard持久卷。这个持久卷用于将vineyard客户端配置文件挂载到pipeline中。
+
+此外，您可以按照以下步骤检查源代码的修改。
+
+- [Save data to vineyard](../../../../samples/vineyard/preprocess-data/preprocess-data.py#L32-L35).
+- [Load data from vineyard](../../../../samples/vineyard/train-data/train-data.py#L15-L16).
+- [load data from vineyard](../../../../samples/vineyard/test-data/test-data.py#L14-L15).
+
+其中主要的修改是使用vineyard来加载和保存数据，而不是使用文件。
diff --git a/docs/zh/samples/vineyard/vineyard_runtime.md b/docs/zh/samples/vineyard/vineyard_runtime.md
index 22b74025..f1710b84 100644
--- a/docs/zh/samples/vineyard/vineyard_runtime.md
+++ b/docs/zh/samples/vineyard/vineyard_runtime.md
@@ -8,19 +8,7 @@ Vineyard 是一个开源的内存数据管理系统，旨在提供高性能的
 
 ## 安装 Fluid
 
-您可以从 [Fluid Releases](https://github.com/fluid-cloudnative/fluid/releases) 下载最新的 Fluid 安装包。参考 [安装文档](../../userguide/install.md) 完成安装。并检查 Fluid 各组件正常运行：
-
-```shell
-$ kubectl get po -n fluid-system
-NAME                                         READY   STATUS              RESTARTS   AGE
-csi-nodeplugin-fluid-56d44                   2/2     Running             0          106s
-csi-nodeplugin-fluid-5l78j                   2/2     Running             0          106s
-csi-nodeplugin-fluid-5mghb                   2/2     Running             0          106s
-dataset-controller-5cd87f8b9b-t7dv2          1/1     Running             0          106s
-fluid-webhook-77d44f5fbc-wttzl               1/1     Running             0          106s
-```
-
-确保 `dataset-controller`、`fluid-webhook` 的 pod 以及若干 `csi-nodeplugin` pod 正常运行。 `vineyard-runtime-controller` 会在使用 VineyardRuntime 的时候动态创建。
+参考 [安装文档](../../userguide/install.md) 完成安装。
 
 ## 创建Vineyard Runtime 及 Dataset
 
diff --git a/docs/zh/userguide/install.md b/docs/zh/userguide/install.md
index 1ad306d3..f8237a96 100644
--- a/docs/zh/userguide/install.md
+++ b/docs/zh/userguide/install.md
@@ -110,7 +110,7 @@ csi-nodeplugin-fluid-2scs9               2/2     Running     0          50s
 csi-nodeplugin-fluid-7vflb               2/2     Running     0          20s
 csi-nodeplugin-fluid-f9xfv               2/2     Running     0          33s
 dataset-controller-686d9d9cd6-gk6m6      1/1     Running     0          50s
-fluid-crds-upgrade-0.9.0-37e17c6-fp4mm   0/1     Completed   0          74s
+fluid-crds-upgrade-1.0.0-37e17c6-fp4mm   0/1     Completed   0          74s
 fluid-webhook-5bc9dfb9d8-hdvhk           1/1     Running     0          50s
 fluidapp-controller-6d4cbdcd88-z7l4c     1/1     Running     0          50s
 ```
@@ -131,11 +131,10 @@ $ kubectl exec dataset-controller-558c5c7785-mtgfh -n fluid-system -- dataset-co
 
 如果版本一致，您将看到如下信息：
 ```
-kubectl exec dataset-controller-5f56cc4f97-2lfqt -n fluid-system -- dataset-controller version
-  BuildDate: 2022-09-01_13:07:33
-  GitCommit: aa7fdca4c4306762280570b7dc0c2a7c649ff785
+  BuildDate: 2024-03-02_07:35:18
+  GitCommit: 50ee8887239f07592ba74af3e14379efc1487c0c
   GitTreeState: clean
-  GoVersion: go1.17.8
+  GoVersion: go1.18.10
   Compiler: gc
   Platform: linux/amd64
 ```
diff --git a/pkg/common/vineyard.go b/pkg/common/vineyard.go
index cbf0d336..99b3178c 100644
--- a/pkg/common/vineyard.go
+++ b/pkg/common/vineyard.go
@@ -21,6 +21,12 @@ const (
 
 	VineyardChart = VineyardRuntime
 
+	VineyardMasterImageEnv = "VINEYARD_MASTER_IMAGE_ENV"
+
+	VineyardWorkerImageEnv = "VINEYARD_WORKER_IMAGE_ENV"
+
+	VineyardFuseImageEnv = "VINEYARD_FUSE_IMAGE_ENV"
+
 	VineyardFuseIsGlobal = true
 
 	DefaultVineyardMasterImage = "bitnami/etcd:3.5.10"
diff --git a/pkg/controllers/operation_controller.go b/pkg/controllers/operation_controller.go
index f34b690a..a7329912 100644
--- a/pkg/controllers/operation_controller.go
+++ b/pkg/controllers/operation_controller.go
@@ -1,5 +1,5 @@
 /*
-  Copyright 2022 The Fluid Authors.
+  Copyright 2023 The Fluid Authors.
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
diff --git a/pkg/ddc/jindocache/transform.go b/pkg/ddc/jindocache/transform.go
index 306b4b46..784661b6 100644
--- a/pkg/ddc/jindocache/transform.go
+++ b/pkg/ddc/jindocache/transform.go
@@ -270,6 +270,10 @@ func (e *JindoCacheEngine) transformMaster(runtime *datav1alpha1.JindoRuntime, m
 		// to parse cacheset
 		cachesetName := mount.Name
 		cachesetPath := mount.MountPoint
+		if strings.HasPrefix(mount.MountPoint, common.VolumeScheme.String()) {
+			ufsVolumesPath := utils.UFSPathBuilder{}.GenLocalStoragePath(mount)
+			cachesetPath = "local://" + ufsVolumesPath
+		}
 		cacheStrategy := "DISTRIBUTED"
 		metaPolicy := "ALWAYS"
 		readCacheReplica := 1
@@ -451,11 +455,11 @@ func (e *JindoCacheEngine) transformMaster(runtime *datav1alpha1.JindoRuntime, m
 			if secretMountSupport {
 				value.Secret = secretKeyRef.Name
 				if key == "fs."+mountType+".accessKeyId" {
-					value.SecretKey = key
+					value.SecretKey = secretKeyRef.Key
 					e.Log.Info("Get %s From %s!", key, secretKeyRef.Name)
 				}
 				if key == "fs."+mountType+".accessKeySecret" {
-					value.SecretValue = key
+					value.SecretValue = secretKeyRef.Key
 					e.Log.Info("Get %s From %s!", key, secretKeyRef.Name)
 				}
 			} else {
diff --git a/pkg/ddc/vineyard/transform.go b/pkg/ddc/vineyard/transform.go
index 750cbdd1..d6a777cb 100644
--- a/pkg/ddc/vineyard/transform.go
+++ b/pkg/ddc/vineyard/transform.go
@@ -15,9 +15,10 @@ package vineyard
 
 import (
 	"fmt"
-	"github.com/fluid-cloudnative/fluid/pkg/common"
 	"time"
 
+	"github.com/fluid-cloudnative/fluid/pkg/common"
+
 	datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
 	"github.com/fluid-cloudnative/fluid/pkg/utils"
 	"github.com/fluid-cloudnative/fluid/pkg/utils/transfromer"
diff --git a/pkg/ddc/vineyard/utils.go b/pkg/ddc/vineyard/utils.go
index cdcf2c6b..4b1f68e0 100644
--- a/pkg/ddc/vineyard/utils.go
+++ b/pkg/ddc/vineyard/utils.go
@@ -25,6 +25,7 @@ import (
 	datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
 	"github.com/fluid-cloudnative/fluid/pkg/common"
 	"github.com/fluid-cloudnative/fluid/pkg/utils"
+	"github.com/fluid-cloudnative/fluid/pkg/utils/docker"
 )
 
 // getRuntime gets the vineyard runtime
@@ -128,20 +129,26 @@ func (e *VineyardEngine) parseMasterImage(image string, tag string, imagePullPol
 	}
 
 	if len(image) == 0 {
-		masterImageInfo := strings.Split(common.DefaultVineyardMasterImage, ":")
-		if len(masterImageInfo) < 1 {
-			panic("invalid default vineyard master image!")
-		} else {
-			image = masterImageInfo[0]
+		image = docker.GetImageRepoFromEnv(common.VineyardMasterImageEnv)
+		if len(image) == 0 {
+			masterImageInfo := strings.Split(common.DefaultVineyardMasterImage, ":")
+			if len(masterImageInfo) < 1 {
+				panic("invalid default vineyard master image!")
+			} else {
+				image = masterImageInfo[0]
+			}
 		}
 	}
 
 	if len(tag) == 0 {
-		masterImageInfo := strings.Split(common.DefaultVineyardMasterImage, ":")
-		if len(masterImageInfo) < 2 {
-			panic("invalid default vineyard master image!")
-		} else {
-			tag = masterImageInfo[1]
+		tag = docker.GetImageTagFromEnv(common.VineyardMasterImageEnv)
+		if len(tag) == 0 {
+			masterImageInfo := strings.Split(common.DefaultVineyardMasterImage, ":")
+			if len(masterImageInfo) < 2 {
+				panic("invalid default vineyard master image!")
+			} else {
+				tag = masterImageInfo[1]
+			}
 		}
 	}
 
@@ -154,20 +161,26 @@ func (e *VineyardEngine) parseWorkerImage(image string, tag string, imagePullPol
 	}
 
 	if len(image) == 0 {
-		workerImageInfo := strings.Split(common.DefaultVineyardWorkerImage, ":")
-		if len(workerImageInfo) < 1 {
-			panic("invalid default vineyard worker image!")
-		} else {
-			image = workerImageInfo[0]
+		image = docker.GetImageRepoFromEnv(common.VineyardWorkerImageEnv)
+		if len(image) == 0 {
+			workerImageInfo := strings.Split(common.DefaultVineyardWorkerImage, ":")
+			if len(workerImageInfo) < 1 {
+				panic("invalid default vineyard worker image!")
+			} else {
+				image = workerImageInfo[0]
+			}
 		}
 	}
 
 	if len(tag) == 0 {
-		workerImageInfo := strings.Split(common.DefaultVineyardWorkerImage, ":")
-		if len(workerImageInfo) < 2 {
-			panic("invalid default vineyard worker image!")
-		} else {
-			tag = workerImageInfo[1]
+		tag = docker.GetImageTagFromEnv(common.VineyardWorkerImageEnv)
+		if len(tag) == 0 {
+			workerImageInfo := strings.Split(common.DefaultVineyardWorkerImage, ":")
+			if len(workerImageInfo) < 2 {
+				panic("invalid default vineyard worker image!")
+			} else {
+				tag = workerImageInfo[1]
+			}
 		}
 	}
 
@@ -180,20 +193,26 @@ func (e *VineyardEngine) parseFuseImage(image string, tag string, imagePullPolic
 	}
 
 	if len(image) == 0 {
-		fuseImageInfo := strings.Split(common.DefultVineyardFuseImage, ":")
-		if len(fuseImageInfo) < 1 {
-			panic("invalid default vineyard fuse image!")
-		} else {
-			image = fuseImageInfo[0]
+		image = docker.GetImageRepoFromEnv(common.VineyardFuseImageEnv)
+		if len(image) == 0 {
+			fuseImageInfo := strings.Split(common.DefultVineyardFuseImage, ":")
+			if len(fuseImageInfo) < 1 {
+				panic("invalid default vineyard fuse image!")
+			} else {
+				image = fuseImageInfo[0]
+			}
 		}
 	}
 
 	if len(tag) == 0 {
-		fuseImageInfo := strings.Split(common.DefultVineyardFuseImage, ":")
-		if len(fuseImageInfo) < 2 {
-			panic("invalid default vineyard fuse image!")
-		} else {
-			tag = fuseImageInfo[1]
+		tag = docker.GetImageTagFromEnv(common.VineyardFuseImageEnv)
+		if len(tag) == 0 {
+			fuseImageInfo := strings.Split(common.DefultVineyardFuseImage, ":")
+			if len(fuseImageInfo) < 2 {
+				panic("invalid default vineyard fuse image!")
+			} else {
+				tag = fuseImageInfo[1]
+			}
 		}
 	}
 
diff --git a/samples/vineyard/Dockerfile b/samples/vineyard/Dockerfile
new file mode 100644
index 00000000..4cb2b67a
--- /dev/null
+++ b/samples/vineyard/Dockerfile
@@ -0,0 +1,10 @@
+FROM python:3.10
+
+RUN pip3 install pandas requests numpy vineyard scikit-learn==1.4.0 joblib==1.3.2
+
+WORKDIR /
+
+ARG APP
+ENV APP ${APP}
+
+COPY ${APP} /${APP}
diff --git a/samples/vineyard/Makefile b/samples/vineyard/Makefile
new file mode 100644
index 00000000..06a057fe
--- /dev/null
+++ b/samples/vineyard/Makefile
@@ -0,0 +1,47 @@
+REGISTRY := ""
+
+define docker_build
+    if [ -n "$(REGISTRY)" ]; then \
+        docker build $(1)/ -f Dockerfile \
+            --build-arg APP=$(1).py \
+            -t $(REGISTRY)/$(1); \
+    else \
+        docker build $(1)/ -f Dockerfile \
+            --build-arg APP=$(1).py \
+            -t $(1); \
+    fi
+endef
+
+define docker_push
+    if [ -n "$(REGISTRY)" ]; then \
+        docker push $(REGISTRY)/$(1); \
+    else \
+        docker push $(1); \
+    fi
+endef
+
+define kind_load
+    if [ -n "$(REGISTRY)" ]; then \
+        kind load docker-image $(REGISTRY)/$(1); \
+    else \
+        kind load docker-image $(1); \
+    fi
+endef
+
+docker-build:
+	$(call docker_build,prepare-data)
+	$(call docker_build,preprocess-data)
+	$(call docker_build,train-data)
+	$(call docker_build,test-data)
+
+push-images:
+	$(call docker_push,prepare-data)
+	$(call docker_push,preprocess-data)
+	$(call docker_push,train-data)
+	$(call docker_push,test-data)
+
+load-images:
+	$(call kind_load,prepare-data)
+	$(call kind_load,preprocess-data)
+	$(call kind_load,train-data)
+	$(call kind_load,test-data)
diff --git a/samples/vineyard/pipeline-with-vineyard.py b/samples/vineyard/pipeline-with-vineyard.py
new file mode 100644
index 00000000..922151fa
--- /dev/null
+++ b/samples/vineyard/pipeline-with-vineyard.py
@@ -0,0 +1,69 @@
+from kfp import dsl
+
+def PreProcess(data_multiplier: int, registry: str):
+    op =  dsl.ContainerOp(
+        name='Preprocess Data',
+        image = f'{registry}/preprocess-data',
+        container_kwargs={
+            'image_pull_policy': "IfNotPresent",
+        },
+        pvolumes={
+            "/data": dsl.PipelineVolume(pvc="benchmark-data"),
+            "/var/run/vineyard": dsl.PipelineVolume(pvc="vineyard"),
+        },
+        command = ['python3', 'preprocess-data.py'],
+        arguments = [f'--data_multiplier={data_multiplier}',
+                     '--with_vineyard=True'],
+    )
+    op.add_pod_label('fuse.serverful.fluid.io/inject', 'true')
+
+    return op
+
+def Train(comp1, registry: str):
+    op = dsl.ContainerOp(
+        name='Train Data',
+        image=f'{registry}/train-data',
+        container_kwargs={
+            'image_pull_policy': "IfNotPresent",
+        },
+        pvolumes={
+            "/data": comp1.pvolumes['/data'],
+            "/var/run/vineyard": dsl.PipelineVolume(pvc="vineyard"),
+        },
+        command = ['python3', 'train-data.py'],
+        arguments = ['--with_vineyard=True'],
+    )
+    op.add_pod_label('fuse.serverful.fluid.io/inject', 'true')
+
+    return op
+
+def Test(comp2, registry: str):
+    op = dsl.ContainerOp(
+        name='Test Data',
+        image=f'{registry}/test-data',
+        container_kwargs={
+            'image_pull_policy': "IfNotPresent",
+        },
+        pvolumes={
+            "/data": comp2.pvolumes['/data'],
+            "/var/run/vineyard": dsl.PipelineVolume(pvc="vineyard"),
+        },
+        command = ['python3', 'test-data.py'],
+        arguments = ['--with_vineyard=True'],
+    )
+    op.add_pod_label('fuse.serverful.fluid.io/inject', 'true')
+
+    return op
+
+@dsl.pipeline(
+   name='Machine Learning Pipeline with Vineyard',
+   description='An example pipeline that trains and logs a regression model.'
+)
+def pipeline(data_multiplier: int, registry: str):
+    comp1 = PreProcess(data_multiplier=data_multiplier, registry=registry)
+    comp2 = Train(comp1, registry=registry)
+    comp3 = Test(comp2, registry=registry)
+
+if __name__ == '__main__':
+    from kfp import compiler
+    compiler.Compiler().compile(pipeline, __file__[:-3]+ '.yaml')
diff --git a/samples/vineyard/pipeline-with-vineyard.yaml b/samples/vineyard/pipeline-with-vineyard.yaml
new file mode 100644
index 00000000..87734393
--- /dev/null
+++ b/samples/vineyard/pipeline-with-vineyard.yaml
@@ -0,0 +1,119 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Workflow
+metadata:
+  generateName: machine-learning-pipeline-with-vineyard-
+  annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.0, pipelines.kubeflow.org/pipeline_compilation_time: '2024-04-03T11:38:54.011627',
+    pipelines.kubeflow.org/pipeline_spec: '{"description": "An example pipeline that
+      trains and logs a regression model.", "inputs": [{"name": "data_multiplier",
+      "type": "Integer"}, {"name": "registry", "type": "String"}], "name": "Machine
+      Learning Pipeline with Vineyard"}'}
+  labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.0}
+spec:
+  entrypoint: machine-learning-pipeline-with-vineyard
+  templates:
+  - name: machine-learning-pipeline-with-vineyard
+    inputs:
+      parameters:
+      - {name: data_multiplier}
+      - {name: registry}
+    dag:
+      tasks:
+      - name: preprocess-data
+        template: preprocess-data
+        arguments:
+          parameters:
+          - {name: data_multiplier, value: '{{inputs.parameters.data_multiplier}}'}
+          - {name: registry, value: '{{inputs.parameters.registry}}'}
+      - name: test-data
+        template: test-data
+        dependencies: [train-data]
+        arguments:
+          parameters:
+          - {name: registry, value: '{{inputs.parameters.registry}}'}
+      - name: train-data
+        template: train-data
+        dependencies: [preprocess-data]
+        arguments:
+          parameters:
+          - {name: registry, value: '{{inputs.parameters.registry}}'}
+  - name: preprocess-data
+    container:
+      args: ['--data_multiplier={{inputs.parameters.data_multiplier}}', --with_vineyard=True]
+      command: [python3, preprocess-data.py]
+      image: '{{inputs.parameters.registry}}/preprocess-data'
+      imagePullPolicy: IfNotPresent
+      securityContext:
+        privileged: true
+      volumeMounts:
+      - {mountPath: /data, name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4}
+      - {mountPath: /var/run/vineyard, name: pvolume-d7f6fa616076983e0a6a1242a1945f9c18fb44256cdfffaad45ddd9}
+    inputs:
+      parameters:
+      - {name: data_multiplier}
+      - {name: registry}
+    metadata:
+      labels:
+        fuse.serverful.fluid.io/inject: "true"
+        pipelines.kubeflow.org/kfp_sdk_version: 1.8.0
+        pipelines.kubeflow.org/pipeline-sdk-type: kfp
+        pipelines.kubeflow.org/enable_caching: "true"
+    volumes:
+    - name: pvolume-d7f6fa616076983e0a6a1242a1945f9c18fb44256cdfffaad45ddd9
+      persistentVolumeClaim: {claimName: vineyard}
+    - name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4
+      persistentVolumeClaim: {claimName: benchmark-data}
+  - name: test-data
+    container:
+      args: [--with_vineyard=True]
+      command: [python3, test-data.py]
+      image: '{{inputs.parameters.registry}}/test-data'
+      imagePullPolicy: IfNotPresent
+      securityContext:
+        privileged: true
+      volumeMounts:
+      - {mountPath: /data, name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4}
+      - {mountPath: /var/run/vineyard, name: pvolume-d7f6fa616076983e0a6a1242a1945f9c18fb44256cdfffaad45ddd9}
+    inputs:
+      parameters:
+      - {name: registry}
+    metadata:
+      labels:
+        fuse.serverful.fluid.io/inject: "true"
+        pipelines.kubeflow.org/kfp_sdk_version: 1.8.0
+        pipelines.kubeflow.org/pipeline-sdk-type: kfp
+        pipelines.kubeflow.org/enable_caching: "true"
+    volumes:
+    - name: pvolume-d7f6fa616076983e0a6a1242a1945f9c18fb44256cdfffaad45ddd9
+      persistentVolumeClaim: {claimName: vineyard}
+    - name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4
+      persistentVolumeClaim: {claimName: benchmark-data}
+  - name: train-data
+    container:
+      args: [--with_vineyard=True]
+      command: [python3, train-data.py]
+      image: '{{inputs.parameters.registry}}/train-data'
+      imagePullPolicy: IfNotPresent
+      securityContext:
+        privileged: true
+      volumeMounts:
+      - {mountPath: /data, name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4}
+      - {mountPath: /var/run/vineyard, name: pvolume-d7f6fa616076983e0a6a1242a1945f9c18fb44256cdfffaad45ddd9}
+    inputs:
+      parameters:
+      - {name: registry}
+    metadata:
+      labels:
+        fuse.serverful.fluid.io/inject: "true"
+        pipelines.kubeflow.org/kfp_sdk_version: 1.8.0
+        pipelines.kubeflow.org/pipeline-sdk-type: kfp
+        pipelines.kubeflow.org/enable_caching: "true"
+    volumes:
+    - name: pvolume-d7f6fa616076983e0a6a1242a1945f9c18fb44256cdfffaad45ddd9
+      persistentVolumeClaim: {claimName: vineyard}
+    - name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4
+      persistentVolumeClaim: {claimName: benchmark-data}
+  arguments:
+    parameters:
+    - {name: data_multiplier}
+    - {name: registry}
+  serviceAccountName: pipeline-runner
diff --git a/samples/vineyard/pipeline.py b/samples/vineyard/pipeline.py
new file mode 100644
index 00000000..8c2c2406
--- /dev/null
+++ b/samples/vineyard/pipeline.py
@@ -0,0 +1,57 @@
+from kfp import dsl
+
+def PreProcess(data_multiplier: int, registry: str):
+    op =  dsl.ContainerOp(
+        name='Preprocess Data',
+        image = f'{registry}/preprocess-data',
+        container_kwargs={
+            'image_pull_policy': "IfNotPresent",
+        },
+        pvolumes={
+            "/data": dsl.PipelineVolume(pvc="benchmark-data"),
+        },
+        command = ['python3', 'preprocess-data.py'],
+        arguments = [f'--data_multiplier={data_multiplier}'],
+    )
+    return op
+
+def Train(comp1, registry: str):
+    op = dsl.ContainerOp(
+        name='Train Data',
+        image=f'{registry}/train-data',
+        container_kwargs={
+            'image_pull_policy': "IfNotPresent",
+        },
+        pvolumes={
+            "/data": comp1.pvolumes['/data'],
+        },
+        command = ['python3', 'train-data.py'],
+    )
+    return op
+
+def Test(comp2, registry: str):
+    op = dsl.ContainerOp(
+        name='Test Data',
+        image=f'{registry}/test-data',
+        container_kwargs={
+            'image_pull_policy': "IfNotPresent",
+        },
+        pvolumes={
+            "/data": comp2.pvolumes['/data'],
+        },
+        command = ['python3', 'test-data.py'],
+    )
+    return op
+
+@dsl.pipeline(
+   name='Machine Learning Pipeline',
+   description='An example pipeline that trains and logs a regression model.'
+)
+def pipeline(data_multiplier: int, registry: str):
+    comp1 = PreProcess(data_multiplier=data_multiplier, registry=registry)
+    comp2 = Train(comp1, registry=registry)
+    comp3 = Test(comp2, registry=registry)
+
+if __name__ == '__main__':
+    from kfp import compiler
+    compiler.Compiler().compile(pipeline, __file__[:-3]+ '.yaml')
diff --git a/samples/vineyard/pipeline.yaml b/samples/vineyard/pipeline.yaml
new file mode 100644
index 00000000..a13c9f48
--- /dev/null
+++ b/samples/vineyard/pipeline.yaml
@@ -0,0 +1,105 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Workflow
+metadata:
+  generateName: machine-learning-pipeline-
+  annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.0, pipelines.kubeflow.org/pipeline_compilation_time: '2024-04-03T11:04:21.236385',
+    pipelines.kubeflow.org/pipeline_spec: '{"description": "An example pipeline that
+      trains and logs a regression model.", "inputs": [{"name": "data_multiplier",
+      "type": "Integer"}, {"name": "registry", "type": "String"}], "name": "Machine
+      Learning Pipeline"}'}
+  labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.0}
+spec:
+  entrypoint: machine-learning-pipeline
+  templates:
+  - name: machine-learning-pipeline
+    inputs:
+      parameters:
+      - {name: data_multiplier}
+      - {name: registry}
+    dag:
+      tasks:
+      - name: preprocess-data
+        template: preprocess-data
+        arguments:
+          parameters:
+          - {name: data_multiplier, value: '{{inputs.parameters.data_multiplier}}'}
+          - {name: registry, value: '{{inputs.parameters.registry}}'}
+      - name: test-data
+        template: test-data
+        dependencies: [train-data]
+        arguments:
+          parameters:
+          - {name: registry, value: '{{inputs.parameters.registry}}'}
+      - name: train-data
+        template: train-data
+        dependencies: [preprocess-data]
+        arguments:
+          parameters:
+          - {name: registry, value: '{{inputs.parameters.registry}}'}
+  - name: preprocess-data
+    container:
+      args: ['--data_multiplier={{inputs.parameters.data_multiplier}}']
+      command: [python3, preprocess-data.py]
+      image: '{{inputs.parameters.registry}}/preprocess-data'
+      imagePullPolicy: IfNotPresent
+      securityContext:
+        privileged: true
+      volumeMounts:
+      - {mountPath: /data, name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4}
+    inputs:
+      parameters:
+      - {name: data_multiplier}
+      - {name: registry}
+    metadata:
+      labels:
+        pipelines.kubeflow.org/kfp_sdk_version: 1.8.0
+        pipelines.kubeflow.org/pipeline-sdk-type: kfp
+        pipelines.kubeflow.org/enable_caching: "true"
+    volumes:
+    - name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4
+      persistentVolumeClaim: {claimName: benchmark-data}
+  - name: test-data
+    container:
+      command: [python3, test-data.py]
+      image: '{{inputs.parameters.registry}}/test-data'
+      imagePullPolicy: IfNotPresent
+      securityContext:
+        privileged: true
+      volumeMounts:
+      - {mountPath: /data, name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4}
+    inputs:
+      parameters:
+      - {name: registry}
+    metadata:
+      labels:
+        pipelines.kubeflow.org/kfp_sdk_version: 1.8.0
+        pipelines.kubeflow.org/pipeline-sdk-type: kfp
+        pipelines.kubeflow.org/enable_caching: "true"
+    volumes:
+    - name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4
+      persistentVolumeClaim: {claimName: benchmark-data}
+  - name: train-data
+    container:
+      command: [python3, train-data.py]
+      image: '{{inputs.parameters.registry}}/train-data'
+      imagePullPolicy: IfNotPresent
+      securityContext:
+        privileged: true
+      volumeMounts:
+      - {mountPath: /data, name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4}
+    inputs:
+      parameters:
+      - {name: registry}
+    metadata:
+      labels:
+        pipelines.kubeflow.org/kfp_sdk_version: 1.8.0
+        pipelines.kubeflow.org/pipeline-sdk-type: kfp
+        pipelines.kubeflow.org/enable_caching: "true"
+    volumes:
+    - name: pvolume-d9c6725a1237b14c08a2567cb12c489bec539873deeddba7d87f5b4
+      persistentVolumeClaim: {claimName: benchmark-data}
+  arguments:
+    parameters:
+    - {name: data_multiplier}
+    - {name: registry}
+  serviceAccountName: pipeline-runner
diff --git a/samples/vineyard/prepare-data.yaml b/samples/vineyard/prepare-data.yaml
new file mode 100644
index 00000000..a87523ea
--- /dev/null
+++ b/samples/vineyard/prepare-data.yaml
@@ -0,0 +1,54 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: prepare-data
+spec:
+  selector:
+    matchLabels:
+      app: prepare-data
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: prepare-data
+    spec:
+      containers:
+      - name: prepare-data
+        image: test-registry/prepare-data
+        imagePullPolicy: IfNotPresent
+        command: ["python3", "/prepare-data.py"]
+        volumeMounts:
+        - mountPath: /data
+          name: data
+      volumes:
+      - name: data
+        persistentVolumeClaim:
+          claimName: benchmark-data
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: benchmark-data
+spec:
+  storageClassName: manual
+  accessModes:
+  - ReadWriteMany
+  resources:
+    requests:
+      storage: 30Gi
+---
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+  name: benchmark-data
+  labels:
+    type: local
+spec:
+  storageClassName: manual
+  capacity:
+    storage: 30Gi
+  accessModes:
+    - ReadWriteMany
+  hostPath:
+    # mount a nfs volume to the kubernetes nodes
+    path: "/mnt/csi-benchmark"
diff --git a/samples/vineyard/prepare-data/prepare-data.py b/samples/vineyard/prepare-data/prepare-data.py
new file mode 100644
index 00000000..433bc25d
--- /dev/null
+++ b/samples/vineyard/prepare-data/prepare-data.py
@@ -0,0 +1,76 @@
+import time
+
+import numpy as np
+import pandas as pd
+
+
+def generate_random_dataframe(num_rows):
+    return pd.DataFrame({
+            'Id': np.random.randint(1, 100000, num_rows),
+            'MSSubClass': np.random.randint(20, 201, size=num_rows),
+            'LotFrontage': np.random.randint(50, 151, size=num_rows),
+            'LotArea': np.random.randint(5000, 20001, size=num_rows),
+            'OverallQual': np.random.randint(1, 11, size=num_rows),
+            'OverallCond': np.random.randint(1, 11, size=num_rows),
+            'YearBuilt': np.random.randint(1900, 2022, size=num_rows),
+            'YearRemodAdd': np.random.randint(1900, 2022, size=num_rows),
+            'MasVnrArea': np.random.randint(0, 1001, size=num_rows),
+            'BsmtFinSF1': np.random.randint(0, 2001, size=num_rows),
+            'BsmtFinSF2': np.random.randint(0, 1001, size=num_rows),
+            'BsmtUnfSF': np.random.randint(0, 2001, size=num_rows),
+            'TotalBsmtSF': np.random.randint(0, 3001, size=num_rows),
+            '1stFlrSF': np.random.randint(500, 4001, size=num_rows),
+            '2ndFlrSF': np.random.randint(0, 2001, size=num_rows),
+            'LowQualFinSF': np.random.randint(0, 201, size=num_rows),
+            'GrLivArea': np.random.randint(600, 5001, size=num_rows),
+            'BsmtFullBath': np.random.randint(0, 4, size=num_rows),
+            'BsmtHalfBath': np.random.randint(0, 3, size=num_rows),
+            'FullBath': np.random.randint(0, 5, size=num_rows),
+            'HalfBath': np.random.randint(0, 3, size=num_rows),
+            'BedroomAbvGr': np.random.randint(0, 11, size=num_rows),
+            'KitchenAbvGr': np.random.randint(0, 4, size=num_rows),
+            'TotRmsAbvGrd': np.random.randint(0, 16, size=num_rows),
+            'Fireplaces': np.random.randint(0, 4, size=num_rows),
+            'GarageYrBlt': np.random.randint(1900, 2022, size=num_rows),
+            'GarageCars': np.random.randint(0, 5, num_rows),
+            'GarageArea': np.random.randint(0, 1001, num_rows),
+            'WoodDeckSF': np.random.randint(0, 501, num_rows),
+            'OpenPorchSF': np.random.randint(0, 301, num_rows),
+            'EnclosedPorch': np.random.randint(0, 201, num_rows),
+            '3SsnPorch': np.random.randint(0, 101, num_rows),
+            'ScreenPorch': np.random.randint(0, 201, num_rows),
+            'PoolArea': np.random.randint(0, 301, num_rows),
+            'MiscVal': np.random.randint(0, 5001, num_rows),
+            'TotalRooms': np.random.randint(2, 11, num_rows),
+            "GarageAge": np.random.randint(1, 31, num_rows),
+            "RemodAge": np.random.randint(1, 31, num_rows),
+            "HouseAge": np.random.randint(1, 31, num_rows),
+            "TotalBath": np.random.randint(1, 5, num_rows),
+            "TotalPorchSF": np.random.randint(1, 1001, num_rows),
+            "TotalSF": np.random.randint(1000, 6001, num_rows),
+            "TotalArea": np.random.randint(1000, 6001, num_rows),
+            'MoSold': np.random.randint(1, 13, num_rows),
+            'YrSold': np.random.randint(2006, 2022, num_rows),
+            'SalePrice': np.random.randint(50000, 800001, num_rows),
+        })
+
+def prepare_data():
+    print('Start preparing data....', flush=True)
+    st = time.time()
+    for multiplier in 1000, 2000, 3000:
+        df = generate_random_dataframe(10000*(multiplier))
+        df.to_pickle('/data/df_{}.pkl'.format(multiplier))
+        del df
+    ed = time.time()
+    print('##################################', flush=True)
+    print('dataframe to_pickle time: ', ed - st, flush=True)
+
+
+if __name__ == '__main__':
+    st = time.time()
+    print('Preparing data....', flush=True)
+    prepare_data()
+    ed = time.time()
+    print('##################################')
+    print('preparing data time: ', ed - st, flush=True)
+    time.sleep(10000000)
diff --git a/samples/vineyard/preprocess-data/preprocess-data.py b/samples/vineyard/preprocess-data/preprocess-data.py
new file mode 100644
index 00000000..80077436
--- /dev/null
+++ b/samples/vineyard/preprocess-data/preprocess-data.py
@@ -0,0 +1,58 @@
+import argparse
+import os
+import time
+
+from sklearn.model_selection import train_test_split
+
+import pandas as pd
+import vineyard
+
+
+def preprocess_data(data_multiplier, with_vineyard):
+    os.system('sync; echo 3 > /proc/sys/vm/drop_caches')
+    st = time.time()
+    df = pd.read_pickle('/data/df_{0}.pkl'.format(data_multiplier))
+
+    ed = time.time()
+    print('##################################')
+    print('read dataframe pickle time: ', ed - st)
+
+    df = df.drop(df[(df['GrLivArea']>4800)].index)
+
+    X = df.drop('SalePrice', axis=1)  # Features
+    y = df['SalePrice']  # Target variable
+
+    del df
+
+    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
+
+    del X, y
+
+    st = time.time()
+    if with_vineyard:
+        vineyard.put(X_train, name="X_train", persist=True)
+        vineyard.put(X_test, name="X_test", persist=True)
+        vineyard.put(y_train, name="Y_train", persist=True)
+        vineyard.put(y_test, name="Y_test", persist=True)
+    else:
+        X_train.to_pickle('/data/x_train.pkl')
+        X_test.to_pickle('/data/x_test.pkl')
+        y_train.to_pickle('/data/y_train.pkl')
+        y_test.to_pickle('/data/y_test.pkl')
+
+    ed = time.time()
+    print('##################################')
+    print('write training and testing data time: ', ed - st)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--data_multiplier', type=int, default=1, help='Multiplier for data')
+    parser.add_argument('--with_vineyard', type=bool, default=False, help='Whether to use vineyard')
+    args = parser.parse_args()
+    st = time.time()
+    print('Preprocessing data...')
+    preprocess_data(args.data_multiplier, args.with_vineyard)
+    ed = time.time()
+    print('##################################')
+    print('Preprocessing data time: ', ed - st)
diff --git a/samples/vineyard/rbac.yaml b/samples/vineyard/rbac.yaml
new file mode 100644
index 00000000..b8d58abd
--- /dev/null
+++ b/samples/vineyard/rbac.yaml
@@ -0,0 +1,29 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: pipeline-runner
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: pipeline-runner-role
+rules:
+  - apiGroups: [""]
+    resources: ["persistentvolumeclaims"]
+    verbs: ["get", "create", "update", "list", "delete"]
+  - apiGroups: [""]
+    resources: ["pods"]
+    verbs: ["get", "patch", "create", "update", "list", "delete"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: pipeline-runner-rolebinding
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: pipeline-runner-role
+subjects:
+  - kind: ServiceAccount
+    name: pipeline-runner
+    namespace: default
diff --git a/samples/vineyard/train-data/train-data.py b/samples/vineyard/train-data/train-data.py
new file mode 100644
index 00000000..a2409992
--- /dev/null
+++ b/samples/vineyard/train-data/train-data.py
@@ -0,0 +1,39 @@
+import argparse
+import os
+import time
+
+from sklearn.linear_model import LinearRegression
+
+import joblib
+import pandas as pd
+import vineyard
+
+
+def train_model(with_vineyard):
+    os.system('sync; echo 3 > /proc/sys/vm/drop_caches')
+    st = time.time()
+    if with_vineyard:
+        x_train_data = vineyard.get(name="X_train", fetch=True)
+        y_train_data = vineyard.get(name="Y_train", fetch=True)
+    else:
+        x_train_data = pd.read_pickle("/data/x_train.pkl")
+        y_train_data = pd.read_pickle("/data/y_train.pkl")
+    ed = time.time()
+    print('##################################')
+    print('read x_train and y_train data time: ', ed - st)
+
+    model = LinearRegression()
+    model.fit(x_train_data, y_train_data)
+
+    joblib.dump(model, '/data/model.pkl')
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--with_vineyard', type=bool, default=False, help='Whether to use vineyard')
+    args = parser.parse_args()
+    st = time.time()
+    print('Training model...')
+    train_model(args.with_vineyard)
+    ed = time.time()
+    print('##################################')


Test patch:
diff --git a/pkg/ddc/jindocache/transform_test.go b/pkg/ddc/jindocache/transform_test.go
index d437b891..670438bc 100644
--- a/pkg/ddc/jindocache/transform_test.go
+++ b/pkg/ddc/jindocache/transform_test.go
@@ -19,6 +19,8 @@ package jindocache
 import (
 	"os"
 	"reflect"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 	"testing"
 
 	datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
@@ -1370,3 +1372,92 @@ func TestJindoCacheEngine_transformCacheSet(t *testing.T) {
 		})
 	}
 }
+
+func TestJindoEngine_transformSecret(t *testing.T) {
+	jindocacheSecret := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "test",
+			Namespace: "fluid",
+		},
+		Data: map[string][]byte{
+			"AccessKeyId":     []byte("test"),
+			"AccessKeySecret": []byte("test"),
+		},
+	}
+	testObjs := []runtime.Object{}
+	testObjs = append(testObjs, (*jindocacheSecret).DeepCopy())
+
+	client := fake.NewFakeClientWithScheme(testScheme, testObjs...)
+	engine := JindoCacheEngine{
+		name:      "test",
+		namespace: "fluid",
+		Client:    client,
+		Log:       fake.NullLogger(),
+		runtime: &datav1alpha1.JindoRuntime{
+			Spec: datav1alpha1.JindoRuntimeSpec{
+				Fuse: datav1alpha1.JindoFuseSpec{},
+			},
+		},
+	}
+	ctrl.SetLogger(zap.New(func(o *zap.Options) {
+		o.Development = true
+	}))
+
+	var tests = []struct {
+		runtime *datav1alpha1.JindoRuntime
+		dataset *datav1alpha1.Dataset
+		value   *Jindo
+	}{
+		{&datav1alpha1.JindoRuntime{
+			Spec: datav1alpha1.JindoRuntimeSpec{
+				Fuse: datav1alpha1.JindoFuseSpec{},
+				Worker: datav1alpha1.JindoCompTemplateSpec{
+					Replicas:     2,
+					Resources:    corev1.ResourceRequirements{},
+					Env:          nil,
+					NodeSelector: nil,
+				},
+			},
+		}, &datav1alpha1.Dataset{
+			Spec: datav1alpha1.DatasetSpec{
+				Mounts: []datav1alpha1.Mount{{
+					MountPoint: "pvc:///mnt/test",
+					Name:       "test",
+					EncryptOptions: []datav1alpha1.EncryptOption{{
+						Name: "fs.oss.accessKeyId",
+						ValueFrom: datav1alpha1.EncryptOptionSource{
+							SecretKeyRef: datav1alpha1.SecretKeySelector{
+								Name: "test",
+								Key:  "AccessKeyId",
+							},
+						},
+					},
+						{
+							Name: "fs.oss.accessKeySecret",
+							ValueFrom: datav1alpha1.EncryptOptionSource{
+								SecretKeyRef: datav1alpha1.SecretKeySelector{
+									Name: "test",
+									Key:  "AccessKeySecret",
+								},
+							},
+						}},
+				}},
+			},
+		}, &Jindo{}},
+	}
+	for _, test := range tests {
+		err := engine.transformMaster(test.runtime, "/test", test.value, test.dataset, true)
+		if err != nil {
+			t.Errorf("error %v", err)
+		}
+		if test.value.SecretKey != "AccessKeyId" {
+			t.Errorf("expected value AccessKeyId, but got %v", test.value.SecretKey)
+		}
+		if test.value.SecretValue != "AccessKeySecret" {
+			t.Errorf("expected value AccessKeyId, but got %v", test.value.SecretKey)
+		}
+		if test.value.Secret != "test" {
+			t.Errorf("expected value AccessKeyId, but got %v", test.value.SecretKey)
+		}
+	}
+}
diff --git a/pkg/ddc/vineyard/transform_test.go b/pkg/ddc/vineyard/transform_test.go
index 3c626d3c..a6c15e6e 100755
--- a/pkg/ddc/vineyard/transform_test.go
+++ b/pkg/ddc/vineyard/transform_test.go
@@ -14,7 +14,9 @@ limitations under the License.
 package vineyard
 
 import (
+	"os"
 	"reflect"
+	"strings"
 	"testing"
 
 	datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
@@ -37,25 +39,47 @@ func TestTransformFuse(t *testing.T) {
 		o.Development = true
 	}))
 
-	var tests = []struct {
+	var tests = map[string]struct {
 		runtime   *datav1alpha1.VineyardRuntime
 		value     *Vineyard
 		expect    []string
 		expectEnv map[string]string
 	}{
-		{&datav1alpha1.VineyardRuntime{
-			Spec: datav1alpha1.VineyardRuntimeSpec{
-				Fuse: datav1alpha1.VineyardSockSpec{
-					Image:           "dummy-fuse-image",
-					ImageTag:        "dummy-tag",
-					ImagePullPolicy: "IfNotPresent",
-					Env:             map[string]string{"TEST_ENV": "true"},
-					CleanPolicy:     "OnRuntimeDeleted",
+		"test image, imageTag and pullPolicy": {
+			runtime: &datav1alpha1.VineyardRuntime{
+				Spec: datav1alpha1.VineyardRuntimeSpec{
+					Fuse: datav1alpha1.VineyardSockSpec{
+						Image:           "dummy-fuse-image",
+						ImageTag:        "dummy-tag",
+						ImagePullPolicy: "IfNotPresent",
+						Env:             map[string]string{"TEST_ENV": "true"},
+						CleanPolicy:     "OnRuntimeDeleted",
+					},
+				},
+			},
+			value:     &Vineyard{},
+			expect:    []string{"dummy-fuse-image", "dummy-tag", "IfNotPresent", "OnRuntimeDeleted"},
+			expectEnv: map[string]string{"TEST_ENV": "true"},
+		},
+		"test image, imageTag and pullPolicy from env": {
+			runtime: &datav1alpha1.VineyardRuntime{
+				Spec: datav1alpha1.VineyardRuntimeSpec{
+					Fuse: datav1alpha1.VineyardSockSpec{
+						ImagePullPolicy: "IfNotPresent",
+						Env:             map[string]string{"TEST_ENV": "true"},
+						CleanPolicy:     "OnRuntimeDeleted",
+					},
 				},
 			},
-		}, &Vineyard{}, []string{"dummy-fuse-image", "dummy-tag", "IfNotPresent", "OnRuntimeDeleted"}, map[string]string{"TEST_ENV": "true"}},
+			value:     &Vineyard{},
+			expect:    []string{"image-from-env", "image-tag-from-env", "IfNotPresent", "OnRuntimeDeleted"},
+			expectEnv: map[string]string{"TEST_ENV": "true"},
+		},
 	}
-	for _, test := range tests {
+	for k, test := range tests {
+		if strings.Contains(k, "env") {
+			os.Setenv("VINEYARD_FUSE_IMAGE_ENV", "image-from-env:image-tag-from-env")
+		}
 		engine := &VineyardEngine{}
 		engine.Log = ctrl.Log
 		engine.transformFuse(test.runtime, test.value)
@@ -75,6 +99,9 @@ func TestTransformFuse(t *testing.T) {
 		if !reflect.DeepEqual(test.value.Fuse.Env, test.expectEnv) {
 			t.Errorf("Expected Fuse Env %v, got %v", test.expectEnv, test.value.Fuse.Env)
 		}
+		if strings.Contains(k, "env") {
+			os.Unsetenv("VINEYARD_FUSE_IMAGE_ENV")
+		}
 	}
 }
 
@@ -103,11 +130,32 @@ func TestTransformMaster(t *testing.T) {
 				},
 			},
 		},
+		"test image, imageTag and pullPolicy from env": {
+			runtime: &datav1alpha1.VineyardRuntime{
+				Spec: datav1alpha1.VineyardRuntimeSpec{
+					Master: datav1alpha1.MasterSpec{
+						VineyardCompTemplateSpec: datav1alpha1.VineyardCompTemplateSpec{
+							ImagePullPolicy: "IfNotPresent",
+						},
+					},
+				},
+			},
+			wantValue: &Vineyard{
+				Master: Master{
+					Image:           "image-from-env",
+					ImageTag:        "image-tag-from-env",
+					ImagePullPolicy: "IfNotPresent",
+				},
+			},
+		},
 	}
 
 	engine := &VineyardEngine{Log: fake.NullLogger()}
 	ds := &datav1alpha1.Dataset{}
 	for k, v := range testCases {
+		if strings.Contains(k, "env") {
+			os.Setenv("VINEYARD_MASTER_IMAGE_ENV", "image-from-env:image-tag-from-env")
+		}
 		gotValue := &Vineyard{}
 		if err := engine.transformMasters(v.runtime, ds, gotValue); err == nil {
 			if gotValue.Master.Image != v.wantValue.Master.Image {
@@ -132,6 +180,9 @@ func TestTransformMaster(t *testing.T) {
 				)
 			}
 		}
+		if strings.Contains(k, "env") {
+			os.Unsetenv("VINEYARD_MASTER_IMAGE_ENV")
+		}
 	}
 }
 
@@ -160,10 +211,33 @@ func TestTransformWorker(t *testing.T) {
 				},
 			},
 		},
+		"test replicas, image, imageTag and pullPolicy from env": {
+			runtime: &datav1alpha1.VineyardRuntime{
+				Spec: datav1alpha1.VineyardRuntimeSpec{
+					Replicas: 3,
+					Worker: datav1alpha1.VineyardCompTemplateSpec{
+						Replicas:        2,
+						Image:           "test-image",
+						ImageTag:        "test-tag",
+						ImagePullPolicy: "IfNotPresent",
+					},
+				},
+			},
+			wantValue: &Vineyard{
+				Worker: Worker{
+					Image:           "image-from-env",
+					ImageTag:        "image-tag-from-env",
+					ImagePullPolicy: "IfNotPresent",
+				},
+			},
+		},
 	}
 
 	engine := &VineyardEngine{Log: fake.NullLogger()}
 	for k, v := range testCases {
+		if strings.Contains(k, "env") {
+			os.Setenv("VINEYARD_WORKER_IMAGE_ENV", "image-from-env:image-tag-from-env")
+		}
 		gotValue := &Vineyard{}
 		engine.runtimeInfo, _ = base.BuildRuntimeInfo("test", "test", "vineyard", v.runtime.Spec.TieredStore)
 		if err := engine.transformWorkers(v.runtime, gotValue); err == nil {
@@ -196,6 +270,9 @@ func TestTransformWorker(t *testing.T) {
 				)
 			}
 		}
+		if strings.Contains(k, "env") {
+			os.Unsetenv("VINEYARD_WORKER_IMAGE_ENV")
+		}
 	}
 }
 
diff --git a/samples/vineyard/test-data/test-data.py b/samples/vineyard/test-data/test-data.py
new file mode 100644
index 00000000..0021e960
--- /dev/null
+++ b/samples/vineyard/test-data/test-data.py
@@ -0,0 +1,42 @@
+import argparse
+import os
+import time
+
+from sklearn.metrics import mean_squared_error
+
+import joblib
+import pandas as pd
+import vineyard
+
+def test_model(with_vineyard):
+    os.system('sync; echo 3 > /proc/sys/vm/drop_caches')
+    st = time.time()
+    if with_vineyard:
+        x_test_data = vineyard.get(name="X_test", fetch=True)
+        y_test_data = vineyard.get(name="Y_test", fetch=True)
+    else:
+        x_test_data = pd.read_pickle("/data/x_test.pkl")
+        y_test_data = pd.read_pickle("/data/y_test.pkl")
+    ed = time.time()
+    print('##################################')
+    print('read x_test and y_test execution time: ', ed - st)
+
+    model = joblib.load("/data/model.pkl")
+    y_pred = model.predict(x_test_data)
+
+    err = mean_squared_error(y_test_data, y_pred)
+
+    with open('/data/output.txt', 'a') as f:
+        f.write(str(err))
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--with_vineyard', type=bool, default=False, help='Whether to use vineyard')
+    args = parser.parse_args()
+    st = time.time()
+    print('Testing model...')
+    test_model(args.with_vineyard)
+    ed = time.time()
+    print('##################################')
+    print('Testing model data time: ', ed - st)