# Hello from Gefyra | Blazingly-fast rocket, rock-solid, local application development arrow_right with Kubernetes. ::u-page-hero #title :icon{.home-icon mode="svg" name="i-gefyra-logo-vertical"} #description Blazingly-fast, rock-solid, local application development with Kubernetes. #links :::u-button --- color: primary size: xl to: https://gefyra.dev/en/quick-start/installation trailing-icon: i-lucide-arrow-right --- Let's try Gefyra ::: :::u-button --- color: neutral icon: simple-icons-github size: xl to: https://github.com/gefyrahq/gefyra variant: outline --- We're open source ::: :: ::u-container{.text-center.mb-6} :::card-group ::::card{title="The Problem"} Building and pushing containers to test them in Kubernetes is [repetitive and time-consuming]{.font-bold}. Writing and debugging code that depends on services in Kubernetes is daunting. [Especially if they are not reachable]{.font-bold} during development. :::: ::::card{title="The Solution"} [Gefyra]{.font-bold} runs local code in any Kubernetes cluster [without the build and push cycle]{.font-bold}. It overlays containers in the cluster making code changes immediately available. It's a new era of software development. :::: ::: :: ::u-page-section --- class: border-t --- #title Why Gefyra? #features :::u-page-feature --- icon: i-gefyra-deadline --- #title Supercharge Development Speed #description Run your code directly in a Kubernetes cluster and overcome [CI/CD waiting times]{.font-bold}. ::: :::u-page-feature --- icon: i-gefyra-sweat --- #title Fight Environment Bugs #description Uncover bugs [before]{.font-bold} they appear on staging or production environments. ::: :::u-page-feature --- icon: i-gefyra-team --- #title Promote Collaboration #description Share [running code instantly]{.font-bold} and let your team work in a realistic environment. ::: :::u-page-feature --- icon: i-gefyra-play-button --- #title One Click and Go #description Gefyra is [ready in seconds]{.font-bold}, not hours or days. ::: :::u-page-feature --- icon: i-gefyra-link --- #title Flexible Workflows #description Integrate Gefyra [into existing workflows]{.font-bold}. Make Gefyra part of your CI/CD pipeline. ::: :::u-page-feature --- icon: i-gefyra-budget --- #title Cost Efficient #description Improve time-to-market and utilization of resources. Spent [less]{.font-bold} on CI/CD pipelines and container builds. ::: :: ::u-page-section --- class: border-t orientation: horizontal --- #title Docker Desktop Extension #description Gefyra is a Docker Desktop extension that allows you to run your code directly in a Kubernetes cluster. #links :::u-button --- color: primary size: xl target: _blank to: https://www.docker.com/blog/building-a-local-application-development-environment-for-kubernetes-with-the-gefyra-docker-extension/ trailing-icon: i-lucide-arrow-right --- Check it out ::: :: :gefyra-use-cases ::u-page-section --- class: border-t --- #title Let us know about your experience! #description We depend on your feedback - Gefyra's was created out of our own needs and the feedback we received from you, and our community. We'd appreciate it if you could take 2 minutes of your time to fill out our [feedback form]{.font-bold}. #links :::u-button --- color: primary size: xl target: _blank to: https://forms.gle/AWT9NparpTVk8E978 trailing-icon: i-lucide-arrow-right --- Give feedback ::: :: # Gefyra: Blazingly-fast, rock-solid, local application development with Kubernetes. ## Gefyra offers you to - run services locally on a developer machine - operate feature-branches in a production-like Kubernetes environment with all adjacent services - write code in the IDE you already love, be fast, be confident - leverage all the neat development features, such as debugger, code-hot-reloading, overriding environment variables - run high-level integration tests against all dependent services - keep peace-of-mind when pushing new code to the integration environment Gefyra was designed to be fast and robust on an average developer machine and supports most platforms. **Remark:** Gefyra requires a running Docker engine on the development machine. ## Core Features ### Run a container instance on a developer machine and connect it to Kubernetes-based resources You can run an arbitrary container on your local development machine that behaves as it would run within a Kubernetes cluster. It connects to Kubernetes-based resources (such as databases, APIs, or assets), making it very convenient to test a new service in the cluster or write code that depends on Kubernetes resources. ![Run a container instance on a developer machine and connect it to Kubernetes-based resources](https://gefyra.dev/img/gefyra-run-action.png){.w-full} ### Overlay a container running within a Kubernetes Pod with a local instance You can simply replace a container running in a Kubernetes Pod with a local container instance. That will serve the requests to that Pod from your local container instances. That makes it very convenient to test changes in a realistic production-close environment before pushing the code to CI/CD. ![Overlay a container running within a Kubernetes Pod with a local instance](https://gefyra.dev/img/gefyra-bridge-action.png){.w-full} ## Quick Installation ```bash curl -sSL https://raw.githubusercontent.com/gefyrahq/gefyra/main/install.sh | sh - ``` Looking for Homebrew or Windows installation? Checkout the [installation](https://gefyra.dev/en/quick-start/installation) guide. ## Use Cases and Demos If you are interested in more sophisticated use cases or want to develop modern Kubernetes-based architectures, check out the [use cases and demos](https://gefyra.dev/en/usecases-and-demos/getting-started) or the [media](https://gefyra.dev/en/information/media) section. # Installation ## Prerequisites To use Gefyra you need: - Docker client API compatible container runtime (Docker/Docker Desktop/Colima/Rancher Desktop with moby engine) - Overlay networking support (not available on rootless Docker) - Kubernetes cluster with a reachable node port **31820/UDP** ## Install Gefyra on MacOS ### Homebrew ```bash brew tap gefyrahq/gefyra brew install gefyra ``` ### Manual Installation ```bash curl -sSL https://raw.githubusercontent.com/gefyrahq/gefyra/main/install.sh | sh - ``` ## Install Gefyra on Linux ### Manual Installation ```bash curl -sSL https://raw.githubusercontent.com/gefyrahq/gefyra/main/install.sh | sh - ``` ## Install Gefyra on Windows You can download the latest release from {rel=""nofollow""} on your local machine. Chocolatey will be available soon. If you can support this project with packaging and distributing for Windows please get in touch! Todo ## Docker Desktop Extension The Gefyra Docker Desktop Extension is available on the Docker Desktop extension [marketplace](https://hub.docker.com/extensions/gefyra/docker-desktop-extension){rel=""nofollow""} However, you can also install it by running the following command: ```bash docker extension install gefyra/docker-desktop-extension:latest ``` For more details see [Docker Desktop Extension](https://gefyra.dev/en/local-environments/docker-desktop-osx). ## Using Python Package Index You can install Gefyra with pip: ```bash pip install gefyra --upgrade ``` {rel=""nofollow""} # Getting Started **Important:** This getting started guide for [Minikube](https://minikube.sigs.k8s.io/){rel=""nofollow""} requires Gefyra in version >=2.0.0+. ## Prerequisites 1. Minikube is [installed](https://minikube.sigs.k8s.io/docs/start/){rel=""nofollow""} (at least in version v1.26.1) 2. Gefyra is [available](https://gefyra.dev/installation){rel=""nofollow""} (at least in version 2.0.0) ## Creating a local Kubernetes cluster with Minikube ![minikube](https://gefyra.dev/img/minikube2.gif){.w-full} ### 1. Create a local Kubernetes cluster with Minikube by running: ```bash minikube start ``` **Important:** the following example does not *fully* work with `--driver=qemu` since `minikube service` is not currently implemented with the qemu2 driver. See [this GitHub issue](https://github.com/kubernetes/minikube/issues/14146){rel=""nofollow""} for details. Tested drivers are: *docker*, *kvm2*, *kvm*, *virtualbox*. Others are potentially working, but are not tested. After some time of downloading the required resources, the cluster will be running. You may enable the required addons based on your requirements. The `kubectl` context is immediately set to this cluster. You can check if `kubectl config current-context` is set to `minikube`. ```sh kubectl config current-context ``` ### 2. Apply some workload, for example from the testing directory from Gefyra: ```sh kubectl apply -f https://raw.githubusercontent.com/gefyrahq/gefyra/main/testing/workloads/hello.yaml ``` ### 3. Check the output of the deployed app with: ```sh kubectl expose deployment hello-nginxdemo --type=NodePort --port=80 ``` ```sh minikube service hello-nginxdemo ``` ## Running Gefyra ### 1. Set up Gefyra with your Minikube cluster: ```sh gefyra up --minikube ``` **Important**: The `--minikube` switch detects all required connection parameters from your local cluster. The connection won't work if this switch is missing when working with Minikube. ### 2. Run a local Docker container with Gefyra in order to connect it with the cluster. #### 2.1 Build a simple Docker image with a local tag. Save the following two files in a directory on your disk. ```dockerfile [Dockerfile] FROM ubuntu # run a server on port 8000 RUN apt update && apt install -y iproute2 iputils-ping python3 traceroute wget curl COPY local.py local.py CMD python3 local.py ``` ::code-collapse ```py [local.py] import http.server import signal import socket import socketserver import sys from datetime import datetime if sys.argv[1:]: port = int(sys.argv[1]) else: port = 8000 class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() hostname = socket.gethostname() now = datetime.utcnow() self.wfile.write( bytes( f"

Hello from Gefyra. It is {now} on" f" {hostname}.

