unfor19 / kubemanny

Multiple packages for managing your AWS EKS cluster, and deploying Kubeless functions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

kubemanny

Multiple packages for managing your AWS EKS cluster, and deploying Kubeless functions

pronounced: ku-be-manny

Kubemanny-Example

Requirements

Docker - that's it! Everything is included in the kubemanny docker image!

Packages
Package Version
bash 5.0.11
git 2.24.1
kubeless 1.0.6-dirty
NodeJS 12.16.1
yarn 1.22.0
Python 3.8.1
pip 20.0.2
kubectl 1.14.7-eks-1861c5
eksctl GitTag: 0.13.0
helm 3.1.1
terraform 0.12.21
aws-cli 1.18.10
chamber 2.7.5
apache2-utils 2.4.27-r1

Usage

Two common ways to use this image

  • AWS Credentials as env vars

    kubeconfig_path=$(echo ~/.kube/config)
    docker run --rm -it \
             --mount type=bind,source="$(pwd)",target=/code \
             --mount type=bind,source="$kubeconfig_path",target=/root/.kube/config,readonly \
             --env AWS_REGION="${AWS_REGION}" \
             --env AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}" \
             --env AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}" \
             unfor19/kubemanny:v1 \
             bash
  • aws-vault

     kubeconfig_path=$(echo ~/.kube/config)
     aws-vault exec MY_PROFILE -- docker run --rm -it \
              --mount type=bind,source="$(pwd)",target=/code \
              --mount type=bind,source="$kubeconfig_path",target=/root/.kube/config,readonly \
              --env AWS_REGION="${AWS_REGION}" \
              --env AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}" \
              --env AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}" \
              --env AWS_SECURITY_TOKEN="${AWS_SECURITY_TOKEN}" \
              --env AWS_SESSION_TOKEN="${AWS_SESSION_TOKEN}" \
              unfor19/kubemanny:v1 \
              bash

Tip: Use scripts/docker_run.sh

Getting Started with Kubeless

  1. Install an Ingress controller on your cluster, see Kubeless http triggers
  2. Clone this repository
  3. Write your code in src
  4. Expose your functions in src/main.ts
  5. Run container with docker_run.sh
  6. Install dependencies, see package.json
    kubemanny$: yarn install
  7. Build and Deploy your functions with scripts/deploy_function.sh, this script does the following:
    • yarn install
    • yarn build:dev
    • Kubeless - delete function if exists
    • Kubeless - deploy function
    • Kubeless - create http trigger

Quickstart (minikube)

Let's see if it really works, shall we?

Goal

I've created three functions: greet_normal, greet_promise and greet_async, see src/controller.ts

In this example, we'll deploy greet_promise, a function which replies after 3 seconds with a random greeting message.

Requirements

No need for anything! We'll use Hello-Minikube terminal, so all you need is a browser πŸ˜‹

To run locally
  1. Docker
  2. VirtualBox
  3. minikube
  4. Clone this repository
kubemanny$ minikube start -p kubemanny-cluster --kubernetes-version v1.14.0 --vm-driver=virtualbox --memory 3072mb --disk-size 10240mb

kubemanny$ minikube addons enable ingress -p kubemanny-cluster

minikube

