Model Container Source Code Changes for Kubernetes Orchestration

Few changes were necessary to enable the Model’s (MyContainerCl.py) source code to query the NoSQL (MongoDB) container as implemented in Kubernetes PODs. In this capacity, the following Model source code was changed from the Docker source as implemented in Linked Docker containers to that which is implemented in the Kubernetes POD container:

As implemented in Linked Docker Model Container:
client = MongoClient("mongodb://MongoDB")
db = client.portalDB

As implemented in Kubernetes POD Model container:
client = MongoClient("mongodb://localhost:27017")
db = client.portalDB

Apache Virtual Host File Changes

The MyContainerCl.conf file required changes that would prevent necessarily manually coding the Node’s hostname into each “customer” instance pf the Apache virtual file using this app.  In other words; the “app” server name that Apache is proxying on behalf of Python/Flask in the Model container must be specified in the virtual host file MyContainerCl.conf.  So, either hardcode the Node’s hostname in  each MyContainerCl.conf instance in which  this app is deployed, or set up a server hostname variable at run time and that can be referenced by the virtual host file (prior to Apache service being reset), as the author has done here.

As implemented in Linked Docker Model Container:

<VirtualHost *:80>
.
.
.
		ServerName MyContainerCl.com
		ServerAdmin root@MyContainerCl.com


As implemented in Kubernetes POD Model container:

<VirtualHost *:80>
.
.
.
		ServerName $Svc_Host
		ServerAdmin root@$Svc_Host

Portal HTML Source File

The initial HTML source as pulled by the client browser from the Model’s Python/Flask portal (still affectionately labeled sandbox5.html) required changes.  Once the HTML code is pulled by the browser, the browser will initiate pulling js files from the Controller container. This external network action, as described in the previous chapter requires the Service object to proxy the exposed Controller container port (8081) to 30100.  

The HTML code is unchanged from the version described in the Linked Docker folder except that all references to js scripts are identified with port 30100.  The HTML source employed in the Kubernetes POD Model container follows:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Black Hole Route Injection</title>

    <!-- Bootstrap -->
    <!link href="static/js/bootstrap.tmp.css" rel="stylesheet">
    <link href="http://HOST-REF:30100/bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    <link href="http://HOST-REF:30100/bower_components/bootstrap-css/css/bootstrap-theme.min.css" rel="stylesheet">
    <!script type="text/javascript" src="localhost:8081/bower_components/angular/angular.js"></script>
    <!script src="https://rawgit.com/CautemocSg/ng-ip-address/master/ngIpAddress.min.js"></script>
</head>