".encode("utf-8") ) ) my_handler = MyHttpRequestHandler server = socketserver.ThreadingTCPServer(("", port), my_handler) def signal_handler(signal, frame): try: if server: server.server_close() finally: sys.exit(0) signal.signal(signal.SIGINT, signal_handler) try: while True: sys.stdout.flush() server.serve_forever() except KeyboardInterrupt: pass server.server_close() ``` :: #### 2.2 Build it by running `docker build -f Dockerfile . -t pyserver` in your directory. #### 2.3 Execute Gefyra's run command: ```bash gefyra run -d -i pyserver -N mypyserver -n default ``` **Important**: `gefyra run` is just a wrapper for `docker run` (with additional flags), yet it also applies Gefyra's networking configuration to connect the container with Kubernetes. Check out [the docs for `gefyra run`](https://gefyra.dev/en/quick-start/cli#run) ### 3. *Exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash ``` ```sh wget -O- hello-nginx ``` will print out the website of the cluster service *hello-nginx* from within the cluster. 🚀 ### 4. Create a bridge to redirect the traffic from the cluster application to the one running locally: ```sh gefyra bridge -N mypyserver -n default --ports 80:8000 --target deploy/hello-nginxdemo/hello-nginx ``` Check out the locally running server serving the cluster by refreshing the address from: ```sh minikube service hello-nginxdemo ``` It shows you a different message: `Hello from Gefyra. It is ...`. Yes, that is really coming from your local container! 😎 ### 5. List all running *bridges*: You can list all currently active bridges with: ```sh gefyra list --bridges ``` You will find all local containers that are currently linked into the cluster serving requests. ### 6. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge --all ``` Check out the original response from: ```sh minikube service hello-nginxdemo ``` The cluster is now reset to its inital state again. ## Cleaning up Remove Gefyra's components from the cluster and your local Docker host with: ```sh gefyra down ``` ## Deleting the Minikube cluster ```sh minikube delete ``` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Gefyra Docker Desktop Extension [Gefyra's Docker Desktop Extension](https://hub.docker.com/r/gefyra/docker-desktop-extension){rel=""nofollow""} allows you to run containers on your local machine and connect them to Kubernetes-based resources. It is a great way to test a new service in the cluster or write code that depends on Kubernetes resources. ::note Gefyra's Docker Desktop Extension still runs Gefyra v1 internally and thus does not support shared environments. :: **Looking for CLI rather than a GUI?** Check out [Gefyra's CLI](https://gefyra.dev/en/quick-start/cli) ## Installation The Gefyra Docker Desktop Extension is available on the Docker Desktop extension [marketplace](https://hub.docker.com/extensions/gefyra/docker-desktop-extension){rel=""nofollow""}. However, you can also install it by running the following command: ```shell docker extension install gefyra/docker-desktop-extension:latest ``` ## Usage After installing the extension it becomes available in the Docker Desktop Extension sidebar. Gefyra Docker Desktop currently only supports the `run` mode. After clicking on the `run` tile you're guided through the process of running a container on your local machine. ![Docker Desktop Extension Start](https://gefyra.dev/img/extension/home_light.png) Firstly Gefyra needs to know about your cluster to allow you to set all settings accordingly. ![Docker Desktop Extension Cluster Settings](https://gefyra.dev/img/extension/cluster_light.png) After choosing your *kubeconfig* and context you can then proceed to adding the settings for your container. In case you have a remote cluster you need to provide Gefyra with its connection parameters under `Remote Cluster Settings`. ![Docker Desktop Extension Container Settings](https://gefyra.dev/img/extension/container_light.png) There are several settings for the container - most importantly the `image`, `namespace` and `command` settings. The `image` setting is the image that will be used to run the container - Gefyra will you show any image that is available in the local Docker Desktop context as well as images that are available in the chosen Kubernetes namespace. The `namespace` setting is the namespace in which the container will be available. Gefyra allows you to copy the environment variables of a certain workload through the `Copy Environment From` dropdown. You can add volumes and more variables through the `Add Volume` and `Add Environment Variable` buttons. As soon as you're done hit run! ![Docker Desktop Extension Load](https://gefyra.dev/img/extension/load_light.png) Gefyra ensures that its cluster components are in the correct state and starts the container. Once the container is running Gefyra will show you the logs of the container. ## 10 minute demo :gefyra-youtube{video-id="4xmaOVul5Ww"} :gefyra-youtube{video-id="EBArR1O2BGk"} ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Command line tool (CLI) ## Syntax Use the following syntax to run `gefyra` commands from your terminal: ```sh gefyra [-h] [-d] [action] [arguments] ``` where `action` and `arguments` are: - `action`: specifies the operation that you want to perform, for example `up` or `bridge` - `arguments`: specifies the required and optional arguments for a specific action, for example `-n` or `--namespace` Global flags are: - `-h, --help`: show help message and exit - `-d, --debug`: add debug output for each action ## Commands Overview | Command | Description | | :----------------------------------------------- | :---------------------------------------------------------------------------- | | [`bridge`](https://gefyra.dev/#bridge) | Manage your GefyraBridges to redirect traffic from a GefyraBridgeMount target | | [`clients`](https://gefyra.dev/#clients) | Manage GefyraClients for a Gefyra installation | | [`connections`](https://gefyra.dev/#connections) | Manage connections to Kubernetes clusters for a GefyraClient on this machine | | [`down`](https://gefyra.dev/#down) | Remove Gefyra locally and on the cluster | | [`install`](https://gefyra.dev/#install) | Create and print the Kubernetes configs for Gefyra; usage: 'gefyra install... | | [`list`](https://gefyra.dev/#list) | List running containers | | [`mount`](https://gefyra.dev/#mount) | Manage GefyraBridgeMounts for a Gefyra installation | | [`operator`](https://gefyra.dev/#operator) | Manage operator installation | | [`rm`](https://gefyra.dev/#rm) | Remove a Gefyra container and its associated bridges | | [`run`](https://gefyra.dev/#run) | Run a container in Gefyra. | | [`self`](https://gefyra.dev/#self) | Manage this Gefyra executable | | [`status`](https://gefyra.dev/#status) | Get Gefyra's status | | [`uninstall`](https://gefyra.dev/#uninstall) | Removes the Gefyra installation from the cluster | | [`up`](https://gefyra.dev/#up) | Install Gefyra on a cluster and directly connect to it | | [`version`](https://gefyra.dev/#version) | | --- ### bridge Manage your GefyraBridges to redirect traffic from a GefyraBridgeMount target **Example:** ```sh gefyra bridge create gefyra bridge list gefyra bridge delete my-bridge ``` **Subcommands:** - [`bridge create`](https://gefyra.dev/#bridge-create) — Establish a GefyraBridge from a GefyraBridgeMount in the... - [`bridge delete`](https://gefyra.dev/#bridge-delete) — Mark a GefyraBridge for deletion - [`bridge inspect`](https://gefyra.dev/#bridge-inspect) — Describe a GefyraBridge - [`bridge list`](https://gefyra.dev/#bridge-list) — List all GefyraBridges with local target containers [](){#bridge-create}**▶ bridge create** Establish a GefyraBridge from a GefyraBridgeMount in the cluster to a local container **Example:** ```sh gefyra bridge create -t mycontainer -p 8080:8080 --mount my-mount ``` **Arguments:** | Argument | Description | | :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------- | | `-t`, `--local`, `--target` | The name of the local container running in Gefyra **(required)** | | `-N`, `--name` | Assign a custom name to this GefyraBridge | | `-p`, `--ports` | Add forward port mapping in form of ``:`` **(required)** | | `--match-header-exact` | Match header exactly to forward traffic to this client. E.g.: --match-header-exact x-gefyra\:peer | | `--match-header-regex` | Match header regex expression to forward traffic to this client. E.g.: --match-header-regex x-gefyra:(.\*)) | | `--match-header-prefix` | Match header value prefix (and name exactly) to forward traffic to this client. E.g.: --match-header-prefix x-gefyra\:peer1, | | `--match-path-prefix` | Match path prefix to forward traffic to this client. E.g.: --match-path-prefix myroute/ | | `--match-path-regex` | Match patch regex to forward traffic to this client. E.g.: --match-path-regex myroute/(.\*)/all | | `--match-path-exact` | Match path exactly to forward traffic to this client. E.g.: --match-path-exact /only/this | | `-P`, `--no-probe-handling` | Make Carrier to not handle probes during switch operation | | `--mount` | The target GefyraBridgeMount to install this GefyraBridge on **(required)** | | `--connection-name` | Default: `default` | | `--nowait` | Do not wait for the GefyraBridgeMount to be ready | | `--timeout` | Default: `60` | [](){#bridge-delete}**▶ bridge delete** *Aliases: `rm`, `remove`* Mark a GefyraBridge for deletion **Example:** ```sh gefyra bridge delete my-bridge gefyra bridge rm my-bridge ``` **Positional Arguments:** | Argument | Description | | :------- | :---------- | | `name` | | **Arguments:** | Argument | Description | | :------------------ | :------------------------------------------------------ | | `-A`, `--all` | Unbridge all GefyraBridges with local target containers | | `-m`, `--mount` | Unbridge all bridges for a specific mount | | `--nowait` | Do not wait for the GefyraBridge to be deleted. | | `--connection-name` | Default: `default` | | `--timeout` | Default: `60` | [](){#bridge-inspect}**▶ bridge inspect** *Aliases: `describe`, `show`, `get`* Describe a GefyraBridge **Example:** ```sh gefyra bridge inspect my-bridge ``` **Positional Arguments:** | Argument | Description | | :------------ | :------------- | | `bridge_name` | **(required)** | **Arguments:** | Argument | Description | | :------------------------ | :----------------- | | `--output`, `-o` | Default: `text` | | `--connection-name`, `-c` | Default: `default` | [](){#bridge-list}**▶ bridge list** *Aliases: `ls`* List all GefyraBridges with local target containers **Example:** ```sh gefyra bridge list gefyra bridge ls ``` **Arguments:** | Argument | Description | | :------------------ | :-------------------------------------------- | | `-A`, `--all` | List all GefyraBridges from all GefyraClients | | `--connection-name` | Default: `default` | | `-o`, `--output` | Default: `text` | --- ### clients Manage GefyraClients for a Gefyra installation **Example:** ```sh gefyra clients create gefyra clients list gefyra clients delete my-client ``` **Subcommands:** - [`clients config`](https://gefyra.dev/#clients-config) — Get a Gefyra connection config for a client - [`clients create`](https://gefyra.dev/#clients-create) — Create a new GefyraClient - [`clients delete`](https://gefyra.dev/#clients-delete) — Mark a GefyraClient for deletion - [`clients disconnect`](https://gefyra.dev/#clients-disconnect) — Disconnect a GefyraClient - [`clients inspect`](https://gefyra.dev/#clients-inspect) — Describe a GefyraClient - [`clients list`](https://gefyra.dev/#clients-list) — List all GefyraClients [](){#clients-config}**▶ clients config** *Aliases: `write`* Get a Gefyra connection config for a client **Example:** ```sh gefyra clients config -h 1.1.1.1 my-client-id ``` **Positional Arguments:** | Argument | Description | | :---------- | :------------- | | `client_id` | **(required)** | **Arguments:** | Argument | Description | | :------------------------------------- | :--------------------------------------------------------------------------------------- | | `-h`, `--host` | The connection host | | `-p`, `--port` | The connection port (default: 31820) | | `-a`, `--kube-api`, `--kubernetes-api` | The Kubernetes API adress for the host cluster (default: API adresse of your kubeconfig) | | `-o`, `--output` | The output file to write the config to | | `--registry` | The registry URL for the images | | `--mtu` | The MTU for the Wireguard interface (default: auto-detected by WireGuard) | | `--local` | Whether the target cluster is a local k8s cluster | [](){#clients-create}**▶ clients create** Create a new GefyraClient **Example:** ```sh gefyra clients create -n 2 # creates 2 clients ``` **Arguments:** | Argument | Description | | :---------------------- | :--------------------------------------------------------------------------------------------------- | | `--client-id`, `--name` | The client id/name of the GefyraClient | | `-n` | Number of GefyraClient to be generated (not allowed with explicit --client-id/--name) (default: `1`) | | `--registry` | The registry URL for the images | | `--nowait` | Do not wait for the GefyraClient to be ready | | `--timeout` | Timeout in seconds for the GefyraClient to be ready (default: `60`) | [](){#clients-delete}**▶ clients delete** *Aliases: `rm`, `remove`* Mark a GefyraClient for deletion **Example:** ```sh gefyra clients delete my-client-id gefyra clients rm my-client-id gefyra clients remove my-client-id ``` **Positional Arguments:** | Argument | Description | | :---------- | :------------- | | `client_id` | **(required)** | **Arguments:** | Argument | Description | | :---------- | :-------------------------------------------------------------------- | | `--nowait` | Do not wait for the GefyraClient to be deleted | | `--timeout` | Timeout in seconds for the GefyraClient to be deleted (default: `60`) | | `--force` | Force deletion of the GefyraClient | [](){#clients-disconnect}**▶ clients disconnect** *Aliases: `deactivate`, `stop`* Disconnect a GefyraClient **Example:** ```sh gefyra clients disconnect my-client-id ``` **Positional Arguments:** | Argument | Description | | :---------- | :------------- | | `client_id` | **(required)** | [](){#clients-inspect}**▶ clients inspect** *Aliases: `describe`, `show`, `get`* Describe a GefyraClient **Example:** ```sh gefyra clients inspect gefyra clients inspect my-client-id ``` **Positional Arguments:** | Argument | Description | | :---------- | :------------- | | `client_id` | **(required)** | **Arguments:** | Argument | Description | | :--------------- | :------------------------------------------- | | `-o`, `--output` | Output format (json, text) (default: `text`) | [](){#clients-list}**▶ clients list** *Aliases: `ls`* List all GefyraClients **Example:** ```sh gefyra clients list gefyra clients ls ``` **Arguments:** | Argument | Description | | :--------------- | :-------------- | | `-o`, `--output` | Default: `text` | --- ### connections Manage connections to Kubernetes clusters for a GefyraClient on this machine **Example:** ```sh gefyra connections connect -f con_file.json -n my-connection gefyra connections list gefyra connections disconnect my-connection ``` **Subcommands:** - [`connections connect`](https://gefyra.dev/#connections-connect) — Connect this local machine to a Gefyra cluster - [`connections disconnect`](https://gefyra.dev/#connections-disconnect) — Disconnect this local machine from a Gefyra cluster - [`connections inspect`](https://gefyra.dev/#connections-inspect) — Inspect a Gefyra connection - [`connections list`](https://gefyra.dev/#connections-list) — List all Gefyra connections - [`connections remove`](https://gefyra.dev/#connections-remove) — Remove a Gefyra connection [](){#connections-connect}**▶ connections connect** *Aliases: `create`* Connect this local machine to a Gefyra cluster **Example:** ```sh gefyra connections connect -f con_file.json -n my-connection ``` **Arguments:** | Argument | Description | | :------------------------ | :---------------------------------------------------------------------------------------------------- | | `-f`, `--client-config` | | | `-n`, `--connection-name` | Assign a local name to this client connection (default: `default`) | | `--minikube` | Connect Gefyra to a Minikube cluster (accepts minikube profile name, default is 'minikube')) | | `--mtu` | The MTU (Maximum Transmission Unit) for the Wireguard interface (default: auto-detected by WireGuard) | | `--cargo-image` | Use a custom Cargo container image | | `--force` | Force re-connection of client, even if it is already active. | | `--timeout` | Timeout for each connection step in seconds. (default: `60`) | [](){#connections-disconnect}**▶ connections disconnect** *Aliases: `stop`, `halt`* Disconnect this local machine from a Gefyra cluster **Example:** ```sh gefyra connections disconnect my-connection ``` **Positional Arguments:** | Argument | Description | | :---------------- | :---------- | | `connection_name` | | **Arguments:** | Argument | Description | | :---------- | :-------------------------------------------------------- | | `--yes` | Non-interactive mode, do not ask for confirmation | | `--nowait` | Do not wait for the GefyraClient to be in state 'WAITING' | | `--timeout` | Timeout for disconnect in seconds. (default: `60`) | [](){#connections-inspect}**▶ connections inspect** Inspect a Gefyra connection **Example:** ```sh gefyra connections inspect my-connection ``` **Positional Arguments:** | Argument | Description | | :---------------- | :---------- | | `connection_name` | | **Arguments:** | Argument | Description | | :--------------- | :--------------------------------------------------------- | | `--output`, `-o` | Output format for the connection details (default: `text`) | [](){#connections-list}**▶ connections list** *Aliases: `ls`* List all Gefyra connections **Example:** ```sh gefyra connections list ``` **Arguments:** | Argument | Description | | :--------------- | :------------------------------------------------------ | | `--output`, `-o` | Output format for the connection list (default: `text`) | [](){#connections-remove}**▶ connections remove** *Aliases: `rm`* Remove a Gefyra connection **Example:** ```sh gefyra connections rm my-connection ``` **Positional Arguments:** | Argument | Description | | :---------------- | :---------- | | `connection_name` | | **Arguments:** | Argument | Description | | :------- | :------------------------------------------------ | | `--yes` | Non-interactive mode, do not ask for confirmation | --- ### down Remove Gefyra locally and on the cluster **Example:** ```sh gefyra down ``` --- ### install Create and print the Kubernetes configs for Gefyra; usage: 'gefyra install [options] | kubectl apply -f - **Example:** ```sh gefyra install ``` **Arguments:** | Argument | Description | | :------------------------------- | :------------------------------------------------------------------------------------------------- | | `--component`, `--comp` | Limit config creation to this component (available: namespace,rbac,webhook,deployment,service) | | `--preset` | Set configs from a preset (available: aws,gke) | | `--apply` | | | `--wait` | | | `-ns`, `--namespace` | The namespace to install Gefyra into (default: gefyra) | | `--version` | Set the Operator version; components are created according to this Gefyra version (default: 2.5.4) | | `--service-type` | The Kubernetes service for Stowaway to expose the Wireguard endpoint (default: NodePort) | | `--service-port` | The port for Stowaway to expose the Wireguard endpoint (default: 31820) | | `--service-labels` | Additional Kubernetes labels for the Stowaway service (default: [] ) | | `--service-annotations` | Kubernetes annotations for the Stowaway service (default: [] ) | | `--registry` | The registry URL for the images (default: quay.io/gefyra) | | `--mtu` | The MTU for the Wireguard interface (default: auto-detected by WireGuard) | | `--stowaway-storage` | The storage size for the Stowaway PVC in Mi (default: 64) | | `--max-client-connection-age` | The maximum age of a Stowaway connection in seconds (default: None) | | `--disable-client-sa-management` | Whether to create/manage client service accounts for Gefyra (default: False) | | `--bridge-debug` | Enable debug logging for GefyraBridgeMounts/GefyraBridges (default: False) | --- ### list List running containers **Example:** ```sh gefyra list ``` **Arguments:** | Argument | Description | | :------------------------ | :------------------------------------------ | | `-n`, `--connection-name` | Only list from this client connection name. | --- ### mount Manage GefyraBridgeMounts for a Gefyra installation **Example:** ```sh gefyra mount create --target deploy/my-deploy/my-container gefyra mount list gefyra mount delete my-mount ``` **Subcommands:** - [`mount create`](https://gefyra.dev/#mount-create) — Create a new GefyraBridgeMount in the cluster - [`mount delete`](https://gefyra.dev/#mount-delete) — Mark a GefyraBridgeMount for deletion - [`mount inspect`](https://gefyra.dev/#mount-inspect) — Describe a GefyraBridgeMount - [`mount list`](https://gefyra.dev/#mount-list) — List all GefyraBridgeMounts [](){#mount-create}**▶ mount create** Create a new GefyraBridgeMount in the cluster **Example:** ```sh gefyra mount create --target deploy/my-deploy/my-container -n default ``` **Arguments:** | Argument | Description | | :------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--namespace` | The GefyraBridgeMount's target namespace (default: `default`) | | `--name` | Assign a custom name to this GefyraBridgeMount | | `--target` | Install a GefyraBridgeMount to workloads following the notion 'resource/name/container'. Resource can be one of 'deployment', 'statefulset' or 'pod'. E.g.: --target deployment/hello-nginx/nginx **(required)** | | `--tls-key` | Path to key file for tls traffic (within the target container) or secret notation 'secret:{namespace}/{name}:{key}'. To address specific ports, use the format ``@port | | `--tls-certificate` | Path to certificate file for tls traffic (within the target container) or secret notation 'secret:{namespace}/{name}:{key}'. To address specific ports, use the format ``@port | | `--tls-sni` | SNI for tls traffic (within the target container) or secret notation 'secret:{namespace}/{name}:{key}'. To address specific ports, use the format ``@port | | `--connection-name`, `-c` | Default: `default` | | `--nowait` | Do not wait for the GefyraBridgeMount to be ready | | `--timeout` | Default: `60` | [](){#mount-delete}**▶ mount delete** *Aliases: `rm`, `remove`* Mark a GefyraBridgeMount for deletion **Example:** ```sh gefyra mount delete my-mount gefyra mount rm my-mount ``` **Positional Arguments:** | Argument | Description | | :----------- | :------------- | | `mount_name` | **(required)** | **Arguments:** | Argument | Description | | :------------------------ | :--------------------------------------------------- | | `--nowait` | Do not wait for the GefyraBridgeMount to be deleted. | | `--connection-name`, `-c` | Default: `default` | | `--timeout` | Default: `60` | [](){#mount-inspect}**▶ mount inspect** *Aliases: `describe`, `show`, `get`* Describe a GefyraBridgeMount **Example:** ```sh gefyra mount inspect my-mount ``` **Positional Arguments:** | Argument | Description | | :----------- | :------------- | | `mount_name` | **(required)** | **Arguments:** | Argument | Description | | :------------------ | :----------------- | | `-o`, `--output` | Default: `text` | | `--connection-name` | Default: `default` | [](){#mount-list}**▶ mount list** *Aliases: `ls`* List all GefyraBridgeMounts **Example:** ```sh gefyra mount list gefyra mount ls ``` **Arguments:** | Argument | Description | | :------------------ | :----------------- | | `--output`, `-o` | Default: `text` | | `--connection-name` | Default: `default` | --- ### operator Manage operator installation **Example:** ```sh gefyra operator update ``` **Subcommands:** - [`operator update`](https://gefyra.dev/#operator-update) — Update operator to latest or specific version. [](){#operator-update}**▶ operator update** Update operator to latest or specific version. **Example:** ```sh gefyra operator update ``` **Arguments:** | Argument | Description | | :---------- | :------------------------------------------ | | `--version` | Set specific version to update operator to. | --- ### rm Remove a Gefyra container and its associated bridges **Example:** ```sh gefyra rm mycontainer ``` **Positional Arguments:** | Argument | Description | | :------- | :---------- | | `name` | | **Arguments:** | Argument | Description | | :------------------ | :--------------------------------------------------------- | | `-A`, `--all` | Remove all Gefyra containers and their bridges | | `-f`, `--force` | Force remove containers (even if running) | | `--nowait` | Do not wait for containers and bridges to be fully removed | | `--connection-name` | Default: `default` | --- ### run Run a container in Gefyra. ```text  Any additional container engine arguments can be passed after the known options. They are forwarded directly to the Docker/Podman API. Use the docker-py parameter names with '--' prefix and '-' separators:  gefyra run -i myimage -N myname -- --cpu-shares 512 --mem-reservation 256m gefyra run -i myimage -N myname -- --cpu-period 100000 --cpu-quota 50000  See https://docker-py.readthedocs.io/en/stable/containers.html for the full list of supported parameters. ``` **Example:** ```sh gefyra run -i pyserver -N mypyserver -n default ``` **Arguments:** | Argument | Description | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `-d`, `--detach` | Run container in background and print container ID | | `--rm` | Automatically remove the container when it exits | | `-p`, `--expose` | Add port mapping in form of ``:`` | | `--env-from` | Copy the environment from the container in the notation 'Pod/Container' | | `--cpu-from` | Inherit CPU limit from a workload, e.g. 'pod/``', 'deployment/``' or 'statefulset/``' | | `--memory-from` | Inherit memory limit from a workload, e.g. 'pod/``', 'deployment/``' or 'statefulset/``' | | `--cpu` | [Deprecated: pass docker/podman args after '--' instead, e.g. `-- --cpu-period 100000 --cpu-quota 50000` for 0.5 CPU. Note: raw microseconds, k8s-style notation is not supported by the engine] CPU limit for the container (e.g. '500m' or '2') | | `--memory` | [Deprecated: pass docker/podman args after '--' instead, e.g. `-- --memory 512m`. Note: the engine accepts suffixes 'b/k/m/g', not k8s-style 'Mi'/'Gi'] Memory limit for the container (e.g. '512Mi', '1Gi', or '1g') | | `--user` | Username or UID (format: \`\{rel=""nofollow""} ## Running Gefyra ### 1. Set up Gefyra with your Colima cluster: ```sh gefyra up ``` **Important**: ### 2. Run a local Docker container with Gefyra in order to connect it with the cluster. #### 2.1 Build a simple Docker image with a local tag. Save the following two files in a directory on your disk. ```dockerfile [Dockerfile] FROM ubuntu # run a server on port 8000 RUN apt update && apt install -y iproute2 iputils-ping python3 traceroute wget curl COPY local.py local.py CMD python3 local.py ``` ::code-collapse ```py [local.py] import http.server import signal import socket import socketserver import sys from datetime import datetime if sys.argv[1:]: port = int(sys.argv[1]) else: port = 8000 class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() hostname = socket.gethostname() now = datetime.utcnow() self.wfile.write( bytes( f"

