Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bee-hive in kubernetes #163

Merged
merged 8 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions bee-hive/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@ ENV PYTHONUNBUFFERED=1
# Install pip
RUN python3.11 -m ensurepip --upgrade
# Install dependencies and update then uninstall pip (not needed in final image)
RUN python3.11 -m pip install openai pyyaml python-dotenv --no-cache-dir --upgrade && \
RUN python3.11 -m pip install openai pyyaml python-dotenv flask --no-cache-dir --upgrade && \
python3.11 -m pip uninstall -y pip

COPY bee_hive ./bee_hive
COPY entrypoint.sh .
COPY run_workflow.py .
COPY entrypoint_api.sh .
COPY api.py .

RUN chown -R 1000:100 /usr/src/app &&\
mkdir /usr/src/app/media && chown 1000:100 /usr/src/app/media

EXPOSE 5000
USER 1000:100
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
#ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
ENTRYPOINT ["/usr/src/app/entrypoint_api.sh"]
22 changes: 16 additions & 6 deletions bee-hive/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,24 @@ python run_workflow workflow.yaml

* Configure environmental variables: `cp example.env .env`

### Run workflow in local environment with container runtime (e.g. podman)
### Run workflow in local environment with container runtime (e.g. podman) or kubernetes cluster

* Run a local instance of the [Bee Stack](https://github.com/i-am-bee/bee-stack)
* Prepare required environments
* Run a local instance of the [Bee Stack](https://github.com/i-am-bee/bee-stack)
* `curl` is required for `run` command
* for Kubernetes, `kubectl` and `sed` are required
* set CONTAINER_CMD, TARGET_IP and BUILD_FLAGS environment variables to adjust bee-hive.sh script
* CONTAINER_CMD: docker, podman. nerdctl, etc..
* TARGET_IP: 127.0.0.1:"NodePort of the bee-hive service" for kubernetes deployment
* BUILD_FLAGS: image build command extra flag (e.g. "--namespace k8s.io" for nerdctl)

* Build bee-hive container image: `./bee-hive.sh build` in bee-hive/bee-hive directory
* The built bee-hive:latest image need to be pushed/placed in the local retistry for kubernetes deployment

* Build bee-hive container image: `./bee-hive.sh build` in bee-hive/bee-hive directory
* Deploy bee-hive: `./bee-hive.sh deploy BEE_API=http://xxx.xxx.xxx.xxx:4000 BEE_API_KEY=sk-proj-testkey`
* To deploy to kubernetes cluster, user `deploy-k` instead `deploy` as the first argument
Comment on lines +112 to +113
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's make two sections for the deploy, one for docker and one for kubernetes. that would also allow for including some kubernetes-specific instructions:

  • to load the image into the cluster
  • to port-forward the bee-hive service, if necessary

since both of those will differ depending on the k8s used (rancher, kind, etc.), I don't think we need to include specific instructions, but we should mention that the steps are needed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@psschwei Thanks! I'll create another PR for the readme update!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to merge when you're ready (or if you want to wait to see if anyone has comments that's cool too)

* The required environment variables can be provided at the end of command arguments (e.g. `BEE_API=http://192.168.86.45:4000`).

* Prepare agent and workflow definition yaml files in the current directory (e.g. agent.yaml, workflow.yaml)

* Run workflow: `./bee-hive.sh run $PWD agents.yaml workflow.yaml BEE_API=http://xxx.xxx.xxx.xxx:4000 BEE_API_KEY=sk-proj-testkey`
* The required environment variables can be provided at the end of command argunets (e.g. `BEE_API=http://192.168.86.45:4000`).

* Run workflow: `./bee-hive.sh run agents.yaml workflow.yaml
69 changes: 69 additions & 0 deletions bee-hive/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Assisted by watsonx Code Assistant
from flask import Flask, request, jsonify
import os
import json
import sys
import io

import yaml
from bee_hive.workflow import Workflow

app = Flask(__name__)

def parse_yaml(file_path):
with open(file_path, "r") as file:
yaml_data = list(yaml.safe_load_all(file))
return yaml_data

@app.route('/', methods=['POST'])
def process_workflow():
if request.method == 'POST':
# Check if a file was uploaded
if 'agents' not in request.files:
return 'No agent definition'

agents = request.files['agents']

# Check if the file has a filename
if agents.filename == '':
return 'No agents file name'

# Save the file to the server
agents.save("agents")

if 'workflow' not in request.files:
return 'No agent definition'

workflow = request.files['workflow']

# Check if the file has a filename
if workflow.filename == '':
return 'No workflow file name'

# Save the file to the server
workflow.save("workflow")

agents_yaml = parse_yaml("agents")
workflow_yaml = parse_yaml("workflow")
try:
workflow_instance = Workflow(agents_yaml, workflow_yaml[0])
except Exception as excep:
raise RuntimeError("Unable to create agents") from excep

output = io.StringIO()
sys.stdout = output
workflow_instance.run()
sys.stdout = sys.__stdout__

response = {
'workflow': workflow.filename,
'agents': agents.filename,
'output': output.getvalue()
}

return jsonify(response)

return render_template('upload.html')
if __name__ == '__main__':
app.run(host='0.0.0.0')

38 changes: 27 additions & 11 deletions bee-hive/bee-hive.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
#!/bin/sh

cmd=${CONTAINER_CMD:-docker}
if [ "$1" != "build" ] && [ "$1" != "run" ]; then
echo "Invalid argument. Must be 'build' or 'run'."
target=${TARGET_IP:-127.0.0.1:5000}
flags=${BUILD_FLAGS}
if [ "$1" != "build" ] && [ "$1" != "deploy" ]&& [ "$1" != "deploy-k" ] && [ "$1" != "run" ]; then
echo "Invalid argument. Must be 'build', 'deploy' or 'run'."
exit 1
fi

if [ "$1" == "build" ]; then
$cmd build -t bee-hive .
elif [ "$1" == "run" ]; then
echo "Running..."
path=$2
agents=$3
workflow=$4
echo "Building..."
$cmd build $flags -t bee-hive .
elif [ "$1" == "deploy" ]; then
echo "Deploying..."
env=""
while [ "$5" != "" ]; do
env=$env" -e "$5" "
while [ "$2" != "" ]; do
env=$env" -e "$2" "
shift
done
$cmd run -d $env -p $target:5000 bee-hive
elif [ "$1" == "deploy-k" ]; then
echo "Deploying (kubernetes)..."
cp bee-hive.yaml temp-bee-hive.yaml
while [ "$2" != "" ]; do
keyvalue=$2
name=$(echo $keyvalue | cut -d= -f1)
value=$(echo $keyvalue | cut -d= -f2)
sed -i -e "s#env:#env:\n - name: $name\n value: $value#" temp-bee-hive.yaml
shift
done
$cmd run $env --mount type=bind,src=$path,target=/data bee-hive /data/$agents /data/$workflow
kubectl apply -f temp-bee-hive.yaml
elif [ "$1" == "run" ]; then
echo "Running..."
agents=$2
workflow=$3
curl -X POST -L http://$target/ -F "agents=@$agents" -F "workflow=@$workflow"
fi


Expand Down
36 changes: 36 additions & 0 deletions bee-hive/bee-hive.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: bee-hive
spec:
replicas: 1
selector:
matchLabels:
app: bee-hive
template:
metadata:
labels:
app: bee-hive
spec:
containers:
- name: bee-hive
image: bee-hive:latest
imagePullPolicy: Never
ports:
- containerPort: 5000
env:
- name: DUMMY
value: dummyvalue
---
apiVersion: v1
kind: Service
metadata:
name: bee-hive
spec:
selector:
app: bee-hive
ports:
- protocol: TCP
port: 80
targetPort: 5000
type: NodePort
4 changes: 4 additions & 0 deletions bee-hive/entrypoint_api.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

python3.11 api.py