Skip to content

Commit

Permalink
PVCViewers Controller: Add README
Browse files Browse the repository at this point in the history
Signed-off-by: Kimonas Sotirchos <kimwnasptd@arrikto.com>
Reviewed-by: Yannis Zarkadas <yanniszark@arrikto.com>
Github-PR: kubeflow#34
  • Loading branch information
kimwnasptd committed Sep 2, 2021
1 parent 7758f42 commit b94e6e5
Showing 1 changed file with 89 additions and 0 deletions.
89 changes: 89 additions & 0 deletions components/pvcviewer-controller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# PVC Viewers Controller

This `CustomResource` is intented for editing the files of PVCs in a Kubernetes cluster. This is done by mounting a Pod to the requested PVC that will be running a [UI](https://github.com/coderaiser/cloudcmd) that will allow the user to view/edit the contents of that mounted PVC.

This CR will be later used from the Volumes-UI in order to allow the user to edit the files of PVCs.

## Code Structure

The Controller is written using [kubebuilder v2](https://github.com/kubernetes-sigs/kubebuilder) in Go. The structure of the code is the following:
* `api/v1alpha1` contains the Spec of our CustomResource. The `zz_generated.deepcopy.go` file is auto-generated
* `config/` contains the manifests (YAML) and kustomize directories for deploying the Controller on a k8s cluster
* `config/samples` has two CustomResource instances for testing
* `controllers/` contains the main controller and the culling controller
* `util/` has some support functions used from the Controller

## How to Review

For reviewing I'd suggest to:

1. Take a look on the API definition of the CR in `api/v1alpha1/pvcviewer_types.go`
2. Deploy or run the Controller locally (more on how do run below)
3. Edit the `katib` sample CR and give it a Namespace and a PVC you have in your cluster
4. Apply the `katib` CR to you existing k8s cluster
5. Run `kubectl port-forward -n {namespace} svc/pvc-viewer-{pvc} 8080:80`
6. Connect with the browser to `localhost:8080/devices/volumes/{namespace}/{pvc}` and make sure you can see the [UI](https://github.com/coderaiser/cloudcmd)
7. Take a look at the Status of the CR
8. Apply the `config/samples/unschedulable.yaml` and view that PVCViewer's status.
9. Take a look at the logs created from the Controller
10. Finally, take a look at the controllers code

## Implementation Details

### Dependencies
* It is not a Kubeflow specific Controller, although since we will push the Controller ther I added `kubeflow` in some names here and there. If you have a better naming in mind please share
* It has ISTIO as a dependency since it creates a `VirtualService` for each CR
* The Controller expects a Prometheus Service to be running on ISTIO's namespace

### Sub-Resources

Under the hood for each `PVCViewer` CR the Controller will create:
1. A `Pod` that will mount the requested PVC
2. A `Service` for sending the traffic to that Pod. Traffic should be send to `/devices/volumes/{namespace}/{pvc}`
3. A `VirtualService` to expose the Pod outside the cluster

### Spec/Status

The `Spec` has only one field and that is for specifying the PVC we want to edit. This object's `G`roup`V`ersion`K`ind is `kubeflow.org`/`v1alpha1`/`PVCViewer`.

The `Status` of each PVCViewer will contain:
* `Conditions`: A list of [PodConditions](https://github.com/kubernetes/api/blob/master/core/v1/types.go#L2459) which will be a mirror of the underlying Pod's Conditions.
* `Ready`: A bool value that will be true only if the underlying Pod has both a `ContainersReady` and `PodReady` conditions.

### Culling
Culling is the process of deleting PVCViewer CRs whose Pod is idle. Since the user will *not* be able to directly manage these resources from the Volumes UI we want the controller to clean up unused viewers. By default any viewer Pod that doesn't receive traffic for an hour will be considered idle and should be deleted.

Prometheus, that gets deployed with ISTIO, will save http metrics for each Pod. The Controller will be querying that Service in order to get the number of requests a Pod received in the last {configurable} amound of time. If the Pod hasn't received any requests in that time frame then the Controller will delete the underlying Pod for that CR.

The Culling Controller will be periodically making these checks and if a viewer Pod is idle it will simply delete the entire CR.

### Misc

If a PVC we want to edit is `ReadWriteOnce` and it is being used from another Pod, then the k8s Scheduler will never schedule the PVCViewer's Pod ([issue](https://github.com/kubernetes/kubernetes/issues/26567)). In order to avoid this we will:
1. Check if the requested PVC is `ReadWriteOnce`
2. If it is we will check all the Pods in the Namespace and look if any of them is using that PVC
3. If there is at least one, we will check the node in which the first Pod using it is scheduled. Then we will also explicitly tell the k8s scheduler to put our PVCViewer's Pod on that Node.

## Build, Run, Deploy

### Create a Docker image and deploy it (Suggested)

The Makefile will use the `gcr.io/arrikto-playground/pvcviewer-controller:latest`, if you want to use a different image name of tag then simply change that line in the beginning of the makefile.

The Makefile has a `deploy` rule that will build and push the Docker image, create a `pvc-viewer-controller-system` namespace and finally generate and apply the necessary YAMLs.

### Build and Run the Controller locally
In order to build the controller you will need to use Go 1.11 and up in order to have Go Modules support. You will also need to have a k8s cluster.

```bash
# Install the necessary yamls
make install-crd

# Run without culling
make run

# To run with culling first you need to proxy
# the Prometheus svc to localhost.
make proxy-prometheus
make run-culling
```

0 comments on commit b94e6e5

Please sign in to comment.