🎈 Welcome to the Conduit development guide! 👋
This document will help you build, run, and test Conduit from source.
Conduit is primarily written in Rust, Go, and React. At its core is a high-performance data plane written in Rust. The control plane components are written in Go. The dashboard UI is a React application.
cli: Command-lineconduitutility, view and drive the control plane.controllerdestination: Serves service discovery information to theproxy.proxy-api: Accepts requests fromproxyinstances and forwards those requests to the appropriate controller service.public-api: Accepts requests from API clients such ascliandweb, provides access to and control of the conduit service mesh.tap: Provides a live pipeline of requests.telemetry: Collects and aggregates metrics fromproxycomponenets.
proxy-init: Adds a Kubernetes pod to join the Conduit Service Mesh.web: Provides a UI dashboard to view and drive the control plane. This component is written in Go and React.
proxy: High-performance data plane, injected as a sidecar with every service.
conduit_components digraph G { rankdir=LR;
node [style=filled, shape=rect];
"cli" [color=lightblue];
"destination" [color=lightblue];
"proxy-api" [color=lightblue];
"public-api" [color=lightblue];
"tap" [color=lightblue];
"telemetry" [color=lightblue];
"web" [color=lightblue];
"proxy" [color=orange];
"cli" -> "public-api";
"web" -> "public-api";
"destination" -> "kubernetes";
"proxy" -> "proxy-api";
"proxy-api" -> "destination";
"proxy-api" -> "telemetry";
"public-api" -> "tap";
"public-api" -> "telemetry";
"tap" -> "kubernetes";
"tap" -> "proxy";
"telemetry" -> "kubernetes";
"telemetry" -> "prometheus";
} conduit_components
Depending on use case, there are several configurations with which to develop and run Conduit:
- Comprehensive: Integrated configuration using Minikube, most closely matches release.
- Go: Development of the Go components using Docker Compose.
- Web: Development of the Conduit Dashboard.
- Rust: Standalone development of the Rust
proxy.
This configuration builds all Conduit components in Docker images, and deploys them onto Minikube. This setup most closely parallels our recommended production installation, documented at https://conduit.io/getting-started/.
These commands assume a working Minikube environment.
# build all docker images, using minikube as our docker repo
DOCKER_TRACE=1 bin/mkube bin/docker-build
# install conduit
bin/conduit install | kubectl apply -f -
# verify cli and server versions
bin/conduit version
# validate installation
kubectl --namespace=conduit get all
bin/conduit check --expected-version $(bin/root-tag)
# view conduit dashboard
bin/conduit dashboard
# install the demo app
curl https://raw.githubusercontent.com/runconduit/conduit-examples/master/emojivoto/emojivoto.yml | bin/conduit inject - | kubectl apply -f -
# view demo app
minikube -n emojivoto service web-svc --url
# view details per deployment
bin/conduit stat deployments
# view a live pipeline of requests
bin/conduit tap deploy emojivoto/votingThese commands assume working Go and Docker environments.
To run all of the Go apps in a docker-compose environment:
docker-compose build
docker-compose up -d
# view dashboard
open http://$DOCKER_IP:8084If your system is configured to talk to a Kubernetes cluster, you can simulate traffic to the docker-compose environment:
# confirm you are connected to Kubernetes
kubectl version
# simulate traffic
bin/go-run controller/script/simulate-proxy --kubeconfig ~/.kube/config --addr $DOCKER_IP:8086 --max-pods 10 --sleep 10msbin/dep ensure
go test -race ./...
go vet ./...Our instructions use a bin/go-run script in lieu go run.
This is a convenience script that leverages caching via go build to make your
build/run/debug loop faster.
In general, replace commands like this:
go run cli/main.gowith this:
bin/go-run cliYou may also leverage go-run to execute our conduit cli command. While in a
release context you may run:
conduit checkIn development you can run:
bin/go-run cli checkThis is a React app fronting a Go process. It uses webpack to bundle assets, and postcss to transform css.
These commands assume working Go and Yarn environments.
Install Yarn and use it to install dependencies:
brew install yarn
cd web/app
yarncd web/app
yarn && yarn webpack
cd ..
../bin/go-run .The web server will be running on localhost:8084.
Note the web process depends on a public-api server, for which you have three
options:
bin/go-run controller/cmd/public-apiStop the web service, then run it locally and set the --api-addr flag to the
address of the public API server that's running in your docker environment:
docker-compose stop web
cd web
../bin/go-run . --api-addr=$DOCKER_IP:8085If you are running the public API server in Kubernetes, forward localhost:8085
to the Conduit controller pod:
POD_NAME=$(kubectl --namespace=conduit get po --selector=app=controller -o jsonpath='{.items[*].metadata.name}')
kubectl -n conduit port-forward $POD_NAME 8085:8085Then connect the local web process to the forwarded port:
cd web
../bin/go-run . --api-addr=localhost:8085To develop with a webpack dev server, start the server in a separate window:
cd web/app
yarn webpack-dev-serverAnd then set the --webpack-dev-server flag when running the web server:
cd web
../bin/go-run . --webpack-dev-server=http://localhost:8080To add a JS dependency:
cd web/app
yarn add [dep]cd web/app
yarn && yarn webpack
yarn karma start --single-runThese commands assume a working Rust environment.
Note that we only support the most recent stable version of Rust.
To build and run the Rust proxy:
cargo build -p conduit-proxy
CONDUIT_PROXY_LOG=trace \
CONDUIT_PROXY_PUBLIC_LISTENER=tcp://0.0.0.0:5432 \
CONDUIT_PROXY_PRIVATE_FORWARD=tcp://127.0.0.1:1234 \
CONDUIT_PROXY_CONTROL_URL=tcp://127.0.0.1:8086 \
target/debug/conduit-proxyTo connect to a live proxy-api at localhost:8086:
bin/go-run controller/cmd/proxy-apiThe bin/docker-build-proxy script builds the proxy:
DOCKER_TRACE=1 PROXY_UNOPTIMIZED=1 PROXY_SKIP_TESTS=1 bin/docker-build-proxyIt supports two environment variables:
PROXY_UNOPTIMIZED-- When set and non-empty, produces unoptimized build artifacts, which reduces build times at the expense of runtime performance. Changing this will likely invalidate a substantial portion of Docker's cache.PROXY_SKIP_TESTS-- When set and non-empty, prevents the proxy's tests from being run during the build. Changing this setting will not invalidate Docker's cache.
To build the Rust code and run tests, run:
cargo testTo analyze the Rust code and report errors, without building object files or running tests, run:
cargo checkIf you make Protobuf changes, run:
bin/dep ensure
bin/protoc-go.shThe Rust proxy and Go Docker images rely on base dependency images with hard-coded SHA's:
gcr.io/runconduit/go-deps depends on
bin/update-go-deps-shas must be run when go dependencies change.
build_architecture digraph G { rankdir=LR;
"Dockerfile-base" [color=lightblue, style=filled, shape=rect];
"Dockerfile-go-deps" [color=lightblue, style=filled, shape=rect];
"controller/Dockerfile" [color=lightblue, style=filled, shape=rect];
"cli/Dockerfile" [color=lightblue, style=filled, shape=rect];
"cli/Dockerfile-bin" [color=lightblue, style=filled, shape=rect];
"proxy/Dockerfile" [color=lightblue, style=filled, shape=rect];
"proxy-init/Dockerfile" [color=lightblue, style=filled, shape=rect];
"proxy-init/integration-test/iptables/Dockerfile-tester" [color=lightblue, style=filled, shape=rect];
"web/Dockerfile" [color=lightblue, style=filled, shape=rect];
"proxy-init/integration-test/run_tests.sh" -> "proxy-init/integration-test/iptables/Dockerfile-tester";
"_docker.sh" -> "_log.sh";
"_gcp.sh";
"_log.sh";
"_tag.sh";
"dep";
"docker-build" -> "docker-build-controller";
"docker-build" -> "docker-build-web";
"docker-build" -> "docker-build-proxy";
"docker-build" -> "docker-build-proxy-init";
"docker-build" -> "docker-build-cli";
"docker-build-base" -> "_docker.sh";
"docker-build-base" -> "Dockerfile-base";
"docker-build-cli" -> "_docker.sh";
"docker-build-cli" -> "_tag.sh";
"docker-build-cli" -> "docker-build-cli-bin";
"docker-build-cli" -> "cli/Dockerfile";
"docker-build-cli-bin" -> "_docker.sh";
"docker-build-cli-bin" -> "_tag.sh";
"docker-build-cli-bin" -> "docker-build-base";
"docker-build-cli-bin" -> "docker-build-go-deps";
"docker-build-cli-bin" -> "cli/Dockerfile-bin";
"docker-build-controller" -> "_docker.sh";
"docker-build-controller" -> "_tag.sh";
"docker-build-controller" -> "docker-build-base";
"docker-build-controller" -> "docker-build-go-deps";
"docker-build-controller" -> "controller/Dockerfile";
"docker-build-go-deps" -> "_docker.sh";
"docker-build-go-deps" -> "_tag.sh";
"docker-build-go-deps" -> "Dockerfile-go-deps";
"docker-build-proxy" -> "_docker.sh";
"docker-build-proxy" -> "_tag.sh";
"docker-build-proxy" -> "proxy/Dockerfile";
"docker-build-proxy-init" -> "_docker.sh";
"docker-build-proxy-init" -> "_tag.sh";
"docker-build-proxy-init" -> "docker-build-base";
"docker-build-proxy-init" -> "docker-build-go-deps";
"docker-build-proxy-init" -> "proxy-init/Dockerfile";
"docker-build-web" -> "_docker.sh";
"docker-build-web" -> "_tag.sh";
"docker-build-web" -> "docker-build-base";
"docker-build-web" -> "docker-build-go-deps";
"docker-build-web" -> "web/Dockerfile";
"docker-images" -> "_docker.sh";
"docker-images" -> "_tag.sh";
"docker-pull" -> "_docker.sh";
"docker-pull-deps" -> "_docker.sh";
"docker-pull-deps" -> "_tag.sh";
"docker-push" -> "_docker.sh";
"docker-push-deps" -> "_docker.sh";
"docker-push-deps" -> "_tag.sh";
"docker-retag-all" -> "_docker.sh";
"go-run" -> ".gorun";
"go-run" -> "root-tag";
"minikube-start-hyperv.bat";
"mkube";
"protoc" -> ".protoc";
"protoc-go.sh" -> "protoc";
"root-tag" -> "_tag.sh";
".travis.yml" -> "_gcp.sh";
".travis.yml" -> "dep";
".travis.yml" -> "docker-build";
".travis.yml" -> "docker-pull";
".travis.yml" -> "docker-pull-deps";
".travis.yml" -> "docker-push";
".travis.yml" -> "docker-push-deps";
".travis.yml" -> "docker-retag-all";
".travis.yml" -> "protoc-go.sh";
"update-go-deps-shas" -> "_tag.sh";
"update-go-deps-shas" -> "cli/Dockerfile-bin";
"update-go-deps-shas" -> "controller/Dockerfile";
"update-go-deps-shas" -> "proxy-init/Dockerfile";
"update-go-deps-shas" -> "web/Dockerfile";
} build_architecture