Hello from Gefyra. It is {now} on" f" {hostname}.

".encode("utf-8") ) ) my_handler = MyHttpRequestHandler server = socketserver.ThreadingTCPServer(("", port), my_handler) def signal_handler(signal, frame): try: if server: server.server_close() finally: sys.exit(0) signal.signal(signal.SIGINT, signal_handler) try: while True: sys.stdout.flush() server.serve_forever() except KeyboardInterrupt: pass server.server_close() ``` :: #### 2.2 Build it by running `docker build -f Dockerfile . -t pyserver` in your directory. #### 2.3 Execute Gefyra's run command: ```sh gefyra run -d -i pyserver -N mypyserver -n default ``` **Important**: `gefyra run` is just a wrapper for `docker run` (with additional flags), yet it also applies Gefyra's networking configuration to connect the container with Kubernetes. Check out [the docs for `gefyra run`](https://gefyra.dev/en/quick-start/cli#run) ### 3. *Exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash ``` ```sh wget -O- hello-nginx ``` will print out the website of the cluster service *hello-nginx* from within the cluster. 🚀 ### 4. Create a bridge to redirect the traffic from the cluster application to the one running locally: ```sh gefyra bridge -N mypyserver -n default --ports 80:8000 --target deploy/hello-nginxdemo/hello-nginx ``` Check out the locally running server serving the cluster by refreshing the address from the service in Kubernetes. It shows you a different message: `Hello from Gefyra. It is ...`. Yes, that is really coming from your local container! 😎 ### 5. List all running *bridges*: You can list all currently active bridges with: ```sh gefyra list --bridges ``` You will find all local containers that are currently linked into the cluster serving requests. ### 6. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge --all ``` Check out the original response from the service. The cluster is now reset to its inital state again. ## Cleaning up 1. Remove Gefyra's components from the cluster and your local Docker host with: ```sh gefyra down ``` 2. Remove the locally running Kubernetes cluster with ```sh colima delete ``` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Getting started with Gefyra and Docker Desktop Kubernetes on MacOS **Try out our [Docker Desktop Extension](https://gefyra.dev/en/quick-start/docker-desktop-extension)!** **Note:** Gefyra works the same for different Kubernetes distributions. Docker Desktop doesn't come with an ingress installed which must be added to the cluster to get things working. You can easily try Gefyra yourself following this small example. ## Prerequisites 1. Follow the [installation](https://gefyra.dev/en/quick-start/installation/) for MacOS. 2. Start the Kubernetes cluster that comes with Docker Desktop. This may take moment. ![docker desktop kubernetes settings](https://gefyra.dev/img/getting_started_docker_desktop_kubernetes.png) 3. Tell kubectl to use your docker-desktop cluster: ```sh kubectl config use-context docker-desktop ``` 4. Install an ingress to enable routing for the cluster. For this guide we use the nginx ingress controller like this: ```sh kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/cloud/deploy.yaml ``` 5. Now patch the nginx ingress controller service to make port `8080` available: ```sh kubectl patch svc -n ingress-nginx ingress-nginx-controller -p '{"spec": {"ports": [{"appProtocol": "http", "name": "http", "port": 8080, "protocol": "TCP", "targetPort": "http"}]}}' --type merge ``` 6. Apply some workload, for example from the testing directory of this repo: ```sh kubectl apply -f https://raw.githubusercontent.com/gefyrahq/gefyra/main/testing/workloads/hello_dd.yaml ``` Check out this workload running under: {rel=""nofollow""} 7. Set up Gefyra with the following command: **For Docker Desktop <4.16.x:** ```sh gefyra up ``` **For Docker Desktop >=4.16.x:** ```sh gefyra up --host=kubernetes.docker.internal ``` ## Running Gefyra ### 1. Run a local Docker image with Gefyra in order to make it part of the cluster. 1. Build your Docker image with a local tag, for example from the testing directory: ```sh cd testing/images/ && docker build -f Dockerfile.local . -t pyserver ``` 2. Execute Gefyra's run command: ```sh gefyra run -i pyserver -N mypyserver -n default ``` 3. *exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash wget -O- hello-nginx ``` will print out the website of the cluster service hello-nginx from within the cluster. ### 2. Create a bridge in order to intercept the traffic to the cluster application with the one running locally ```sh gefyra bridge -N mypyserver -n default --port 8000:80 --target deploy/hello-nginxdemo/hello-nginx ``` Check out the locally running server comes up under: {rel=""nofollow""} ### 3. List all running *bridges*: ```sh gefyra list --bridges ``` ### 4. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge -N mypybridge ``` Check out the initial response from: {rel=""nofollow""} ## Cleaning up Remove Gefyra's components from the cluster with ```sh gefyra down ``` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Getting started with Gefyra and k3d ## Prerequisites 1. K3d is [installed](https://k3d.io/#installation){rel=""nofollow""} (at least in version v5.4.9) 2. Gefyra is [available](https://gefyra.dev/en/quick-start/installation) (at least in version 2.0.0) **Hint** there is a bug in Docker Desktop v4.17-v4.18 which causes `gefyra up` to fail with k3d clusters that run on that DD version. ## Creating a local Kubernetes cluster ![minikube](https://gefyra.dev/img/minikube2.gif){.w-full} ### 1. Create a local Kubernetes cluster with k3d by running: ```sh k3d cluster create mycluster --agents 1 -p 8080:80@agent:0 -p 31820:31820/UDP@agent:0 ``` This creates a Kubernetes cluster that binds port 8080 and 31820 to localhost. The `kubectl` context is immediately set to this cluster. ### 2. Apply some workload, for example from the testing directory of this repo: ```sh kubectl apply -f https://raw.githubusercontent.com/gefyrahq/gefyra/main/testing/workloads/hello.yaml ``` Check out this workload running under: {rel=""nofollow""} ## Running Gefyra ### 1. Set up Gefyra with your k3d cluster: ```sh gefyra up ``` ### 2. Run a local Docker container with Gefyra in order to connect it with the cluster. #### 2.1 Build a simple Docker image with a local tag. Save the following two files in a directory on your disk. ```dockerfile [Dockerfile] FROM ubuntu # run a server on port 8000 RUN apt update && apt install -y iproute2 iputils-ping python3 traceroute wget curl COPY local.py local.py CMD python3 local.py ``` ::code-collapse ```py [local.py] import http.server import signal import socket import socketserver import sys from datetime import datetime if sys.argv[1:]: port = int(sys.argv[1]) else: port = 8000 class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() hostname = socket.gethostname() now = datetime.utcnow() self.wfile.write( bytes( f"

Hello from Gefyra. It is {now} on" f" {hostname}.