Consider this as if you're starting a Cluster with one worker node Node

  1. 🚢 Go to Hello-Minikube
  2. πŸ‘Š Hit Launch Terminal
  3. ❗ Press CTRL+C to stop the default start.sh script
    $ start.sh
    Starting Kubernetes...minikube version: v1.6.2
    commit: 54f28ac5d3a815d1196cd5d57d707439ee4bb392
    * minikube v1.6.2 on Ubuntu 18.04
    * Selecting 'none' driver from user configuration (alternates: [])
    * Running on localhost (CPUs=2, Memory=2461MB, Disk=47990MB) ...
    * OS release is Ubuntu 18.04.3 LTS
    ^C^C
  4. πŸ’» Recreate a new minikube machine with kubernetes v1.14 (here's why)
    $ minikube delete && minikube start --kubernetes-version v1.14.0
    * Uninstalling Kubernetes v1.17.0 using kubeadm ...
    ...
    * Successfully deleted profile "minikube"
    ...
    * Launching Kubernetes ...
    * Configuring local host environment ...
    * Waiting for cluster to come online ...
    * Done! kubectl is now configured to use "minikube"
    ! /usr/bin/kubectl is version 1.17.0, and is incompatible with Kubernetes 1.14.0. You will need to update /usr/bin/kubectl or use 'minikube kubectl' to connect with this cluster
    Note: We don't care about this message ☝️ because the kubemanny image has kubectl-v1.14
  5. πŸ”ƒ Install nginx ingress controller to the cluster
    $ minikube addons enable ingress
    * ingress was successfully enabled
    Note: Even though it took 1 second to deploy the nginx-ingress-controller, it takes a few minutes until it's actually ready
Why do I need an ingress controller?

An ingress controller routes traffic from the outside world, to the releavnt service in the cluster.

The routing rules are defined with ingress resources.

Each Kubeless function has an ingress rule, a service and a deployment.

You guessed it right, the deployment is our actual Kubeless function (containerized).

Process
  1. The ingress controller routes traffic to the function according to its hostname (or path > Expose a function)

  2. Kubeless function ingress rule contains the name of the service and its port

  3. Kubeless function service contains the name of the targeted deployment

Is there a dashboard or something like that?

Yes there is!

$ minikube dashboard

Tip: The nginx-ingress-controller is deployed in the kube-system namespace

kubemanny container

This is our workspace, with all the applications and packages that we need.

  1. ⬇️ Clone this repository, and get in!

    $ git clone https://github.com/unfor19/kubemanny.git
    ...
    Unpacking objects: 100% (57/57), done.
    $ cd kubemanny/     # <-- don't forget to change directory!
  2. πŸ‹ Run the container

    $ bash ./scripts/docker_run_minikube.sh
    Unable to find image 'unfor19/kubemanny:v1' locally
    ...
    Status: Downloaded newer image for unfor19/kubemanny:v1
    /code (master)$      # <-- we're in!!!
Why do I need bind mounts?

The container uses bind mounts, so each time you add/create/modify/delete a file within the container, or locally on your machine, it is mirrored both on the Docker container and your local machine.

In order for it to work, we are mounting the following directories:

  1. $HOME/.minikube (readonly)
  2. $HOME/.kube/config (readonly)
  3. Current working directory (readwrite)

Tip: Take a look at the scripts/docker_run_minikube.sh file

Deploy Kubeless

Kubeless allows us to deploy our functions to the Kubernetes cluster. In order to have this ability, we first need to deploy Kubeless to our cluster.

  1. πŸ”ƒ Create a namespace for Kubeless

    /code (master)$ kubectl create ns kubeless
    
    namespace/kubeless created
  2. πŸ”ƒ Create the Kubeless deployment

    /code (master)$ kubectl create -f https://github.com/kubeless/kubeless/releases/download/v1.0.6/kubeless-v1.0.6.yaml
    
    configmap/kubeless-config created
    ...
    customresourcedefinition.apiextensions.k8s.io/cronjobtriggers.kubeless.io created

Source

basic-auth

It's always good practice to protect your functions, so let's use a simple basic-auth mechanism

  1. 🈹 Generate a secret with htpasswd

    /code (master)$ htpasswd -cb auth my_user_name my_password
    
    Adding password for user my_user_name
  2. πŸ”ƒ Create a basic-auth secret

    /code (master)$ kubectl create secret generic basic-auth --from-file=auth
    
    secret/basic-auth created

Note: We'll use the above credentials when sending a basic-auth request, see scripts/curl_example.sh

Can I view this secret?

Yes you can! But you'll still need the username and password, when you request to invoke a Kubeless function.

/code (master)$ echo $(kubectl get secret basic-auth -o=jsonpath='{.data.auth}')
bXlfdXNlcl9uYW1lOiRhcHIxJG5BcjBUbEgvJE1USTBKUlhoaEhlN1R1dm4zSWlYRzEK   # <-- basic-auth secret

Let's decode it with base64, and let's view the auth file.

/code (master)$ echo $(kubectl get secret basic-auth -o=jsonpath='{.data.auth}' | base64 -d)
my_user_name:$apr1$ukcReKFZ$aE./88O0KMWZ2IsqL/xyk.   # <-- decoded

/code (master)$ cat auth
my_user_name:$apr1$ukcReKFZ$aE./88O0KMWZ2IsqL/xyk.   # <-- generated with htpasswd

Cool huh? Read more about it here - htpasswd

Note: The file auth is ignored in .gitignore

Deploy Kubeless function

🀘 Now for the fun part! Let's deploy the greet_promise function

/code (master)$ bash ./scripts/deploy_function.sh -fn greet_promise -hn localhost

yarn install v1.22.0
...
INFO[0000] Waiting for greet-promise to be ready ... Ready!
INFO[0000] View logs:
kubectl logs -f -l function=greet-promise

Execute Kubeless function

🀞 The scripts/curl_example.sh script gets the function's ingress, and then POSTs a basic auth request. Run with --help flag to see available options.

/code (master)$ bash ./scripts/curl_example.sh -fn greet-promise --name meir
INFO[0000] Function Name:     greet-promise
INFO[0000] Hostname:          greet-promise.172.17.0.56.nip.io
INFO[0000] Username:          my_user_name
INFO[0000] Password:          my_password
INFO[0000] Invoking a request ...
INFO[0000] Response:      Guten Targ meir
INFO[0000] Response time: 3.024527ms

Tip: Deploy the greet-normal function, and curl it. Watch for the response time!

Cleanup

Close the browser tab 😎

Locally

IMPORTANT: make sure you're not in the container, otherwise it won't work

Let's delete the minikube profile that we've created

/code (master)$ exit
exit
kubemanny$: minikube delete -p kubemanny-cluster
πŸ”₯  Deleting "kubemanny-cluster" in virtualbox ...
πŸ’”  The "kubemanny-cluster" cluster has been deleted.
πŸ”₯  Successfully deleted profile "kubemanny-cluster"

About

Multiple packages for managing your AWS EKS cluster, and deploying Kubeless functions

License:MIT License


Languages

Language:Shell 77.5%Language:Dockerfile 8.5%Language:JavaScript 7.7%Language:TypeScript 6.3%