<body>
    <div ng-app="myApp" ng-controller="HomeCtrl">
        <form name="SearchForm">

            <div ng-if="PhaseOne">
                <div class="container">
                    <div class="header">
                        <nav>
                            <ul class="nav nav-pills pull-right">
                            </ul>
                        </nav>
                        <h3 align="center">Route Black-Hole Portal</h3>
                    </div>
                    <div class="jumbotron">
                        <h3 align="left">Re-push all B-H prefixes? Or search for a B-H prefix in the Data Base?</h3>
                        <button class="w3-btn w3-large w3-blue" ng-click="Repush()">Repush ?</button>
                        <button class="w3-btn w3-large w3-blue" ng-click="DBaseSearch()">Database Search ?</button>
                    </div>
                </div>
            </div>
            <div ng-if="repush">
                <div>
                    <div class="container">
                        <div class="header">
                            <nav>
                                <ul class="nav nav-pills pull-right">
                                </ul>
                            </nav>                                                  
                        </div>
                        <div class="jumbotron">
                            <h3 align="left">Push results </h3>
                            <span ng-show="repushed == 'false'">
                                <button ng-click="Repush()">Repush all Prefixes</button> </span>
                            <div ng-if="PushedErr == 'true'">
                                There were problems:likely DB content/access issues                                
                                <label for="txtmessage" class="control-label">Error Message:</label>
                                <input type="text" ng-readonly="ReadOnly" class="form-control" ng-model="message" id="txtmessage">
                                <input type="button" value="Refresh the Page For New Request ?" onClick="window.location.reload()">                                
                            </div>  
                            <div ng-if="PushedErr == 'false'">
                                <label for="txtPrefixes" class="control-label">Prefixes Copied:</label>
                               <input type="text" ng-readonly="ReadOnly" class="form-control" ng-model="PrefixCopied" id="txtPrefixes">
                                <input type="button" value="Refresh the Page For New Request ?" onClick="window.location.reload()">
                            </div> 
                        </div>
                    </div>
                </div>
            </div>
            <div ng-if="DBSearched && buttonpressed == false">
                <div class="container">
                    <div class="header">
                        <nav>
                            <ul class="nav nav-pills pull-right">
                            </ul>
                        </nav>
                        <h3 align="center">Route Black-Hole Portal</h3>
                    </div>
                    <div class="jumbotron">
                        <h3 align="center">Data base Search </h3>
                        <div>
                            <fieldset>
                                <legend>Enter Address for Search</legend>
                                <label>IP Address</label>
                                <input type="text" name="SearchInput1" ng-model="$parent.ipAddress1" ng-ip-address />
                                <span ng-if="SearchForm.SearchInput1.$invalid">Invalid</span>
                                <div>
                                    <span ng-if="SearchForm.SearchInput1.$dirty && SearchForm.SearchInput1.$valid">
                                    Valid
                                    <button ng-click="selectentry()">Select</button></span>
                                </div>
                            </fieldset>
                        </div>
                    </div>
                </div>
            </div>
            <div>
                <div ng-if="DBSearched && buttonpressed">
                    <div class="container">
                        <div class="header">
                            <nav>
                                <ul class="nav nav-pills pull-right">
                                </ul>
                            </nav>
                            <h3 align="center">Route Black-Hole Portal</h3>
                        </div>
                        <div class="jumbotron">
                            <h3 align="center">Data base Search </h3>
                            <div>
                                <fieldset>

                                    <div ng-if="PrefixFound != 0 && PrefixRemain != 0">
                                        Prefix Found
                                        <button ng-click="Removeentry()">remove Entry?</button>
                                    </div>
                                    <div ng-if="PrefixFound == 0 && AddaPrefix == 0">
                                        No Such prefix in Data Base
                                        <button ng-click="Addentry()">Add Entry?</button>
                                    </div>
                                    <div ng-if="AddaPrefix">
                                        <legend>Enter any Additional BGP Attributes</legend>
                                        <div class="form-group">
                                            <label for="txtNeighbor" class="control-label">Neighbor:</label>
                                            <input type="text" class="form-control" ng-model="info.neighbor" id="txtNeighbor">
                                        </div>
                                        <div class="form-group">
                                            <label for="txtNextHop" class="control-label">NextHop:</label>
                                            <input type="text" class="form-control" ng-model="info.nexthop" id="txtNextHop">
                                        </div>
                                        <div class="form-group">
                                            <label for="txtASPath" class="control-label">ASPath</label>
                                            <input type="text" class="form-control" ng-model="info.aspath" id="txtASPath">
                                        </div>
                                        <div class="form-group">
                                            <label for="txtLocalPref" class="control-label">LocalPref:</label>
                                            <input type="text" class="form-control" ng-model="info.localpref" id="txtLocalPref">
                                        </div>
                                        <div class="form-group">
                                            <label for="txtOperationNotes" class="control-label">OperationNotes:</label>
                                            <input type="text" class="form-control" ng-model="info.opnotes" id="txtOperationNotes">
                                        </div>
                                        <div ng-show="AddSuccess == 0">
                                            <button ng-click="AnnouncePrefix()">Announce the Prefix</button>
                                        </div>
                                        <div ng-if="AddSuccess == info.prefix">
                                            <input type="button" value="Success !!! Refresh the Page For New Request ?" onClick="window.location.reload()">
                                        </div>
                                    </div>
                                    <div>
                                        <div ng-if="DeleteAPrefix == 1">
                                            <div ng-show="DeleteAPrefix == 1 && PrefixRemain != 0">
                                                <button ng-click="DenounceEntry()">Remove the Prefix</button>
                                            </div>
                                            <div ng-if="PrefixRemain == 0">
                                                No Such prefixes Remain in the Data Base !
                                                <input type="button" value="Success !!! Refresh the Page For New Request ?" onClick="window.location.reload()">
                                            </div>
                                        </div>
                                    </div>
                                </fieldset>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </form>

    </div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <!script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script type="text/javascript" src="http://HOST-REF:30100/bower_components/angular/angular.min.js"></script>
    <script type="text/javascript" src="http://HOST-REF:30100/bower_components/jquery/dist/jquery.min.js"></script>
    <script type="text/javascript" src="http://HOST-REF:30100/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="http://HOST-REF:30100/bower_components/ng-ip-address/ngIpAddress.min.js"></script>
    <script type="text/javascript" src="http://HOST-REF:30100/app-ip.js"></script>
    <script type="text/javascript" src="http://HOST-REF:30100/announce_prefix3.js"></script>
</body>

</html>

Docker file Changes

Model Dockerfile differences between version of the Linked Dockerfiles (previous folder) and the Kubernetes POD implementation of the current Model Dockerfile are minimal. 

Docker file changes between versions are noted below: 

RUN a2ensite MyContainerCl  

commented out in Kubernetes POD container Dockerfile and enabled in the wrapper.sh file

COPY apache-VH-conf.sh apache-VH-conf.sh

added to Kubernetes POD version of Model Dockerfile.  Thiswill be executed during container run time wrapper.sh execution 

wrapper.sh 

The Model container’s wrapper.sh code has been significantly updated so as to operate properly in a Kubernetes POD environment. This version of the wrapper.sh source is annotated below:

#!bin/bash

create a hostname variable referencing the POD Node’s hostname.  This variable value must be created only once, here. The actual hostname need not be referenced in source after this. 

echo  “export Svc_Host=e.2a.3da9.ip4.static.sl-reverse.com” >> ~/.bash_login

export the hostname variable so that it is available in a shell session

echo “export Svc_IP=169.61.42.14” >> ~/.bash_login

source ~/.bash_login

replace place holder references to the server hostname in the HTML source with the hostname

sed -i “s/HOST-REF/$Svc_Host/g” /var/www/ContClBase/ContClBase/templates/sandbox5.html

create the virtual host file with real server hostname references

./apache-VH-conf.sh >  /etc/apache2/sites-available/MyContainerCl.conf

now add the server host for proxying by Apache

a2ensite MyContainerCl

time to restart Apache

service apache2 restart

start up the Python/Flask app as a “native portal app”

python /var/www/ContClBase/ContClBase/MyContainerCl.py &

need to keep the container open. Choose your weapon. This is just one way. 

exec /bin/bash -c “trap : TERM INT; sleep infinity & wait”