From 2abccb0257282b5b5afaffcbdef5040d60957b81 Mon Sep 17 00:00:00 2001 From: Rajasekharan Vengalil Date: Sun, 11 Feb 2018 10:03:15 +0530 Subject: [PATCH] Add readme for web provider Also rename sample web provider implemented in Rust to `web-rust`. --- providers/web/README.md | 157 ++++++++++++++++++ .../.helmignore | 0 .../Chart.yaml | 0 .../templates/NOTES.txt | 0 .../templates/_helpers.tpl | 0 .../templates/deployment.yaml | 2 +- .../values.yaml | 2 +- providers/web/rust-web-provider/Dockerfile | 9 - .../.gitignore | 0 .../Cargo.lock | 22 +-- .../Cargo.toml | 2 +- providers/web/web-rust/Dockerfile | 9 + .../scripts/buildDocker.sh | 6 +- .../src/main.rs | 0 .../src/unit_provider.rs | 2 +- .../src/utils.rs | 4 +- 16 files changed, 186 insertions(+), 29 deletions(-) create mode 100644 providers/web/README.md rename providers/web/charts/{virtual-kubelet-web => web-rust}/.helmignore (100%) rename providers/web/charts/{virtual-kubelet-web => web-rust}/Chart.yaml (100%) rename providers/web/charts/{virtual-kubelet-web => web-rust}/templates/NOTES.txt (100%) rename providers/web/charts/{virtual-kubelet-web => web-rust}/templates/_helpers.tpl (100%) rename providers/web/charts/{virtual-kubelet-web => web-rust}/templates/deployment.yaml (97%) rename providers/web/charts/{virtual-kubelet-web => web-rust}/values.yaml (81%) delete mode 100644 providers/web/rust-web-provider/Dockerfile rename providers/web/{rust-web-provider => web-rust}/.gitignore (100%) rename providers/web/{rust-web-provider => web-rust}/Cargo.lock (99%) rename providers/web/{rust-web-provider => web-rust}/Cargo.toml (93%) create mode 100644 providers/web/web-rust/Dockerfile rename providers/web/{rust-web-provider => web-rust}/scripts/buildDocker.sh (93%) rename providers/web/{rust-web-provider => web-rust}/src/main.rs (100%) rename providers/web/{rust-web-provider => web-rust}/src/unit_provider.rs (99%) rename providers/web/{rust-web-provider => web-rust}/src/utils.rs (68%) diff --git a/providers/web/README.md b/providers/web/README.md new file mode 100644 index 000000000..2ae895f73 --- /dev/null +++ b/providers/web/README.md @@ -0,0 +1,157 @@ +Web provider for Virtual Kubelet +================================ + +Virtual Kubelet providers are written using the Go programming language. While +Go is a great general purpose programming language, it is however a fact that +other programming languages exist. The problem that Virtual Kubelet solves is as +applicable to applications written in those languages as it is for those written +using Go. This provider aims to serve as a bridge between technology stacks and +programming languages, as it were, by adapting the Virtual Kubelet provider +interface using a web endpoint, i.e., this provider is a thin layer that +forwards all calls that Kubernetes makes to the virtual kubelet to a +pre-configured HTTP endpoint. This frees the provider's implementor to write +their code in any programming language and technology stack as they see fit. + +The `providers/web/web-rust` folder contains a sample provider implemented in +the Rust programming language. Here's a diagram that depicts the interaction +between Kubernetes, the virtual kubelet web provider and the Rust app. + + +----------------+ +---------------------------+ +------------------------------+ + | | | | HTTP | | + | Kubernetes | <-----> | Virtual Kubelet: Web | <------> | Provider written in Rust | + | | | | | | + +----------------+ +---------------------------+ +------------------------------+ + +Provider interface +------------------ + +The web provider uses an environment variable to determine the endpoint to use +for forwarding requests. The environment variable must be named +`WEB_ENDPOINT_URL` and must implement the following HTTP API: + +| Path | Verb | Query | Request | Response | Description | +|-------------------|--------|-----------------------------------------|----------|---------------------------------------------------|---------------------------------------------------------------------------| +| /createPod | POST | - | Pod JSON | HTTP status code | Create a new pod | +| /updatePod | PUT | - | Pod JSON | HTTP status code | Update pod spec | +| /deletePod | DELETE | - | Pod JSON | HTTP status code | Delete an existing pod | +| /getPod | GET | namespace, name | - | Pod JSON | Given a pod namespace and name, return the pod JSON | +| /getContainerLogs | GET | namespace, podName, containerName, tail | - | Container logs | Given the namespace, pod name and container name, return `tail` log lines | +| /getPodStatus | GET | namespace, name | - | Pod status JSON | Given a pod namespace and name, return the pod's status JSON | +| /getPods | GET | - | - | Array of pod JSON strings | Fetch list of created pods | +| /capacity | GET | - | - | JSON map containing resource name and values | Fetch resource capacity values | +| /nodeConditions | GET | - | - | Array of node condition JSON strings | Get list of node conditions (Ready, OutOfDisk etc) | +| /nodeAddresses | GET | - | - | Array of node address values (type/address pairs) | Fetch a list of addresses for the node status | + +A typical deployment configuration for this setup would be to have the provider +implementation be deployed as a container in the same pod as the virtual kubelet +itself (as a "sidecar"). + +Take her for a spin +------------------- + +A sample web provider implementation is included in this repo in order to +showcase what this enables. The sample has been implemented in +[Rust](http://rust-lang.org). The easiest way to get this up and running is +to use the Helm chart available at `providers/web/charts/web-rust`. Open a +terminal and install the chart like so: + + $ cd providers/web/charts + $ helm install -n web-provider ./web-rust + + $ kubectl get pods + NAME READY STATUS RESTARTS AGE + web-provider-virtual-kubelet-web-6b5b7446f6-279xl 2/2 Running 0 3h + +If you list the nodes in the cluster after this you should see something that +looks like this: + + $ kubectl get nodes + NAME STATUS ROLES AGE VERSION + aks-nodepool1-35187879-0 Ready agent 37d v1.8.2 + aks-nodepool1-35187879-1 Ready agent 37d v1.8.2 + aks-nodepool1-35187879-3 Ready agent 37d v1.8.2 + virtual-kubelet-web Ready agent 3h v1.8.3 + +In case the name of the node didn't give it away, the last entry in the output +above is the virtual kubelet. If you try to list the containers in the pod that +represents the virtual kubelet you should be able to see the sidecar Rust +container: + + $ kubectl get pods -o=custom-columns=NAME:.metadata.name,CONTAINERS:.spec.containers[*].name + NAME CONTAINERS + web-provider-virtual-kubelet-web-6b5b7446f6-279xl webrust,virtualkubelet + +In the output above, `webrust` is the sidecar container and `virtualkubelet` is +the broker that forwards requests to `webrust`. You can run a query on the +`/getPods` HTTP endpoint on the `webrust` container to see a list of the pods +that it has been asked to create. To do this we first use `kubectl` to setup a +port forwarding server like so: + + $ kubectl port-forward web-provider-virtual-kubelet-web-6b5b7446f6-279xl 3000:3000 + +Now if we run `curl` on the `http://localhost:3000/getPods` URL you should see +the pod JSON getting dumped to the terminal. I ran my test on a Kubernetes +cluster deployed on [Azure](https://docs.microsoft.com/en-us/azure/aks/) which +happens to deploy a daemonset with some, what I imagine are "system" pods to +every node in the cluster. You can filter the output to see just the pod names +using the [jq](https://stedolan.github.io/jq/) tool like so: + + $ curl -s http://localhost:3000/getPods | jq '.[] | { name: .metadata.name }' + { + "name": "kube-proxy-czz57" + } + { + "name": "kube-svc-redirect-7qlpd" + } + +You can deploy workloads to the virtual kubelet as you normally do. Here's a +sample pod spec that uses `nodeSelector` to cause the deployment to be scheduled +on the virtual kubelet. + + apiVersion: v1 + kind: Pod + metadata: + name: vk-pod + labels: + foo: bar + spec: + containers: + - name: web1 + image: nginx + nodeSelector: + type: virtual-kubelet + +Let's go ahead and deploy the pod and run our `/getPods` query again: + + $ kubectl apply -f ~/tmp/pod1.yaml + pod "vk-pod" created + + $ curl -s http://localhost:3000/getPods | jq '.[] | { name: .metadata.name }' + { + "name": "kube-proxy-czz57" + } + { + "name": "kube-svc-redirect-7qlpd" + } + { + "name": "vk-pod" + } + + $ kubectl get pods + NAME READY STATUS RESTARTS AGE + vk-pod 0/1 Running 0 1m + web-provider-virtual-kubelet-web-6b5b7446f6-279xl 2/2 Running 6 4h + +As you can tell, a new pod has been scheduled to run on our virtual kubelet +instance. Deleting pods works as one would expect: + + $ kubectl delete -f ~/tmp/pod1.yaml + pod "vk-pod" deleted + + $ curl -s http://localhost:3000/getPods | jq '.[] | { name: .metadata.name }' + { + "name": "kube-proxy-czz57" + } + { + "name": "kube-svc-redirect-7qlpd" + } diff --git a/providers/web/charts/virtual-kubelet-web/.helmignore b/providers/web/charts/web-rust/.helmignore similarity index 100% rename from providers/web/charts/virtual-kubelet-web/.helmignore rename to providers/web/charts/web-rust/.helmignore diff --git a/providers/web/charts/virtual-kubelet-web/Chart.yaml b/providers/web/charts/web-rust/Chart.yaml similarity index 100% rename from providers/web/charts/virtual-kubelet-web/Chart.yaml rename to providers/web/charts/web-rust/Chart.yaml diff --git a/providers/web/charts/virtual-kubelet-web/templates/NOTES.txt b/providers/web/charts/web-rust/templates/NOTES.txt similarity index 100% rename from providers/web/charts/virtual-kubelet-web/templates/NOTES.txt rename to providers/web/charts/web-rust/templates/NOTES.txt diff --git a/providers/web/charts/virtual-kubelet-web/templates/_helpers.tpl b/providers/web/charts/web-rust/templates/_helpers.tpl similarity index 100% rename from providers/web/charts/virtual-kubelet-web/templates/_helpers.tpl rename to providers/web/charts/web-rust/templates/_helpers.tpl diff --git a/providers/web/charts/virtual-kubelet-web/templates/deployment.yaml b/providers/web/charts/web-rust/templates/deployment.yaml similarity index 97% rename from providers/web/charts/virtual-kubelet-web/templates/deployment.yaml rename to providers/web/charts/web-rust/templates/deployment.yaml index 2cd61719b..72bea41a0 100644 --- a/providers/web/charts/virtual-kubelet-web/templates/deployment.yaml +++ b/providers/web/charts/web-rust/templates/deployment.yaml @@ -19,7 +19,7 @@ spec: release: {{ .Release.Name }} spec: containers: - - name: rustwebprovider + - name: webrust image: "{{ .Values.rustwebimage.repository }}:{{ .Values.rustwebimage.tag }}" imagePullPolicy: {{ .Values.rustwebimage.pullPolicy }} ports: diff --git a/providers/web/charts/virtual-kubelet-web/values.yaml b/providers/web/charts/web-rust/values.yaml similarity index 81% rename from providers/web/charts/virtual-kubelet-web/values.yaml rename to providers/web/charts/web-rust/values.yaml index 63d7690f0..de1fd6a4f 100644 --- a/providers/web/charts/virtual-kubelet-web/values.yaml +++ b/providers/web/charts/web-rust/values.yaml @@ -1,5 +1,5 @@ rustwebimage: - repository: avranju/rust-web-provider + repository: avranju/web-rust tag: latest pullPolicy: Always port: 3000 diff --git a/providers/web/rust-web-provider/Dockerfile b/providers/web/rust-web-provider/Dockerfile deleted file mode 100644 index fa8c72c66..000000000 --- a/providers/web/rust-web-provider/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM debian:stretch-slim - -WORKDIR /app -ADD ./rust-web-provider /app/rust-web-provider - -ENV RUST_LOG=info -EXPOSE 3000 - -ENTRYPOINT [ "/app/rust-web-provider" ] diff --git a/providers/web/rust-web-provider/.gitignore b/providers/web/web-rust/.gitignore similarity index 100% rename from providers/web/rust-web-provider/.gitignore rename to providers/web/web-rust/.gitignore diff --git a/providers/web/rust-web-provider/Cargo.lock b/providers/web/web-rust/Cargo.lock similarity index 99% rename from providers/web/rust-web-provider/Cargo.lock rename to providers/web/web-rust/Cargo.lock index 609e34c62..a1555d3ac 100644 --- a/providers/web/rust-web-provider/Cargo.lock +++ b/providers/web/web-rust/Cargo.lock @@ -558,17 +558,6 @@ dependencies = [ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rust-web-provider" -version = "0.1.0" -dependencies = [ - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "kube_rust 1.0.0 (git+https://github.com/avranju/kube-rust?rev=058de6366d0d75cb60b2d0fd5ba1abd2e7d83fff)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "virtual-kubelet-adapter 0.1.0 (git+https://github.com/avranju/rust-virtual-kubelet-adapter?rev=4250103d31e2864725e47bdd23295e79ee12b6d0)", -] - [[package]] name = "rustc-serialize" version = "0.3.24" @@ -852,6 +841,17 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "web-rust" +version = "0.1.0" +dependencies = [ + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kube_rust 1.0.0 (git+https://github.com/avranju/kube-rust?rev=058de6366d0d75cb60b2d0fd5ba1abd2e7d83fff)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "virtual-kubelet-adapter 0.1.0 (git+https://github.com/avranju/rust-virtual-kubelet-adapter?rev=4250103d31e2864725e47bdd23295e79ee12b6d0)", +] + [[package]] name = "winapi" version = "0.2.8" diff --git a/providers/web/rust-web-provider/Cargo.toml b/providers/web/web-rust/Cargo.toml similarity index 93% rename from providers/web/rust-web-provider/Cargo.toml rename to providers/web/web-rust/Cargo.toml index 13e97b587..68e1b35f5 100644 --- a/providers/web/rust-web-provider/Cargo.toml +++ b/providers/web/web-rust/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rust-web-provider" +name = "web-rust" version = "0.1.0" authors = ["Rajasekharan Vengalil "] diff --git a/providers/web/web-rust/Dockerfile b/providers/web/web-rust/Dockerfile new file mode 100644 index 000000000..12d65f6b6 --- /dev/null +++ b/providers/web/web-rust/Dockerfile @@ -0,0 +1,9 @@ +FROM debian:stretch-slim + +WORKDIR /app +ADD ./web-rust /app/web-rust + +ENV RUST_LOG=info +EXPOSE 3000 + +ENTRYPOINT [ "/app/web-rust" ] diff --git a/providers/web/rust-web-provider/scripts/buildDocker.sh b/providers/web/web-rust/scripts/buildDocker.sh similarity index 93% rename from providers/web/rust-web-provider/scripts/buildDocker.sh rename to providers/web/web-rust/scripts/buildDocker.sh index 71e07a86c..e65a7e85c 100755 --- a/providers/web/rust-web-provider/scripts/buildDocker.sh +++ b/providers/web/web-rust/scripts/buildDocker.sh @@ -6,8 +6,8 @@ SCRIPT_NAME=$(basename "$0") DIR=$(cd "$(dirname "$0")" && pwd) ROOT_FOLDER="$DIR/.." PUBLISH_DIR=$ROOT_FOLDER/target/publish -TARGET_NAME=rust-web-provider -IMAGE_NAME=rust-web-provider +TARGET_NAME=web-rust +IMAGE_NAME=web-rust IMAGE_VERSION=latest BUILD_RELEASE=true SOURCE_RELEASE_DIR=$ROOT_FOLDER/target/release @@ -20,7 +20,7 @@ usage() echo "Note: You might have to run this as root or sudo." echo "" echo "options" - echo " -i, --image-name Image name (default: rust-web-provider)" + echo " -i, --image-name Image name (default: web-rust)" echo " -v, --image-version Docker Image Version (default: latest)" echo " -r, --build-release Build release configuration - true|false (default: true)" exit 1; diff --git a/providers/web/rust-web-provider/src/main.rs b/providers/web/web-rust/src/main.rs similarity index 100% rename from providers/web/rust-web-provider/src/main.rs rename to providers/web/web-rust/src/main.rs diff --git a/providers/web/rust-web-provider/src/unit_provider.rs b/providers/web/web-rust/src/unit_provider.rs similarity index 99% rename from providers/web/rust-web-provider/src/unit_provider.rs rename to providers/web/web-rust/src/unit_provider.rs index 063feb618..52b1ae6ba 100644 --- a/providers/web/rust-web-provider/src/unit_provider.rs +++ b/providers/web/web-rust/src/unit_provider.rs @@ -74,7 +74,7 @@ impl Provider for UnitProvider { info!("Getting pod: {}", name); self.pods_map .get(name) - .filter(|pod| { + .xfilter(|pod| { let empty = String::from(""); let ns = pod.metadata() .map(|m| m.namespace()) diff --git a/providers/web/rust-web-provider/src/utils.rs b/providers/web/web-rust/src/utils.rs similarity index 68% rename from providers/web/rust-web-provider/src/utils.rs rename to providers/web/web-rust/src/utils.rs index e70c249b1..d965ad411 100644 --- a/providers/web/rust-web-provider/src/utils.rs +++ b/providers/web/web-rust/src/utils.rs @@ -1,9 +1,9 @@ pub trait Filter { - fn filter bool>(self, predicate: P) -> Self; + fn xfilter bool>(self, predicate: P) -> Self; } impl Filter for Option { - fn filter bool>(self, predicate: P) -> Self { + fn xfilter bool>(self, predicate: P) -> Self { match self { Some(x) => { if predicate(&x) {