".encode("utf-8") ) ) my_handler = MyHttpRequestHandler server = socketserver.ThreadingTCPServer(("", port), my_handler) def signal_handler(signal, frame): try: if server: server.server_close() finally: sys.exit(0) signal.signal(signal.SIGINT, signal_handler) try: while True: sys.stdout.flush() server.serve_forever() except KeyboardInterrupt: pass server.server_close() ``` :: #### 2.2 Build it by running `docker build -f Dockerfile . -t pyserver` in your directory. #### 2.3 Execute Gefyra's run command: ```sh gefyra run -d -i pyserver -N mypyserver -n default ``` **Important**: `gefyra run` is just a wrapper for docker run (with additional flags), yet it also applies Gefyra's networking configuration to connect the container with Kubernetes. Check out [the docs for gefyra run](https://gefyra.dev/en/quick-start/cli#run) ### 3. *Exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash ``` ```sh wget -O- hello-nginx ``` will print out the website of the cluster service *hello-nginx* from within the cluster. 🚀 ### 4. Create a bridge to redirect the traffic from the cluster application to the one running locally: ```sh gefyra bridge -N mypyserver -n default --ports 80:8000 --target deploy/hello-nginxdemo/hello-nginx ``` Check out the locally running server serving the cluster by refreshing the address from the service in Kubernetes. It shows you a different message: `Hello from Gefyra. It is ...`. Yes, that is really coming from your local container! 😎 ### 5. List all running *bridges*: You can list all currently active bridges with: ```sh gefyra list --bridges ``` You will find all local containers that are currently linked into the cluster serving requests. ### 6. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge --all ``` Check out the original response from the service. The cluster is now reset to its inital state again. ## Cleaning up Remove Gefyra's components from the cluster and your local Docker host with: ```sh gefyra down ``` ## Deleting the locally running k3d Kubernetes cluster with ```sh k3d cluster delete mycluster ``` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Getting started with Gefyra and kind ## Prerequisites 1. Follow the [installation](https://gefyra.dev/en/quick-start/installation) for your preferred platform. 2. Create a local Kubernetes cluster with `kind` like this: Create a file `kind-config.yaml`: ```yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 31820 hostPort: 31820 protocol: udp ``` Run: ```bash kind create cluster --config kind-config.yaml ``` ## Running Gefyra ### 1. Set up Gefyra with ```sh gefyra up ``` ### 2. Run a local Docker image with Gefyra in order to make it part of the cluster. #### 2.1 Build your Docker image with a local tag, for example from the testing directory: ```sh cd testing/images/ && docker build -f Dockerfile.local . -t pyserver ``` #### 2.2 Execute Gefyra's run command: ```sh gefyra run -i pyserver -N mypyserver -n default ``` #### 2.3 *Exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash wget -O- hello-nginx ``` will print out the website of the cluster service hello-nginx from within the cluster. ### 3. Create a bridge in order to intercept the traffic to the cluster application with the one running locally: ```sh gefyra bridge -N mypyserver -n default --port 8000:80 --target deploy/hello-nginxdemo/hello-nginx ``` Check out the locally running server comes up under: {rel=""nofollow""} ### 4. List all running *bridges*: ```sh gefyra list --bridges ``` ### 5. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge -N mypybridge ``` Check out the initial response from: {rel=""nofollow""} ## Cleaning up 1. Remove Gefyra's components from the cluster with ```sh gefyra down ``` 2. Remove the locally running Kubernetes cluster with ```sh kind delete cluster ``` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Getting started with Gefyra and Minikube ::note Please refer to the general [getting started guide](https://gefyra.dev/en/local-environments/getting-started) for Gefyra as this is about Minikube, too. :: ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Setting up a Shared Kubernetes Cluster ::card-group :::card --- title: Installing Gefyra in a Cluster to: https://gefyra.dev/en/shared-environments/installation --- Installing Gefyra to a remote cluster is usually slightly different to a local setup. This is because the networking aspect differs considerably between a local cluster, that might be created with overlay networks and port-forwarding, and remote clusters with cloud-specific routing components. Starting with Gefyra 2, you get good control of the cluster-side components. ::: :::card --- title: Managing Gefyra Clients to: https://gefyra.dev/en/shared-environments/clients --- Gefyra Clients provide a way to grant multiple clients (i.e. users, robots, pipelines, etc.) limited access to a Kubernetes cluster in order to use Gefyra's capabilities. They are managed with gefyra clients [COMMAND]. ::: :::card --- title: Connecting to Gefyra to: https://gefyra.dev/en/shared-environments/connecting --- If you have a Gefyra client file and want to connect to a shared Kubernetes cluster, ::: :::card --- title: Guides to Remote Kubernetes Clusters to: https://gefyra.dev/en/remote-k8s/getting-started --- This chapter contains guides on how to set up shared remote Kubernetes for Gefyra. These guides are usually for multiple client use cases. ::: :: # Gefyra (Remote) Cluster Installation ## Prerequisites - Gefyra is [available](https://gefyra.dev/en/quick-start/installation/) (at least in version 2.0.0) ## The Installation There are a couple of options for the installation procedure. Gefyra's executable ships with all required Kubernetes configs for that specific version. To introspect what is going to be installed into your cluster, just run `gefyra install`. This command generates a list of Kubernetes objects that can either be stored for manual modification, or directly applied to the cluster. ```sh > gefyra install apiVersion: v1 kind: Namespace metadata: name: gefyra --- apiVersion: v1 kind: ServiceAccount metadata: name: gefyra-operator namespace: gefyra --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole [...] ``` Please check out the [CLI reference for that command](https://gefyra.dev/en/quick-start/cli#install). If the default configuration is suitable for your environment, directly apply it with: ```sh gefyra install | kubectl apply -f - ``` That will pipe the Kubernetes configs generated by Gefyra's install command directly into the cluster context that is currently active. ::note Check your active cluster context with `kubectl config current-context` . :: ## Default networking Gefyra depends on a working [Wireguard VPN](https://www.wireguard.com/){rel=""nofollow""} connection between the cluster and Gefyra's clients. Setting up that connection is completely managed by Gefyra and only requires little configuration from a cluster admin: that is configuring the VPN route. ::note Gefyra's default to expose its Wireguard endpoint is via a Kubernetes service of type **NodePort** . However, this can only work if the Kubernetes nodes have a public (internet-routable) IP address, or at least this IP is reachable for all clients. :: You can check out the Kubernetes service object in the output of `gefyra install`. ```sh gefyra install | grep "type:" -B21 ``` ```yaml apiVersion: v1 kind: Service metadata: annotations: {} labels: gefyra.dev/app: stowaway gefyra.dev/provider: stowaway gefyra.dev/role: connection name: gefyra-stowaway-wireguard namespace: gefyra spec: ports: - name: gefyra-wireguard nodePort: 31820 port: 51820 protocol: UDP targetPort: 51820 selector: gefyra.dev/app: stowaway gefyra.dev/provider: stowaway gefyra.dev/role: connection type: NodePort ``` This service will open up the port **31820** on all of your Kubernetes nodes and route VPN traffic to Gefyra. If you don't want to expose Gefyra via a *NodePort* service, or you don't have routable IPs on your Kubernetes nodes, you need to set up a **UDP load balancing** for Gefyra. Luckily, Gefyra's got you covered. ## Setting up a UDP `Loadbalancer` ::note Gefyra's VPN connection is established using UDP traffic. Not all cloud providers offer a UDP load balancing solution. If you can not use a *Loadbalancer* , you have to stick with the *NodePort* service. :: To switch the load balancer service for the installation, just set the appropriate option flag for the `gefyra install` command: ```sh gefyra install --service-type=Loadbalancer ``` In many cases, the external infrastructure for a Kubernetes cluster is managed via service annotations. With Gefyra you can set custom annotations easily using the `--service-annotations` as often as you need. For example: ```sh gefyra install --service-type=Loadbalancer --service-annotations service.beta.kubernetes.io/aws-load-balancer-nlb-target-type=ip --service-annotations service.beta.kubernetes.io/aws-load-balancer-scheme=internet-facing ``` will create the following service in your cluster: ```yaml apiVersion: v1 kind: Service metadata: annotations: # see these annotations service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing labels: gefyra.dev/app: stowaway gefyra.dev/provider: stowaway gefyra.dev/role: connection name: gefyra-stowaway-wireguard namespace: gefyra spec: ports: - name: gefyra-wireguard port: 31820 protocol: UDP targetPort: 51820 selector: gefyra.dev/app: stowaway gefyra.dev/provider: stowaway gefyra.dev/role: connection type: LoadBalancer ``` Please be aware that Gefyra comes with a few manually crafted presets for popular Kubernetes offering. Check out the next section to learn how you install Gefyra using an available installation preset. ## Presets To make it as convenient as possible, Gefyra offers presets for widely used Kubernetes offerings, such as Google's GKE or Amazon EKS. Please check available presets with: ```sh gefyra install --help | grep preset --preset TEXT Set configs from a preset (available: aws,gke) ``` Currently, it's only *aws* and *gke*. If you want to add another preset for another popular Kubernetes provider, please consider[ opening a ticket on GitHub](https://github.com/gefyrahq/gefyra/issues/new?assignees=&labels=enhancement&projects=&template=feature-request.yaml){rel=""nofollow"" target="blank"} for it. **Example:** If you install Gefyra to an EKS cluster, you only have to set the preset `gefyra install --preset aws | kubectl apply -f -`, and it will automatically create the *Network Load Balancer* via the required annotations on the Kubernetes service: ```yaml apiVersion: v1 kind: Service metadata: annotations: # see these annotations service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing service.beta.kubernetes.io/aws-load-balancer-type: nlb labels: gefyra.dev/app: stowaway gefyra.dev/provider: stowaway gefyra.dev/role: connection name: gefyra-stowaway-wireguard namespace: gefyra spec: ports: - name: gefyra-wireguard port: 31820 protocol: UDP targetPort: 51820 selector: gefyra.dev/app: stowaway gefyra.dev/provider: stowaway gefyra.dev/role: connection type: LoadBalancer ``` # Working With Gefyra Clients ::note Gefyra Clients provide a way to grant multiple clients (i.e. users, robots, pipelines, etc.) limited access to a Kubernetes cluster in order to use Gefyra's capabilities. They are managed with [gefyra clients [COMMAND]](https://gefyra.dev/en/quick-start/cli#clients) . :: ## Shared Cluster Access Each created client object get a dedicated *Kubernetes Service Account* attached that is being used by any Gefyra client during its interaction with the cluster. The corresponding *client file*, which contains the connection parameters for the *Service Account* can be retrieved from the cluster by the administrator with Gefyra's CLI. This client file can be then distributed to anyone which needs to `connect`, `run` or `bridge` workloads in the given cluster. The permissions of the Kubernetes service account are limited, following the principle of the least privilege. Hence, Gefyra clients can only operate in the cluster with the well-defined set of Gefyra's actions. This flow gives a brief overview of Gefyra's workflow for teams: ::mermaid --- :config: config code: flowchart%20TD%3B%0A%20%20%20%20install%5B%22DevOps%20installs%20Gefyra%20(%3Ca%20href%3D'%2Fen%2Fquick-start%2Fcli%23install'%3Egefyra%20install%3C%2Fa%3E)%22%5D%0A%20%20%20%20generate%5B%22DevOps%20generates%20Gefyra%20client%20(%3Ca%20href%3D'%2Fen%2Fquick-start%2Fcli%23clients'%3Egefyra%20clients%20create%3C%2Fa%3E)%22%5D%0A%20%20%20%20save%5B%22DevOps%20saves%20Gefyra%20client%20files%20(%3Ca%20href%3D'%2Fen%2Fquick-start%2Fcli%23clients-config'%3Egefyra%20clients%20config%3C%2Fa%3E)%22%5D%0A%20%20%20%20distribute%5B%22DevOps%20distributes%20client%20file%22%5D%0A%20%20%20%20connect%5B%22Developer%20connects%20via%20client%20file%20(%3Ca%20href%3D'%2Fen%2Fquick-start%2Fcli%23connections'%3Egefyra%20connections%3C%2Fa%3E)%22%5D%0A%20%20%20%20run%5B%22Developer%20runs%20workload%20(%3Ca%20href%3D'%2Fen%2Fquick-start%2Fcli%23run'%3Egefyra%20run%3C%2Fa%3E)%22%5D%0A%20%20%20%20install--%3Egenerate%0A%20%20%20%20generate--%3Esave%0A%20%20%20%20save--%3Edistribute%0A%20%20%20%20distribute--%3Econnect%0A%20%20%20%20connect--%3Erun --- :: ::warning{:title="Don't share client connections"} Although clients may be used by multiple machines, it is neither recommended not will it work simultaneously. Once a client connects to a cluster, it agrees with Gefyra's Operator on a dedicated IP-range that no other client can use at the same time. Clients may connect and disconnect at any time. When disconnecting from the cluster, clients release their VPN peer (and thus their IP-range) association. :: ## Prerequisites - Gefyra is [available](https://gefyra.dev/en/quick-start/installation) (at least in version 2.0.0) - Gefyra is [installed](https://gefyra.dev/en/shared-environments/installation) to a shared Kubernetes cluster - Admin access to the shared cluster ## Creating a Gefyra Client You can create as many clients as you need in a cluster. Every client will have it's very own VPN connection to the cluster. An admin manages clients via Gefyra's `gefyra client` command group in the CLI. Gefyra operates with the currently active cluster context on the machine it is running on. ::note Check your active cluster context with `kubectl config current-context` . :: ```sh > gefyra client Manage clients for a Gefyra installation Commands: config (write) Get a Gefyra connection config for a client create Create a new Gefyra client delete (rm,remove) Mark a Gefyra client for deletion inspect (show,get) Discribe a Gefyra client list (ls) List all Gefyra clients ``` You can create one client object with: ```sh > gefyra client create 1 client(s) created successfully ``` That command created a randomly named client in your cluster. You can find it with: ```sh > gefyra clients ls ID STATE CREATED 20d50da476524eaf8dd511deed55fc63 GefyraClientState.REQUESTED Creating... ``` Once the client is ready, you will find the following output: ```sh > gefyra clients ls ID STATE CREATED 20d50da476524eaf8dd511deed55fc63 GefyraClientState.WAITING 2023-10-06T15:21:19.771717Z ``` The client is now in the waiting state and ready for connection. To manage human-readable clients, you can set the client name with: ```sh gefyra clients create --client-id my-fancy-client ``` or create many clients at once using: ```sh gefyra clients create -n 10 ``` This will create a set of 10 clients in the cluster. ## Retrieving a *Client File* Gefyra clients require a client file to connect to this cluster. The admin is responsible to fetch these client files and distribute them to other machines, developers, etc. ### A Default Client File The following command prints the client file of the selected client to the console: ```sh gefyra clients config 20d50da476524eaf8dd511deed55fc63 {"client_id": "20d50da476524eaf8dd511deed55fc63", "kubernetes_server": "https://", "provider": "stowaway", "token": "", "namespace": "", "ca_crt": "", "gefyra_server": ":31820"} ``` As you can see, the *client file* is JSON-structured and contains a lot of secret information. Especially the *access token* of the Kubernetes service account that is associated with this Gefyra client, but also the other connection parameters are **highly sensible**. ::note Please handle the *client files* with care as they contain confidential information. Leaking these files may allow unidentified individuals access to your Gefyra cluster. :: You can either pipe that output to a file on your local machine: ```sh gefyra clients config 20d50da476524eaf8dd511deed55fc63 > 20d50da476524eaf8dd511deed55fc63.json ``` or use the *output flag* ```sh gefyra clients config 20d50da476524eaf8dd511deed55fc63 -o 20d50da476524eaf8dd511deed55fc63.json ``` in your current working directory. ### Providing Custom Connection Data ::note In this process, Gefyra tries to determine as many connection parameters as possible automatically. However, if there are network-related customizations to made for your client, please provide them at this point. :: If you need to specify the connection endpoint for Kubernetes differently, please use the `--kubernetes-api` option, e.g. ```sh gefyra clients config 20d50da476524eaf8dd511deed55fc63 --kubernetes-api "https://k8s.blueshoe.io" ``` If you need to specify Gefyra's VPN connection endpoint, please use the `--host` and/or `--port` option, e.g. ```sh gefyra clients config 20d50da476524eaf8dd511deed55fc63 --host 192.169.0.1 ``` This data will be written into the `client file` so that your clients can connect to the cluster using these parameters. If you fail to provide correct data to your clients, they might be unable to connect to the cluster. ### Distributing the Client File This *client file* is all a Gefyra client needs in order to establish a connection. Of course, you are free to distribute these files any way you want, but please keep in mind the security implications. ## Deleting a Gefyra Client You can delete a Gefyra client in every stage of its lifecycle. This will disconnect the client (forcefully) and render its client file invalid, thus the owner of the file will no longer be able to connect to the cluster. ```sh > gefyra clients delete 20d50da476524eaf8dd511deed55fc63 Client 20d50da476524eaf8dd511deed55fc63 marked for deletion ``` When you delete a Gefyra client, its credentials are also irretrievably deleted. # Connecting to Gefyra ::tip If you have a Gefyra client file and want to connect to a shared Kubernetes cluster, just run `gefyra connections connect -f ` :: ## Prerequisites - Gefyra is [available](https://gefyra.dev/en/quick-start/installation) (at least in version 2.0.0) - A running Docker host on the machine that connects - A Gefyra [client file](https://gefyra.dev/en/shared-environments/clients#a-default-client-file) ## Managing connections Client connections to a Gefyra cluster are managed with the `gefyra connections` command group. The connection itself consists of a file, that is located in a local user directory, and *usually* a Docker container that acts as a VPN endpoint on a local machine. ### Connect ::note You can only connect to a Gefyra cluster with a [client file](https://gefyra.dev/en/shared-environments/clients#distributing-the-client-file) . If you don't have such a client file, either [set up Gefyra in a Kubernetes cluster](https://gefyra.dev/en/shared-environments/installation) and create yourself [a Gefyra client](https://gefyra.dev/en/shared-environments/clients#creating-a-gefyra-client) , or find the responsible person and ask for access. :: Establishing a connection (**for the first time**) to Gefyra works like this: ```sh > gefyra connections connect -f myfancyclient.json Creating the cluster connection 'default' | ▶▶▶▶▶▶▶ | / 0 in 28s Connection established with connection name 'default'. Run 'gefyra connections list' to see all connections. ``` This example assumes, there is a client that provides the client file *myfancyclient.json*. A couple of things happened during this process: 1. Gefyra fetched the ad-hoc VPN credentials for this connection 2. A container for the Gefyra connection with name *default* has been started 3. A dedicated Docker network has been created 4. The connection was successfully checked If you check your Docker host, you will find a container named `gefyra-cargo-default` running. That's the gateway into the cluster. ::warning Since we didn't specify a *connection name* and there was no *default* connection available before, creating it was successful. However, there is only one *default* connection on a client machine. Additional connections must [be assigned a name](https://gefyra.dev/#connection-names) . :: Once you have a stopped connection, you don't need the client file anymore to connect. Just run the following with the *default* connection: ```sh gefyra connections connect ``` The Gefyra connection will be back up in no time. Of course, if you do have multiple connections, you have to specify the connection name with the `--connection-name` option. ::warning After you successfully connected a machine with a Gefyra cluster, the *client file* is typically superseded at that point. Gefyra stores the credentials from the file elsewhere, so a user doesn't have to handle the file. However, if you remove your connection and want to reconnect to the cluster (assuming the Gefyra client is still the same) you may connect to the cluster with that file again. Yet, you can also request a new one, which is safer than having a *client file* dangling. :: ### Listing connections To see all Gefyra connections on a local machine, please run the following: ```sh > gefyra connections list NAME VERSION CREATED STATUS default 2.0.0 2023-10-10T18:36:15.519969679Z running ``` You will find the status of all of your connections here. It can be `running`, `stopped` or `error`. ### Disconnect To actively disconnect from the cluster, you run this command: ```sh gefyra connections stop ``` This assumes you have a *default* connection currently running. If not, you have to provide a valid connection name with the `[connection-name]` argument. You will find this connection to be stopped from the client's side. However, if you want to reconnect to the cluster, you can now run `gefyra connections connect` again. The connection process will be superfast this time. ::note If you want to delete a connection, and thus release the Gefyra client in the cluster, you can run `gefyra connections remove` . If you want to reconnect later, you will need a *client file* again. :: ### Connection Names You can assign (and have to) names to your connections if you have more than one. Almost all commands of the Gefyra CLI support the `--connection-name` option to specify the connection a certain command is targeting. Most importantly, for `gefyra run --connection-name` you specify to which cluster a local container is connected. To create a new connection with a name (in this example `my-conn1`), please run the following to set up a connection with a given name: ```sh gefyra connections connect --connection-name my-conn1 ... ``` The connection will show up in the connection list: ```sh > gefyra connections list NAME VERSION CREATED STATUS default 2.0.0 2023-10-10T18:36:15.519969679Z running my-conn1 2.0.1 2023-10-12T12:14:11.48715/726Z running ``` You can manage connections based on the local names, i.e. halt the connection, reconnect, remove it, and run containers with it. ## Simultaneous Connections As you can see above, it is possible to create a list of connections simultaneously. They can be individually managed, like started and stopped, even at the same time. It is possible to have multiple connections to one cluster, too. # Setting up Shared Kubernetes Clusters Hey! We would be very happy to know about your Kubernetes development setup. If you can't find your distribuition in this list, please request a guide by creating [a GitHub issue using this template](https://github.com/gefyrahq/gefyra/issues/new?assignees=&labels=enhancement&template=guide-request.md&title=%5BGuide+request%5D%3A+){rel=""nofollow""}. It's that simple and very helpful. Select your preferred Kubernetes provider from below to start working with Gefyra. ::card-group :::card --- icon: i-material-icon-theme:gcp title: Google Cloud Platform (GCP) to: https://gefyra.dev/en/remote-k8s/gcp --- This guide will show you how to use Gefyra for the remote development of a Kubernetes Application running in the Google Kubernetes Engine (GKE). ::: :::card --- icon: i-simple-icons-amazoneks title: Elastic Kubernetes Service (EKS) to: https://gefyra.dev/en/remote-k8s/eks --- This guide will show you how to use Gefyra for the remote development of a Kubernetes ::: :::card --- icon: i-simple-icons-kubernetes title: SysEleven MetaKube to: https://gefyra.dev/en/remote-k8s/sys11 --- This guide will show you how to use Gefyra for the remote development of a Kubernetes Application running on MetaKube. ::: :: # Getting started with Gefyra and the Google Cloud Platform ## Prerequisites 1. You have the [gcloud](https://cloud.google.com/sdk/docs/install-sdk){rel=""nofollow""} command installed 2. Follow the [installation](https://gefyra.dev/en/quick-start/installation) of Gefyra for your preferred platform Additionally you need an account for the Google Cloud Platform including the permission to create a new cluster. Make sure your gcloud is using the right project configuration. Googles documentation is available [here](https://cloud.google.com/sdk/docs/install-sdk){rel=""nofollow""}. ## Setup a cluster 1. The easiest way to create a new cluster is using gcloud: ```sh gcloud container clusters create spacecraft ``` This may take a few minutes, there will be 3 VM instances running a kubernetes cluster ready to serve your applications. gcloud will set your kubectl context to the created cluster, nothing to worry about! 2. The last thing we need to do is open a port in the firewall. This allows gefyra to connect to the cluster using wireguard: ```sh gcloud compute firewall-rules create gefyra --allow udp:31820 ``` 3. Apply some workload, for example from the testing directory of this repo: ```sh kubectl apply -f https://raw.githubusercontent.com/gefyrahq/gefyra/main/testing/workloads/hello_dd.yaml ``` ## Running Gefyra 1. At first, we need a host IP of one of our compute instances. You can get them with running `gcloud compute instances list`. Pick one of them. 2. Now you can run `gefyra up --host ` 3. Run a local Docker image with Gefyra in order to make it part of the cluster. 1. Build your Docker image with a local tag, for example from the testing directory: ```sh cd testing/images/ && docker build -f Dockerfile.local . -t pyserver ``` 2. Execute Gefyra's run command: ```sh gefyra run -i pyserver -N mypyserver -n default ``` 3. *Exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash ``` 4. Print out the website of the cluster service *hello-nginx* from within the cluster. ```sh wget -O- hello-nginx ``` 4. Create a bridge in order to intercept the traffic to the cluster application with the one running locally: ```sh gefyra bridge -N mypyserver -n default --port 80:8000 --target deploy/hello-nginxdemo/hello-nginx ``` 5. List all running *bridges*: ```sh gefyra list --bridges ``` 6. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge -N mypybridge ``` ## Cleaning up Remove Gefyra's components from the cluster with `gefyra down` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Getting started with Gefyra and Elastic Kubernetes Service (EKS) ## Prerequisites 1. You have the [aws](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html){rel=""nofollow""} command installed and configured 2. Follow the [installation](https://gefyra.dev/en/quick-start/installation) of Gefyra for your preferred platform Additionally, you need an account for the Amazon Web Services including the permission to create a new cluster. Make sure your `aws` is using the right project configuration and/or profile. ## Setup a cluster 1. The easiest way to create a new cluster is using `aws`: ```sh aws eks create-cluster --name gefyra --kubernetes-version 1.22 --role-arn arn:aws:iam::111122223333:role/myAmazonEKSClusterRole --resources-vpc-config subnetIds=subnet-ExampleID1,subnet-ExampleID2,securityGroupIds=sg-ExampleID1 ``` This may take a long time. You can check the cluster status with: ```sh > aws eks describe-cluster --name gefyra --query "cluster.status" "ACTIVE" ``` 2. Depending on your way of creating the cluster, you may have to add a `NodeGroup` to the cluster, so you can actually run workloads. 3. Pull the `kubectl` configuration to connect to the cluster, with: ```sh aws eks update-kubeconfig --name gefyra ``` Now you should be able to run any `kubectl` command in that cluster. 4. Apply some workload, for example from the testing directory of this repo: ```sh kubectl apply -f https://raw.githubusercontent.com/gefyrahq/gefyra/main/testing/workloads/hello_dd.yaml ``` 5. **Important:** before Gefyra can connect from outside the cluster, you must set the security group of the nodes to allow UDP traffic on port 31820. Find out the security group of the cluster. Then, create the required inbound traffic rule: ```sh > aws eks describe-cluster --name gefyra --query "cluster.resourcesVpcConfig.clusterSecurityGroupId" ``` ```sh aws ec2 authorize-security-group-ingress --group-id "" --protocol udp --port 31820 --cidr 0.0.0.0/0 ``` ## Running Gefyra 1. At first, we need a host IP of one of our nodes. You can get them by running ```sh kubectl get nodes -o wide | awk {'print $1" " $2 " " $7'} | column -t ``` Pick one of them from the `EXTERNAL-IP` column. 2. Now you can run ```sh gefyra up --host ``` 3. Run a local Docker image with Gefyra to make it part of the cluster. 1. Build your Docker image with a local tag, for example from the testing directory: ```sh cd testing/images/ && docker build -f Dockerfile.local . -t pyserver ``` 2. Execute Gefyra's run command: ```sh gefyra run -i pyserver -N mypyserver -n default ``` 3. *Exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash ``` 4. Print out the website of the cluster service *hello-nginx* from within the cluster. ```sh wget -O- hello-nginx ``` 4. Create a bridge to intercept the traffic to the cluster application with the one running locally: ```sh gefyra bridge -N mypyserver -n default --port 80:8000 --target deploy/hello-nginxdemo/hello-nginx ``` 5. List all running *bridges*: ```sh gefyra list --bridges ``` 6. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge -N mypybridge ``` ## Cleaning up Remove Gefyra's components from the cluster with `gefyra down` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Getting started with Gefyra and SysEleven MetaKube ## Prerequisites 1. You have a [MetaKube](https://metakube.syseleven.de/){rel=""nofollow""} account and privileges to create a new cluster 2. Follow the [installation](https://gefyra.dev/en/quick-start/installation) of Gefyra for your preferred platform ## Setup a cluster You may follow [this guide to create a cluster using the MetaKube management console](https://docs.syseleven.de/metakube/en/tutorials/create-a-cluster){rel=""nofollow""}. This guide assumes you are running an **OpenStack**-based Kubernetes cluster on SysEleven. ![syseleven cluster settings](https://gefyra.dev/img/sys11_image2.png){.w-full} **Important:** Before Gefyra can connect from outside the cluster, you must set the security group of the nodes to allow UDP traffic on port 31820. ![syseleven security group settings](https://gefyra.dev/img/sys11_image1.png){.w-full} Please set the direction to *Ingress* and the protocol to *UDP*. The port range should be set to *31820* and the source CIDR to *0.0.0.0/0*. That way, Gefyra can connect to any data plane node of the cluster using a [Floating-IP](https://docs.syseleven.de/syseleven-stack/en/reference/network){rel=""nofollow""}. After all of the MetaKube components are ready, you can download the *kubeconfig* to access the cluster using `kubectl`. Just click on the "Download Config" button in the MetaKube management console and save the file to your local machine. ## Running Gefyra 1. You may apply some workload, for example from Gefyra's testing directory: ```sh kubectl apply -f https://raw.githubusercontent.com/gefyrahq/gefyra/main/testing/workloads/hello_dd.yaml ``` 2. At first, we need a host IP of one of our nodes. You can get it by running: ```sh kubectl get nodes -o wide | awk {'print $1" " $2 " " $7'} | column -t ``` Pick one of them from the `EXTERNAL-IP` column. 3. Now you can run ```sh gefyra up --host ``` using the IP you just picked. This will create the Gefyra components in your cluster and local host. 4. Run a local Docker image with Gefyra to make it part of the cluster. 1. Build your Docker image with a local tag, for example from Gefyra's testing directory (in the repo): ```sh cd testing/images/ && docker build -f Dockerfile.local . -t pyserver ``` 2. Execute Gefyra's run command: ```sh gefyra run -i pyserver -N mypyserver -n default ``` 3. *Exec* into the running container and look around. You will find the container to run within your Kubernetes cluster. ```sh docker exec -it mypyserver bash ``` 4. Print out the website of the cluster service *hello-nginx* from within the cluster. ```sh wget -O- hello-nginx ``` 5. Create a bridge to redirect the traffic from the cluster application to the one running locally: ```sh gefyra bridge -N mypyserver -n default --ports 80:8000 --target deploy/hello-nginxdemo/hello-nginx ``` 6. List all running *bridges*: ```sh gefyra list --bridges ``` 7. *Unbridge* the local container and reset the cluster to its original state: ```sh gefyra unbridge --all ``` ## Cleaning up Remove Gefyra's components from the cluster with `gefyra down` ::card Did everything work as expected? How was the experience of using Gefyra? We'd appreciate if you could take 2 minutes of your time to fill out our [feedback form](https://forms.gle/AWT9NparpTVk8E978){rel=""nofollow""} . #title Please provide us with your feedback :: # Use Cases and Demos ::card-group :::card --- icon: i-simple-icons-go title: Developing Go Applications with Gefyra to: https://gefyra.dev/en/usecases-and-demos/golang --- This guide will show you how to use Gefyra for the remote development of a Go application. ::: :::card --- icon: i-devicon-plain:oauth title: OAuth2 Demo with a Sidecar to: https://gefyra.dev/en/usecases-and-demos/oauth2-demo --- This guide will show you how to use Gefyra for the remote development of a OAuth2 demo with a sidecar. ::: :::card --- icon: i-material-icon-theme:gcp title: Remote Development on Google Kubernetes Engine (GKE) to: https://gefyra.dev/en/usecases-and-demos/remote-gke --- This guide will show you how to use Gefyra for the remote development of a Kubernetes Application running on MetaKube. ::: :::card --- icon: i-simple-icons-ubuntu title: Run an Ubuntu Container in a Namespace to: https://gefyra.dev/en/usecases-and-demos/ubuntu-in-namespace --- This example demonstrates how to run a local Ubuntu container instance as part of your Kubernetes namespace. ::: :: # Developing Go Applications with Gefyra ::tip Simple Usecase :: ## What you will learn - Running a Go application in a local container with hot code reloading - Using Gefyra to bridge the container into a Kubernetes cluster ## What you will need - [Gefyra](https://gefyra.dev/en/quick-start/installation) - [Getdeck](https://github.com/Getdeck/getdeck){rel=""nofollow""} for setting up the development infrastructure (runs on `k3d`) - A copy of {rel=""nofollow""} - Optionally: [k3d](https://k3d.io){rel=""nofollow""} or any other preferred Kubernetes cluster ## Creating the Development Infrastructure After cloning the gefyra-demos repository, you can start a local k3d based Kubernetes cluster with the Go demo workload by running ```sh cd golang-demo deck get deck.yaml ``` Once everything is up and running, you can visit {rel=""nofollow""} to verify that everything worked as expected. ## The Demo Application You can look at and tweak the code for the demo application in `app/main.go`. You will find a very simple HTTP API that returns a String when it receives GET requests at the base route. In the `app`-directory, you'll also find the Dockerfile that is used to build the container image containing our application. **Note**: In the Dockerfile, we install [air](https://github.com/cosmtrek/air){rel=""nofollow""}, a hot reloading utillity for Go development. In a production Dockerfile, you'd want to specify a dedicated build target to install air. ## Enter Gefyra In order to connect a locally running container to a Kubernetes cluster, we use Gefyra. First of all, we need to build an image on our development machine like so: ```sh cd app docker build . -t gefyra-golang-example ``` Once the build is finished, we are ready to get started with Gefyra: ```sh gefyra up gefyra run -i gefyra-golang-example -N gefyra-golang-example -n golang-demo -c air -v $(pwd):/app gefyra bridge -N gefyra-golang-example --container-name gefyra-golang-demo --deployment gefyra-golang-demo --port 3333:3333 -n golang-example ``` `gefyra up` will start the cluster and client side components needed for Gefyra to do it's thing. The `gefyra run` command will then start a container from the image that we just build in the development infrastructure that we created before. Finally, 'gefyra bridge' will overlay our local container over the one that we specified in the run command. Once Gefyra tells you that the bridge is established, you're ready to make some changes and check out hot code reloading in Kubernetes in action. Visit {rel=""nofollow""} in your browser and try changing the contents of the `io.WriteString` function. Since we mounted our code into the container during `gefyra run`, air will detect the changes and rebuild/restart our application. Refresh your browser and check out the results! # Create a Backend Application with a Sidecar and OAuth2 Authentication ::warning Advanced Usecase :: This is more of an advanced use-case, if you just want an easy example of how Gefyra works, check out the [getting started guide](https://gefyra.dev/en/local-environments/getting-started). ## What you will learn - Create a (Python-based) backend application that reads a JWT (JSON web token) - Get a local identity provider with [Keycloak](https://www.keycloak.org/){rel=""nofollow""} - Apply the Kubernetes sidecar pattern with [OAuth2-Proxy](https://oauth2-proxy.github.io/oauth2-proxy/){rel=""nofollow""} and connect the app to Keycloak - Find and fix a bug - Start coding locally within the Kubernetes cluster having the sidecar active ## What you will need - [Gefyra](https://gefyra.dev/en/quick-start/installation) - [Getdeck](https://github.com/Getdeck/getdeck){rel=""nofollow""} for setting up the development infrastructure (runs on `k3d`) - `kubectl` - A copy of {rel=""nofollow""} - Optionally: [k3d](https://k3d.io){rel=""nofollow""} or any other preferred Kubernetes cluster - Optionally: VSCode with Python debugger installed (or any other preferred IDE) That's about it. Let's get started. ## Creating the Development Infrastructure First, we need a Kubernetes-based development infrastructure which contains all required components. Luckily this can be achieved quite easily with the [`Deck CLI` from here](https://github.com/Getdeck/getdeck){rel=""nofollow""}. Just run: ```sh deck get --name oauth2-demo https://github.com/gefyrahq/gefyra-demos.git ``` and you will get a fresh `k3d` cluster running locally with all required components installed. **Important:** These workloads are intended for demonstration purposes and are not safe for production deployments. **Optional:** If you don't want to create the development infrastructure using `Getdeck` you can also provide it yourself. You need: - a Kubernetes cluster - an identity provider (preferably Keycloak) - a custom realm with an oauth2 client for the backend service - a test user with required privileges - ingress config that supports a full-fledged oauth2 login flow - the workload manifests for the backend application with the OAuth2-Proxy sidecar ## Getting the App Running **Optional:** In order to observe the workload booting up, check out [the Kubernetes dashboard](http://dashboard.127.0.0.1.nip.io:8080/#/workloads?namespace=oauth2-demo){rel=""nofollow""} coming with this `deck`. A healthy cluster looks like this: ![Kubernetes dashboard](https://gefyra.dev/img/usecases_oauth2-demo_dashboard1.png){.w-full} Once you have the workload running in Kubernetes, head over to {rel=""nofollow""}. The following page should come up asking you to sign in with *OpenID Connect*: ![OAuth2-Proxy login portal](https://gefyra.dev/img/usecases_oauth2-demo_oauth2-proxy.png){.mx-auto} Once you click the button you will be redirected to the central login of Keycloak, which looks like this: ![Keycloak login page](https://gefyra.dev/img/usecases_oauth2-demo_kc-login.png){.mx-auto} Please notice how you got redirected to the local domain of Keycloak [http://keycloak.127.0.0.1.nip.io:8080/...](http://keycloak.127.0.0.1.nip.io:8080/){rel=""nofollow""}. The demo workload contains a prepared user in Keycloak's database. You can use it to perform a login. The credentials are as follows: **Username**: ****Password**: ** Once you hit the *Sign In* button you will be redirected back to the beginning, but this time you will see the json output of the backend service: ```json {"Hello":"World"} ``` Voilà, we have a full-fledged [OpenID Connect](https://openid.net/connect/){rel=""nofollow""} login flow running in a Kubernetes cluster. So are we done yet? Not quite. Let's move on to the internals. ## The Scheme of the Infrastructure ### Kubernetes Overview The Kubernetes cluster is running three important components for this use case: - Keycloak: the identity provider compatible with OpenID Connect (OIDC) - OAuth2-Proxy: a reverse proxy compatible with OpenID Connect - Backend Application: a [FastAPI](https://fastapi.tiangolo.com/){rel=""nofollow""} application The OAuth2-Proxy is implemented as a sidecar and runs side-by-side in each [*Pod*](https://kubernetes.io/docs/concepts/workloads/pods/){rel=""nofollow""} with the backend application. If you are not yet familiar with the sidecar pattern [please check out this resource](https://www.oreilly.com/library/view/designing-distributed-systems/9781491983638/ch02.html){rel=""nofollow""}. Keycloak runs in a *StatefulSet* and is connected to a *PostgreSQL* database. The Kubernetes objects of the workload are as follows: ![Kubernetes object relation](https://gefyra.dev/img/usecases_oauth2-demo-k8s1.png){.w-full} In this picture you can find two [*Ingresses*](https://kubernetes.io/docs/concepts/services-networking/ingress/){rel=""nofollow""} definitions: one is serving the application [*Deployment*](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/){rel=""nofollow""} *oauth2-demo* which schedules one *Pod* under [oauth2-demo.127.0.0.1.nip.io:8080](http://oauth2-demo.127.0.0.1.nip.io:8080){rel=""nofollow""}, the other is serving Keycloak under [keycloak.127.0.0.1.nip.io:8080](http://keycloak.127.0.0.1.nip.io:8080){rel=""nofollow""}. **Important:** Please mind that port *8080* is a port mapping. From within the cluster you will see it running on port *80*. You can introspect the Ingress also with `kubectl`: ```sh > kubectl --namespace oauth2-demo get ingress NAME CLASS HOSTS ADDRESS PORTS AGE keycloak keycloak.127.0.0.1.nip.io 172.23.0.2 80, 443 56m keycloak-console keycloak.127.0.0.1.nip.io 172.23.0.2 80, 443 56m oauth2-demo oauth2-demo.127.0.0.1.nip.io 172.23.0.2 80 56m dashboard-kubernetes-dashboard dashboard.127.0.0.1.nip.io 172.23.0.2 80 56m ``` The next layer adds the Kubernetes [*Service*](https://kubernetes.io/docs/concepts/services-networking/service/){rel=""nofollow""} objects which are required to access a Pod. You can introspect the Services also with `kubectl`: ```sh > kubectl --namespace oauth2-demo get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE keycloak-http ClusterIP 10.43.40.200 80/TCP,8443/TCP,9990/TCP 62m keycloak-headless ClusterIP None 80/TCP 62m keycloak-postgresql ClusterIP 10.43.231.210 5432/TCP 62m keycloak-postgresql-headless ClusterIP None 5432/TCP 62m oauth2-demo ClusterIP 10.43.160.68 8080/TCP 62m dashboard-kubernetes-dashboard ClusterIP 10.43.159.219 61348/TCP 62m ``` Please ignore the other services as they are not important for this example. Finally, please also check out the Pods in the cluster's namespace with `kubectl`. It should be similar to: ```sh > kubectl --namespace oauth2-demo get pod NAME READY STATUS RESTARTS AGE oauth2-demo-675f5c55b5-xxj57 2/2 Running 0 63m dashboard-kubernetes-dashboard-65dbdd8978-gd9jt 1/1 Running 0 63m keycloak-postgresql-0 1/1 Running 0 63m keycloak-0 1/1 Running 0 63m ``` ### The OAuth2-Demo Sidecar Workload If you want to know more about the implementation of the sidecar pattern in this example please head over to the [workload manifest](https://github.com/gefyrahq/gefyra-demos/blob/main/oauth2-demo/oauth2-demo.yaml#L37){rel=""nofollow""}. The important part is that the Pod template specifies two containers. The first is *name: oauth2-proxy* and the second is *name: oauth2-demo-app*: ```yaml [...] containers: - name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1 imagePullPolicy: IfNotPresent [...] ports: - containerPort: 8809 protocol: TCP name: http envFrom: - configMapRef: name: oauth2-oauth2proxy - name: oauth2-demo-app [...] image: "quay.io/gefyra/oauth2-demo:latest" imagePullPolicy: Always ports: - name: http-intern containerPort: 8155 protocol: TCP [...] ``` Please have a closer look at the port configuration. The oauth2-proxy runs on port *8809* (with name *http*) and oauth2-demo-app runs on port *8155*. You can describe the associated service with `kubectl` to see which of both ports the traffic is pointed to: ```sh > kubectl -n oauth2-demo describe service oauth2-demo Name: oauth2-demo Namespace: oauth2-demo Labels: app.kubernetes.io/instance=gefyra-demos app.kubernetes.io/name=oauth2-demo Annotations: Selector: app.kubernetes.io/instance=gefyra-demos,app.kubernetes.io/name=oauth2-demo Type: ClusterIP IP Families: IP: 10.43.160.68 IPs: 10.43.160.68 Port: http 8080/TCP TargetPort: http/TCP Endpoints: 10.42.1.4:8809 Session Affinity: None Events: ``` For the sidecar pattern to function, the service speaks to the target Pod on port *8809* which is served by the oauth2-proxy. A closer review of oauth2-proxy's configuration reveals to which address the proxy upstreams all requests: ```yaml [...] OAUTH2_PROXY_UPSTREAMS: "http://127.0.0.1:8155" [...] ``` This is precisely the connection to the backend application **in each Pod**. ### The OpenID Connect Flow in Brief The following image depicts the OpenID Connect flow in brief how it is working in this example: ![The OIDC flow in brief](https://gefyra.dev/img/usecases_oauth2-demo-oidc.png){.w-full} As you can see, the OAuth2-Proxy only passes authenticated traffic to the backend application. That breaks the application free from (potentially unsafe) custom OIDC code and authorization handling. **This is standard procedure and should not be part of your code**. Make use of this pattern when having this requirement. Ok! Enough for the workload internals. Let's check out how Gefyra helps out with fixing nasty bugs. ## The Example Bug If you hit the troublesome route {rel=""nofollow""} (with *123* as an example for any int value) you will face the `Internal Server Error` message. That is a *HTTP 500* status. The code being executed can be found here: {rel=""nofollow""} ```py @app.get("/items/{item_id}") async def get_item(item_id: int, x_forwarded_access_token: Optional[str] = Header(None)): if x_forwarded_access_token: data = jwt.decode(x_forwarded_access_token, options={"verify_signature": False}) mail = data["Email"] return {"item_id": item_id, "Email": mail} else: return {"item_id": item_id, "Email": "not given"} ``` Of course, you are a very attentive reader and found the mistake immediately, but let's move on for the sake of this example. ## Gefyra to the Rescue As always, the first would be to spin up Gefyra with `gefyra up`. Please be sure to still have the development cluster active in your current `kubectl` context. ### Running a Development Instance of the Container In order to inspect the application and pinpoint the bug, it requires a local instance of the container. Ideally with a debug server running. Since you need the sidecar in place (for the OIDC logic), the development instance must be placed in a Pod with the sidecar pattern. Gefyra offers you a unique mechanism to achieve exactly that. Start the development instance like so (set `LOCAL_DIR` to the directory where you've copied/cloned `gefyra-demos` to): ```sh export LOCAL_DIR=/home/<...>/gefyra-demos/oauth2-demo/app gefyra run -i quay.io/gefyra/oauth2-demo -N myfastapi-demo \ -n oauth2-demo -v $LOCAL_DIR:/app \ -c "bash -c 'python -m debugpy --wait-for-client --listen 0.0.0.0:5678 -m uvicorn main:app --host 0.0.0.0 --port 8155 --reload'" ``` No worries, the following explains the parameter list: - *-i quay.io/gefyra/oauth2-demo*: run the Docker image which is also running in the cluster - *-N myfastapi-demo*: name this local Docker instance *myfastapi-demo* for further reference - *-n oauth2-demo*: place this Docker instance in the Kubernetes namespace *oauth2-demo* (where this example plays) - *-v /home/<...>/gefyra-demos/oauth2-demo/app\:/app*: mount the source code on your disk to this Docker instance at */app* - *-c "CMD"*: start this Docker instance with [*debugpy*](https://github.com/microsoft/debugpy){rel=""nofollow""}, the rest is like from the Kubernetes workload manifest of the application [debugpy](https://github.com/microsoft/debugpy){rel=""nofollow""} is an implementation of the *Debug Adapter Protocol* for Python. This protocol is also available for a countless number of programming languages. It basically spins up a server, in this case waiting for a debugger client to connect, and runs the application wrapped in with debugging capabilities. ### Attaching a Debugger to the Development Instance Now that you are running a development instance with this Docker image locally, you need to connect the debugger client. This example is prepared with *VSCode* and the Python extension installed. In order to do that, you need to find out the local IP address Gefyra assigned to your container with: ```sh docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' myfastapi-demo ``` This will be part of the CLI soon (or maybe it already is). The command shown tells the IP of the container which is needed for VSCode. Please get the code for the backend application from [the repository](https://github.com/gefyrahq/gefyra-demos/tree/main/oauth2-demo/app){rel=""nofollow""} and open up VSCode. Select the *Remote Attach* option to connect to the running debugpy instance at the given IP. The port is *5678* (please review the command above). ![starting the VSCode remote debugger](https://gefyra.dev/img/usecases_oauth2-demo_vscode1.png){.w-full} In the *DEBUG CONSOLE* it will display the following output: ```text INFO: Will watch for changes in these directories: ['/app'] INFO: Uvicorn running on http://0.0.0.0:8155 (Press CTRL+C to quit) INFO: Started reloader process [438166] using watchgod ``` Awesome. You have a debugger connected to the development instance. Now it's time to receive a request from the oauth2-proxy container. ### Bridging the Development Instance in the Cluster In order to receive requests (i.e. traffic) from within the cluster, basically when you hit the route {rel=""nofollow""} in your browser, a `gefyra bridge ...` is needed. Just create a bridge with: ```sh > gefyra bridge -N myfastapi-demo -n oauth2-demo \ --target deploy/oauth2-demo/oauth2-demo-app \ --port 8155:8155 [INFO] Creating bridge for Pod oauth2-demo-675f5c55b5-xxj57 [INFO] Waiting for the bridge(s) to become active [INFO] Bridge myfastapi established ``` The parameter list specifies the following: - *-N myfastapi-demo*: the bridge targets (on one end) the local Docker instance with the name *myfastapi-demo* - *-n oauth2-demo*: the target workload (the other end of the bridge) is in the Kubernetes namespace *oauth2-demo* - *--deployment oauth2-demo*: Gefyra intercepts all Pods of the Deployment *oauth2-demo* (don't confuse it with the name of the namespace) - *--port 8155:8155*: the bridge to map port 8155 of the container in the cluster to 8155 on the local instance - *--container-name oauth2-demo-app*: since this Pod contains multiple containers (see the sidecar pattern above), Gefyra is asked to intercept the application container *oauth2-demo-app* ### Debugging the Application Now you are ready to stop the execution of the code in your VSCode debugger. Place the breakpoint anywhere near the position you would expect the error to happen: ![breakpoint in VSCode](https://gefyra.dev/img/usecases_oauth2-demo_vscode2.png){.w-full} Point your browser to {rel=""nofollow""} again. Once you hit the breakpoint, you can easily look around and introspect the JWT (json web token) issued from Keycloak and verified with OAuth2-Proxy. ![introspecting variables and the JWT token](https://gefyra.dev/img/usecases_oauth2-demo_vscode3.png){.w-full} As you may see, the key in the token is written in a lowercase "email". This is causing the *KeyError: 'Email'* resulting in a 500 error. **Remark:** Of course you could have found this out reading the logs, but where is the fun? Anyway, debugging software is a tool for hunting down causes of way more complex misbehaving then in this example. ### Fixing the Bug Since the development instance is started with your local source code mounted into the container and the *--reload* flag turned on, please move on and fix this bug. The fix looks like this: ```py [...] data = jwt.decode(x_forwarded_access_token, options={"verify_signature": False}) mail = data["email"] # the key is with a lowercase 'email' return {"item_id": item_id, "Email": mail} [...] ``` Once you have saved the changes, the application is immediately restarted with the fixed code. The output of the route {rel=""nofollow""} is now in the browser: ```json {"item_id":123,"Email":"john@gefyra.dev"} ``` Awesome! Commit and push. This way you can be quite sure that this will work in all Kubernetes environments provisioned with these workloads. **Remark:** Gefyra is able to run and bridge as many applications as you need. This is useful in complex request/response scenarios with multiple involved services - and potentially all with a debugger attached. Isn't that neat? ### Shutting Down Gefyra In order to clean everything up, you can run `gefyra down`. This will remove the running bridges and shut down the development container instances. You will now find the cluster reset to the state with the original bug around. For the fix to become persistent you will need to roll out a new version of the container image specified in the Kubernetes workload manifest. ## Remove the Development Infrastructure If you have initially created the development infrastructure using `Getdeck` you can now run: ```sh > deck remove --cluster https://github.com/gefyrahq/gefyra-demos.git [INFO] Deleting the k3d cluster with name gefyra-demos ``` If you created the infrastructure yourself, you probably already know how to get rid of everything yourself ;-) ## Additional Notes If you are developing django applications, be sure to check out [Django-Hurricane](https://django-hurricane.io/){rel=""nofollow""}, a Kubernetes-native stack specifically created for django and [Pycloak](https://github.com/Blueshoe/pycloak){rel=""nofollow""}, a package that's makes it super easy to integrate OpenID Connect/OAuth2 workflows in django. # Developing a backend application with Django on the Google Kubernetes Engine (GKE) ::note Intermediate Usecase :: This is more of an advanced use-case, if you just want an easy example of how Gefyra works, check out the [getting started guide](https://gefyra.dev/en/local-environments/getting-started). ## What you will learn - How to set up a Kubernetes cluster with the Google Kubernetes Engine - Deploy a Django-based demo application - Set out with Gefyra to run a local container instance as part of the remote cluster To follow this guide, you need to have the following tools installed: - [gcloud](https://cloud.google.com/sdk/docs/install-sdk){rel=""nofollow""} - [kubectl](https://kubernetes.io/docs/tasks/tools/){rel=""nofollow""} - [Helm](https://helm.sh/docs/intro/install/){rel=""nofollow""} - [Gefyra](https://gefyra.dev/en/quick-start/installation) Additionally you need an account for the Google Cloud Platform including the permission to create a new cluster. Make sure your gcloud is using the right project configuration. Googles documentation is available [here](https://cloud.google.com/docs/get-started){rel=""nofollow""}. ## Setup a cluster In this guide we will spin up a small demo application called spacecrafts, featuring Django Hurricane. If you already have a cluster running, you are free to use this as well. The easiest way to create a new cluster is using `gcloud`: `gcloud container clusters create spacecraft`. This may take a few minutes, there will be 3 VM instances running a kubernetes cluster ready to serve your applications. `gcloud` will set your kubectl context to the created cluster, nothing to worry about! The last thing we need to do is open a port in the firewall. This allows gefyra to connect to the cluster using wireguard: `gcloud compute firewall-rules create gefyra --allow udp:31820` ## Running the Spacecrafts Demo To have some actual application to develop against, we want to deploy our spacecrafts demo to our cluster. Clone the repository and deploy it using helm: ```sh git clone https://github.com/django-hurricane/spacecrafts-demo.git cd spacecrafts-demo/helm helm install spacecrafts spacecrafts/ ``` Check if everything is up and running with `kubectl get pods`. Now we need to deploy a load balancer so Google exposes our service on a public IP. Use the following service definition with `kubectl apply -f service.yaml`: ```yaml [service.yaml] apiVersion: v1 kind: Service metadata: name: hello spec: type: LoadBalancer selector: app.kubernetes.io/name: spacecrafts strategy: ports: - port: 80 targetPort: 8080 --- ``` It takes some time to actually get an IP. You can check the state running `kubectl get service`. There will be a service named `hello` of the type `LoadBalancer`. As soon as an IP is available, feel free to visit it in your browser. If you can see a 404 error from Django, everything is alright! ## Setting up Gefyra Now we can run `gefyra up`. This way gefyra sets up all requirements to enjoy local development supported by services in the cluster. At first, we need a host IP of one of our compute instances. You can get them with running `gcloud compute instances list`. Pick one of them. Now you can run `gefyra up --host `. Gefyra now sets up a wireguard connection into the cluster and prepares everything to allow us to run local containers linked to the cluster. ## Local development backed by the cluster Lets say we want to debug and fix the 404 on the index page. It's possible to do this in the remote cluster, but Gefyra enables us to do this on your machine! The following command will spin your local development container for spacecrafts up. Please note you need to adjust the name of the container, run `kubectl get pods` to get the right identifier. ```sh export podname=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" | grep -v postgres) gefyra run --env-from $podname/spacecrafts \ -i quay.io/django-hurricane/spacecrafts-demo \ -N myspacecraft \ -v src/:/app \ -c "python manage.py serve --autoreload --static --command 'collectstatic --noinput' --command 'migrate'" ``` Some explanation: We pass the image for the container with `-i`, name the container with `-N`, mount our source directory inside the container for hot-reloading using `-v` and specify the command to be executed on startup. Thats it. To get the IP of the container, run ```sh gefyra list --containers ``` Now you can open your browser at `:8000` and get the same `404-Error`. You can watch the logs using ```sh docker logs -f myspacecraft ``` The reason why we get a 404 not found is simply a missing route. We should add one: ```diff [src/configuration/urls.py] urlpatterns = [ # django-admin: + path("", csrf_exempt(GraphQLView.as_view(graphiql=True))), path("admin/doc/", include(admindocs_urls)), # noqa: DJ05 path("admin/", admin.site.urls), path("graphql/", csrf_exempt(GraphQLView.as_view(graphiql=True))), ``` If you now reload your browser tab, you should see a graphql input field! # Making any container part of your Kubernetes namespace ::tip Simple Usecase :: ## What you will learn - Run a Ubuntu container as part of a Kubernetes namespace - Install additional software to that instance - Use this container to call Kubernetes services ## What you will need - [Gefyra](https://gefyra.dev/en/quick-start/installation) - [Getdeck](https://github.com/Getdeck/getdeck){rel=""nofollow""} for setting up the development infrastructure (runs on `k3d`) - [kubectl](https://kubernetes.io/docs/tasks/tools/){rel=""nofollow""} - Optionally: [k3d](https://k3d.io){rel=""nofollow""} or any other preferred Kubernetes cluster ## Creating the local development infrastructure First, we need a Kubernetes-based development infrastructure which contains all required components. Luckily this can be achieved quite easily with the [`Deck CLI` from here](https://github.com/Getdeck/getdeck){rel=""nofollow""}. Just run: ```sh deck get https://github.com/Blueshoe/buzzword-charts.git ``` and you will get a fresh `k3d` cluster running locally with all required components installed. **Important:** These workloads are intended for demonstration purposes and are not safe for production deployments. **Optional:** If you don't want to create the development infrastructure using `Getdeck` you can also provide it yourself. You need: - a Kubernetes cluster - some workload, you can choose the example from [here](https://github.com/Blueshoe/buzzword-charts/tree/main/buzzword-counter){rel=""nofollow""} and `helm install` it yourself - a node port at 31820:31820/UDP (if running it locally) ## Getting the App Running **Optional:** In order to observe the workload booting up, check out [the Kubernetes dashboard](http://dashboard.127.0.0.1.nip.io:8080/#/workloads?namespace=buzzword){rel=""nofollow""} coming with this `deck`. ## Connecting Gefyra to the Kubernetes cluster The first would be to spin up Gefyra with `gefyra up`. Please be sure to still have the development cluster active in your current `kubectl` context. **Important:** If you are running a remote Kubernetes cluster you need to specify the `--host` argument with *IP* of one of your data plane nodes. The default port is *31820* (`--port`), it may be different depending on firewalls and the cluster networking. ## Running a container in a Kubernetes namespace In this example, a Ubuntu will become part of the cluster namespace *buzzword*. Start the container instance like so : ```sh > gefyra run -i ubuntu -N myubuntu -n buzzword -c "bash -c 'tail -f /dev/null'" [INFO] Container image 'ubuntu:latest' started with name 'myubuntu' in Kubernetes namespace 'buzzword' ``` No worries, the following explains the parameter list: - *-i ubuntu*: run the public Docker image ob Ubuntu from here: {rel=""nofollow""} - *-N myubuntu*: name this local Docker instance *myubuntu* for further reference - *-n buzzword*: place this Docker instance in the Kubernetes namespace *buzzword* (where this example plays) - *-c "bash -c 'tail -f /dev/null'"*: start this Docker instance and keep it running forever You can check the output of `docker ps` to see your container instance running. It should look something like this: ```text CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 660ce52ce4e1 ubuntu "bash -c 'tail -f /d…" 9 seconds ago Up 8 seconds myubunut e0add97dee80 gefyra-cargo:20220426153151 "/init" 14 seconds ago Up 13 seconds gefyra-cargo 97f9908c55df rancher/k3d-proxy:4.4.8 "/bin/sh -c nginx-pr…" 12 minutes ago Up 12 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp, 0.0.0.0:34089->6443/tcp k3d-another-cluster-serverlb 1dccf93fc087 rancher/k3s:v1.20.4-k3s1 "/bin/k3s agent" 12 minutes ago Up 12 minutes 0.0.0.0:31820->31820/udp, :::31820->31820/udp k3d-another-cluster-agent-0 91ef49d000b5 rancher/k3s:v1.20.4-k3s1 "/bin/k3s server --t…" 12 minutes ago Up 12 minutes k3d-another-cluster-server-0 ``` ### Enter the container and call a service Now that the container is running, you can enter a bash by running: `docker exec -it myubuntu bash` ```sh root@6178770cd6b1:/# ``` In order to call an http service from this Kubernetes namespace a terminal application could be handy. The official Ubuntu Docker image does not provide on of my favorites out of the box, but it is easy to add it. ```sh root@6178770cd6b1:/# apt update && apt install wget -y [...] ``` On another terminal (so not in your Ubuntu bash) you can consult `kubectl` to inspect the services in the *buzzword* namespace. For this example it tells: ```sh > kubectl -n buzzword get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-kubernetes-dashboard ClusterIP 10.43.147.1 8080/TCP 18m [...] buzzword-counter ClusterIP 10.43.221.222 9000/TCP 18m buzzword-counter-postgresql ClusterIP 10.43.140.176 5432/TCP 18m buzzword-counter-postgresql-headless ClusterIP None 5432/TCP 18m buzzword-counter-rabbitmq ClusterIP 10.43.0.48 4369/TCP,5672/TCP,25672/TCP,15672/TCP 18m buzzword-counter-rabbitmq-headless ClusterIP None 4369/TCP,5672/TCP,25672/TCP,15672/TCP 18m ``` Let's see how this works. From within your running Ubuntu bash, you can now call the *buzzword-counter* service on port 9000: ```sh root@6178770cd6b1:/# wget -O- buzzword-counter:9000 --2022-04-26 13:41:43-- http://buzzword-counter:9000/ Resolving buzzword-counter (buzzword-counter)... 10.43.221.222 Connecting to buzzword-counter (buzzword-counter)|10.43.221.222|:9000... connected. HTTP request sent, awaiting response... 200 OK Length: 565 [text/html] Saving to: 'STDOUT' - 0%[ ] 0 --.-KB/s

