项目作者: jpsalado92

项目描述 :
Udacity's Dev Ops Nano Degree project. Deploying a Machine Learning App with Kubernetes.
高级语言: Shell
项目地址: git://github.com/jpsalado92/Udacity-DOND_DeployKubernetesMLApp.git


jpsalado92

DeployKubernetesMLApp

This project will guide the reader on setting up a AWS environment in order to operationalize a Flask application containing a Machine Learning model using AWS.

The app is containerized with Docker & Kubernetes making it a scalable solution and it consists on a pre-trained sklearn model based on the data from the Boston Housing challenge.

1. Getting the project environment ready

Launch a Cloud9 environment

In order to run this project on AWS, we must first set up a Cloud9 environment, which works as a powerful IDE with many useful resources.
The selected EC2 instance type should be m5.large, running the Amazon Linux platform and it must belong to a public subnet of a VPC.

Fetch the model and the Flask implementation

The EC2 instance in which we are working has GIT already installed, so in order to get the flask application containing the trained ML model and the rest of the files required for this project, we can easily clone the source code repository in our file system.

  1. git clone https://github.com/jpsalado92/ML-Microservice-API-Operationalization.git

The files related to the ML model are placed in the /model_data, and the flask implementation is described in app.py

Add extra space to the instance

The default size for our EC2 instance is 10GiB, which is not enough for this project. To solve this problem, resize_ec2.sh contains all the necesary commands to resize the EBS partition associated to our EC2 instance up to 20GB. We must simply make it executable and run it.

  1. chmod +x resize_ec2.sh
  2. ./resize_ec2.sh

Create and activate a python3 virtual environment

The following code creates and activates a python3 virtual environment in the user’s home directory.

TODO WHY

  1. python3 -m venv ~/.devops
  2. source ~/.devops/bin/activate

Install hadolint

Hadolint is a useful tool to lint Dockerfiles, which we are using in this project.

  1. sudo wget -O /bin/hadolint https://github.com/hadolint/hadolint/releases/download/v1.17.5/hadolint-Linux-x86_64
  2. sudo chmod +x /bin/hadolint

Install minikube & kubectl

These files allow us to use Kubernetes for our deployment. We will get the latests releases and place them in our PATH.


minikube:

  1. sudo curl -Lo /bin/minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
  2. sudo chmod +x /bin/minikube
  3. minikube version

minikube version: v1.10.1

commit: 63ab801ac27e5742ae442ce36dff7877dcccb278

kubectl:

  1. sudo curl -Lo /bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.18.2/bin/linux/amd64/kubectl
  2. sudo chmod +x /bin/kubectl
  3. kubectl version --client

Client Version: version.Info{Major:”1”, Minor:”18”, GitVersion:”v1.18.2”, GitCommit:”52c56ce7a8272c798dbc29846288d7cd9fbae032”, GitTreeState:”clean”, BuildDate:”2020-04-16T11:56:40Z”, GoVersion:”go1.13.9”, Compiler:”gc”, Platform:”linux/amd64”}

Create a Docker account

Docker is already installed in our EC2 instance by default, but in order to be able to push our containers to Dockerhub we will need to create a free docker account

2. Build the flask app in a new docker container

We must create a Dockerfile containing all the steps that will be performed when building the image.

  1. # Start building from a base python image.
  2. FROM python:3.7.3-stretch
  3. # Create a working directory in the Docker container
  4. WORKDIR /app
  5. # Copy source code to working directory
  6. COPY . app.py /app/
  7. COPY . model_data /app/
  8. # Install packages from requirements.txt
  9. # hadolint ignore=DL3013
  10. RUN pip install --upgrade pip &&\
  11. pip install --trusted-host pypi.python.org -r requirements.txt
  12. # Expose containers port 80
  13. EXPOSE 80
  14. # Run app.py at container launch
  15. CMD ["python", "app.py"]

Once the Dockerfile is created, use the following command to build it as ml_app.

  1. docker build -t ml_app .



Successfully built 53015318b353

Successfully tagged ml_app:latest

Check that the new image has been created by listing the available docker images:

  1. docker image ls

3. Push the image to Docker HUB

Our docker image was built at the previous step, and now we are going to upload it to Docker HUB.
The shell script upload_docker.sh can perform this action for us, but first, we must create our repository at hub.docker.com.

  1. #!/usr/bin/env bash
  2. # This file tags and uploads an image to Docker Hub
  3. # Assumes that an image is built via `run_docker.sh`
  4. # Step 1:
  5. # Authenticate
  6. username=<USERNAME>
  7. cat token.txt | docker login --username=$username --password-stdin
  8. # Step 2:
  9. # Tag
  10. docker_image_id=<DOCKER_IMAGE_ID>
  11. repo=<REPO_NAME>
  12. docker tag $docker_image_id $username/$repo:price_predictor
  13. # Step 3:
  14. # Push image to a docker repository
  15. docker push $username/$repo

After creating the repository, we must request a new token access token at Account Settings > Security > New Access Token. Make sure to copy the token to a file called token.txt in our working directory.

Now, after including our username, docker_image_id and repo_name at upload_docker.sh we are ready to execute it.

  1. chmod +x upload_docker.sh
  2. ./upload_docker.sh

4. Deploy the app wth Kubernetes

First, we must start the minikube service.

  1. minikube start

As in the previous step, all the commands required to perform this step are described in the shell script run_kubernetes.sh

  1. #!/usr/bin/env bash
  2. # Step 1:
  3. # Authenticate
  4. username=<USERNAME>
  5. cat token.txt | docker login --username=$username --password-stdin
  6. # Step 2
  7. # Run the Docker Hub container with kubernetes
  8. repo=<REPO_NAME>:<TAG>
  9. app_name=ml_app
  10. kubectl run $app_name\
  11. --image=$username/$repo\
  12. --port=80 --labels app=$app_name
  13. # Step 3:
  14. # List kubernetes pods
  15. kubectl get pods
  16. # Step 4:
  17. # Forward the container port to a host
  18. kubectl port-forward $app_name 8000:80
  19. kubectl describe pod $app_name

Running the script will get our Kubernetes app deployed.

  1. chmod +x run_kubernetes.sh
  2. ./run_kubernetes.sh

Make sure to stop the minikube service after using the container.

  1. minikube delete