Buzzwords

Buzzword Count Increase Decrease
- 100%[==================================================================================================>] 565 --.-KB/s in 0s 2022-04-26 13:41:43 (18.9 MB/s) - written to stdout [565/565] ``` Et voila! The service responded to the HTTP Get request with the same answer you would get with your browser at: {rel=""nofollow""}. You can now look around and make yourself familiar with the services in this namespace - or even connect with the `psql` client to the *PostgreSQL* instance running in the cluster. ### Remove the Ubuntu container Once you are done with your work, you can remove this Ubuntu instance again with: `docker kill myubuntu`. That's it. ## Remove the Development Infrastructure First run `gefyra down` to uninstall Gefyra's components. If you have initially created the development infrastructure using `Getdeck` you can now run: ```sh > deck remove --cluster https://github.com/Blueshoe/buzzword-charts.git [INFO] Deleting the k3d cluster with name another-cluster ``` If you created the infrastructure yourself, you probably already know how to get rid of everything yourself ;-) # How does it work? ![Gefyra connects to a Kubernetes cluster](https://gefyra.dev/img/gefyra-overview.png){.mx-auto} With these components, Gefyra is able to control a local development machine, and the development cluster, too. Both sides are now in the hand of Gefyra. Once the developer's work is done, Gefyra well and truly removes all components from the cluster without leaving a trace. A few things are required in order to achieve this: - a *tunnel* between the local development machine and the Kubernetes cluster - a local end of that tunnel to steer the traffic, DNS, and encrypt everything passing over the line - a cluster end of the tunnel, forwarding traffic, taking care of the encryption - a local DNS resolver that behaves like the cluster DNS - sophisticated IP routing mechanisms - a traffic interceptor for containers already running withing the Kubernetes cluster Gefyra builds on top of the following popular open-source technologies: ## Docker [*Docker*](https://docker.io){rel=""nofollow""} is currently used in order to manage the local container-based development setup, including the host, networking and container management procedures. ## Wireguard [*Wireguard*](https://wireguard.com){rel=""nofollow""} is used to establish the connection tunnel between the two ends. It securely encrypts the UDP-based traffic and allows to create a *site-to-site* network for Gefyra. That way, the development setup becomes part of the cluster and containers running locally are actually able to reach cluster-based resources, such as databases, other (micro)services and so on. ## CoreDNS [*CoreDNS*](https://coredns.io){rel=""nofollow""} provides local DNS functionality. It allows resolving resources running within the Kubernetes cluster. ## Nginx [*Nginx*](https://www.nginx.com/){rel=""nofollow""} is used for all kinds of proxying and reverse-proxying traffic, including the interceptions of already running containers in the cluster. ## Architecture of the entire development system ### Local development setup The local development happens with a running container instance of the application in question on the developer machine. Gefyra takes care of the local Docker host setup, and hence needs access to it. It creates a dedicated Docker network which the container is deployed to. Next to the developed application, Gefyra places a *sidecar* container. This container, as a component of Gefyra, is called *Cargo*. Cargo acts as a network gateway for the app container and, as such, takes care of the IP routing into and from the cluster. In addition, Cargo provides a CoreDNS server which forwards all requests to the cluster. That way, the app container will be able to reach resources running within the Kubernetes cluster. ![Gefyra local development](https://gefyra.dev/img/gefyra-development.png){.mx-auto} This local setup allows developers to use their existing tooling, including their favorite code editor and debuggers. The application, when it is supported, can perform code-hot-reloading upon changes and pipe logging output to a local shell (or other systems). Of course, developers are able to mount local storage volumes into the container, override environment variables and modify everything as they'd like to. Replacing a container in the cluster with a local instance is called *bridge*: from an architectural perspective the local application is *bridged* into the cluster. If the container is already running within a Kubernetes Pod, it gets replaced and all traffic to the originally running container is proxied to the one on the developer machine. During the container startup of the application, Gefyra modifies the container's networking from the outside and sets the *default gateway* to Cargo. That way, all container's traffic is passed to the cluster via Cargo's encrypted tunnel. The same procedure can be applied for multiple app containers at the same time. The neat part is that with a debugger and two or more *bridged* containers, developers can introspect requests from the source to the target and back around while being attached to both ends. ## The *bridge* operation in action This chapter covers the important *bridge* operation by following an example. ### Before the bridge operation Think of a provisioned Kubernetes cluster running some workload. There is an Ingress, Kubernetes Services and Pods running containers. Some of them use the [*sidecar*](https://medium.com/nerd-for-tech/microservice-design-pattern-sidecar-sidekick-pattern-dbcea9bed783){rel=""nofollow""} pattern. ![Gefyra development workflow step 1](https://gefyra.dev/img/gefyra-process-step-1.png){.mx-auto} ### Preparing the bridge operation Before the *brigde* can happen, Gefyra installs all required components to the cluster. A valid and privileged connection must be available on the developer machine to do so. The main component is the cluster agent called *Stowaway*. The Stowaway controls the cluster side of the tunnel connection. It is operated by [Gefyra's Operator application](https://github.com/gefyrahq/gefyra/tree/main/operator){rel=""nofollow""}. ![Gefyra development workflow step 2](https://gefyra.dev/img/gefyra-process-step-2.png){.mx-auto} Stowaway boots up and dynamically creates Wireguard connection secrets (private/public key-pair) for itself and Cargo. Gefyra copies these secrets to Cargo for it to establish a connection. This is a UDP connection. It requires a Kubernetes Service of kind *nodeport* to allow the traffic to pass through *for the time of an active development session*. Gefyra's operator installs these components with the requested parameters and removes it after the session terminates. By the way: Gefyra's operator removes all components and itself from the cluster in case the connection was disrupted for some time, too. Once a connection could be establised from Cargo to Stowaway (after running `gefyra up`), Gefyra can spin up the app container on the local side for the developer to start working (by running `gefyra run ...`). Another job of Gefyra's operator is to rewrite the target pods, i.e. exchange the running container through Gefyras proxy, called *Carrier* (upon running `gefyra bridge ...`). For that, it creates a temporary Kubernetes Service that channels the Ingress traffic (or any other kind of cluster internal traffic) to the container through Stowaway and Cargo to the locally running app container. ### During the bridge operation A bridge can robustly run as long as it is required to (given the connection does not drop in the meanwhile). Looking at the example, Carrier was installed in pod \ on port *XY*. That port was previously occupied by the container running there originally. In most cases, the local app container represents the development version of that originally provisioned container. Traffic coming from the Ingress, passing on to the Service \ hits Carrier (the proxy). Carrier bends the request to flow through Gefyras Service to the local app container via Stowaway and Cargo's tunnel. This works since the app container's IP is routable from within the cluster. The local app container does not simply return a response, but fires up another subsequent request by itself to Service \. The request roams from the local app container back into the cluster and hits Pod \'s container via Service \. The response is awaited. Once the local app container is done with constructing its initial answer the response gets back to Carrier and afterwards to the Ingress and back to the client. ![Gefyra development workflow step 3](https://gefyra.dev/img/gefyra-process-step-3.png){.mx-auto} With that, the local development container is reachable exactly the same way another container from within the cluster would be. That fact is a major advantage, especially for frontend applications or domain-sensitive services. Developers now can run local integration tests with new software while having access to all interdependent services. Once the development job is done, Gefyra properly removes everything, resets Pod \ to its original configuration, and decommissions Carrier and Stowaway. # What is Gefyra? ![Gefyra controls docker and kubeapi](https://gefyra.dev/img/gefyra-intro.png){.mx-auto} (*Kubectl* is not really required but kinda makes sense to be in this picture) In order for this to work, a few requirements have to be satisfied: - a Docker host must be available for the user on the development machine (it is convenient if [docker can be run without sudo-privileges](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user){rel=""nofollow""}) - Overlay networking must be supported by the Docker host - there are a few container capabilities required on both sides, within the Kubernetes cluster and on the local computer - a node port must be opened on the development cluster for the duration of the development work Gefyra makes sure your development container runs as part of the cluster while you still have full access to it. In addition, Gefyra is able to intercept the target application running within the cluster, i.e. a container in a Pod, and tunnels all traffic hitting said container to the one running locally. Now, developers can add new code or fix bugs and run it right away in the Kubernetes cluster, or simply introspect the traffic. Gefyra provides the entire infrastructure to do so and provides a high level of developer convenience. ## Did I hear developer convenience? The idea is to relieve developers from the hassle to go back and forth to the integration system with containers. Instead, take the integration system closer to the developer and make the development cycles as short as possible. No more waiting for the CI to complete just to see the service failing on the first request. Cloud-native (or Kubernetes-native) technologies have completely changed the developer experience: infrastructure is increasingly becoming part of developer's business with all the barriers and obstacles, but also chances to turn the software for the better. Gefyra is here to provide a development workflow with the highest convenience possible. It brings low setup times, rapid development, high release cadence and super-satisfied managers. ## Gotchas & Current Limitations - Gefyra's VPN needs a reachable `NodePort`. In most non-local Kubernetes scenarios this requires to set a firewall rule in order to **allow port 31820 for UDP traffic**. It's simple for most Cloud-providers ("Hyperscaler") and doable for custom installations, too. - Kubernetes-probes can be faked by Gefyra's Pod component ("Carrier") in order to keep Kubernetes from removing *bridged* Pods. However, this is currently only supported for `httpGet` probes. Otherwise, you need to turn off probes during development. - You will experience issues if you want to *bridge* containers in Pods which specify a specific `command` (other than common shells). - This project is in a quite early stage. I assume there are still a few bugs around. ## Why "Gefyra"? "Gefyra" is the Greek word for "Bridge" and fits nicely with Kubernetes' nautical theme. # Run vs. Bridge Operation | | Run | Bridge | | ---------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | What | Run a local container and connect it to a Kubernetes cluster | Build on top of run. Connect a local container to a Kubernetes cluster and reroute traffic to it | | Multi-User | Multiple users can run multiple containers connected to the same cluster | Multiple users cannot bridge the same workload | | When | When you want to test a service in the cluster or write code that depends on Kubernetes resources | When you want to expose a local container to other services within the cluster | ## Run Operation **Run** - allows to run a local container and connect it to a Kubernetes cluster. It is executed within a given namespace and can communicate with other services running in the cluster. This allows your local container to talk to things databases or internal APIs within the cluster you connected it to. Multiple users can run multiple containers connected to the same cluster. ## Bridge Operation **Bridge** - builds on top of `Run`. In certain situation you want other services to connect to your local container. For this, your local container needs some kind of representation within the Kubernetes cluster it is connected to. With `Bridge` Gefyra patches a given workload within your Kubernetes cluster and reroutes all the incoming traffic to your local container. Multiple users cannot bridge the same workload. # What changed between Gefyra v1 and Gefyra v2? **Operator** - Gefyra's operator was completely refactored. It now acts as a state machine and shows much more stable and consistent behaviour. It manages 2 custom resources - `GefyraClients` and `GefyraBridges`. **Access Management** - While Gefyra `v1` just installed its operator into the cluster via the `up` command, Gefyra 2 allows for a more fine grained control. `gefyra up` was split into `gefyra install`, `gefyra client` and the `gefyra connection` commands. Every connection to the cluster is now controlled by a `GefyraClient` object which represents an indiviual client connection to the cluster. For every `GefyraClient` a separate service account is created. **Load Balancer Presets** - Not every cluster is just reachable through a public IP. To expose it for Gefyra's connection purposes we allow you to use *Load Balancer Presets* which expose the necessary parts of Gefyra to make things work. **CLI** - Gefyra's command line interface has been refactored - it's now written in [Click](https://click.palletsprojects.com/){rel=""nofollow""}. The TUI is much more readable, it includes some progress bars - generally a much nicer experience. **API** - Gefyra's core functionality is now moved into a separate Python package. It provides an API to control Gefyra's processes - like `install`, `run`, `bridge`. # Media ## Conferences **Local containers on board! Connect your local containers to K8s using Gefyra | Kubernetes Community Days Munich 2022, Munich** :gefyra-youtube{video-id="-HtBGPtaVo8"} **Debugging a container with a sidecar using Gefyra | Cloud-native Rejects 2022, Valencia** :gefyra-youtube{video-id="P6LKFCwelvo"} **Debugging a container with a sidecar using Gefyra | Conf42 Cloud Native 2022** :gefyra-youtube{video-id="FazRUwBWPUI"} ## Podcasts **Accelerate And Simplify Cloud Native Development For Kubernetes Environments With Gefyra - Episode 359** :gefyra-youtube{video-id="82qp1QFd+pR6zngj0"} ## Other Presentations **Gefyra Docker Desktop Extension Demo April 2023** :gefyra-youtube{video-id="EBArR1O2BGk"} **Gefyra Docker Desktop Extension Demo Feb 2023** :gefyra-youtube{video-id="4xmaOVul5Ww"} **Gefyra Docker Desktop Extension Demo Jan 2023** :gefyra-youtube{video-id="k1HsJNnRS3w"} ## Development Sessions :gefyra-youtube{video-id="9BWeokWlYnQ"} :gefyra-youtube{video-id="DApYfK4v8_g"} :gefyra-youtube{video-id="zGxoLcOQh2U"} ## Blog - **An alternative to Telepresence 2: Gefyra**{rel=""nofollow""} - **Creating a Python CLI with Go(lang)-comparable startup times**{rel=""nofollow""} - **How does local Kubernetes development work?**{rel=""nofollow""} # About Gefyra ## License Gefyra is distributed by an [Apache-2.0 License](https://github.com/gefyrahq/gefyra/tree/main/LICENSE){rel=""nofollow""}. ## Contributors This open-source project is currently mainly carried out by [Michael Schilonka](https://github.com/Schille){rel=""nofollow""}. Follow me on [LinkedIn](https://www.linkedin.com/in/michael-schilonka){rel=""nofollow""}. ## Sponsors This project is sponsored by [Blueshoe GmbH](https://blueshoe.io){rel=""nofollow""}.