Cloud Computing Topics
Cloud Computing Topics
Learning Objectives
If you have an iPad or Tablet with enough memory, you may also be able to use
them.
Sometimes you may want to adjust the zoom of your reader to increase or
decrease it. Please adjust your zoom to a level that is comfortable for you. On
macOS with a larger monitor, we found that zooming out multiple times results
in very good rendering allowing you to see the source code without horizontal
scrolling.
1.3 CORRECTIONS ☁
The material collected in this document is managed in
https://github.com/cloudmesh-community/book/chapters
In case you see an error or like to make a contribution of your own section or
chapter, you can do so in github via pull requests.
The easiest way to fix an error is to read the ePub and click on the cloud
symbol in a heading where you see the error. This will bring you to an editable
document in github. You can directly fix the error in the web browser and create
there a pull request. Naturally, you need to be signed into github before you can
edit and create a pull request.
1.4 CONTRIBUTORS ☁
Contributors are sorted by the first letter of their combined Firstname and
Lastname and if not available by their github ID. Please, note that the authors are
identified through git logs in addition to some contributors added by hand. The
git repository from which this document is derived contains more than the
documents included in this document. Thus not everyone in this list may have
directly contributed to this document. However if you find someone missing that
has contributed (they may not have used this particular git) please let us know.
We will add you. The contributors that we are aware of include:
1.5 NOTATION ☁
The material here uses the following notation. This is especially helpful, if you
contribute content, so we keep the content consistent.
if you like to see the details on how to create them in the markdown documents,
you will have to look at the file source while clicking on the cloud in the heading
of the Notation section (Section 1.5). This will bring you to the markdown tex,
but you will still have to look at the raw content to see the details.
☁ or 
$
Content in bash is marked with verbatim text and a dollar sign
$ This is a bash text
[1]
References are indicated with a number and are included in the >
reference chapter [1]. Use it in markdown with > [@las14cloudmeshmultiple].
References must be added to the refernces.bib file in BibTex format.
or
Chapters marked with this emoji are not yet complete or have some
issue that we know about. These chapters need to be fixed. If you like
to help us fixing this section, please let us know. Use it in markdown
with :o2: or if you like to use the image with .
REST 36:02
Slides 10
Slides 10
[Question](images/question.png).
Sections that need modifications are indicated with this emoji ![Comment]
(images/comment.png).
Other emojis
This is the list of emojis that canbe converted to PDF. So if you like a PDF,
please limit your emojis to
1.5.1 Figures
Figures have a caption and can be refereed to in the ePub simple with a number.
We show such a reference pointer while referring to Figure 1.
Note that the text must be in one line and must not be broken up even if it is
longer than 80 characters. You can refer to them with @fig:code-example. Please note in
order for numbering to work figure references must include the #fig: followed by
a unique identifier. Please note that identifiers must be really unique and that
identifies such as #fig:cloud or similar simple identifiers are a poor choice and will
likely not work. To check, please list all lines with an identifier such as.
$ grep -R "#fig:" chapters
To create hyperlinks in the document other than images, we need to use proper
markdown syntax in the source. This is achieved with a refernce for example in
sections headers. Let us discuss the refernce header for this section,
e.g. Notation. We have augmented the section header as follows:
# Notation {#sec:notation}
1.5.3 Equations
a2 + b2 = c2 (1)
The equation number is optional. Inline equations just use one dollar sign and do
not need an equation number:
This is the Pythagoras theorem: $a^2+b^2=c^2$
1.5.4 Tables
x y z
--- --- ---
1 2 3
4 5 42
As usual make sure the label is unique. When compiling it will result in an error
if labels are not unique. Additionally there are several md table generators
available on the internet and make creating table more efficient.
1.6 UPDATES ☁
As all documents are managed in github, the list of updates is documented in the
commit history at
https://github.com/cloudmesh-community/book/commits/master
In case you do a lecture withus we recommend that you download a new version
oof the ePub every week. This way you are typically staying up to date. You can
check the commit history and identify if the version of the ePub is older than the
committed version, if so we recommend that you download a new version.
Learning Objectives
In this book we provide a number of chapters that will allow you to easily get
knowledge in cloud computing on theoretical and practical levels.
Although the following was originally covered in this book, we decided to split
out its contents as to make the core cloud engineering book smaller. In case you
take one of our classes using the book, we expect that you pick up the material
covered also by these additional books. Please be aware that some of the class
material is based on Python and Linux. You will need no knowledge of them as
you can pick it up while reading this book.
Cloud Computing
Linux for Cloud Computing
Python for Cloud Computing
Scientific Writing with Markdown
We will start with the definition of what cloud computing is and motivate
why it is important to not only know technologies such as AI or ML or
Databases. We present you with evidence that Clouds are absolutely
relevant to todays technologies. We see furthermore a trend to utilize AI
and ML services on in the cloud. Technologies such as virtual machine and
containers and Function as a Service are essential to the repertoire of a
modern Cloud or Data engineer. There is more than ML … ☺
Data Center
This chapter will explain you why we need cloud data centers, how a cloud
data center look likes and which environmental impact such data centers
have.
Architecture
This chapter will introduce you to the basic architectural features and
designs of cloud computing. We will discuss architectures for IaaS, and
contrast it to other architectures. We will discuss the NIST definition of the
cloud and the Cloud Security Alliance Reference Architecture. We will
discuss the multi-cloud architecture introduced by cloudmesh as well as the
Big Data Reference Architecture.
REST
This chapter will introduce you to a way on how to define services in the
cloud that you can easily access via language independent client APIs. It
will introduce you to the fundamental concepts of REST. We will more
importantly introduce you to OpenAPI that allows you to specify REST
services via a specification document so you can create APIs and clients
form the document automatically. We will showcase you how to do that
with flask.
GraphQL
Hypervisors
In this chapter we introduce you to the basic concepts and distinguish the
various forms of virtualization.
IaaS
In this section we will also provide you with information about multicloud
management with cloudmesh which makes it extremly easy to switch
between and use services from multiple cloud.s
Important to note is that the appendix contains very useful information that
augments this section. This includes a more detailed list of services for
some IaaS providers as well as information on how to use chameleon cloud
which has been adapted by us for this chapter.
Map/Reduce
In this chapter we discuss about the background of Mapreduce along with
Hadoop and it’s core components. We will also introduce Spark to you in
this section to Spark. you in this section.
You will be presented on how you can use the systems on a single resource
so you can explore them more easily, but we will also let you know how to
install them on a cluster in principal.
In fact we have here two sections that need to be delineated a bit better
which we hope we can do with your help.
Container
you will help us improving this section if you elect to conduct a project
on comet.
We conclude the section with letting you know how to run Tensorflow via
singularity,
Serverless Computing
Recently a new paradigm in cloud computing has been introduced. Instead
of using virtual machines or containers functions with limited resource
requirements are specified that can than be executed on function capable
execution services hosted by cloud providers.
We will introduce you to this concept and showcase you some examples of
FaaS services and frameworks.
Messaging Services
Many devices in the cloud need to communicate with each other. In this
chapter we look into how we can provide alternatives to REST services that
provide messaging capabilities. We will focus on MQTT which is often
used to connect cloud edge devices between each other and the cloud.
GO
Cloud AI Services
As part of the class we will be exploring AI services that are are hosted in
cloud and offered as service. If interested you will be able to use them in
your projects. As part of this class you will also be developing AI services
and those can be hosted in the cloud and reused by others. While using
cross-platform specifications, clients for Java, Python, Scala, Go, and other
programming languages will be automatically created for you. This will
allow others to reuse your services.
3 DEFINITION OF CLOUD COMPUTING ☁
Learning Objectives
Videos:
NIST
Wikipedia
Gartner
You must be that TALLL to survive in Cloud Computing and Big Data
We need to be aware not only what is currently a trend, but what will be
future trends
Learning Objectives
Before we go into more details of a data center we like to motivate why we need
them. Here we start with looking at the amount of data that recently got created
and provide one of many motivational aspects. Not all data will or should be
stored in data centers. However a significant amount of data will be in such
centers.
One of the issues we have is to comprehend how much data is created. It’s hard
to imagine and put into a perspective how much total data is created over a year,
a month, a week, a day or even just an hour. Instead to easily visualize the
amount of data produced we often find graphics easier to comprehend that shows
how much data was generated in a minute. Such depictions usually include
examples of data generated as a part of popular cloud services or the internet in
general.
One such popular depiction is Data Never Sleeps (see Figure 3). It has been
produced a number of times over the years and is now at version 7.0 released in
2019. If you identify a newer version, please let us know.
Observations for 2019: It is worth while to study this image in detail and identify
some of the data that you can relate to of service you use. It is also a possible
indication to study other services that are mentioned. For the data for 2019 we
observe that a staggering ~4.5Mil google searches are executed every minute
which is slightly lower than the number of videos watched on youtube. 18Mil
text messages are send every minute. Naturally the numbers are averages over
time.
Figure 2: Data Never Sleeps [2]
While reviewing the image from last year from the same author, we find not
only increases, but also declines. Looking at facebook showcases a loss of 73000
logins per minute. This loss is substantial. We can see that facebook services are
replaced by other services that are more popular with the younger generation
who tend to pick up new services quickly (see Figure 5).
Figure 5: Internet Minute 2017-2018 [4]
It is also interesting to compare such trends over a longer period of time (see
Figure 6, Figure 7). An example is provided by looking at Google searches
http://www.internetlivestats.com/google-search-statistics/.
When looking at the trends, many predict an exponential growth in data. This
trend is continuing.
A data center is a facility that hosts the information technology related to servers
and data serving a large number of customers. data centers evolved from the
need to originally have large rooms as the original computers filled in the early
days of the compute revolution filled rooms. Once multiple computers were
added to such facilities super computer centers created for research purposes.
With the introduction of the internet and offering services such as Web hosting
large business oriented server rooms were created. The need for increased
facilities was even accelerated by the development of virtualization and servers
being rented to customers in shared facilities. As the need of web hosting still is
important but has been taken over by cloud data centers, the terms internet data
center, and cloud data center are no longer used to distinguish it. Instead we use
today just the term data center. There may be still an important difference
between research data centers offered in academia and industry that focus on
providing computationally potent clusters focus on numerical computation. Such
data centers are typically centered around the governance around a smaller
number of users that are either part of an organization or a virtual organization.
However, we see that even in the research community data centers not only host
supercomputers, but also Web server infrastructure and these days even private
clouds that support the organizational users. In case of the latter we speak about
supporting the long tail about science.
The latter is driven by the 80%-20% rule. E.g. 20% of the users use 80% of the
compute power. This means that the top 20% of scientists are served by the
leadership class super computers in the nation, while the rest are either served by
other servers, cloud offerings through research and public clouds.
Due to the data and the server needs in the cloud and in research such data
centers may look very different. Some focus on large scale computational
resources, some on commodity hardware offered to the community. The size of
them is also very different. While a supercomputing center as part of a university
was one of the largest such data centers two decades ago, they dwarf the centers
now deployed by industry to serve the long tail of customers.
Facility: the entire data center will be hosted in a building. The building
may have specific requirements related to security, environmental concerns,
or even the integration into the local community with for example
providing heat to surrounding residences.
Servers
Network Services
Disks
Data Backup Services
Operations staff: The facility will need to be staffed with the various groups
that support such data centers. It includes
IT Staff
Security and Facility Staff
Support Infrastructure Staff
Variation in Size: Data centers range in size from small edge facilities to
megascale or hyperscale filling large ware houses.
Variation in cost per server: Although many data centers standardize their
components, specialized services may be offered not on a 1K server, but on
a 50K server.
Energy Cost: Data centers use a lot of energy. The energy cost varies per
region. A motivation to reduce energy use and cost is also been trended by
environmental awareness, not only by the operators, but by the community
in which such centers operate.
Reliability: Although through operational efforts the data center can be
made more reliable, failure still can happen. Examples are
https://www.zdnet.com/article/microsoft-south-central-u-s-datacenter-
outage-takes-down-a-number-of-cloud-services/
https://www.datacenterknowledge.com/archives/2011/08/07/lightning-in-
dublin-knocks-amazon-microsoft-data-centers-offline
https://techcrunch.com/2012/10/29/hurricane-sandy-attacks-the-web-
gawker-buzzfeed-and-huffington-post-are-down/
One of the most important factor to ensure smooth operation and offering of
services is to employ metrics that will be able to provide significant impacting
the operations. Having metrics allows the staff to monitor and adapt to dynamic
situations but also to plan operations.
4.1.5.1 Data Center Energy Costs
One of the easiest to monitor metrics for a datacenter is the cost of energy used
to operate all of the equipment. Energy is one of the largest costs a datacenter
incurs during its operation as all of the servers, networking, and cooling
equipment require power 24/7. For electricity, billing is usually measured in
terms of kilowatt hours (kWh) and kilowatts (kW). Depending on circumstances,
there may also be costs for public purpose programs, cost recovery, and stranded
costs, but they are beyond the scope of this book.
Energy costs for a datacenter, then, are composed of two things: charges for
energy and charges for demand. Energy is the amount of total energy consumed
by the datacenter and will be the total kWh multiplied by the cost per kWh.
Demand is somewhat more complicated: it is the highest total consumption
measured in a 15 minute period. Taking the previous example, if a datacenter
has 1,000 servers, the total energy consumption would be 750 kWh in the hour,
but the demand charge would be based off of 1,200 kW (or 1.2 MW).
The costs, then, are how the utility company recoups its expenses: the charge per
kWh is it recouping the generation cost while the kW charge is recouping the
cost of transmission and distribution (T&D). Typically, the demand charge is
much higher and will depend on utility constraints - if a utility is challenged on
the T&D front, expect these costs to be over $6-$10/kW. If the assumed cost-
per-kWh is $0.12 and cost-per-kW is $8, the cost to run our servers for a month
would be:
kW h = 0.75 * 24 * 30 * 0.12 * 1000 = 64, 800 (3)
This would total to $74,400. It’s important to note that fixing demand charges
can have a tremendous payback: had the servers simply consumed 750 kW over
the course of the hour, then our demand charges would’ve been halved to $4,800
while the energy costs remained the same. This is also why server virtualization
can have a positive impact on energy costs: by having fewer servers running at a
higher utilization, the demand charge will tend to level itself out as, on average,
each server will be more fully utilized. For example, it’s better to pay for 500
servers at 100% utilization than 1000 servers at 50% utilization even though the
amount of work done is the same since, if the 1,000 servers momentarily all
operate at 100% utilization for even a brief amount of time in a month, the
demand charge for the datacenter will be much higher.
Scientists world wide have identified a link between carbon emission and global
warming. As the energy consumption of a data center is substantial, it is prudent
to estimate the overall carbon emission. Schneider Electric (formerly APC) has
provided a report on how to estimate the Carbon footprint of a data center [7].
Although this report is already a bit older, it provides still valuable information.
It defines key terms such as
Peaker plant:
Peaking power plants, also known as peaker plants, and occasionally just
peakers, are power plants that generally run only when there is a high
demand, known as peak demand, for electricity. Because they supply power
only occasionally, the power supplied commands a much higher price per
kilowatt hour than base load power. Peak load power plants are dispatched
in combination with base load power plants, which supply a dependable and
consistent amount of electricity, to meet the minimum demand. These
plants are generally coal-fired which causes a huge amount of CO2
emissions. A peaker plant may operate many hours a day, or it may operate
only a few hours per year, depending on the condition of the region’s
electrical grid. Because of the cost of building an efficient power plant, if a
peaker plant is only going to be run for a short or highly variable time, it
does not make economic sense to make it as efficient as a base load power
plant. In addition, the equipment and fuels used in base load plants are often
unsuitable for use in peaker plants because the fluctuating conditions would
severely strain the equipment. For these reasons, nuclear, geothermal,
waste-to-energy, coal and biomass are rarely, if ever, operated as peaker
plants.
Avoided emissions:
This type of carbon offset provides perhaps the simplest options that will
ease the adoption of low carbon practice. When these practices become
generally accepted (or compulsory), they will no longer qualify as offsets
and further efficiencies will need to be promoted.
The data center will have a total carbon profile, that includes the many different
aspects of a data center contributing to carbon emissions. This includes
manufacturing, packaging, transportation, storage, operation of the data center,
and decommissioning. Thus it is important to notice that we not only need to
consider the operation but also the construction and decommission phases.
One of the main operational impacts is the cost and emissions of a data center
cause by running, and cooling the servers in the data center. Naturally this is
dependent on the type of fuel that is used to produce the energy. The actual
carbon impact using electricity certainly depends on the type of powerplant that
is used to provide it. These energy costs and distribution of where the energy
comes from can often be looked up by geographical regions on the internet or
form the local energy provider. Municipal government organizations may also
have such information. Tools such as the Indiana State Profile and Energy Use
[8].
https://www.schneider-electric.com/en/work/solutions/system/s1/data-
center-and-network-systems/trade-off-tools/data-center-carbon-footprint-
comparison-calculator/tool.html
http://it-resource.schneider-electric.com/digital-tools/calculator-data-center-
carbon
If we calculate the total cost, we need naturally add all costs arising from build
and teardown phase as well as operational upgrades.
One of the frequent measurements in data centers that is used is the Power usage
effectiveness or PUE in short. It is a measurement to identify how much energy
is ued for the computing equipment versus other energy costs such as air
conditioning.
Formally we define it as
The best value of PUE is 1.0. Any data center must be higher than this value as
offices and other cost surely will arise when we look at the formula
To tal Facility Energy
PUE =
IT Equ ipmen t Energy
https://www.42u.com/measurement/pue-dcie.htm
It does not integrate for example climate based differences, such as that the
energy use to cool a data center in colder climates is less than in warmer
climates. However, this may actually be a good side-effect as this will
likely result in less cooling needs sand therefor energy costs.
It also forces large data centers with many shared servers in contrast to
small data centers where operational cost may become relevant.
It does not take in consideration recycled energy to for example heat other
buildings outside of the data center.
Hence it is prudent not to just look at the PUE but also at other metrics that lead
to the overall cost and energy usage of the total ecosystem the data center is
located in.
Already in 2006, Google reported its six data centers efficiency as 1.21 and
Microsoft as 1.22 which at that time were considered very efficient. However
over time these target has shifted and today’s data centers achieve much lower
values. The Green IT Cube in Darmstadt, Germany even reported 1.082.
According to Wikipedia an unnamed Fortune 500 company achieved with 30000
SuperMicro blades a PUE of 1.06 in 2017.
Exercises
What is the lowest PUE you can find. Provide details about the
system as well as the date when the PUE was reported.
To understand hot-cold aisles, one must take a brief foray into the realm of
physics and energy. Specifically, understanding how a temperature gradient tries
to equalize. The most important formula to know is the heat transfer Equation 5.
q = hc A(ta − ts ) (5)
Here, q is the amount of heat transferred for a given amount of time. For this
example, we will calculate it as W/hour as that is, conveniently, how energy is
billed. Air moving at a moderate speed will transfer approximately 8.47 Watts
per Square Foot per Hour. A 1U server is 19 inches wide and about 34 inches
deep. Multiplying the two values gives us a cross section of 646 square inches,
or 4.48 square feet. Plugging these values into our Equation 5 us:
From the previous listing, we can see that a 35 degree delta allows the center to
dissipate 1,300 Watts of waste heat from a 1U server while a 17.5 degree delta
allows us to only dissipate 664 Watts of energy. If a server is consuming more
than 664 Watts, it’ll continue to get warmer and warmer until it eventually
reaches a temperature differential high enough to create an equilibrium (or
reaches a thermal throttle and begins to reduce performance).
See Figure 10 to understand how the hot-cold isle configuration is setup in a data
center.
As the name somewhat implies in cold air containment, the data centers is
designed so that only cold air goes into the cold isle, this makes sure that the
system only draws in cold air for cooling purposes. Conversely in hot isle
containment design, the hot isle is contained so that the hot air collected in the
hot isle is drawn out by the cooling system and so that the cold air does not flow
into the hot isles[10].
Another good way of reducing the energy consumption is to install water cooled
doors directly at he rack as shown in Figure 11. Cooling even can be actively
controlled so that in case of idle servers less energy is spend to conduct the
cooling. There are many vendors that provide such cooling solutions.
Figure 11: Active Rear Door link
Clouds and especially university data centers do not just provide virtual
machines but provide traditional super computer services. This includes the NSF
sponsored XSEDE project. As part of this project the "XDMoD auditing tool
provides, for the first time, a comprehensive tool to measure both utilization and
performance of high-end cyberinfrastructure (CI), with initial focus on XSEDE.
Several case studies have shown its utility for providing important metrics
regarding resource utilization and performance of TeraGrid/XSEDE that can be
used for detailed analysis and planning as well as improving operational
efficiency and performance. Measuring the utilization of high-end
cyberinfrastructure such as XSEDE helps provide a detailed understanding of
how a given CI resource is being utilized and can lead to improved performance
of the resource in terms of job throughput or any number of desired job
characteristics.
https://open.xdmod.org/7.5/index.html
Gregor von Laszewski and Fugang Wang are providing a scientific impact
metric to XDMoD and XSEDE. It is a framework that (a) integrates publication
and citation data retrieval, (b) allows scientific impact metrics generation at
different aggregation levels, and (c) provides correlation analysis of impact
metrics based on publication and citation data with resource allocation for a
computing facility. This framework is used to conduct a scientific impact metrics
evaluation of XSEDE, and to carry out extensive statistical analysis correlating
XSEDE allocation size to the impact metrics aggregated by project and Field of
Science. This analysis not only helps to provide an indication of XSEDE’S
scientific impact, but also provides insight regarding maximizing the return on
investment in terms of allocation by taking into account Field of Science or
project based impact metrics. The findings from this analysis can be utilized by
the XSEDE resource allocation committee to help assess and identify projects
with higher scientific impact. Through the general applicability of the novel
metrics we invented, it can also help provide metrics regarding the return on
investment for XSEDE resources, or campus based HPC centers [12].
Futuregrid, could monitor all of them and published its result in its Metrics
portal. Monitoring the VMs is an important activity as they can identify VMs
that may no longer be used (the user has forgotten to terminate them) or too
much usage of a user or project can be detected in early stages.
Monitoring tools for containers such as for kubernetes are listed at:
https://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-
monitoring/
Such tools can be deployed alongside kubernetes in the data center, but will
likely have restrictions to its access. They are for those who operate such
services for example in kubernetes. We will discuss this in future sections in
more detail.
In this section we will be giving some data center examples while looking at
some of the mayor cloud providers.
4.1.6.1 AWS
AWS focuses on security aspects of their data centers that include four aspects
[14]:
Perimeter Layer
Infrastructure Layer
Data Layer
Environmental Layer
4.1.6.2 Azure
Azure claims to have more global regions [16] than any other cloud provider.
They motivate this by their advertisement to bring and applications to the users
around the world. The goal is similar as other commercial hyper-scale providers
by introducing preserving data residency, and offering comprehensive
compliance and resilience. As of Aug 29, 2018 Azure supports 54 regions
worldwide. These regions can currently be accessed by users in 140 countries
(see Figure 15). Not every service is offered in every region as the service to
region matrix shows:
https://azure.microsoft.com/en-us/global-infrastructure/services/
4.1.6.3 Google
From Google [17] we find that on Aug. 29th Google has the following data
center locations (see Figure 16):
https://www.google.com/about/datacenters/efficiency/
The PUE [18] data for all large-scale Google data centers is shown in Figure 17
An important lesson from Google is the PUE boundary. That is the different
efficiency based on the closeness of the IT infrastructure to the actual data center
building. This indicates that it is important to take at any providers definition of
PUE in order not to report numbers that are not comparable between other
vendors and are all encompassing.
Figure 18 shows the Google data center PUE measurement boundaries. The
average PUE [18] for all Google data centers is 1.12, although we could boast a
PUE as low as 1.06 when using narrower boundaries.
As a consequence, Google is defining its PUE in detail in Equation 7.
ESIS + EIT S + ETX + EHV + ELV + EF
P UE = (7)
EIT S − ECRAC − EUP S − ELV + EN et1
4.1.6.4 IBM
IBM maintains almost 60 data centers, which are placed globally in 6 regions
and 18 availability zones. IBM targets businesses while offering local access to
its centers to allow for low latency. IBM states that trough this localization users
can decide where and how data and workloads and address availability, fault
tolerance and scalability. As IBM is business oriented it also stresses its certified
security.
https://www.ibm.com/cloud/data-centers/
4.1.6.5 XSEDE
https://www.xsede.org/
https://portal.xsede.org/resource-monitor
For cloud Computing the following systems are of especial importance although
selected others may also host container based systems while using singularity
(see Figure 19):
4.1.6.5.1 Comet
The comet machine is a larger cluster and offers bare metal provisioning based
on KVM and SLURM. Thus it is a unique system that can run at the same time
traditional super computing jobs such as MPI based programs, as well as jobs
that utilize virtual machines. With its availability of >46000 cores it provides
one of the larges NSF sponsored cloud environment. Through its ability to
provide bare metal provisioning and the access to Infiniband between all virtual
machines it is an ideal machine for exploring performance oriented virtualization
techniques.
4.1.6.5.2 Jetstream
https://dcops.iu.edu/
https://www.chameleoncloud.org/
https://www.chameleoncloud.org/hardware/
Indiana University has a data center in which many different systems are housed.
This includes not only jetstream, but also many other systems. The systems
include production, business, and research clusters and servers. See Figure 20
https://kb.iu.edu/d/bezu (Karst)
https://kb.iu.edu/d/aolp (Carbonate)
One of the special systems located in the data center and managed by the Digital
Science Center is called Futuresystems, which provides a great resource for the
advanced students of Indiana University focusing on data engineering. While
systems such as Jetstream and Chameleon cloud specialize in production ready
cloud environments, Futuresystems, allows the researchers to experiment with
state-of-the-art distributed systems environments supporting research. It is
available with Comet and thus could also serve as an on-ramp to using larger
scale resources on comet while experimenting with the setup on Futuresystems.
A few years ago data centers build from shipping containers were very popular.
This includes several main Cloud providers. Such providers have found that they
are not the best way to develop centers at scale. This includes Microsoft and
Google The current trend however is to build mega or hyperscale data centers.
One of the driving factors in cloud computing and the rise of large scale data
centers is the ability to use server virtualization to place more than one server on
the same hardware. Formerly the services were hosted on their own servers.
Today they are managed on the sae hardware although they look to the customer
like separate servers.
Due to the immense number of servers in data centers, as well as the increased
workload on its servers, the energy consumption of data centers is large not only
to run the servers, but to provide the necessary cooling. Thus it is important to
revisit the impact such data centers have on the energy consumption. One of the
studies that looked into this is from 2016 and is published by LBNL [19] In this
study the data center electricity consumption back to 2000 is analyzed while
using previous studies and historical shipment data. A forecast is with different
assumption is contrasts till 2020
Figure Energy Forecast depicts “an estimate of total U.S. data center electricity
use (servers, storage, network equipment, and infrastructure) from 2000-2020”
(see Figure 21).
While in “2014 the data centers in the U.S. consumed an estimated 70 billion
kWh” or “about 1.8% of total U.S. electricity consumption”. However, more
recent studies find an increase by about 4% from 2010-2014. This contrasts a
large derivation from the 24% that were originally predicted several years ago.
The study finds that the predicted energy use would be approximately 73 billion
kWh in 2020.
The scenarios are identified that will significantly impact the prediction:
The PUE (Power Usage Effectiveness) of Phase1 vessel was 1.07 which is very
efficient and a perfect WUE (Water Usage Effectiveness) of exactly 0, while
land data centers consume ~4.8 liters of water per KWH. This vessel consumed
computer power equivalent to 300 Desktop PCs and was of 38000 lbs and it
operated for 105 days.
Figure 22: The Leona Philpot prototype
See Figure 22, The Leona Philpot prototype was deployed off the central coast
of California on Aug. 10, 2015. Source: Microsoft [20]
The phase 2 started in June 2018 and lasted for 90 days. Microsoft deployed a
vessel at the European Marine Energy Center in UK.
The phase 2 vessel was 40ft long and had 12 racks containing 864 servers.
Microsoft powered this data center using 100% renewable energy. This data
ceter is claimed to be able to operate without maintenance for 5 years. For
cooling Microsoft used infrastructure which pipes sea water through radiators in
back on server racks and then move water back in to ocean.
Figure 23 shows the Northern Isles prototype being deployed near Scotland.
1. How doe the vesil increase the surrounding water temperature and effects
the ecosystem
2. If places in saltwater, corrosion can occur that may not only effect the
vesel, but also the ecosystem
3. Positive effects could also be created on ecosystems, which is for example
demonstrated by creation of artificial reefs. However if the structure has to
be removed after 20 years, which impat has it than on the ecosystem.
Solar: https://9to5google.com/2019/01/17/largest-ever-solar-farms-google/
Wind: https://www.datacenterknowledge.com/wind-powered-data-centers
Hydro: http://www.hydroquebec.com/data-center/advantages/clean-
energy.html there will be others
Thermal: find better resource
https://spectrum.ieee.org/energywise/telecom/internet/iceland-data-center-
paradise
Recyclers: https://www.datacenterknowledge.com/data-centers-that-
recycle-waste-heat
Batteries
Store energy in other forms such as potential energy.
We find a world wide trend in society to shift towards renewables. This includes
government efforts to support renewable in benefit of the society:
Also look at the US state of California and others that project renewable energy.
https://www.irena.org/-
/media/Files/IRENA/Agency/Publication/2018/Jan/IRENA_2017_Power_Costs_2018.pd
We predict that any country not being heavily committed in renewable energies
will fall behind while missing out on research opportunities in renewable
energies themselfs. Today the cost of renewable energy producing power plants
have so drastically improved they are not only producing less green house gasses
but are today even cheaper to operate and build than combustion based energy
producing power plants.
It is important that we recognize that datacenter outages can happen and thus
such outages must be build into the operations of the cloud services that are
offered to the customers to assure an expectation level of quality of service.
Here is an example:
Reference
4.1.13 Exercises
Exercises
E.Datacenter.2.a: Table
World wide we have many data centers. Your task will be to find the
carbon emission of a data center and its cost in $ based on energy
use on a yearly basis. Make sure you avoid redundant reporting and
find a new datacenter. Add your data to the table in this link under
the Sheet DataCenter
E.Datacenter.2.b: Table
place a file in your repository called datacenter.md (note the spelling all lower
case) and describe details about you data center without plagiarizing. Provide
references to back up your data and description.
Yearly
Data Electricity IT Yearly Equivalent
Location Year CO2
Center Cost* Load Cost in Cars
Footprint
If you find other estimates for a data center or an entire data center
fleet such as AWS world wide, please provide citations.
http://carbonfootprint.c2es.org/
Add your data to the table in this link under the Sheet
CarbonFootPrint
E.Datacenter.4:
Pick a renewal energy from Section 4.1.10 and describe what it is.
Find data centers that use this energy form. Include the information
in your hid directory under the file datacenter.md.
You will do the energy form based on taking the last digit from your
HID and getting the modulo 6 and looking up the value in this table
0. Solar
1. Wind
2. Hydro
3. Thermal
4. Recyclers
5. Others
If your modulo is undefined please use 5 (e.g. if your digit at the end
of your hid 0)
E.Datacenter.5:
E.Datacenter.6:
E.Datacenter.7:
E.Datacenter.8:
Find major data center outages and discuss the concrete impact on
the internet and user community. Concrete means here not users of
the center xyz lost services, but can you identify how many users or
how many services were impacted and which? Is there a cost revenue
loss projected somewhere? If you find an outage do significant
research on it. For example other metrics could include what media
impact did this outage have?
E.Datacenter.9:
5.1 ARCHITECTURES ☁
Learning Objectives
Mainframe computing is using the larger and more reliable computers, like IBM
System z9, to run the critical applications, bulk data processing, enterprise
resource planning and business transaction processing.
5.1.1.2 PC Computing
The term PC is short for personal computer. The first PCs were introduced by
IBM to the market. PCs need an operating system such as Windows, macOS, or
Linux
PC Computing refers to
and its evolution is defined in The Grid-Idea and Its Evolution. The original
definition of Grid computing has been summarised as follows:
This definition is certainly including services that are today offered by the
Cloud. Hence in the early days of cloud computing there was a large debate
occurring if cloud is just another term for Grid. In Cloud Computing and Grid
Computing 360-Degree Compared an analysis is conducted between the
different architecture models outlining that collective resources and connectivity
protocols introduced by the Grid community have been replaced by the cloud
with platform and unified resources.
while the Grid was originally designed to give a few scientist access to the
biggest agglomerated research supercomputers,
business focused on serving originally millions of users with the need to run
only a view data or compute services.
With the ocurance of the WWW protocols, internet commuting brought to the
consumers a global computer network providing a variety of information and
communication facilities.
devices that are interconnected via the internet while they are
embedded in things or common objects. The dives send and receive
data to be integrated into a network with sensors and actuators
reacting upon sensory and other data.
In addition, we need to point out two additional terms that we will integrate in
this image. Edge Computing and Fog Computing. Currently there is still some
debate about what these terms are, but we will follow the following definitions:
computing conducted in-between the cloud and the edge devices. This
could be for example part of a smart network, that hosts a small set of
analytics capabilities, so that the data does not have to travel back to
the data center, but the edge device is not powerful enough to do the
calculation. Thus a Fog computing infrastructure provides tha ability
to conduct the analysis closer to the edge saving valuable resources
while not needing to transmit all data to the data center although it
will be analyzed
The typical triangular diagram (see Figure 26) is often used to represent it.
When we analyse these functions for example for Amazon Web services we find
the following
Compute
Storage
Databases
Migration
Networking & Content Delivery
Developer Tools
Management Tools
Media Services
Security, Identity & Compliance
Machine Learning
Analytics
Mobile
Augmented reality and Virtual Reality
Application Integration
Customer Engagement
Business Productivity
Desktop & App Streaming
Internet of Things
Game Development
AWS Marketplace Software
AWS Cost Management
From this we derive that for the initial contact to the customer the functionality
is put in foreground, rather than the distinction between SaaS, PaaS, and IaaS. If
we sort these services into the as a Service mode we find:
IaaS
Compute
Storage
Databases
Migration
Networking & Content Delivery
PaaS
Developer Tools
Management Tools
Media Services
Security, Identity & Compliance
Machine Learning
Analytics
Mobile
Augmented reality and Virtual Reality
Application Integration
Customer Engagement
Business Productivity
Desktop & App Streaming
Game Development
AWS Marketplace Software
AWS Cost Management
Internet of Things
Other examples for product lists such as the one from Azure are provided in the
Appendix.
The group of industry experts based use the following guiding principles when
publishing their reference Architecture.
An overview of the architecture is shown in the diagram from the Cloud Security
Alliance. See Figure 28
One of the earliest such tools is Cloudmesh.org, which is lead by von Laszewski.
The tool was developed at a time when AWS and Nimbus, and Eucalyptus
where predominant players. At that time OpenStack had just transitioned from a
NASA project to a community development.
FutureGrid was one of the earliest academic cloud offerings to explore the
effectiveness of the different cloud infrastructure solutions. It was clear that a
unifying framework and abstraction layer was needed allowing us to utilize them
easily. In fact cloudmesh did not only provide a REST based API, but also a
commandline shell allowing to switch between clouds with a single variable. It
also provided bare metal provisioning before OpenStack even offered it.
Through an evolution of developments the current cloudmesh architecture that
allows multicloud services is depicted in the next figure. We still distinguish the
IaaS level which included not only IaaS Abstractions, but also Containers, and
HPC services. Platforms are typically integrated through DevOps that can be
hosted on the IaaS. Examples are Hadoop, and Spark The services are exposed
through a client API hiding much of the internals to the user. A portal and
application services have successfully demonstrated the feasibility of this
approach (see Figure 29).
Figure 29: Cloudmesh Arch [1]
Students from e516 can and are in fact expected to participate actively on the
development of Cloudmesh v4.0. In addition the OpenAPI service specifications
developed for the project will be integrated in Volume 8 of the NIST Big data
reference architecture, which is discussed elsewhere.
5.1.7 Resources
[24] http://www.lifl.fr/iwaise12/presentations/tata.pdf
[25]
https://media.amazonwebservices.com/AWS_Cloud_Best_Practices.pdf
[26]
http://staff.polito.it/alessandro.mantelero/cloud_computing/Sun_Wp2009.pdf
[27]
https://resources.sei.cmu.edu/asset_files/Presentation/2010_017_001_23337.pdf
[28] https://www.oracle.com/technetwork/articles/entarch/orgeron-top-10-
cloud-1957407.pdf
[29] http://www.oracle.com/technetwork/topics/entarch/oracle-wp-cloud-
ref-arch-1883533.pdf
[30]
https://pdfs.semanticscholar.org/cecd/c193b73ec1e7b42d132b3c340e6dd348d3f4.pdf
Learning Objectives
One of the major technical areas in the cloud is to define architectures that can
work with Big Data. For this reason NIST has work now for some time on
identifying how to create a data interoperability framework. The idea here is that
at one point architecture designers can pick services that they can chose to
combine them as part of their data pipeline and integrate in a convenient fashion
into their solution.
Besides just being a high level description NIST also encourages the verification
of the architecture through interface specifications, especially those that are
currently under way in Volume 8 of the document series. You have the unique
opportunity to help shape this interface and contribute to it. We will provide you
not only mechanisms on how you theoretically can do this, but also how you
practically can contribute.
As part of your projects in 516 you will need to integrate a significant service
that you can contribute to the NIST document in form of a specification and in
form of an implementation.
The Nist Big Data Public Working Group (NBD-PWG) was established as
collaboration between industry, academia and government “to create a
consensus-based extensible Big Data Interoperability Framework (NBDIF)
which is a vendor-neutral, technology- and infrastructure-independent
ecosystem” [31]. It will be helpful for Big Data stakeholders such as data
architects, data scientists, researchers, implementers to integrate and utilize “the
best available analytics tools to process and derive knowledge through the use of
standard interfaces between swappable architectural components” [31]. The
NBDIF is being developed in three stages:
Nist has developed the following volumes as listed in Table: BDRA volumes that
surround the creation of the NIST-BDRA. We recommend that you take a closer
look at these documents as in this section we provide a focussed summary with
the aspect of cloud computing in mind.
Volume 1 of the series introduces the community to common definitions that are
used as part of the field of Big data. This includes the analysis of characteristics
such as volume, velocity, variety, variability and the use of structures and
unstructured data. As part of the field of data science and engineering it lists a
number of areas that are to be believed to be essential including that they must
master including data structures, parallelism, metadata, flow rate, visual
communication. In addition we believe that an additional skill set must be
prevalent that allows a data engineer to deploy such technologies onto actual
systems.
3.3.6. Deployments:
Volume: Big for data means lots of bytes. This could be achieved in many
different ways. Typically we look at tha actual size of a data set, but also how
this data set is stored for example in many thousands of smaller files that are part
of the data set. It is clear that in many of such cases analysis of a large volume of
data will impact the architectural design for storage, but also the workflow on
how this data is processed.
Velocity: We see often that big data is associated with high data flow rates
caused by for example streaming data. It can however also be caused by
functions that are applied to large volumes of data and need to be integrated
quickly to return the result as fast as posible. Needs for real time processing as
part of the quality of service offered contribute also to this. Examples of IoT
devices that integrate not only data in the cloud, but also on the edge need to be
considered.
Variety: In todays world we have many different data resources that motivate
sophisticated data mashup strategies. Big data hence not only deals with
information from one source but a variety of sources. The architectures and
services utilized are multiple and needed to enable automated analysis while
incorporating various data source.
Variability: Any data over time will change. Naturally that is not an exception
in Big data where data may be a time to live or needs to be updated in order not
to be stale or obsolete. Hence one of the characteristics that big data could
exhibit is that its data be variable and is prone to changes.
Veracity: Veracity refers to the accuracy of the data. Accuracy can be increased
by adding metadata.
Validity: Refers to data that is valid. While data can be accurately measured, it
could be invalid by the time it is processed.
Volatility: Volatility refers to the change in the data values over time.
Value: Naturally we can store lots of information, but if the information is not
valuable then we may not need to store it. This is recently been seen as a trend as
some companies have transitioned data sets to the community as they do not
provide value to the service provider to justify its prolonged maintenance.
In other cases the data has become so valuable and that the services offered have
been reduced for example as they provide too many resource needs by the
community. A good example is Google scholar that used to have much more
liberal use and today its services are significantly scaled back for public users.
While looking at the characteristics of Big Data it is obvious that Big data is on
the one hand a motivator for cloud computing, but on the other hand existing Big
Data frameworks are a motivator for developing Big Data Architectures a certain
way.
Hence we have to always look from both sides towards the creation of
architectures related to a particular application of big data.
This is also motivated by the rich history we have in the field of parallel and
distributed computing. For a long time engineers have dealt with the issue of
horizontal scaling, which is defined by adding more nodes or other resources to
a cluster. Such resources may include
In addition to the horizontal scaling issues we also have to worry about the
vertical scaling issues, this is how the overall sytem architecture fits together to
adress an end-to-end use case. In such efforts we look at
interface designs,
workflows between components and services,
privacy of data and other security issues,
reusability within other use-cases.
Naturally the cloud offers the ability to cloudify existing relational databases as
cloud services while leveraging the increased performance and special hardware
and software support that may be otherwise unaffordable for an individual user.
However we see also the explosive growth of non sql databases because some of
them can more effectively deal with the characteristics of big data than
traditional mostly weel structured data bases. In addition many of these
frameworks are able to introduce advanced capability such as distributed and
reliable service integration.
Although we have been used to the term cloud wile using virtualized resources
and the term Grid by offering a network of supercomputers in a virtual
organization, We should not forget that Cloud service providers also offer High
performance computers resources for some of their most advanced users.
Naturally such resources can be used not only for numerical intensif
computations but also for big data applications as the Physics community has
demonstrated.
When looking at the number of devices that are being added daily to the global
IT infrastructure we observe that cellphones and soon Internet of Things (IoT)
devices will produce the bulk of all data. However not all data will be moved to
the cloud and lots of data will be analyzed locally on the devices or even not
being considered to be uploaded to the cloud either because it project to low or
to high value to be moved. However a considerable portion will put new
constraints on our services we offer in the cloud and any architecture addressing
this must be properly deal with scaling early on in the architectural design
process.
Next we present the Big data reference architecture. It is Depicted in Figure 30.
According to the document (Volume 2) the five main components representing
the central roles include
For a detailed definition wich is beyond the scope of this document we refer to
the Volume 2 of the documents.
Traditionally cloud computing has started with offering IaaS, followed by PaaS
and SaaS. We see the IaaS reflected in three categories for big data:
Messaging and communication takes place between these layer while resource
management is used to address efficiency.
Data collections
Data curation
Data Analytics
Data Visualization
Data Access
Through the interplay between these services data consumer sand data producers
can be served.
5.2.8 Fabric
Security and general management are part of the governing fabric in which such
an architecture is deployed.
The interface definitions for the BDRA are specified in Volume 8. We are in the
second phase of our document specification while we switch from our pure
Resource descripyion to an OpenAPI specification. Before we can provide more
details we need to introduce you to REST which is an essential technology for
many moder cloud computing services.
In this taxonomy we are concerned about how resources are placed on physical
models and are interconnected with each other to facilitate for example
scheduling algorithms. @{fig:graph-y} depicts the different models integrated in
the Taxonomy. It includes:
Learning Objectives
Hence REST can use HTTP for the four CRUD operations:
Create resources
Read resources
Update resources
Delete resources
As part of the HTTP protocol we have methods such as GET, PUT, POST, and
DELETE. These methods can than be used to implement a REST service. This is
not surprising as the HTTP protocol was explicitly designed to support these
operations. As REST introduces collections and items we need to implement the
CRUD functions for them. We distinguish single resources and collection of
resources. The semantics for accessing them is explained next illustrating how to
implement them with HTTP methods (See REST on Wikipedia [34]).
GET
List the URIs and perhaps other details of the collections members
PUT
POST
Create a new entry in the collection. The new entry’s URI is assigned
automatically and is usually returned by the operation.
DELETE
GET
POST
Not generally used. Treat the addressed member as a collection in its own
right and create a new entry within it.
DELETE
Due to the well defined structure that REST provides a number of tools have
been created that manage the creation of the specification for rest services and
their programming. We distinguish several different categories:
6.2.1.1 OPENAPI
Over the years, Open API specification has become the most popular with a
much larger community behind it. Therefore, this section would focus on the
latest specification, OpenAPI 3.0 (OAS 3.0) [45].
API specifications can be written in YAML or JSON. OAS also comes with a
rich toolkit that includes Swagger Editor [47], Swagger UI [48] and Swagger
Codegen [41], that creates an end-to-end development environment, even for the
users who are new to OAS.
Section OpenAPI Specification details more on the OAS 2.0 specification.
Basic structure of the definitions would look like this. The sample REST service,
exposes http://localhost:8080/cloudmesh basepath. Under that base path, an
endpoint has been exposed as cloudmesh/cpu which would return CPU
information of the server. It uses a predefined schema to return the results, which
is defined under the components/schemas. See the Section OpenAPI REST
Service via Introspection for the detailed example.
openapi: 3.0.2
info:
title: cpuinfo
description: A simple service to get cpuinfo as an example of using OpenAPI 3.0
license:
name: Apache 2.0
version: 0.0.1
servers:
- url: http://localhost:8080/cloudmesh
paths:
/cpu:
get:
summary: Returns cpu information of the hosting server
operationId: cpu.get_processor_name
responses:
'200':
description: cpu info
content:
application/json:
schema:
$ref: "#/components/schemas/cpu"
components:
schemas:
cpu:
type: "object"
required:
- "model"
properties:
model:
type: "string"
6.2.1.1.1.1 Definitions
Metadata:
OAS 3.0 requires a specification definition at the start under the openapi field.
openapi: 3.0.2
Next, metadata can be specified under info field such as title, version,
description, etc. Additionally, license, contact information can also be specified.
tile and version are mandatory fields under info.
info:
title: cpuinfo
description:
A simple service to get cpuinfo as an example of using OpenAPI 3.0
license:
name: Apache 2.0
version: 0.0.1
Servers:
The servers section defines the server URLs with the basepath. Optionally, a
description can be added.
servers:
- url: http://localhost:8080/cloudmesh
description: Cloudmesh server basepath
Paths:
The paths section specifies all the endpoints exposed by the API and the HTTP
operations supported by these endpoints.
paths:
/cpu:
get:
summary: Returns cpu information of the hosting server
operationId: cpu.get_processor_name
responses:
'200':
description: cpu info
content:
application/json:
schema:
$ref: "#/components/schemas/cpu"
Operation ID:
When using introspection for REST services (using Connexion), we would need
to point to the operation that would ultimately carry out the request. This
operation is specified by the operationID.
...
paths:
/cpu:
...
operationId: cpu.get_processor_name
Parameters:
Request Body:
When a request is sent with a body, such as POST, that will be specified in the
requestBody under a path.
paths:
/upload:
post:
summary: upload input
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
'200':
description: OK
Responses:
For each path, responses can be specified with the corresponding status codes
such as 200 OK or 404 Not Found. A response may return a response body, that
can be defined under content.
...
paths:
/cpu:
...
responses:
'200':
description: cpu info
content:
application/json:
schema:
$ref: "#/components/schemas/cpu"
Schemas:
...
components:
schemas:
cpu:
type: "object"
required:
- "model"
properties:
model:
type: "string"
Authentication:
security:
- BasicAuth: []
6.2.1.2 RAML
Furthermore, there are tools available to switch between the specifications, such
as RAML Web API Parser which can convert RAML to Open API and vice-
versa.
6.2.1.4 JsonAPI
6.2.1.5 Tinyspec
6.2.1.6 Tools
6.2.1.6.1 Connexion
Connexion[51] is one such tool that is based on Open API and it is widely used
in the Python environment. This framework allows users to define webservices
in Open API and then map those services to Python functions conveniently. We
would be using Connexion when we create REST services using introspection
Section 6.2.2.
info:
title: Hello World
version: "1.0"
servers:
- url: http://localhost:9090/v1.0
paths:
/greeting/{name}:
post:
summary: Generate greeting
description: Generates a greeting message.
operationId: hello.post_greeting
responses:
200:
description: greeting response
content:
text/plain:
schema:
type: string
example: "hello dave!"
parameters:
- name: name
in: path
description: Name of the person to greet.
required: true
schema:
type: string
example: "dave"
if __name__ == '__main__':
app = connexion.FlaskApp(__name__, port=9090, specification_dir='openapi/')
app.add_api('helloworld-api.yaml', arguments={'title': 'Hello World Example'})
app.run()
The simplest way to create an OpenAPI service is to use the conexion service
and read in the specification from its yaml file. It will than be introspected and
dynamically methods are created that are used for the implementation of the
server.
https://media.readthedocs.org/pdf/connexion/latest/connexion.pdf
if __name__ == "__main__":
app.run(port=8080, debug=True)
This will run our REST service under the assumption we have a cpu.yaml and a cpu.py
files as our yaml file calls out methods from cpu.py
servers:
- url: http://localhost:8080/cloudmesh
paths:
/cpu:
get:
summary: Returns cpu information of the hosting server
operationId: cpu.get_processor_name
responses:
'200':
description: cpu info
content:
application/json:
schema:
$ref: "#/components/schemas/cpu"
components:
schemas:
cpu:
type: "object"
required:
- "model"
properties:
model:
type: "string"
Here we simply implement a get method and associate is with the URL /cpu.
The operationid, defines the method that we call which as we used the local
directory is included in the file cpu.py. This is controlled by the prefix in the
operation id.
A very simple function to return the cpu information is defined in cpu.py which we
list next
import os, platform, subprocess, re
from flask import jsonify
def get_processor_name():
if platform.system() == "Windows":
p = platform.processor()
elif platform.system() == "Darwin":
command = "/usr/sbin/sysctl -n machdep.cpu.brand_string"
p = subprocess.check_output(command, shell=True).strip().decode()
elif platform.system() == "Linux":
command = "cat /proc/cpuinfo"
all_info = subprocess.check_output(command, shell=True).strip().decode()
for line in all_info.split("\n"):
if "model name" in line:
p = re.sub(".*model name.*:", "", line, 1)
else:
p = "cannot find cpuinfo"
pinfo = {"model": p}
return jsonify(pinfo)
To simplify working with this example, we also provide a makefile for OSX that
allows us to call the server and the call to the servoer in two different terminals
define terminal
osascript -e 'tell application "Terminal" to do script "cd $(PWD); $1"'
endef
install:
pip install -r requirements.txt
demo:
$(call terminal, python server.py)
sleep 3
@echo "==============================================================================="
@echo "Get the info"
@echo "==============================================================================="
curl http://localhost:8080/cloudmesh/cpu
@echo
@echo "==============================================================================="
When we call
make demo
6.2.2.1 Verification
https://editor.swagger.io/
Go to the Web site, remove the current petstore example and simply paste your
yaml file in it. Debug meessages will be helping you to correct things.
A terminal based command may als be helpful, but is a bit difficult to read.
$ connexion run cpu.yaml --stub --debug
6.2.2.2 Swagger-UI
Swagger comes with a convenient UI to invoke REST API calls using the web
browser rather than relying on the curl commands.
Once the request and response definitions are properly specified, you can start
the server by,
$ python server.py
Then the UI would also be spawned under the service URL http://[service
url]/ui/
Example: http://localhost:8080/cloudmesh/ui/
6.2.2.4 Exercise
OpenAPI.Conexion.1:
Modify the makefile so it works also on ubuntu, but do not disable the
ability to run it correctly on OSX. Tip use if’s in makefiles base on the
OS. You can look at the makefiles that create this book as example.
find alternatives to sarting a terminal in Linux.
OpenAPI.Conexion.2:
OpenAPI.Conexion.3:
OpenAPI.Conexion.4:
OpenAPI.Conexion.5:
To create the REST services, we would be using OpenAPI 3.0 REST service via
introspection.
A POST request with a file containing points to create the k-means clustering
model. POST content would be multipart/form-data.
For an example consider the following 6 points in XY dimensions,
1, 2
1, 4
1, 0
10, 2
10, 4
10, 0
Curl command:
$ curl -X POST "http://localhost:8080/kmeans/upload" \
-H "accept: application/json" \
-H "Content-Type: multipart/form-data" \
-F "[email protected];type=text/csv"
Service implementation would look like this. File content will be received as a
werkzeug.datastructures.FileStorage object in Flask, which can be used to
stream into the filesystem. Backend keeps two dicts to map Job ID to file and
vise-versa (inputs and inputs_r).
def upload_file(file=None):
filename = file.filename
If the request is successful, a JSON will be returned with the file name and the
associated job ID. Job ID can be considered ID that would connect, inputs to the
models and the predicted outputs.
{
"filename": "model.csv",
"job_id": 0
}
A POST request with a JSON body containing Job ID and model parameters that
need to passed on to the scikit-learn KMeans model initialization such as,
number of clusters (n_clusters), maximum iterations (max_iter), etc.
Example:
{
"job_id": 0,
"model_params": {
"n_clusters": 3
}
}
curl command:
$ curl -X POST "http://localhost:8080/kmeans/fit" \
-H "accept: text/csv" \
-H "Content-Type: application/json" \
-d "{\"job_id\":0,\"model_params\":{\"n_clusters\":3}}"
Service implementation looks like this. POST request body will be populated as
a dict and passed on to the method by Flask (body). Once the model is fitted, it
will be put into a in memory dict (models) against its Job ID. Labels will be
written to disk as a file, and the content will be returned as a CSV.
def kmeans_fit(body):
print(body)
job_id = body['job_id']
params = dict(default_model_params)
params.update(body['model_params'])
kmeans = KMeans(**params).fit(X)
return send_file(labels)
The response CSV file will be returned with the corresponding labels for the
input points.
1.000000000000000000e+00
1.000000000000000000e+00
1.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
2.000000000000000000e+00
A POST request with a file containing the points to be predicted and the
corresponding Job ID as multipart/form-data.
job_id=0
Points to be predicted
0, 0
12, 3
curl command:
$ curl -X POST "http://localhost:8080/kmeans/predict" \
-H "accept: text/csv" \
-H "Content-Type: multipart/form-data" \
-F "job_id=0" \
-F "[email protected];type=text/csv"
Service implementation looks like this. Note that there is a strange behavior in
Flask with Connextion where the file content will be passed on to the file object
as a werkzeug.datastructures.FileStorage object but the Job ID is passed as a
dict to body object.
def kmeans_predict(body, file=None):
job_id = int(body['job_id'])
if job_id in models:
p_file = OUTPUT_DIR + '/' + str(job_id) + '.p'
file.save(p_file)
result = models[job_id].predict(p)
print(result)
return send_file(res_file)
else:
abort(500, "model not found for job id " + str(job_id))
return
The response would send out the corresponding labels of the passed points as a
CSV file.
1.000000000000000000e+00
0.000000000000000000e+00
6.2.3.2 Files
Upload a file
$ curl -X POST "http://localhost:8080/kmeans/upload" \
-H "accept: application/json" \
-H "Content-Type: multipart/form-data" \
-F "[email protected];type=text/csv"
Additionally, you can access the Swagger UI for kmeans service in your
Flask server from here
6.2.3.4 Notes
https://flask-restful.readthedocs.io/en/latest/
We will provide a simple example that showcases some hard coded data to be
served as a rest service. It will be easy to replace this for example with functions
and methods that obtain such information dynamically from the operating
system.
This example has not been tested. We like that the class defines a beautiful
example to contribute to this section and explains what happens in this example.
from flask import Flask
from flask_restful import reqparse, abort
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
COMPUTERS = {
'computer1': {
'processor': 'iCore7'
},
'computer2': {
'processor': 'iCore5'
},
'computer3': {
'processor': 'iCore3'
},
}
def abort_if_cluster_doesnt_exist(computer_id):
if computer_id not in COMPUTERS:
abort(404, message="Computer {} does not exist".format(computer_id))
parser = reqparse.RequestParser()
parser.add_argument('processor')
class Computer(Resource):
''' shows a single computer item and lets you delete a computer
item.'''
# ComputerList
class ComputerList(Resource):
''' shows a list of all computers, and lets you POST to add new computers'''
def get(self):
return COMPUTERS
def post(self):
args = parser.parse_args()
computer_id = int(max(COMPUTERS.keys()).lstrip('computer')) + 1
computer_id = 'computer%i' % computer_id
COMPUTERS[computer_id] = {'processor': args['processor']}
return COMPUTERS[computer_id], 201
##
## Setup the Api resource routing here
##
api.add_resource(ComputerList, '/computers')
api.add_resource(Computer, '/computers/<computer_id>')
if __name__ == '__main__':
app.run(debug=True)
https://www.django-rest-framework.org/
https://www.django-rest-framework.org/#example
To document your django framework with Swagger you can look at this
example:
https://www.django-rest-framework.org/topics/documenting-your-api/
However, we believe that for our purposes the approach to use conexion from an
OpenAPI is much more appealing, also using conexion and also flask for the
REST service is easier to acomplish. Django is a large package that will take
mor time to getting used to.
Instead of using a REST service for IaaS, let us here inspect a REST service for
the Github.com platform.
https://developer.github.com/v3/
We see that Github offers many resources that can be accessed by the users
which includes
Activities
Checks
Gists
Git Data
GitHub Apps
Issues
Migrations
Miscellaneous
Organizations
Projects
Pull Requests
Reactions
Repositories
Searches
Teams
Users
Most likely we forgot the one or the other Resource that we can access via
REST. It will be out of scope for us to explore all of these issues, so let us focus
on how we for example access Github Issues. In fact we will use the script that
we use to create issue tables for this book to showcase how easy the interaction
is and to retrieve the information.
6.5.1 Issues
The REST service for issues is described in the following Web page as
specification
https://developer.github.com/v3/issues/
List issues
List issues for a repository
Get a single issue
Create an issue
Edit an issue
Lock an issue
Unlock an issue
Custom media types
Let us now explore how to easily query some information. In our example we
like to retrive the list of issues for a repository as LaTeX table but also as
markdown. This way we can conveniently integrate it in documents of either
format. As LaTeX has a more sophisticated table management, let us first create
a LaTeX table document and than use a program to convert LaTeX to
markdown. For the later we can reuse a program called pandoc that can convert the
table for LaTeX to markdown.
Let us assume we have a program called issues.py that prints the table in markdown
format
$ python issues.py
https://github.com/cloudmesh-community/book/blob/master/bin/issues.py
Although python provides the very nice module requests which we typically use for
such issues. we have here just wrapped the commandline call to curl into a system
command and redirect its output to a file. However, as we only get limited
information back in pages, we need to continue such a request multiple times. To
keep things simple we identified that for the project at this time not more that n
pages need to be fetched, so we append the output from each page to the file.
Your task is it to improve this script and automatize this activity so that no
maximum fetches have to be entered.
The reason why this program is so short is that we leverage the build in function
for json data structure manipulation, hear a read and a dump. When we look in the
issue.json file that is created as intermediary file we see a list of items such as
[
...
{
"url": "https://api.github.com/repos/cloudmesh-community/book/issues/46",
"repository_url": "https://api.github.com/repos/cloudmesh-community/book",
"labels_url": "https://api.github.com/repos/cloudmesh-community/book/issues/46/labels{/name}",
"comments_url": "https://api.github.com/repos/cloudmesh-community/book/issues/46/comments",
"events_url": "https://api.github.com/repos/cloudmesh-community/book/issues/46/events",
"html_url": "https://github.com/cloudmesh-community/book/issues/46",
"id": 360613438,
"node_id": "MDU6SXNzdWUzNjA2MTM0Mzg=",
"number": 46,
"title": "Taken: Virtualization",
"user": {
"login": "laszewsk",
"id": 425045,
"node_id": "MDQ6VXNlcjQyNTA0NQ==",
"avatar_url": "https://avatars1.githubusercontent.com/u/425045?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/laszewsk",
"html_url": "https://github.com/laszewsk",
"followers_url": "https://api.github.com/users/laszewsk/followers",
"following_url": "https://api.github.com/users/laszewsk/following{/other_user}",
"gists_url": "https://api.github.com/users/laszewsk/gists{/gist_id}",
"starred_url": "https://api.github.com/users/laszewsk/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/laszewsk/subscriptions",
"organizations_url": "https://api.github.com/users/laszewsk/orgs",
"repos_url": "https://api.github.com/users/laszewsk/repos",
"events_url": "https://api.github.com/users/laszewsk/events{/privacy}",
"received_events_url": "https://api.github.com/users/laszewsk/received_events",
"type": "User",
"site_admin": false
},
"labels": [],
"state": "open",
"locked": false,
"assignee": {
"login": "laszewsk",
"id": 425045,
"node_id": "MDQ6VXNlcjQyNTA0NQ==",
"avatar_url": "https://avatars1.githubusercontent.com/u/425045?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/laszewsk",
"html_url": "https://github.com/laszewsk",
"followers_url": "https://api.github.com/users/laszewsk/followers",
"following_url": "https://api.github.com/users/laszewsk/following{/other_user}",
"gists_url": "https://api.github.com/users/laszewsk/gists{/gist_id}",
"starred_url": "https://api.github.com/users/laszewsk/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/laszewsk/subscriptions",
"organizations_url": "https://api.github.com/users/laszewsk/orgs",
"repos_url": "https://api.github.com/users/laszewsk/repos",
"events_url": "https://api.github.com/users/laszewsk/events{/privacy}",
"received_events_url": "https://api.github.com/users/laszewsk/received_events",
"type": "User",
"site_admin": false
},
"assignees": [
{
"login": "laszewsk",
"id": 425045,
"node_id": "MDQ6VXNlcjQyNTA0NQ==",
"avatar_url": "https://avatars1.githubusercontent.com/u/425045?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/laszewsk",
"html_url": "https://github.com/laszewsk",
"followers_url": "https://api.github.com/users/laszewsk/followers",
"following_url": "https://api.github.com/users/laszewsk/following{/other_user}",
"gists_url": "https://api.github.com/users/laszewsk/gists{/gist_id}",
"starred_url": "https://api.github.com/users/laszewsk/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/laszewsk/subscriptions",
"organizations_url": "https://api.github.com/users/laszewsk/orgs",
"repos_url": "https://api.github.com/users/laszewsk/repos",
"events_url": "https://api.github.com/users/laszewsk/events{/privacy}",
"received_events_url": "https://api.github.com/users/laszewsk/received_events",
"type": "User",
"site_admin": false
}
],
"milestone": null,
"comments": 0,
"created_at": "2018-09-16T07:35:35Z",
"updated_at": "2018-09-16T07:35:35Z",
"closed_at": null,
"author_association": "CONTRIBUTOR",
"body": "Develop a section about Virtualization"
},
...
]
As we can see from this entry there is a lot of information associated that for our
purposes we do not need, but certainly could be used to mine github in general.
We like to point out that github is actively mined for exploits where passwords
are posted in clear text for AWS, Azure and other clouds. This is a common
mistake as many sample programs ask the student to place the password directly
into their programs instead of using a configuration file that is never part of the
code repository.
6.5.2 Exercise
E.github.issues.1:
Develop a new code like the one in this section, but use python
requests instead of the os.system call.
E.github.issues.2:
E.github.issues.3:
E.github.issues.4:
Use github to develop some cool python programs that show some
statistics about github. An example would be: Given a github
repository, show the checkins by data and visualize them graphically
for one committer and all committers. Use bokeah or matplotlib.
E.github.issues.6:
Swagger itself has a number of tools which together build a framework for
developing REST services for a variety of languages.
Swagger Core
Swagger Codegen
Swagger Editor
Swagger Hub
The developed APIs can be hosted and further developed on an online repository
named SwaggerHub https://app.swaggerhub.com/home The convenient online
editor is available which also can be installed locally on a variety of operating
systems including macOS, Linux, and Windows.
notify us about other tools that you find and would like us to mention here.
Swagger toolbox is a utility that can convert json to swagger compatible yaml
models. It is hosted online at
https://swagger-toolbox.firebaseapp.com/
https://github.com/essuraj/swagger-toolbox
It is important to make sure that the json model is properly configured. As such
each datatype must be wrapped in “quotes” and the last element must not have a
, behind it.
In case you have large models, we recommend that you gradually add more and
more features so that it is easier to debug in case of an error. This tool is not
designed to provide back a full featured OpenAPI, but help you getting started
deriving one.
Let us look at a small example. Let us assume we want to create a REST service
to execute a command on the remote service. We know this may not be a good
idea if it is not properly secured, so be extra careful. A good way to simulate this
is to just use a return string instead of executing the command.
As you can see it is far from complete, but it could be used to get you started.
Based on this tool develop a rest service to which you send a schema in JSON
format from which you get back the YAML model.
Next, we will focus on how to make a RESTful web service with Python Eve.
Eve makes the creation of a REST implementation in python easy. More
information about Eve can be found at:
http://python-eve.org/
Although we do recommend Ubuntu 17.04, at this time there is a bug that forces
us to use 16.04. Furthermore, we require you to follow the instructions on how
to install pyenv and use it to set up your python environment. We recommend
that you use either python 2.7.14 or 3.6.4. We do not recommend you to use
anaconda as it is not suited for cloud computing but targets desktop computing.
If you use pyenv you also avoid the issue of interfering with your system wide
python install. We do recommend pyenv regardless if you use a virtual machine
or are working directly on your operating system. After you have set up a proper
python environment, make sure you have the newest version of pip installed
with
$ pip install pip -U
A student or student group of this class are invited to discuss on piazza on how
to install mongoDB on Windows 10 and come up with an easy installation
solution. Naturally we have the same 2 different ways on how to run mongo. In
user space or in the system. As we want to make sure your computer stays
secure. the solution must have an easy way on how to shut down the Mongo
services.
After downloading Mongo, create the db directory. This is where the Mongo
data files will live. You can create the directory in the default location and assure
it has the right permissions. Make sure that the /data/db directory has the right
permissions by running
6.7.1.5 Verification
In order to check the MongoDB installation, please run the following commands
in one terminal:
$ mkdir -p ~/cloudmesh/data/db
$ mongod --dbpath ~/cloudmesh/data/db
In this section we will focus on creating a simple rest service. To organize our
work we will create the following directory:
$ mkdir -p ~/cloudmesh/eve
$ cd ~/cloudmesh/eve
As Eve needs a configuration and it is read in by default from the file settings.py we
place the following content in the file ~/cloudmesh/eve/settings.py:
MONGO_HOST = 'localhost'
MONGO_PORT = 27017
MONGO_DBNAME = 'student_db'
DOMAIN = {
'student': {
'schema': {
'firstname': {
'type': 'string'
},
'lastname': {
'type': 'string'
},
'university': {
'type': 'string'
},
'email': {
'type': 'string',
'unique': True
}
'username': {
'type': 'string',
'unique': True
}
}
}
}
RESOURCE_METHODS = ['GET', 'POST']
The DOMAIN object specifies the format of a student object that we are using as
part of our REST service. In addition we can specify RESOURCE_METHODS which methods
are activated for the REST service. This way the developer can restrict the
available methods for a REST service. To pass along the specification for
mongoDB, we simply specify the hostname, the port, as well as the database
name.
Now that we have defined the settings for our example service, we need to start
it with a simple python program. We could name that program anything we like,
but often it is called simply run.py. This file is placed in the same directory where
you placed the settings.py. In our case it is in the file ~/cloudmesh/eve/run.py and
contains the following python program:
from eve import Eve
app = Eve()
if __name__ == '__main__':
app.run()
This is the most minimal application for Eve, that uses the settings.py file for its
configuration. Naturally, if we were to change the configuration file and for
example change the DOMAIN and its schema, we would naturally have to
remove the database previously created and start the service new. This is
especially important as during the development phase we may frequently change
the schema and the database. Thus it is convenient to develop necessary cleaning
actions as part of a Makefile which we leave as easy exercise for the students.
Next, we need to start the services which can easily be achieved in a terminal
while running the commands:
This is done in its own terminal, so we can observe the log messages easily.
Next we start in another window the Eve service with
$ cd ~/cloudmesh/eve
$ python run.py
You can find the codes and commands up to this point in the following
document.
Yet in another window, we can now interact with the REST service. We can use
the commandline to save the data in the database using the REST api. The data
can be retrieved in XML or in json format. Json is often more convenient for
debugging as it is easier to read than XML.
Naturally, we need first to put some data into the server. Let us assume we add
the user Albert Zweistein.
$ curl -H "Content-Type: application/json" -X POST \
-d '{"firstname":"Albert","lastname":"Zweistein", \
"school":"ISE","university":"Indiana University", \
"email":"[email protected]", "username": "albert"}' \
http://127.0.0.1:5000/student/
To achieve this, we need to specify the header using H tag saying we need the
data to be saved using json format. And X tag says the HTTP protocol and here
we use POST method. And the tag d specifies the data and make sure you use
json format to enter the data. Finally, the REST api endpoint to which we must
save data. This allows us to save the data in a table called student in MongoDB
within a database called eve.
In order to check if the entry was accepted in mongo and included in the server
issue the following command sequence in another terminal:
$ mongo
Now you can query mongo directly with its shell interface
> show databases
> use student_db
> show tables # query the table names
> db.student.find().pretty() # pretty will show the json in a clear way
Naturally this is not really necessary for A REST service such as eve as we show
you next how to gain access to the data via mongo while using REST calls. We
can simply retrieve the information with the help of a simple URI:
$ curl http://127.0.0.1:5000/student?firstname=Albert
Naturally, you can formulate other URLs and query attributes that are passed
along after the ?.
This will now allow you to develop sophisticated REST services. We encourage
you to inspect the documentation provided by Eve to showcase additional
features that you could be using as part of your efforts.
Let us explore how to properly use additional REST API calls. We assume you
have MongoDB up and running. To query the service itself we can use the URI
on the Eve port
$ curl -i http://127.0.0.1:5000
Your payload should look like the one listed next, if your output is not formatted
like this try adding ?pretty=1
$ curl -i http://127.0.0.1:5000?pretty=1
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 150
Server: Eve/0.7.6 Werkzeug/0.11.15 Python/2.7.16
Date: Wed, 17 Jan 2018 18:34:07 GMT
{
"_links": {
"child": [
{
"href": "student",
"title": "student"
}
]
}
Remember that the API entry points include additional information such as links
and a child, and href.
Set up a python environment that works for your platform. Provide explicit
reasons why anaconda and other prepackaged python versions have issues for
cloud related activities. When may you use anaconda and when should you not
use anaconda. Why would you want to use pyenv?
In this case how many child resources are available through our API?
Define curl calls to store data into the service and retrieve it.
Write a Makefile and in it a target clean that cleans the data base. Develop
additional targets such as start and stop, that start and stop the mongoDB but
also the Eve REST service
Next we wont to enhance our example a bit. First, let us get back to the eve
working directory with
$ cd ~/cloudmesh/eve
if __name__ == '__main__':
app.run(debug=True, host="127.0.0.1")
After creating and saving the file. Run the following command to start the
service
$ python run2.py
After running the command, you can interact with the service while entering the
following url in the web browser:
http://127.0.0.1:5000/student/alberts
This example illustrates how easy it is to create REST services in python while
combining information from a dict with information retrieved from the system.
The important part is to understand the decorator app.route. The parameter
specifies the route of the API endpoint which will be the address appended to the
base path, http://127.0.0.1:5000. It is important that we return a jsonified object, which
can easily be done with the jsonify function provided by flask.As you can see the
name of the decorated function can be anything you lok. The route specifies how
we access it from the service.
Another way of managing the data is to utilize class definitions and response
types that we explicitly define.
If we want to create an object like Student, we can first define a python class.
Create a file called student.py. Please, note the get method that returns simply
the information in the dict for the class. It is not related to the REST get
function.
class Student(object):
def __init__(self, firstname, lastname, university, email):
self.firstname = firstname
self.lastname = lastname
self.university = university
self.email = email
self.username = 'undefined'
def get(self):
return self.__dict__
def setUsername(self, name):
self.username = name
return name
Next we define a REST service with Eve as shown in the following listing
from eve import Eve
from student import Student
import platform
import psutil
import json
from flask import Response
import getpass
app = Eve()
@app.route('/student/albert', methods=['GET'])
def processor():
student = Student("Albert",
"Zweistein",
"Indiana University",
"[email protected]")
response = Response()
response.headers["Content-Type"] = "application/json; charset=utf-8"
try:
student.setUsername(getpass.getuser())
response.headers["status"] = 200
except:
response.headers["status"] = 500
response.data = json.dumps(student.get())
return response
if __name__ == '__main__':
app.run(debug=True, host='127.0.0.1')
In contrast to our earlier example, we are not using the jsonify object, but create
explicitly a response that we return to the clients. The response includes a header
that we return the information in json format, a status of 200, which means the
object was returned successfully, and the actual data.
In the Section Rest Services with Eve we created our own REST API application
using Python Eve. Now once the service running, a we need to learn how to
interact with it through clients.
Here we create a new python file called client.py. The file include the following
content.
import requests
import json
def get_all():
response = requests.get("http://127.0.0.1:5000/student")
print(json.dumps(response.json(), indent=4, sort_keys=True))
def save_record():
headers = {
'Content-Type': 'application/json'
}
data = '{"firstname":"Gregor",
"lastname":"von Laszewski",
"university": "Indiana University",
"email":"[email protected]",
"username": "jane"}'
response = requests.post('http://localhost:5000/student/',
headers=headers,
data=data)
print(response.json())
if __name__ == '__main__':
save_record()
get_all()
Run the following command in a new terminal to execute the simple client by
$ python client.py
Here when you run this class for the first time, it will run successfully, but if you
tried it for the second time, it will give you an error. Because we did set the
email to be a unique field in the schema when we designed the settings.py file in
the beginning. So if you want to save another record you must have entries with
unique emails. In order to make this dynamic you can include a input reading by
using the terminal to get the student data first and instead of the static data you
can use the user input data from the terminal to get dynamic data. But for this
exercise we do not expect that or any other form data functionality.
In order to get the saved data, you can comment the record saving function and
uncomment the get all function. In python commenting is done by using #.
This client is using the requests python library to send GET, POST and other
HTTP requests to the server so you can leverage build in methods to simplify
your work.
The get_all function provides a way to get the output to the console with all the
data in the student database. The save_record function provides a way to save data in
the database. You can create dynamic functions in order to save dynamic data.
However it may take some time for you to apply as exercise.
https://github.com/cloudmesh/cloudmesh.rest/blob/master/cloudmesh/admin/command/a
The implementation based on what we provided in the Make file seems straight
forward. A great extension is to load the objects definitions or eve
e.g. settings.py not from the class, but from a place in .cloudmesh. I propose to
place the file at:
~/.cloudmesh/db/settings.py
the location of this file is used when the Service class is initialized with None.
Prior to starting the service the file needs to be copied there. This could be
achieved with a set command.
6.7.2 HATEOAS ☁
In the previous section we discussed the basic concepts about RESTful web
service. Next we introduce you to the concept of HATEOAS
HATEOAS stands for Hypermedia as the Engine of Application State and this is
enabled by the default configuration within Eve. It is useful to review the
terminology and attributes used as part of this configuration. HATEOS explains
how REST API endpoints are defined and it provides a clear description on how
the API can be consumed through these terms:
_links
Links describe the relation of current resource being accessed to the rest of
the resources. It is like if we have a set of links to the set of objects or
service endpoints that we are referring in the RESTful web service. Here an
endpoint refers to a service call which is responsible for executing one of
the CRUD operations on a particular object or set of objects. More on the
links, the links object contains the list of serviceable API endpoints or list
of services. When we are calling a GET request or any other request, we
can use these service endpoints to execute different queries based on the
user purpose. For instance, a service call can be used to insert data or
retrieve data from a remote database using a REST API call. About
databases we will discuss in detail in another chapter.
title
The title in the rest endpoint is the name or topic that we are trying to
address. It describes the nature of the object by a single word. For instance
student, bank-statement, salary,etc can be a title.
parent
The term parent refers to the very initial link or an API endpoint in a
particular RESTful web service. Generally this is denoted with the primary
address like http://example.com/api/v1/.
href
The term href refers to the url segment that we use to access the a particular
REST API endpoint. For instance “student?page=1” will return the first
page of student list by retrieving a particular number of items from a remote
database or a remote data source. The full url will look like this,
“http://www.exampleapi.com/student?page=1”.
http://python-eve.org/features.html
Field Description
_created
item creation date.
_updated
item last updated on.
_etag
ETag, to be used for concurrency control and conditional requests.
_id
unique item key, also needed to access the individual item endpoint.
6.7.2.1 Filtering
Clients can submit query strings to the rest service to retrieve resources based on
a filter. This also allows sorting of the results queried. One nice feature about
using mongo as a backend database is that Eve not only allows python
conditional expressions, but also mongo queries.
A python expression
$ curl -i http://eve-demo.herokuapp.com/people?where=lastname=="Doe"
If this does not work you can always use python to beautify a json output with
$ curl -i http://localhost/people?pretty
or
$ curl -i http://localhost/people | python -m json.tool
6.7.2.3 XML
If for some reason you like to retrieve the information in XML you can specify
this for example through curl with an Accept header
$ curl -H "Accept: application/xml" -i http://localhost
6.7.3 Extensions to Eve ☁
Students have the opportunity to pic one of the community extensions and
provide a section for the handbook.
Pick one of the extension, research it and provide a small section for the
handbook so we add it.
http://python-eve.org/
This code will have a master branch but will also have a dev branch in which we
will add gradually more objects. Objects in the dev branch will include:
virtual directories
virtual clusters
job sequences
inventories
You may want to check our active development work in the dev branch.
However for the purpose of this class the master branch will be sufficient.
6.7.3.1.1 Installation
First we have to install mongodb. The installation will depend on your operating
system. For the use of the rest service it is not important to integrate mongodb
into the system upon reboot, which is focus of many online documents.
However, for us it is better if we can start and stop the services explicitly for
now.
TODO: Section can be contributed by student. If you elect Windows 10. You
could be using the online documentation provided by starting it on Windows, or
running it in a docker container.
In future we may want to add ssl authentication in which case you may need to
install it as follows:
$ brew install mongodb --with-openssl
We have provided a convenient Makefile that currently only works for macOS.
It will be easy for you to adapt it to Linux. Certainly you can look at the targets
in the makefile and replicate them one by one. Important targets are deploy and
test.
When using the makefile you can start the services with:
$ make deploy
IT will start two terminals. IN one you will see the mongo service, in the other
you will see the eve service. The eve service will take a file called
sample.settings.py that is base on sample.json for the start of the eve service.
The mongo service is configured in such a way that it only accepts incoming
connections from the local host which will be sufficient for our case. The mongo
data is written into the $USER/.cloudmesh directory, so make sure it exists.
To test the services you can say:
$ make test
The example demonstrated how easy it is to create a mongodb and an eve rest
service. Now let us use this example to create your own. For this we have
modified a tool called evegenie to install it onto your system.
http://evegenie.readthedocs.io/en/latest/
https://github.com/cloudmesh/evegenie
This should install in your system evegenie. YOu can verify this by typing:
$ which evegenie
If you see the path evegenie is installed. With evegenie installed its usage is
simple:
$ evegenie
Usage:
evegenie --help
evegenie FILENAME
It takes a json file as input and writes out a settings file for the use in eve. Lets
assume the file is called sample.json, than the settings file will be called
sample.settings.py. Having the evegenie program will allow us to generate the
settings files easily. You can include them into your project and leverage the
Makefile targets to start the services in your project. In case you generate new
objects, make sure you rerun evegenie, kill all previous windows in which you
run eve and mongo and restart. In case of changes to objects that you have
designed and run previously, you need to also delete the mongod database.
You can write the API definition in json for yaml format. Let us discuss this
format briefly and focus on yaml as it is easier to read and maintain.
On the root level of the yaml document we see fields like swagger, info, and so
on. Among these fields, swagger, info, and path are required. Their meaning is
as follows:
swagger
specifies the version number. In our case a string value ‘2.0’ is used as we
are writing the definition conforming to the v2.0 specification.
info
defines metadata information related to the API. E.g., the API version, title
and description, termsOfService if applicable, contact information and
license, etc. Among these attributes, version and title are required while
others are optional.
path
defines the actual endpoints of the exposed RESTful API service. Each
endpoint has a field pattern as the key, and a Path Item Object as the value.
In this example we have defined /vc and /vc/{id} as the two service
endpoints. They will be part of the final service URL, appended after the
service host and basePath, which will be explained later.
Let us focus on the Path Item Object. It contains one or more supported
operations on the service endpoint. An operation is keyed by a valid HTTP
operation verb, e.g., one of get, put, post, delete, or patch. It has a value of
Operation Object that describes the operations in more detail.
Besides the required field, the Operation Object can have summary and
description to indicate what the operation is about; and operationId to
uniquely identify the operation; and consumes and produces to indicate
what MIME types it expects as input and for returns, e.g., application/json
in most modern RESTful APIs. It can further specify what input parameter
is expected using parameters, which requires a name and in fields. name
specifies the name of the parameter, and in specifies from where to get the
parameter, and its possible values are query, header, path, formData or
body. In this example in the /vc/{id} path we obtain the id parameter from
the URL path wo it has the path value. When the in has path as its value,
the required field is required and has to be set as true; when the in has value
other than body, a type field is required to specify the type of the parameter.
While the three root level fields mentioned previously are required, in most
cases we will also use other optional fields.
host
schemas
basePath
to specify the common base URL to be append after the host to form the
base path for all the endpoints, e.g., /api or /api/1.0/. In this example with
the values specified we would have the final service endpoints
http://localhost:8080/api/vcs and http://localhost:8080/api/vc/{id} by
combining the schemas, host, basePath and paths values.
consumes and produces
can also be specified on the top level to specify the default MIME types of
the input and return if most paths and the defined operations have the same.
definitions
The definitions field really contains the object definition of the customized
objects involved in the API, similar to a class definition in any Object
Oriented programming language. In this example, we defined a VC object,
and hierarchically a Node object. Each object defined is a type of Schema
Object in which many field could be used to specify the object (see details
in the REF link at top of the document), but the most frequently used ones
are:
type
to specify the type, and in the customized definition case the value is mostly
object.
required
properties
Node
as part of a cluster.
6.8.1.1.1 Terminology
VC
A virtual cluster, which has one Front-End (FE) management node and
multiple compute nodes. A VC object also has id and name to identify the
VC, and nnodes to indicate how many compute nodes it has.
FE
A management node from which to access the compute nodes. The FE node
usually connects to all the compute nodes via private network.
Node
A computer node object that the info ncores to indicate number of cores it
has, and ram and localdisk to show the size of RAM and local disk storage.
6.8.1.1.2 Specification
swagger: "2.0"
info:
version: "1.0.0"
title: "A Virtual Cluster"
description: "Virtual Cluster as a test of using swagger-2.0 specification and codegen"
termsOfService: "http://swagger.io/terms/"
contact:
name: "IU ISE software and system team"
license:
name: "Apache"
host: "localhost:8080"
basePath: "/api"
schemes:
- "http"
consumes:
- "application/json"
produces:
- "application/json"
paths:
/vcs:
get:
description: "Returns all VCs from the system that the user has access to"
produces:
- "application/json"
responses:
"200":
description: "A list of VCs."
schema:
type: "array"
items:
$ref: "#/definitions/VC"
/vcs/{id}:
get:
description: "Returns all VCs from the system that the user has access to"
operationId: getVCById
parameters:
- name: id
in: path
description: ID of VC to fetch
required: true
type: string
produces:
- "application/json"
responses:
"200":
description: "The vc with the given id."
schema:
$ref: "#/definitions/VC"
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
definitions:
VC:
type: "object"
required:
- "id"
- "name"
- "nnodes"
- "FE"
- "computes"
properties:
id:
type: "string"
name:
type: "string"
nnodes:
type: "integer"
format: "int64"
FE:
type: "object"
schema:
$ref: "#/definitions/Node"
computes:
type: "array"
items:
$ref: "#/definitions/Node"
tag:
type: "string"
Node:
type: "object"
required:
- "ncores"
- "ram"
- "localdisk"
properties:
ncores:
type: "integer"
format: "int64"
ram:
type: "integer"
format: "int64"
localdisk:
type: "integer"
format: "int64"
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
6.8.1.2 References
The official OpenAPI 2.0 Documentation
The simplest way to create an OpenAPI service is to use the conexion service
and read in the specification from its yaml file. It will than be introspected and
dynamically methods are created that are used for the implementation of the
server.
https://github.com/cloudmesh-community/nist/tree/master/examples/flask-
connexion-swagger
https://media.readthedocs.org/pdf/connexion/latest/connexion.pdf
if __name__ == "__main__":
app.run(port=8080, debug=True)
This will run our REST service under the assumption we have a cpu.yaml and a cpu.py
files as our yaml file calls out methods from cpu.py
Here we simply implement a get method and associate is with the URL /cpu.
The operationid, defines the method that we call which as we used the local
directory is included in the file cpu.py. This is controlled by the prefix in the
operation id.
A very simple function to return the cpu information is defined in cpu.py which we
list next
import os, platform, subprocess, re
from flask import jsonify
def get_processor_name():
if platform.system() == "Windows":
p = platform.processor()
elif platform.system() == "Darwin":
command = "/usr/sbin/sysctl -n machdep.cpu.brand_string"
p = subprocess.check_output(command, shell=True).strip().decode()
elif platform.system() == "Linux":
command = "cat /proc/cpuinfo"
all_info = subprocess.check_output(command, shell=True).strip().decode()
for line in all_info.split("\n"):
if "model name" in line:
p = re.sub(".*model name.*:", "", line, 1)
else:
p = "cannot find cpuinfo"
pinfo = {"model": p}
return jsonify(pinfo)
To simplify working with this example, we also provide a makefile for OSX that
allows us to call the server and the call to the servoer in two different terminals
define terminal
osascript -e 'tell application "Terminal" to do script "cd $(PWD); $1"'
endef
install:
pip install -r requirements.txt
demo:
$(call terminal, python server.py)
sleep 3
@echo "==============================================================================="
@echo "Get the info"
@echo "==============================================================================="
curl http://localhost:8080/cloudmesh/cpu
@echo
@echo "==============================================================================="
When we call
make demo
6.8.2.1 Verification
https://editor.swagger.io/
Go to the Web site, remove the current petstore example and simply paste your
yaml file in it. Debug meessages will be helping you to correct things.
A terminal based command may als be helpful, but is a bit difficult to read.
$ connexion run cpu.yaml --stub --debug
6.8.2.3 Exercise
OpenAPI.Conexion.1:
Modify the makefile so it works also on ubuntu, but do not disable the
ability to run it correctly on OSX. Tip use if’s in makefiles base on the
OS. You can look at the makefiles that create this book as example.
find alternatives to sarting a terminal in Linux.
OpenAPI.Conexion.2:
OpenAPI.Conexion.3:
OpenAPI.Conexion.4:
OpenAPI.Conexion.5:
In this subsection we are discussing how to use OpenAPI 2.0 and Swagger
Codegen to define and develop a REST Service.
We assume you have been familiar with the concept of REST service, OpenAPI
as discussed in section Overview of Rest.
In next section we will further look into the Swagger/OpenAPI 2.0 specification
Swagger Specification and use a slight more complex example to walk you
through the design of a RESTful service following the OpenAPI 2.0
specifications.
Step 1 (Section Step 1: Define Your REST Service. Define the REST
service conforming to Swagger/OpenAPI 2.0 specification. It is a YAML
document file with the basics of the REST service defined, e.g., what
resources it has and what actions are supported.
Step 3 (Section Step 3: Install and Run the REST Service. Install the server
side code and run it. The service will then be available.
Step 4 (Section Step 4: Generate Client Side Code and Verify. Generate
client side code. Develop code to call the REST service. Install and run to
verify.
In this example we define a simple REST service that returns the hosting
server’s basic CPU info. The example specification in yaml is as follows:
swagger: "2.0"
info:
version: "0.0.1"
title: "cpuinfo"
description: "A simple service to get cpuinfo as an example of using swagger-2.0 specification and codegen"
termsOfService: "http://swagger.io/terms/"
contact:
name: "Cloudmesh REST Service Example"
license:
name: "Apache"
host: "localhost:8080"
basePath: "/api"
schemes:
- "http"
consumes:
- "application/json"
produces:
- "application/json"
paths:
/cpu:
get:
description: "Returns cpu information of the hosting server"
produces:
- "application/json"
responses:
"200":
description: "CPU info"
schema:
$ref: "#/definitions/CPU"
definitions:
CPU:
type: "object"
required:
- "model"
properties:
model:
type: "string"
With the REST service having been defined, we can now generate the server
side stub code easily.
You will need to install the Swagger Codegen tool if not yet done so. For macOS
we recommend that you use the homebrew install via
$ brew install swagger-codegen
On Ubuntu you can install swagger as follows (update the version as needed):
$ mkdir ~/swagger
$ cd ~/swagger
$ wget https://oss.sonatype.org/content/repositories/releases/io/swagger/swagger-codegen-cli/2.3.1/swagger-codegen-cli-2.3.1.jar
$ alias swagger-codegen="java -jar ~/swagger/swagger-codegen-cli-2.3.1.jar"
Add the alias to your .bashrc or .bash_profile file. After you start a new terminal you
can use in that terminal now the command
swagger-codegen
For other platforms you can just use the .jar file, which can be downloaded from
this link.
Also make sure Java 7 or 8 is installed in your system. To have a well defined
location we recommend that you place the code in the directory ~/cloudmesh. In this
directory you will also place the cpu.yaml file.
After you have the codegen tool ready, and with Java 7 or 8 installed in your
system, you can run the following to generate the server side stub code:
$ swagger-codegen generate \
-i ~/cloudmesh/cpu.yaml \
-l python-flask \
-o ~/cloudmesh/swagger_example/server/cpu/flaskConnexion \
-D supportPython2=true
:rtype: CPU
"""
return 'do some magic!'
Please note the do some magic! string at the return of the function. This ought to be
replaced with actual implementation what you would like your REST call to be
really doing. In reality this could be some call to a backend database or
datastore; a call to another API; or even calling another REST service from
another location. In this example we simply retrieve the cpu model information
from the hosting server through a simple python call to illustrate this principle.
Thus you can define the following code:
import os, platform, subprocess, re
def get_processor_name():
if platform.system() == "Windows":
return platform.processor()
elif platform.system() == "Darwin":
command = "/usr/sbin/sysctl -n machdep.cpu.brand_string"
return subprocess.check_output(command, shell=True).strip()
elif platform.system() == "Linux":
command = "cat /proc/cpuinfo"
all_info = subprocess.check_output(command, shell=True).strip()
for line in all_info.split("\n"):
if "model name" in line:
return re.sub(".*model name.*:", "", line, 1)
return "cannot find cpuinfo"
And then change the cpu_get() function to the following:
def cpu_get(): # noqa: E501
"""cpu_get
:rtype: CPU
"""
return CPU(get_processor_name())
Please note we are returning a CPU object as defined in the API and later
generated by the codegen tool in the models directory.
It is best not to include the definition of get_processor_name() in the same file as you see
the definition of cpu_get(). The reason for this is that in case you need to regenerate
the code, your modified code will naturally be overwritten. Thus, to minimize
the changes, we do recommend to maintain that portion in a different filename
and import the function as to keep the modifications small.
Now we can install and run the REST service. It is strongly recommended that
you run this in a pyenv or a virtualenv environment.
In case you are not using pyenv, please use virtual env as follows:
$ virtualenv RESTServer
$ source RESTServer/bin/activate
$ cd ~/cloudmesh/swagger_example/server/cpu/flaskConnexion
$ pip install -r requirements.txt
http://localhost:8080/api/cpu
Assignment: How would you verify that your service works with a curl call?
In addition to the server side code swagger can also create a client side code.
Generate the client side code in a similar fashion as we did for the server side
code:
$ java -jar swagger-codegen-cli.jar generate \
-i ~/cloudmesh/cpu.yaml \
-l python \
-o ~/cloudmesh/swagger_example/client/cpu \
-D supportPython2=true
Although we could have installed the client in the same python pyenv or
virtualenv, we showcase here that it can be installed in a completely different
environment. That would make it even possible to use a python 3 based client
and a python 2 based server showcasing interoperability between python
versions (although we just use python 2 here). Thus we create ane new python
virtual environment and conduct our install.
$ virtualenv RESTClient
$ source RESTClient/bin/activate
$ pip install -U pip
$ cd swagger_example/client/cpu
$ pip install -r requirements.txt
$ python setup.py install
6.8.3.4.3 Using the client API to interact with the REST service
try:
api_response = api_instance.cpu_get()
pprint(api_response)
except ApiException as e:
print("Exception when calling DefaultApi->cpu_get: %s\n" % e)
We can then run this code to verify the calling to the REST service actually
works. We are expecting to see a return similar to this:
{'model': 'Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz'}
Although we develop and run the example on one localhost machine, you can
separate the process into two separate machines. E.g., on a server with external
IP or even DNS name to deploy the server side code, and on a local laptop or
workstation to deploy the client side code. In this case please make changes on
the API definition accordingly, e.g., the host value.
6.9 EXERCISES ☁
E.OpenAPI.1:
E.OpenAPI.2:
E.OpenAPI.3:
E.OpenAPI.4:
E.OpenAPI.5:
After you have gone through the entire section and verified it works
for you add create a more sophisticated schema and add more
attributes exposing more information from your system.
How can you for example develop a rest service that exposes portions
of your file system serving large files, e.g. their filenames and their
size? How would you download these files? Would you use a rest
service, or would you register an alternative service such as ftp,
DAV, or others? Please discuss in piazza. Note this will be a helping
you to prepare a larger assignment. Think about this first before you
implement.
You can try expand the API definition with more resources and
actions included. E.g., to include more detailed attributes in the CPU
object and to have those information provided in the actual
implementation as well. Or you could try defining totally different
resources.
The codegen tool provides a convenient way to have the code stubs
ready, which frees the developers to focus more on the API definition
and the real implementation of the business logic. Try with complex
implementation on the back end server side code to interact with a
database/datastore or a 3rd party REST service.
Learning Objectives
GraphQL allows clients to request they need while specifing attributes in the
query without thinking much about the API implementation. It simplifies access
and reduces traffic as the application has control over the data it needs and its
format. Hence GraphQL reduces the network traffic as only the necessary data is
transfered from server to client.
Unlike REST APIs, which require often loading data via multiple queries,
GraphQL can get typically all the data in a single request. GraphQL APIs are
defined in terms of types and fields. Types help GraphQL to ensure that client
only asks for what is possible and in case of faults, provides clear and helpful
errors.
Initially GraphQL was implemented in JavaScript. Today there are several other
implementations in different languages available. To show case how to use
GraphQL, we will explore the graphql-python implementation in this chapter.
The official documentation of GraphQL is available at [54]
7.1 PREREQUISITES
Before we start we need to install a number of tools that we use throughout the
chapter
For the purpose of demonstrating in this chapter, we will use Django as Python
web framework. Django is a popular Python web framework which already
comes with a lot of boilerplate code. It is mature and has a very large
community. It has inbuilt support for Object Relational Mapping which is based
on Database Code-First approach. Please refer [55] for more Django
information. Use pip to install Django
$ pip install django==2.0.2 django-filter==1.1.0
In case you prefer to use a browser interface which could be useful for
debugging purposes a number of GraphQL browsers are available. A free
version is GraphiQL. It is an IDE(Interactive Development Environment) for
GraphQL where you can run a GraphQL Query. There are many
implementations of GraphiQL available. For this chapter we will use GraphiQL.
You can download the GraphiQL installation files specific to your OS from
GraphiQL Releases.
Insomnia
Altair
In GraphQL a query is what a client requests from the GraphQL server. The
result will be obtained in a structure defined by type and schema. Thus, the
client will know ahead of time what it is going to get as result as part of a well
formed response. For this to work, the data is often assumed to be structured
data.
To demonstrate the type system we will use a simple example while looking at
authors and co-authors of papers. We represent in this example a database that
contains a number of authors. Each author has a publication count and a number
of coauthors that are identified by name. We assume for this simple example that
all author names are unique.
The response is
{
"author": {
"name": "John Doe",
"publication_count": 25,
"coauthors": [
{
"name": "Mary Jane"
},
{
"name": "David Miller"
}
]
}
}
For this to work, we need to define the types that are going to be honored by the
GraphQL service so that when a query is received by the server, it is first
validated against a schema that defines the types contained within the GraphQL
service.
Hence, types must be defined as part of each GraphQL service. They are defined
with the GraphQL schema language which is programming language agnostic.
An example of a GraphQL type is:
type Author {
name: String!
publication_count: Int
coauthors: [Author!]!
}
Here we define the type author with three fields name, publication, and coauthors. Note
that the ! indicates a field value, that cannot be null and must have a defined
value. [Author!]! means that an array is returned, but that array cannot be null and
also none of the items in the array can be null.
ID: Represents a unique identifier which can be used as a key to fetch the
object
enum is a scalar type which defines restricted set of values. When a GraphQL
schema defines a field of enum type, we expect that the field’s value be of the type
enum including only the values that are included in that enumeration. An example
of an enum type is
enum ContainerType {
Docker
Kubernetes
DockerSwarm
}
7.2.4 Interfaces
interface ComputeService {
id: ID!
name: String!
memory: Int!
}
As the name suggests a union type represents the union of two or more types. The
following example shows how we can define a union type. As you can see we use
the | character to indicate the union operator.
union ComputeType = Container | VirtualMachine
Now when we write a GraphQL query to get the ComputeType information, we can ask
some of the common fields and some of the specific fields conditionally. In the
next example we request AllComputeTypes with common fields like id, name and fields
specific to either VirtualMachine or Container.
{
AllComputeTypes {
id
name
... on VirtualMachine {
user
}
... on Container {
type
}
}
}
A very simple definition of a query is to ask for specific fields that belong to an
object stored in GraphQL.
As we can see the response data format looks exactly like the query. This way a
client knows exactly what data it has to consume. In the previous example, the
name field returns the data of type String. Clients can also ask for an object
As you may already know in REST services you can pass parameters as part of a
request via query parameters through GET or a request body through POST.
However in GraphQL, for every field, you provide an argument restricting the
data returned to only the information that you need. This reduces the traffic for
returning the information that is needed without doing the postprocessing on the
client. These restricting arguments can be of scalar type, enumeration type and
others.
Let us look at an example of a query where we only ask for first 3 repositories in
cloudmesh community
{
repositories(first: 3) {
name
url
}
}
7.3.3 Fragments
7.3.4 Variables
Variables are used to pass dynamic values to queries. Instead of passing hard-
coded values to a query, variables can be defined for these values. Now these
variables can be passed to queries.
In case you use GraphiQL, variables can be defined in the Query Variables panel
at left bottom of the GraphiQL client. It is defined as a JSON object and this is
how it looks like
{
"name": "book"
}
7.3.5 Directives
Directives are used to change the structure of queries at runtime using variables.
Directives provide a way to describe additional options to GraphQL executors.
Currently the core GraphQL specification supports two directives
To demonstrate its usage, we define the variable isAdmin and assign a value of true to
it.
{
"isAdmin": true
}
Since we have defined showOwnerInfo as true, the response includes ownerInfo data.
{
"data": {
"repositories": [{
"name": "book",
"url": "https://github.com/cloudmesh-community/book",
"ownerInfo": {
"name": "cloudmesh-community"
}
}]
}
}
7.3.6 Mutations
Mutations are used to modify the server side data. To demonstrate this, let us
look at the query and the data to be passed along with it
mutation CreateRepositoryForCommunity($community: Community!, $repository: Repository!) {
createRepository(community: $community, repository: $repository) {
name
url
}
}
{
"community": "cloudmesh-community",
"repository": {
"name": "cm-burn",
"url": "https://github.com/cloudmesh/cm-burn"
}
}
The response will be as follow, indicating that a repository has been added.
{
"data": {
"createRepository": {
"name": "cm-burn",
"url": "https://github.com/cloudmesh/cm-burn"
}
}
}
In an application we need to validate the user input. If it is invalid we can use the
GraphQLError class or Python exceptions to raise validation errors.
To execute the example you need to go in the specific directory. Thus, for
cloudmeshrepo say
$ cd book/examples/graphql/cloudmeshrepo
The last command will start a server on localhost and you can access it at
http://localhost:8000
The last command will start a server on the localhost and you can access it at the
URL
http://localhost:8000
It will show you the welcome page for django. Now open the file
cloudmeshrepo/cloudmeshrepo/settings.py
Clients can request for data to GraphQL server via GraphQL queries. They can
also use mutations to insert data into GraphQL server’s database. Django follows
the principle of separating different modules in a project into apps. For this
example, we will have two apps, one for Users and one for Repositories. For the
demo purpose, we have decided not use backend such as MongoDB but instead
we will use SQLite.
Django provides startapp utility to create blank app with some biolerplate code.
Go to the root dir of project and execute the following command which will
create an app for repository.
python manage.py startapp repository
Now open the file cloudmeshRepository/settings.py and append following line into
INSTALLED_APPS
INSTALLED_APPS = (
# After the graphene_django app
'Repositories',
)
Go to root folder and execute following commands. It will create table for new
model
$ python manage.py makemigrations
$ python manage.py migrate
Naturally, for us to demonstrate the server, we need to ingest some data into the
server. We can easily do this with the django shell while calling
$ python manage.py shell
Inside the shell, execute following command to create some example data. We
have taken this data from github’s API and used the repositories in the
cloudmesh community at
https://api.github.com/users/cloudmesh-community/repos.
You could use either wget or curl command to download this data through shell. As
this data is huge, we have used a small subset for this example. You can have a
python script, shell script or any other program to clean and remodel the data as
per your need; the implementation details for the cleaning process is out of scope
for this chapter.
from Repositories.models import Repository
Repository.objects.create(
name="boat",
full_name="cloudmesh-community/boat",
url="https://github.com/cloudmesh-community/boat",
description="S.T.A.R. boat")
Repository.objects.create(
name="book",full_name="cloudmesh-community/book",
url="https://github.com/cloudmesh-community/book",
description="Gregor von Laszewski")
Repository.objects.create(name="cm",
full_name="cloudmesh-community/cm",
url="https://github.com/cloudmesh-community/cm",
description="Cloudmesh v4")
Repository.objects.create(name="cm-burn",
full_name="cloudmesh-community/cm-burn",
url="https://github.com/cloudmesh/cm-burn",
description="Burns many SD cards so we can build a Raspberry PI cluster")
exit()
Now create the file Repositories/schema.py with the following code. The code will create
a custom type Repository and query with a resolver function for Repositories. The
GraphQL server uses a resolver function to resolve the incoming queries.
Queries can respond to only those fields or entities of schema for which resolver
function has been defined. A Resolver function’s responsibility is to return data for
that specific field or entity. We will create one for Repositories list. When you
query repositories, resolver function will return all the repositories objects from
database.
import graphene
from graphene_django import DjangoObjectType
class RepositoryType(DjangoObjectType):
class Meta:
model = Repository
class Query(graphene.ObjectType):
Repositories = graphene.List(RepositoryType)
Next create the file cloudmeshRepository/schema.py with following code. It just inherits the
query defined in Repositories app. This way we are able to isolate schema to
their apps.
import graphene
import Repositories.schema
schema = graphene.Schema(query=Query)
Next, we create a Schema and use it within GraphiQL which is a playground for
GraphQL queries. Open the file cloudmeshrepository/urls.py and append the following
code
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
urlpatterns = [
path('admin/', admin.site.urls),
path('graphql/', csrf_exempt(GraphQLView.as_view(graphiql=True))),
]
http://localhost:8000/graphql
You will see GraphiQL window. In the left pane you can add queries. Let us add
the following query
{
repositories {
name
fullName
url
description
}
}
In the right pane you will see following output
{
"data": {
"repositories": [
{
"name": "boat",
"fullName": "cloudmesh-community/boat",
"url": "https://github.com/cloudmesh-community/boat",
"description": "S.T.A.R. boat"
},
{
"name": "book",
"fullName": "cloudmesh-community/book",
"url": "https://github.com/cloudmesh-community/book",
"description": "Gregor von Laszewski"
},
{
"name": "cm",
"fullName": "cloudmesh-community/cm",
"url": "https://github.com/cloudmesh-community/cm",
"description": "Cloudmesh v4"
},
{
"name": "cm-burn",
"fullName": "cloudmesh-community/cm-burn",
"url": "https://github.com/cloudmesh/cm-burn",
"description": "Burns many SD cards so we can build a Raspberry PI cluster"
}
]
}
}
Similar to a query, you can add a mutation to create your own data. To achieve
this, add a CreateRepository class for new repository object which will inherit from
graphene’s Mutation class. This class will accept a new repository as an
argument. Please see the following code snippet which is added to
repositories/models.py.
class CreateRepository(graphene.Mutation):
url = graphene.String()
name = graphene.String()
full_name = graphene.String()
description = graphene.String()
class Arguments:
url = graphene.String()
name = graphene.String()
full_name = graphene.String()
description = graphene.String()
return CreateRepository(url=repository.url,
name=repository.name,
full_name=repository.full_name,
description=repository.description)
Now you can run the following mutation on GraphiQL to add a new repository
mutation {
createRepository (
url: "https://github.com/cloudmesh-community/repository-test",
name: "repository-test",
fullName: "cloudmesh-community/repository-test",
description: "Test repository"
) {
url
name
fullName
description
}
}
This will insert a new repository repository-test and also immediately return its
inserted data fields (url, name, fullName, description).
{
"data": {
"createRepository": {
"url": "https://github.com/cloudmesh-community/repository-test",
"name": "repository-test",
"fullName": "cloudmesh-community/repository-test",
"description": "Test repository"
}
}
}
We can add a REST API endpoint which will take care of authenticating
the user and only the logged in users can make GraphQL queries. This
method can also be used to restrict only a subset of GraphQL queries. This
is ideal for existing applications, which have REST endpoints, and which
are trying to migrate over to GraphQL.
We can add basic authentication to the GraphQL server which will just
accept credentials in raw format and once authenticated, logged in user can
start GraphQL querying
We can add JSON Web Token authentication to GraphQL server, since
most of the applications these days are stateless.
JWT tokens are bearer tokens which need to be passed in HTTP authorization
header. JWT tokens are very safe against CSRF attacks and are trusted and
verified since they are digitally signed.
MIDDLEWARE = [
'graphql_jwt.middleware.JSONWebTokenMiddleware',
[
AUTHENTICATION_BACKENDS = [
'graphql_jwt.backends.JSONWebTokenBackend',
'django.contrib.auth.backends.ModelBackend',
]
Run the server using runserver command and fire the token mutation providing
username and password. You can either run this mutation on GraphiQL or using
curl command.
The JWT library comes with a built-in directive called login_required. You can
add this to any of your Query resolvers to prevent unauthenticated access. We
have annotated it to the resolve_repositories which means it will throw authentication
error to query which does not have JWT token passed. Whenever a valid JWT
token is present in the query, it is considered as authenticated or logged in
request, and data will be served only to these queries.
from graphql_jwt.decorators import login_required
...
class Query(graphene.ObjectType):
repositories = graphene.List(RepositoryType)
@login_required
def resolve_repositories(self, info, **kwargs):
return Repository.objects.all()
Now if you try to query our repositories from GraphQL, you will see this error
{
"errors": [
{
"message": "You do not have permission to perform this action",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"repositories"
]
}
],
"data": {
"repositories": null
}
}
Henceforth you need to pass token with every repository query. This token needs
to be passed as header. Unfortunately, the GraphiQL UI client does not support
this. Hence you can use either a curl query from command line or more
advanced GraphQL clients that support authentication.
JWT tokens have a time-to-life and expire after a while. This is controlled by the
GraphQL server and is usually communicated to the client in transparent
documented fashion.
If the token is about to expire, you can call the refreshToken mutation to refresh the
Token and to return the refreshed token to the client. However, if the token has
already expired we will need to request a new token by calling tokenAuth mutation.
More information about JWT tokens can be found at [56] and the GraphQL
authentication page at [57].
GitHub has implemented as part of its API v4 also GraphQL which allows you
to query or mutate data of repositories that you can access via github.com. To
demonstrate its use, we will use GraphiQL.
To access the information, we need an OAuth token to access GitHub API. You
can generate an OAuth token by following the steps listed at
https://help.github.com/articles/creating-a-personal-access-token-for-the-
command-line/
Next we demonstrate the use of Github within a GraphQL browser called Open
GraphiQL. First you need to click edit headers at upper-right corner and add a
new header with key Authorization and value Bearer your_token.
https://api.github.com/graphql
in the GraphQL endpoint textbox and keep the method as POST only. To test if
the changes have been applied successfully you can use the query
query {
viewer {
login
name
}
}
To add a comment using mutation we need to get the issue id with the query
{
repository(owner:"MihirNS", name:"Temp_Repository") {
issue(number: 1) {
id
}
}
}
Now we can use the id as subjectId for mutation to add a comment to an issue with
the query
mutation AddComment {
addComment(input:{subjectId:"MDU6SXNzdWUzNjUxMDIwOTE=",body:"This comment is done using GitHub API v4"}) {
commentEdge {
node {
repository{
nameWithOwner
}
url
}
}
}
}
For this reason we like you to be reminded about the Section describing the
resolver function. It allows us to add functions on the server side that return the
data from various data sources.
It is similar in nature than our example in the REST OpenAPI section, where we
associate call backs that execute dynamic operations. More information about
the functionality in REST is provided in the Section OpenAPI Specification as
part of the path definition.
Seperation of concern is achieved between client and server. Client requests data
entities with fields needed for the UI in one query request while server knows
about the data structure and how to resolve the data from its sources which could
be database, web service, microservice, external APIs, etc.
Versioning is simpler than REST, since we only have to take care of it when we
want to remove any of the fields. We can even introduce the property of a
deprecated field for a while to inform the service users. At a later time the field
could be entirely be removed.
type Car {
id: ID!
make: String
description: String @deprecated(reason: "Field is deprecated!")
}
7.8 DISADVANTAGES OF USING GRAPHQL
GraphQL query can get very complex. A client may not necessarily know how
expensive the queries can be for server to go and gather the data. This can be
overcome by limiting, for example, the query depth and recursion.
Caching gets pretty tricky and messy in case of GraphQL. In REST, you can
have separate API url for each resource requested, caching can be done at this
resource level. However, in GraphQL you can have different queries but they
can operate over a single API url. This means that caching needs to be done at
the field level introducing additional complexity.
7.9 CONCLUSION
GraphQL is gaining momentum as growing and the integration into services
such as Github, Pinterest, Intuit, Coursera, and Shopify, demonstrates this. Many
GraphQL editors, IDEs and packages have recently been developed.
In general there are several reasons to use GraphQL due to its simplicity and
flexibility. It also fits well with the microservices architecture which is a new
trend in cloud architectures. With that being said, REST APIs still have it is own
place and may prove better choice in certain use cases. Both REST and
GraphQL have some tradeoffs which need to be understood before making a
choice between the one or the other. Github shows that both can be used.
7.9.1 Resources
7.10 EXCERSISES
E.GraphQL.1:
E.GraphQL.2:
See an example
https://github.com/graphql-python/graphene-
mongo/tree/master/examples/flask_mongoengine
https://graphene-mongo.readthedocs.io/en/latest/tutorial.html
E.GraphQL.3:
E.GraphQL.8: Cloudmesh
8.1 VIRTUALIZATION ☁
Learning Objectives
The use of a system as a virtual machine has its clear advantages for the cloud.
We distinguish two main ways of system virtualizing:
End users and developers will benefit from using virtual machines in case they
need to operate or support on different hardware or porting software on it.
As example, the hypervisor has the ability to present generic I/O devices and it
has no access to non-generic I/O devices. Generic I/O devices are network,
interface cards, CD-ROMs. Examples for non-generic I/O devices are PCI data
acquisition card, etc. However with appropriate driver support even such devices
could be made accessible to the VMs.
Often we also find that hosted virtualization supports connected USB drives in
the VMs which becomes very practical for USB attached devices needed in
storage, or even edge computing applications.
Advantages of Hosted Virtualization include
8.1.4 Summary
To showcase how these technologies relate to each other you may review
Figure 34
8.1.5.2 Paravirtualization
Cloud providers, such as AWS, Azure, and Google, and OpenStack use for
example QEMU and KVM technologies for compute instance virtualization.
To use Intel’s Virtualization Technology for Directed I/O (VT-d), both the
motherboard chipset and system firmware (BIOS or UEFI) need to fully support
the IOMMU I/O virtualization functionality for it to be usable [62].
A number of noteworthy virtualization software and tools exist which make the
development and use of virtualization on the hardware possible. They include
Libvirt
KVM
Xen
Hyper-V
QEMU
VMWare
VirtualBox
8.1.6.4.1 Libvirt
https://libvirt.org/
8.1.6.4.2 QEMU
Once QEMU has been installed, it should be ready to run a guest OS from a disk
image. This image is a file that represents the filesystem and OS on a hard disk.
From the perspective of the guest OS, it actually is a file on hard disk, and it can
create its own filesystem on the virtual disk.
QEMU supports either XEN or KVM to enable virtualization. With the help of
KVM, QEMU can virtualize x86, server and embedded PowerPC, 64-bit
POWER, S390, 32-bit and 64-bit ARM, and MIPS guests according to the
QEMU Wiki.
Useful links include the following:
8.1.6.4.3 KVM
KVM includes a fork of the QEMU executable. The QEMU project focuses on
hardware emulation and portability. KVM focus on the kernel module and
interfacing with the rest of the userspace code. KVM comes with a kvm-qemu
executable that just like QEMU manages the resources while allocating RAM,
loading the code. However instead of recompiling the code it spawns a thread
which calls the KVM kernel module to switch to guest mode. It than proceeds to
execute the VM code. When privileged instructions are found, it switches back
to the KVM kernel module, and if necessary, signals the QEMU thread to handle
most of the hardware emulation. This means that the guest code is emulated in a
posix thread which can be managed with common Linux tools [64].
8.1.6.4.4 Xen
Xen is one of the most widely adopted hypervisors by IaaS cloud. It is supported
by the earliest and still the most popular public cloud offering, i.e., Amazon Web
Service (AWS). Eucalyptus, one open-source effort to replicate what AWS had
to offer, and the then most popular private cloud software, supported Xen from
the start. And later Openstack, the most popular open-source IaaS cloud software
at present, also supports Xen.
8.1.6.4.5 Hyper-V
Hyper-V is still getting a lot of popularity comparing to XEN and KVM which
we attribute to the increasing presence of Microsoft’s Azure cloud offering.
Figure 35: Popularity of KVM, Xen, and Hyper-V according to
Google Trends Source
8.1.6.4.6 VMWare
VMware is well known for the company bringing hypervisors to the amss
market. The company is now owned by Dell. It has developed the first type 2
hypervisor. Today VMWare offer type 1 hypervisors and type 2 hypervisors
[65].
Because the initial software virtualized “hardware for a video adapter, a network
adapter, and hard disk adapters” as well as “pass-through drivers for guest USB,
serial, and parallel devices” [65] it provided an attractive solution for many to
use it to run different OSs on their host computers. One important advantage is
that it does not rely on virtualization extensions to the x86 instruction set as it
was developed before they became available. This means it can run on many
other platforms. However this advantage is diminished with the ubiquitous
available of these features in the hardware.
8.1.6.5 Parallels
Parallels Desktop for Mac, which for x86 machines allows users to run
virtual machines independently using Windows, Linux, Solaris.
Parallels Workstation for Microsoft Windows and Linux users which for
x86 machines allows user to run virtual machines independently on the
Windows host.
8.1.6.5.1 VirtualBox
One of the nice features for us is thet VirtualBox is able to create and manage
guest virtual machines such as Windows, Linux, BSD, OSx86 and even in part
also macOS (on Apple hardware). Hence it makes it for us a very valuable tool
while being able to run virtual machines on a local desktop or computer to
simulate cloud resources without charging cost. In addition we find command
line tools such as Vagrant that make the use convenient while not having to
utilize the GUI or the more complex virtual box command interfaces. A guest
additions package allows compatibility with the host OS, to for example allow
window management between host and guest OS.
QEMU and KVM are better integrated in Linux and has a smaller footprint. This
may result in better performance. VirtualBox is targeted as virtualization
software and limited to x86 and amd64. As Xen uses QEMU it allows hardware
virtualization. However, Xen can also use paravirtualization [67]. In the
following table we summarize support for full- and paravirtualization
Storage virtualization allows the system to integrate the logical view of the
physical storage resources into a single pool of storage. Users are unaware while
using virtual storage that it is not hosted on the same hardware resources, such as
disks. Storage virtualization is done across the various layers that build state of
the art storage infrastructures. This includes Storage devices, the Block
aggregation layer, the File/record layer, and the Application layer. Most recently
hosting files as part of the application layer in the cloud is changing how we
approach data storage needs in the enterprise. A good example for a cloud based
virtual storage is google drive. Other systems include Box, AWS3 and Azure.
8.1.6.7 Selected Network Virtualization Software and Tools
Note, that we will not cover this topic in this introductory class. However
students can contribute a section or chapter
To create an image file with the size of 10GB and qcow2 format (default format for
QEMU images), run:
$ qemu-img create -f qcow2 testing-image.img 10G
Note that a new file called testing-image.img is now created at your home folder (or the
place where you run the terminal). Note also that the size of this file is not 10
Gigabytes, it is around 150KB only; QEMU will not use any space unless
needed by the virtual operating system, but it will set the maximum allowed
space for that image to 10 Gigabytes only.
Now that we have created our image file, if we have an ISO file for a Linux
distribution or any other operating system and we want to test it using QEMU
and use the new image file we created as a hard drive, we can run:
qemu-system-x86_64 \
-m 1024 \
-boot d \
-enable-kvm \
-smp 3 \
-net nic -net user \
-hda testing-image.img \
-cdrom ubuntu-16.04.iso
-m 1024 :
Here we chose the RAM amount that we want to provide for QEMU
when running the ISO file. We chose 1024MB here. You can change it
if you like according to your needs.
-boot -d :
The boot option allows us to specify the boot order, which device
should be booted first? -d means that the CD-ROM will be the first,
then QEMU will boot normally to the hard drive image. We have
used the -cdrom option as you can see at the end of the command. You
can use -c if you want to boot the hard drive image first.
-enable-kvm :
:
-smp 3
If we want to use more than 1 core for the emulated operating system,
we can use this option. We chose to use 3 cores to run the virtual
image which will make it faster. You should change this number
according to your computer’s CPU.
:
-net nic -net user
:
-hda testing-image.img
Here we specified the path for the hard drive which will be used. In
our case, it was the testing-image.img file which we created before.
-cdrom ubuntu-16.04.iso :
Finally we told QEMU that we want to boot our ISO file ubuntu-16.04.iso.
Now, if you want to just boot from the image file without the ISO file (for
example if you have finished installing and now you always want to boot the
installed system), you can just remove the -cdrom option:
$ qemu-system-x86_64 -m 1024 -boot d -enable-kvm -smp 3 -net nic -net user -hda testing-image.img
Next, you have to download the Raspbian image. Download a .img file from
Raspbian website:
https://www.raspberrypi.org/downloads/raspbian/
To start the emulator type in the following command to have QEMU emulate an
ARM architecture:
$ qemu-system-arm -kernel ./kernel-qemu-4.4.34-jessie \
-append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" \
-hda raspbian-stretch-lite.img \
-cpu arm1176 -m 256 -machine versatilepb \
-no-reboot -serial stdio
8.2.6 Resources
General
Comparison
http://opensourceforu.com/2012/05/virtualisation-faceoff-qemu-virtualbox-
vmware-player-parallels-workstation/
https://stackoverflow.com/questions/43704856/what-is-the-difference-
qemu-vs-virtualbox
Where is the machine name of the hypervisor. If you want to initiate a read-only
connection, append the previous command with -readonly.
To display the guest list and their current states with virsh:
virsh list [ --inactive | --all]
The –inactive option lists inactive domains (domains thxsat have been defined
but are not currently active). The –all domain lists all domains, whether active or
not.
https://linux.die.net/man/1/virsh
9.1 INTRODUCTION ☁
Learning Objectives
compute resources
network resources
storage resources
We also like to remind you that such IaaS as parts of clouds can either be
accessed public, private or in a hybrid fashion.
Within the next view section we will focus on some of the main providers of
IaaS.
This includes
Watson
Chameleon Cloud.
Some of the services listed provide a free small contingent of IaaS offerings that
you can use. The use of this free tier will be sufficient to conduct this class.
Amazon Web Services offers a large number of products that are centered
around their cloud services. These services have grown considerably over the
years from the core offering related to virtual machine (EC2) and datastorage
(S3). An overview of them is provided by Amazon in the following document:
https://d0.awsstatic.com/whitepapers/aws-overview.pdf
We list the product in screenshots from their Product Web page panel in Figure:
Figure 36, Figure 37.
Figure 36: AWS Products 1 Source
Compute
Storage
Database
Migration
Networking and Content Delivery
Developer Tools
Management Tools
Media Services
Machine Learning
Analytics
Security and Identity Compliance
Mobile Services
AR and VR
Application Integration
Customer Engagement
Business Productivity
Desktop and App Streaming
Internet of Things
Game Development
Software
Aws Core Management
Within each category you have several products. When choosing products form
AWS it is best to start with the overview paper and identify products that can be
of benefit to you. For our purpose we focus on the traditional Compute and
Storage offerings. We list the products that are available In Sep. 2018 next.
https://aws.amazon.com/lambda/
9.2.1.5 Storage
AWS provides many storage services that users can leverage for developing
applications and solutions. The next list showcases AWS storage services.
Amazon offers the following storage services
9.2.1.6 Databases
AWS also provides many data base solutions. AWS has both SQL based
databases and NoSQL based databases. The next list shows the database services
that AWS offers. And other database related services
Amazon Aurora
Amazon RDS
Amazon DynamoDB
Amazon ElastiCache
Amazon Redshift
Amazon Neptune
AWS Database Migration Service
AWS Marketplace
9.2.2 Locations
Next you will be asked to provide further details such as your name, address and
phone number. After the additional details have been provided. AWS will ask
for credit/debit card details as shown: Figure 40. They require this information to
verify your identity and make sure they have a method to charge you if needed.
However no charges will be applied to your credit/debit card unless you use the
AWS services and exceed the free tier limits, which will be discussed in the next
section.
Figure 40: Payment Information Source
After the credit/debit card has been verified AWS will use your phone number to
verify your identity. Once you are logged into your account you will be able to
sign into the console, from the link on the top right corner in your account. Once
you are in the AWS console the services tab in the left top corner will allow you
to access all the services that are available to you through AWS as shown in the
image : Figure 41.
Figure 41: AWS Console Source
9.2.4.1 Introduction
Amazon’s CLI allows for programatic interaction with AWS product through the
command line. CLI provide many pre-built functions that allow for interaction
with Amazon’s Elastic Compute Cloud (EC2) instances and S3 storage.
9.2.4.2 Prerequisites
Linux
Python
PIP
AWS Account
AWS Key Pair
Using the following code to configure AWS using. You will need to specify four
parameters:
9.2.5.1 Introduction
9.2.5.2 Prerequisites
Linux environment
9.2.5.3.2 Assign a security policy to the created group granting full admin access
AWS provides a set of services free of charge. These free services are to allow
new users test and experiment with various AWS services without worrying
about any cost. Free services are provided as a product that is free until a certain
amount of usage, that is if you exceed those limits you will be charged for the
additional usage. However the free quotas are typically more than sufficient for
testing and learning purposes. For example under the free tier you are able to use
750 hours of EC2 resources per month for the first 12 months after account
creation. However it is important to make note of important details that are
included in the limits. For example for the 750 hours of free EC2 usage, you can
only use “EC2 Micro” instances, using any other instance type for your EC2
machine will not fall under the free tier agreement and you will be charged for
them, see picture: Figure 42. To view all the AWS free tier details visit AWS
Free Tier
12 months free offer are only good for the first 12 months after you create your
AWS account. The always free offer are valid even after the first 12 months.
When using AWS services make sure you understand how and
when you will be charged for.
For example if you are using an EC2 to run some application, usage of the
instance will be calculated from the time you started the instance to the time you
stop or terminate the instance. So even if you do not use the application itself, if
you are have the instance in an active mode that will be added to the usage hours
and you will be billed if you exceed the 750 hour limit. In EC2 even if you stop
the instance you might be charged for data that is stored in the instance so
terminating it would be the most safest option if you do not have any important
data stored in the instance. You can look up other such tricky scenarios at
Avoiding Unexpected Charges to make sure you will not get an unexpected bill
As we discussed previously we can access all the service and product offerings
that are provided by AWS from the AWS console. In the following section we
will look into how we can start and stop a virtual machine using AWS EC2
service. Please keep in mind that this will reduce time from your free tier limit of
750 hours/month, So be careful when starting EC2 instances and make sure to
terminate them after you are done.
9.2.8.1 Starting a VM
To go to the EC2 services you can click on the services link on the top left
corner in the console and then click on EC2 which is listed under “Compute”.
Then you will see a blue button labeled “Launch instance”. Click on the button
and the console will take you to the page shown next: Figure 43. Notice that the
check box for “Free tier only” is clicked to make sure the instance type we
choose is eligible for the free tier hours. The instance type you select defines the
properties of the virtual machine you are staring such as RAM, Storage,
processing power. However since we are using instance that are free tier eligible
we will only be able to use “EC2 Micro instances”. You can also select a OS that
you want to be started as the virtual machine. We will select “Ubuntu Server
16.04 LTS” as our Operating system. press the blue select button to do so.
Figure 43: Launch Instance
Once you select the OS type you will be asked to select the instance type. You
can notice that only the “t2.micro” is marked as free tier eligible as shown in the
image: Figure 44. Now that you have selected all the basic details press the
“Review and Launch” button located in the button right corner. This will give
you a summary of your current selections.
Before we can launch the VM we need to perform one more step. We need to
setup a SSH key pair for the new VM. Creating this will allow us to access our
VM through SSH. Once you click on the launch button, you will get the
following dialog box: Figure 45. If you already have a worked with SSH keys
and if you already have a key pair you can use it, otherwise you can create a new
key pair as we will do. To create a new key pair select the “Create a new key
pair” in the first drop down box and enter a name of your choosing as the name.
Next you need to download and save the private key, Keep the private key in a
safe place and do not delete it since you will need it when you are accessing the
VM (This tutorial will not cover accessing the VM through SSH but you need to
keep the private key so you can use the same key value pair later). Once you
have downloaded the private key, the “Launch Instance” button will activate.
Press this button to start the VM.
After starting the instance go back to the EC2 dashboard ( Services -> EC2).
Now the dashboard will show the number of running instance as shown in the
image: Figure 46. If you do not see is initially, refresh the page after a little
while, starting the VM may take a little time so the dashboard will not be
updated until the VM starts.
Figure 46: Running Instance1
Now to get a more detailed view click on the “Running Instances” link. This will
give you the following view: Figure 47. Is shows the current instance that you
are running
9.2.8.2 Stopping a VM
In AWS EC2 you can either stop a VM or terminate it. If you terminate it you
will loose all the data that was stored in the VM as well, simply stopping will
save the data for future use if you restart the instance again. In order to stop the
VM you can select the VM machines you want to stop from the GUI and go to
“Actions -> Instance status” and click on stop: Figure 48. This will stop your
VM machine.
Figure 48: Instance Stop
After a little while the dashboard will show the instance as stopped as the
following: Figure 49. If you want to go further and terminate the instance you
can again go to “Actions -> Instance status” and select terminate, which will
terminate the VM.
AWS also provides an command line interface that can be used to manage all the
AWS services through simple commands. Next are two example commands.
aws s3 <Command> [<Arg> ...]
aws ec2 <Command> [<Arg> ...]
You can find more information regarding the AWS CLI in the following
documents.
Amazon Web Services (AWS) is a cloud platform that provides a large number
os services for individuals and enterprises. You can get an overview of the AWS
offering at Amazon Web Services Overview. This section will guide through the
processes of creating an AWS account and explain the free tier details so that
you can leverage the tools and products available in AWS for your work and
research.
9.2.11 Boto
https://boto3.readthedocs.io/en/latest/
https://github.com/boto/boto3
9.2.12 libcloud
“Libcloud is a Python library for interacting with many of the popular cloud
service providers using a unified API. It was created to make it easy for
developers to build products that work between any of the services that it
supports.” A more detailed description on Libcloud and how you can use it to
connect with AWS is provided in the Section Python libcloud.
For more information about the features and supported providers, please refer to
the documentation
9.3.1 Products
AI + Machine Learning
Analytics
Compute
Containers
Databases
Developer Tools
DevOps
Identity
Integration
Internet of Things
Management Tools
Media
Migration
Mobile
Networking
Security
Storage
Web
compute,
container, and
data resources
For a more elaborate list please consult our Appendix. To see the complete list
lease visit the Microsoft Web page via this link.
9.3.1.1 Virtual Machine Infrastructure as a Services
Source: https://support.microsoft.com/en-us/allproducts
Microsoft offers core IaaS Compute compute resources. This includes the
following services:
9.3.1.3 Databases
9.3.1.4 Networking
9.3.2 Registration
In order for you to register in Azure and start your free account, you will need to
go to
https://azure.microsoft.com/en-us/free/
On that image you click the Start free button to obtain a free one year account. You
will have to either create a new Microsoft account or use the one from Indiana
University which will be your IU id followed by the ??? domain. You will be
redirected to the single sign on from IU to proceed. If you use another e-mail
you can certainly do that and you free account sis not associated with the IU
account. This could be your Skype account or some other e-mail. After
registration you will be provided with 12 months of free usage of a few selected
services and $200 credits for 30 days. At the end of 30 days, Azure disables your
subscription. Your subscription is disabled to protect you from accidentally
incurring charges for usage beyond the credit and free services included with
your subscription. To continue using Azure services, you must upgrade your
subscription to a Pay-As-You-Go subscription. After you upgrade, your
subscription still has access to free services for 12 months. You only get charged
for usage beyond the free services and quantities. The Azure Student Account
requires that you to activate the account after 30 days of use. If you do not
activate, you will lose access to your Azure Student Account and can not use the
services.
The Azure student account FAQ will likely answer questions you might have
pertaining to an Azure Student Account, what you will have access to, how long
you will enjoy access, and additional general overview information including
terms of the account. https://azure.microsoft.com/en-us/free/free-account-
students-faq
Once you have set up the Azure Student account, you will gain access the Azure
environment through the Azure Portal https://portal.azure.com. To log in, please
use the credentials you determined during the set up.
9.3.4 Creating a VM
Choose Create a resource in the upper left-hand corner of the Azure portal. Select a
VM name, and the disk type as SSD, then provide a username. The password
must be at least 12 characters long and meet the defined complexity
requirements. As the following: Figure 51.
Source: https://docs.microsoft.com/en-us/azure/virtual-
machines/windows/media/quick-create-portal/create-windows-vm-portal-basic-
blade.png
Here are the steps to create a Ubuntu Server 18.04 LTS Virtual Machine in
Azure.
Next, the locate the Virtual Machines option and select it:(see Figure 52).
Figure 52: virtualmachines
This will present you the configuration options needed to create a new virtual
machine:(see Figure 54).
Figure 54: createavirtualmachine
Authentication type: password (Choose a username and a password that meet the
requirements).
For Networking you can choose all the default configuration settings or modify to
your liking:(see Figure 56).
For Management you can choose all the default configuration settings or modify to
your liking:(see Figure 57).
Figure 57: management
Once the new VM has been created, Naviagate back to the Virtual machines and now
discover your Virtual Machine:(see Figure 59).
After creation the virtual machine will be in a running status. You will want to
decide if you want your virtual machine in a running status, else stop the VM so
that you do not waste resources.
To remote access a virtual machine, you can use a client application like Putty:
https://www.putty.org .
To use Putty and access the virtual machine, you can configure DNS name in
Azure instead of using an IP. This is performed in the Virtual Machine
configuration under DNS name:(see Figure 60).
Click Configure. You can chose a static IP setting or a dynamic IP (This example uses a
static IP setting):(see Figure 61).
Note: If you have not configured the port that connection will use, then
connection will not be successful.
In your Virtual machine settings click Connect and review the connection settings.
This example shows the designated port 22 to be the port that will remote connect
to the virtual machine:(see Figure 62).
Figure 62: connectandport
To learn more about working with ports you can review the following:
https://docs.microsoft.com/en-us/azure/virtual-machines/windows/nsg-
quickstart-portal
Next, to connect to the virtual machine, lauch the Putty client and enter the DNS
name of the virtual machine to connect to the virtual machine:(see Figure 63).
After the key is cached, it will be remember the next time you access the VM
with the Putty client. After the VM is successfully accessed in Puty, you will be
prompted to enter your server credentials as specified in the virtual machine
setup.
Once credentials are provided, you will be logged into your virtual machine:(see
Figure 65).
Figure 65: loggedinviaputty
To learn more about connecting to Azure virtual machines you can visit:
https://docs.microsoft.com/en-us/azure/virtual-machines/windows/connect-logon
9.3.7 Starting a VM
Now we like to introduce you how to start a VM. Please note that VMS do cost
and reduce your free hours on Azure. Hence you need to make sure you
carefully review the charging rates and chose VM sizes and types that minimize
your charges.
It is the most important to stop your VMS once they are not in used, or you get
continuously charged. The portal allows you to see the list of VM that you run as
follows
9.3.9 Exercises
E.Azure.0:
Identify all products related to IaaS service offerings and mark them
with ⭐ after the bullet. Do copy the aws.md file into your own
repository, do not yet create a pull request. Confirm in a team your
findings and agree with each other.
E.Azure.1:
E.Azure.2:
E.Azure.3:
IBM’s Watson’s is well known for its ability to play and successfully win the
popular gameshow, jeopardy! IBM startled the world in 2011 when Watson beat
Jeopardy! pros Ken Jennings and Brad Rutter over several rounds. Watson
completed the formidable task by combining 15 terabytes of human knowledge
with a variety of computer disciplines including automated reasoning, natural
language processing, knowledge representation, information retrieval and
machine learning.
IBM’s goal of having computers understand the questions humans ask while
providing answers in a similar fashion is not unique to them. In recent years,
products like Amazon’s Alexa and Google Home have brought the awareness of
this capability mainstream for millions of households. In short, it has become a
race to serve up relevant content with the least amount of effort in the most
consumable format.
While The next section walks through how to create a free account, let’s
continue with an example of leveraging a foundation and building on-top with
Watson Assistant Basic. Please see steps: Figure 68, Figure 69, Figure 70,
Figure 71, Figure 72, Figure 73
Instead of starting with a blank page IBM steps are put in place and working
examples can be customized.
Figure 68: Step 1
Figure 69: Step 2
In the previous case when I was trying the Watson Assistant It was not personal
when I asked the Assistant’s name so it can be modified to digress!
In addition to using these modules to help build there is also a variety of APIs
and services that can be used:
The list of APIs and services include: * Watson Assistant * Watson Discovery *
Natural Language Understanding * Discovery News * Knowledge Studio *
Language Translator * Natural Language Classifier * Personality Insights *
Tone Analyzer * Visual Recognition * Speech to Text * Text to Speech
This section will guide through the processes of creating an IBM Watson
account and explain the free tier details so that you can leverage the tools and
products available in AWS for your work and research.
First you need to visit the IBM Watson home page and click in the “Get Started
Free” link on the top right corner. You will then be asked to provide some basic
details including your email address as shown in the image Figure 74.
Figure 74: Watson Signup
Once you have submitted the signup form an confirmation email will be sent to
your email account, check your inbox and click on the confirm account link in
the email you receive. This will activate your IBM Watson account. Once you
have accepted the terms and conditions you will be taken to the product and
service catalog of IBM Watson as shown in the image Figure 75.
Figure 75: Watson Catalog Source
IBM watson provides a set of services for free with their Lite account. Since you
did not provide any credit/debit card information when creating the account, by
default you will have a Lite account. The lite plan does apply usage caps for
services offered under the plan. If you need to expand and remove such limits
you would have to upgrade to a payed account However the free quotas are
typically more than sufficient for testing and learning purposes. For example
under the Lite plan you can use the “Watson Assistant” service with caps such as
10K API calls per month.
Google Cloud Platform is a part of Google Cloud, which includes the Google
Cloud Platform public cloud infrastructure, as well as G Suite, Cloud Identity,
Apigee, Firebase, enterprise versions of Android and Chrome OS, and Google
Maps Platform. The platform and all its offerings can be managed via a
customizable dashboard Figure 76.
https://cloud.google.com
We have copied the information form that location and made them conveniently
available in this section.
9.5.1.1 Overview
Google offers many machine learning and artificial intelligence tools, including
tools for text-to-speech, speech-to-text, translation, and image and video analysis
as well as various tools for making models and predictions and deploying
pipelines and out-of-the-box algorithms.
API tools include monetization and analytic tools as well as deployment tools.
Apigee Edge integrates these tools together into a platform for managing APIs
through the use of API proxies, which are combined together with a service plan
into an API product.
Apigee API Platform: Develop, secure, deploy, and monitor your APIs
everywhere.
API Analytics: Insight into operational and business metrics for APIs.
API Monetization: Flexible, easy-to-use solution to realize value from
APIs.
Apigee Sense: Intelligent behavior detection to protect APIs from attacks.
Cloud Endpoints: Develop, deploy, and manage APIs on GCP.
DeveloperPortal: Enable developers and API teams with a turnkey self-
service platform.
Apigee healthcare APIx: Accelerate building new FHIR API-based digital
services.
Apigee Open Banking APIx: Accelerate open banking and PSD2
compliance.
Cloud Healthcare API: Secure APIs powering actionable healthcare
insights.
Figure 78: Google API management Source
9.5.1.4 Compute
9.5.1.6 Databases
A flow chart is even provided for helping determine the best service for your
needs Figure 79.
Google’s developer tools include tools for Visual Studio, IntelliJ, Google Cloud,
and Powershell, cloud-hosted git repositories, a infrastructure for testing mobile
apps, and a deployment management tool.
Google currently offers two media tools, Anvato for live-streaming videos, and
Zync Render for rendering videos.
9.5.2 Migration
9.5.2.1 Networking
The Google Virtual Private Cloud Network is Google’s own world-wide
network where you can host your applications and services. Google also has load
balancing, DNS, CDN, and connectivity tools for working with this network.
9.5.2.2 Security
9.5.2.3 Storage
Google’s storage services include all the services mentioned in its database
services as well as Persistent Disk, which offers block service for virtual
machines and containers.
Locate the Try for Free button option on the top right portion of the webpage. The
free trial allows a person access to all Cloud Platform Products. You get
everything you need to build and run your apps, websites and services, including
Firebase and the Google Maps API. Note, you will be asked you for your credit
card to make sure you are not a robot. You will not be charged unless you
manually upgrade to a paid account. Disclaimer: Please be aware that you pay
for this service only after you accrue costs, via an automatic charge when you
reach your billing threshold or 30 days after your last automatic payment,
whichever comes first. You will be presented the option to agree and continue.
Once you satisfy all the formalities you will be granted the 12-month free trial.
This material was obtained from Google on the Cloud Console Tour. This information
covers the core features of Cloud Console to get you ready to build and manage
your applications on Google Cloud Platform. You will learn about the following
concepts: * GCP projects and resources * High-level resource overview and
activity logs * Console navigation and search * User and permissions
management * Technical support * GCP’s browser-based command line
GCP resources are the fundamental components that make up all Google Cloud
services. Resources are organized hierarchically and help organize your work on
GCP. Projects are the first level of the resource hierarchy, and they contain other
low-level resources like Cloud Storage buckets and Compute Engine instances.
Project navigation Easily navigate across your GCP projects using the
scopepicker in Cloud Console. Switching projects will tailor the view to that
project and all of its child resources.
Easily navigate across your GCP projects using the scopepicker in Cloud
Console. Switching projects will tailor the view to that project and all of its child
resources.
Figure 80: Scope Picker Example
For any service that you visit regularly, pin the section to the top of the
navigation menu by hovering over the section item and clicking the pin icon. See
a high-level overview of any project * Home dashboard The Home dashboard
provides a high-level overview of the selected GCP project, highlighting key
metrics, billing, and other useful information. * Customization You can
customize your dashboard by clicking Customize. Any card can be hidden,
shown, and reordered on the page. Each card also has custom options accessible
from the overflow menu when hovering a card. Customize Figure:
With Activity Stream, you will be able to understand all the activities that occur
across your GCP resources in one place. See what your teammates are updating
in any project to track down issues and audit access. Easily filter through the
feed to find exactly what you need.
If you ever get stuck, or need help navigating the world of GCP, the Google
support team is here to help. Access support from the navigation menu.
More information regarding support options and details can be found at:
https://cloud.google.com/support
Google Cloud Identity and Access Management (Cloud IAM) enables you to
manage and create permissions for your GCP resources. As your team continues
to grow, you can grant access to teammates using Cloud IAM in the IAM & Admin
section. Add users, groups, or service accounts and assign them any number of
roles to grant them the permissions they need.
Google Cloud Shell provides you with command-line access to your cloud
resources directly from your browser. You can easily manage your projects and
resources without having to install the Google Cloud SDK or other tools on your
system. With Cloud Shell, the Cloud SDK gcloud command-line tool and other
utilities you need are always available, up to date and fully authenticated when
you need them.
Since we have been exploring virtual machines in this class, I thought that I
would provide an additional example explaining how to create a Linux virtual
machine instance in Compute Engine using the Google Cloud Platform Console.
Navigate to Compute Engine Open the menu on the left side of the console.
Then, select the Compute Engine section.
Click the Create instance button. * Select a name and zone for this instance. * In
the Firewall selector, select Allow HTTP traffic. This opens port 80 (HTTP) to
access the app. * Click the Create button to create the instance. Note: Once the
instance is created your billing account will start being charged according to the
GCE pricing. You will remove the instance later to avoid extra charges.
While the instance is being created take your time to explore the VM instances
page. * At the bottom you can see the list of your VMs * At the top you can see
a control panel allowing you to * Create a new VM instance or an instance group
* Start, stop, reset and delete instances.
Compute Engine lets you use virtual machines that run on Google’s
infrastructure. Create micro-VMs or larger instances running Debian, Windows,
or other standard images. Create your first VM instance, import it using a
migration service, or try a quickstart to build a sample app. More detail can be
found at the following link regarding VM instances:
https://cloud.google.com/compute/?
hl=en_US&_ga=2.98598104.-779866669.1550427921
When the VM instance is created, you’ll run a web server on the virtual
machine. The SSH buttons in the table will open up an SSHsession to your
instance in a separate window.
For this tutorial you will connect using Cloud Shell. Cloud Shell is a built-in
command line tool for the console.
Open the Cloud Shell Open Cloud Shell by clicking the Activate Cloud Shell button in
the navigation bar in the upper-right corner of the console. Wait for the instance
creation to finish The instance creation needs to finish before the tutorial can
proceed. The activity can be tracked by clicking the notification menu from the
navigation bar at the top.
To Connect to the instance, enter the following command to SSH into the VM. If
this is your first time using SSH from Cloud Shell, you will need to create a
private key. Enter the zone and name of the instance you created.
$ gcloud compute --project \"regal-buckeye-232200" ssh --zone \<vm-zone> <vm-name>
Create a simple index.html file with the following command inside the
parenthesis and double quotes: echo Hello World index.html
9.5.3.6 Cleanup
To remove your instance, select the checkbox next to your instance name and
click the Delete button.
9.6 OPENSTACK ☁
9.6.1 Introduction
9.6.3 Components
The components in OpenStack can be divided into several sub-groups. And each
group has several components which specialize in various tasks. The following
list shows all the major component groups and components that are listed under
each group. The list is referenced from the OpenStack documentation -
OpenStack Service List
Compute
Bare Metal
IRONIC - Bare Metal Provisioning Service
CYBORG - Accelerators resource management
Storage
Networking
NEUTRON - Networking
OCTAVIA - Load balancer
DESIGNATE - DNS service
Shared Services
Orchestration
HEAT - Orchestration
SENLIN - Clustering service
MISTRAL - Workflow service
ZAQAR - Messaging Service
BLAZAR - Resource reservation service
AODH - Alarming Service
Workload Provisioning
Application Lifecycle
MASAKARI - Instances High Availability Service
MURANO - Application Catalog
SOLUM - Software Development Lifecycle Automation
FREEZER - Backup, Restore, and Disaster Recovery
API Proxies
Web Frontend
HORIZON - Dashboard
This list just includes the open stack services. Additionally, there are several
other major component groups such as Operational Services, Add-Ons to
Services and Bridges for Adjacent Tech listed in the services page at -
OpenStack Services.
Among all the service components that are available for OpenStack, there are 9
services that are considered to be Core services, these services are essential to
any OpenStack deployment.
Glance adds image services capabilities to OpenStack, this allows open stack
users to manage virtual machine images and provides services such as image
registration and discovery.
Ceilometer provides developers with billing and usage services that allow
developers to bill end users based on each individuals usage amounts. It also
records and saves usage values of the cloud for each user so that anything that
needs verification can be done.
9.6.5.1 Libcloud
9.6.5.2 DevStack
Construction
This section has some features missing and does not yet use cloudmesh v4
With all the cloud providers and cloud services that are currently available, it
becomes hard to manage and maintain services that work with several services.
Therefore it is good to have a unified service that allows developers to access
many of the cloud services through a single abstraction. Apache Libcloud is a
python library that was developed for this purpose. Apache Libcloud provides a
unified API for many of the popular cloud providers and services.
However, it is good to keep in mind that the Libcloud API might not support
some of the advanced features that are provided by some cloud services or some
of the most recent features that are yet to be integrated into Libcloud
Cloud Servers and Block Storage - services such as Amazon EC2 and
Rackspace CloudServers
Cloud Object Storage and CDN - services such as Amazon S3 and
Rackspace CloudFiles
Load Balancers as a Service - services such as Amazon Elastic Load
Balancer and GoGrid LoadBalancers
DNS as a Service - services such as Amazon Route 53 and Zerigo
Container Services - container virtualization like Docker and Rkt as well as
container based services
Backup as a Service - services such as Amazon EBS and OpenStack
Freezer
each category has a set of terms that represent various constructs and services.
For example the following list is the list of terms used in for Compute related
services, this list is extracted from the Compute docs
9.7.1.0.1 Compute
9.7.2 Installation
Libcloud can be installed via pip. Execute the following command in order to
install Libcloud
pip install apache-libcloud
The following basic example shows you how the Python Libcloud library can be
used to access information in a cloud provider
from pprint import pprint
import libcloud
cls = libcloud.get_driver(
libcloud.DriverType.COMPUTE,
libcloud.DriverType.COMPUTE.OPENSTACK)
driver = cls('username', 'api key')
pprint(driver.list_sizes())
pprint(driver.list_nodes())
Often you will need as part of your code to access cloud credentails. Theas could
be read in interactively, from environment variables, or from a configuration file.
To make things easy for now, we assume the credentials are stored in a yaml file
that is stores in ~/.cloudmesh/cloudmesh.4.yaml. An example is listed at
https://raw.githubusercontent.com/cloudmesh/cloudmesh-
configuration/master/cloudmesh/configuration/etc/cloudmesh.yaml
With the help of this yaml file it is now easy to manage credentials for multiple
clouds. We provide next a simple example on how to get the credentials for the
cloud calles aws.
from cloudmesh.common.util import path_expand
from cloudmesh.management.configuration.config import Config
name="aws"
credentials = Config()["cloudmesh"]["cloud"][name]["credentials"]
Certianly you should be encrypting this file and an extension could be developed
by you to manage the encryption and decryption for example while using your
password protected public/private keypair or other methods.
In the following section we will look into how Libcloud can be used to perform
various functions in specific cloud providers. One of the main aspects that
change between different cloud providers is how authentication is done. Because
of the unified API most of the other features are executed in the same manner.
There are two main steps that are common to all providers
After you obtain the connection, it can be used to invoke various services
o get a driver via libcloud for AWS you first have to set up the cloudmesh.yaml
file and install the convenience methods from cloudmesh as documented in
https://cloudmesh-community.github.io/cm/install.html#installation-via-
pip-development
This will provide you with a convenient config method that reads the Azure
configuration parameters from the cloudmesh.yaml file which you need to place
in ~/.cloudmesh
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from cloudmesh.common.util import path_expand
from cloudmesh.management.configuration.config import Config
from pprint import pprint
name = "azure"
# This assumes the cloudname for azure to be *azure*
pprint(credentials)
#AZURE_MANAGEMENT_CERT_PATH = path_expand('~/.cloudmesh/azure_cert.pem')
driver = get_driver(Provider.AZURE)
connection = self.driver(
credentials["EC2_ACCESS_ID"],
credentials["EC2_SECRET_KEY"],
region=credentials["region"])
pprint(connection.__dict__)
9.7.5.1.2 Azure
9.7.5.1.2.1 Azure Classic Driver
Please note that libcloud has multiple drivers to interact with Azure. The
following is an example using the classic method.
To get a driver via libcloud for azure you first have to set up the cloudmesh.yaml
file and install the convenience methods from cloudmesh as documented in
https://cloudmesh-community.github.io/cm/install.html#installation-via-
pip-development
This will provide you with a convenient config method that reads the Azure
configuration parameters from the cloudmesh.yaml file which you need to place
in ~/.cloudmesh
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from cloudmesh.common.util import path_expand
from cloudmesh.management.configuration.config import Config
from pprint import pprint
name = "azure"
# This assumes the cloudname for azure to be *azure*
pprint(credentials)
#AZURE_MANAGEMENT_CERT_PATH = path_expand('~/.cloudmesh/azure_cert.pem')
driver = get_driver(Provider.AZURE)
connection = driver(
subscription_id=credentials["AZURE_SUBSCRIPTION_ID"],
key_file=path_expand(credentials["AZURE_KEY_FILE"])
)
pprint(connection.__dict__)
https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-
group-overview
To connect to Azure you need your tenant ID and subscription ID. Using the
Azure cross platform CLI, use azure account list to get these values.
azure ad app create --name "<Your Application Display Name>" --home-page "<https://YourApplicationHomePage>" --identifier-uris
azure ad sp create "<Application_Id>"
azure role assignment create --objectId "<Object_Id>" -o Owner -c /subscriptions/{subscriptionId}/
name = "azure_arm"
# This assumes the cloudname for azure to be *azure_arm*
pprint(credentials)
driver = get_driver(Provider.AZURE_ARM)
connection = driver(
tenant_id=credentials["TENANT_ID"],
subscription_id=credentials["AZURE_SUBSCRIPTION_ID"],
key=credentials["APPLICATION_ID"],
secret=credentials["PASSWORD"]
)
pprint(connection.__dict__)
9.7.5.1.3 OpenStack
To get a driver via libcloud for OpenStack you first have to set up the
cloudmesh.yaml file and install the convenience methods from cloudmesh as
documented in
https://cloudmesh-community.github.io/cm/install.html#installation-via-
pip-development
This will provide you with a convenient config method that reads the Azure
configuration parameters from the cloudmesh.yaml file which you need to place
in ~/.cloudmesh
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from cloudmesh.common.util import path_expand
from cloudmesh.management.configuration.config import Config
from pprint import pprint
name = "chameleon"
# This assumes the cloudname for azure to be *azure*
pprint(credentials)
#AZURE_MANAGEMENT_CERT_PATH = path_expand('~/.cloudmesh/azure_cert.pem')
driver = get_driver(Provider.AZURE)
connection = self.driver(
credentials["OS_USERNAME"],
credentials["OS_PASSWORD"],
ex_force_auth_url=credentials['OS_AUTH_URL'],
ex_force_auth_version='2.0_password',
ex_tenant_name=credentials['OS_TENANT_NAME'])
pprint(connection.__dict__)
9.7.5.1.4 Google
https://libcloud.readthedocs.io/en/latest/compute/drivers/gce.html
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from cloudmesh.common.util import path_expand
from cloudmesh.management.configuration.config import Config
from pprint import pprint
pprint(credentials)
driver = get_driver(Provider.GCE)
# Datacenter is set to 'us-central1-a' as an example, but can be set to any
# zone, like 'us-central1-b' or 'europe-west1-a'
connection = driver(
credentials['SERVICE_ACCOUNT_EMAIL'],
credentials['PATH_TO_PEM_FILE'],
datacenter=credentials['DATA_CENTER'],
project=credentials['PROJECT_ID'])
pprint(connection.__dict__)
In this section we will look into how we can use the connection created as
previously instructed to perform various services such as creating nodes, listing
nodes, starting nodes and stopping nodes.
In this section we will look at the code that can be used to create a node in the
provider a node which represents a virtual server
...
# retrieve available images and sizes
images = conn.list_images()
sizes = conn.list_sizes()
In this section we will look at the code that can be used to list the nodes that
have been created in the provider
...
nodes = connection.list_nodes()
print (nodes)
After the node (Virtual server) has been created the following code can be used
to start the node
...
nodes = connection.list_nodes()
node = [n for n in nodes if 'yourservername' in n.name][0]
connection.ex_start(node=node)
When needed the following command can be used to stop a node that has been
started
...
nodes = connection.list_nodes()
node = [n for n in nodes if 'yourservername' in n.name][0]
connection.ex_stop(node=node)
9.7.6 Cloudmesh Community Program to Manage Clouds
As you have noticed since the authentication can change from cloud services to
cloud service it would be much easier to use a simple python script to
automatically handle the differences in the code.
We have provided such a python script which you can leverage to manage
different cloud providers. You can find the python script and the corresponding
.yaml file in the cloudmesh-community github repository.
When using the script and yaml file please keep in mind the following steps to
make sure you do not share your private keys and passwords on your publicly
accessible Github account.
1. Create a folder in your computer that is not within a git clone that you have
made. For example maybe you can use a new directory on your desktop
2. Copy the cm.py and cloudmesh.yaml files into this folder. Just to make sure you
are not working with the files under the git repo you should delete the
cloudmesh.yaml file in that is in your local git repo.
3. change the needed fields in the yaml file and use the python script to access
the cloud services using libcloud.
To illustrate how simple the program is and that it significantly improves your
management of credentials we provide the follwoing code:
cm = cloudmesh()
cm.config()
driver = cm.get_driver("aws")
print("driver=", driver)
To switch to a different cloud, you just have to create it in the yaml file and use
that name.
We intent to host the code sometime soon on pypi so you can issue the command
$ pip install cm-community
No
Next we explain how to use Amazon Web Services (AWS) S3 via libcloud.
Apache libcloud is a python library that provides abstraction layer and hides the
complexities of directly integrating with AWS API’s, for that matter it allows
you to do so for different cloud providers. In the next sections more detailed
steps are shown to install and use libcloud for AWS S3.
In S3 you first need to create a bucket which is nothing but a container where
you store your data in the form of files. This is where you can also define access
controls.
Click on S3 link on the AWS console under storage section, this will bring
you to the create bucket window.
Click on “Create Bucket” button, this opens up a wizard.
Answer all mandatory questions on each page.
Important point here is to note the “Bucket Name” and the “Region” you
are creating this bucket in, as this information will be used while calling the
API.
List Containers function list all the containers of buckets available for the user in
that particular region.
cls = get_driver(Provider.S3_US_EAST2)
driver = cls('api key', 'api secret key')
d = driver.list_containers()
print (d)
List container objects function shows the list of all objects in that container.
Please note the output could be large depending on the files present in the
bucket.
cls = get_driver(Provider.S3_US_EAST2)
driver = cls('api key', 'api secret key')
container = driver.get_container(
container_name='<bucket name>')
d = driver.list_container_objects(container)
print(d)
cls = get_driver(Provider.S3_US_EAST2)
driver = cls('api key', 'api secret key')
container = driver.get_container(
container_name='<bucket name>')
extra = {
'meta_data': {
'owner': '<owner name>',
'created': '2018-03-24'
}
}
9.7.7.6 References
https://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html
storage driver
http://libcloud.readthedocs.io/en/latest/_modules/libcloud/storage/drivers/s3.html
Examples:
https://libcloud.readthedocs.io/en/latest/storage/examples.html
API docs
http://libcloud.apache.org/apidocs/0.6.1/libcloud.storage.base.StorageDriver.html
Construction
This section has some features missing and does not yet use cloudmesh v4
Boto is a software development kit (SDK) that provides AWS interface for
Python applications. It enables to write applications in Python that make use of
Amazon Web Services.
Boto supports different AWS services such as, Elastic Compute Cloud (EC2),
DynamoDB, AWS Config, CloudWatch and Simple Storage Service (S3).
https://github.com/boto/boto3
http://aws.amazon.com/sdk-for-python
Before you install it we suggest that you either use pyenv or venv.
$ python setup.py install
An initial setup is required to be able to access AWS EC2 from BOTO wherein
you provide the key and region details. You can find the key details from IAM
console on AWS.
BOTO can be configured in two ways, either by using the aws configure
command if you have AWS Command line interface installed or simply by
manually creating and editing the ~/.aws/credentials file to include important
parameters highlighted next.
[default]
aws_access_key_id = <YOUR_ACCESS_KEY>
aws_secret_access_key = <YOUR_SECRET_KEY>
Similar to libcloud, BOTO also requires the region where you would create your
EC2 instance, the same can be maintained by creating a config file.
$ emacs .aws/config
[default]
region=<region name> # for example us-east
The code to list the running instances (if you have some) is very simple:
import boto3
ec2 = boto3.client('ec2')
response = ec2.describe_instances()
print(response)
Instance type specifies the storage and type of platform. Secutity groups are
required to provide access rights such as access to SSH into the instance.
function.
connection.terminate_instances(instance_ids=['<id1>','<id2>', ..])
The next example showcases how to reboot an instance, which is copied from
http://boto3.readthedocs.io/en/latest/guide/ec2-example-managing-
instances.html
# Code copied form
# http://boto3.readthedocs.io/en/latest/guide/ec2-example-managing-instances.html
import boto3
from botocore.exceptions import ClientError
ec2 = boto3.client('ec2')
try:
ec2.reboot_instances(InstanceIds=['INSTANCE_ID'], DryRun=True)
except ClientError as e:
if 'DryRunOperation' not in str(e):
print("You don't have permission to reboot instances.")
raise
try:
response = ec2.reboot_instances(InstanceIds=['INSTANCE_ID'], DryRun=False)
print('Success', response)
except ClientError as e:
print('Error', e)
Create a connection
connection = boto.connect_s3('<access-key>','<secret-key>')
Bucket name has to be unique name accross all the AWS regions and hence
globally unique.
bucket = conn.create_bucket('<bucket_name>')
If bucket name is unique, a new bucket of specified name will get created. If
bucket name is not unique, application will throw error as
boto.exception.S3CreateError: S3Error[409]: Conflict
To upload a file in the S3 bucket, first create a key object from new_key()
function of bucket.
key = bucket.new_key('hello2.txt')
key.set_contents_from_string('Hello World!')
This will create hello.txt file with content Hello World! in the text file. This file
can be found inside the bucket in which new key is created.
One account can have maximum 100 buckets in which data objects can be
stored.
result = connection.get_all_buckets()
The get_all_buckets function of S3Connection lists all the buckets within account. It
returns ResultSet object which has list of all buckets.
To delete any data object from bucket, delete_key function of bucket is used.
k = Key(<bucket-name>, <file-name>)
k.delete()
To delete a bucket, provide a bucket name and call the delete_bucket function of
S3Connection object.
connection.delete_bucket('<bucket-name>')
9.8.9 References
https://github.com/boto/boto3
https://boto3.readthedocs.io/en/latest/guide/quickstart.html#installation
http://boto3.readthedocs.io/en/latest/guide/ec2-example-managing-
instances.html
9.8.10 Excersises
E.boto.cloudmesh.1:
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/ec2-
example-managing-instances.html.
https://github.com/cloudmesh-community/cm
instance_id = sys.argv[2]
action = sys.argv[1].upper()
ec2 = boto3.client('ec2')
if action == 'ON':
# Do a dryrun first to verify permissions
try:
ec2.start_instances(InstanceIds=[instance_id], DryRun=True)
except ClientError as e:
if 'DryRunOperation' not in str(e):
raise
# Dry run succeeded, run start_instances without dryrun
try:
response = ec2.start_instances(InstanceIds=[instance_id], DryRun=False)
print(response)
except ClientError as e:
print(e)
else:
# Do a dryrun first to verify permissions
try:
ec2.stop_instances(InstanceIds=[instance_id], DryRun=True)
except ClientError as e:
if 'DryRunOperation' not in str(e):
raise
# Dry run succeeded, call stop_instances without dryrun
try:
response = ec2.stop_instances(InstanceIds=[instance_id], DryRun=False)
print(response)
except ClientError as e:
print(e)
E.boto.cloudmesh.2:
E.boto.cloudmesh.3:
We start out our section with a review of the python lambda expression as well
as the map function. Understanding these concepts is helpful for our overall
understanding of map reduce.
So before you watch the video, we encourage you to learn Sections {#s-python-
lambda} and {#s-python-map}.
Now that you have a basic understanding of the map function we recommend to
watch our videos about mapreduce, hadoop and spark which we provide within
this chapter.
1. Map: This method processes the very initial data set. Generally, the data is
in file format which can be stored in HDFS (Hadoop File System). Map
function reads the data line by line and creates several chunks of data and
that is again stored in HDFS. This broken set of data is in key/value pairs.
So in multi-threaded environment, there will be many worker nodes
operating on the data using this map() function and write this intermediate
data in form of key/value to temporary data storage.
2. Shuffle: In this stage, worker nodes will shuffle or redistribute the data in
such a way that there is only one copy for each key.
3. Reduce: This function always comes at last and it works on the data
produced by map and shuffle stages and produces even smaller chunk of
data which is used to calculate output.
The Shuffle operation is very important here as that is mainly responsible for
reducing the communication cost. The main advantage of using MapReduce
algorithm is that it becomes very easy to scale up data processing just by adding
some extra computing nodes. Building up map and reduce methods are
sometimes nontrivial but once done, scaling up the applications is so easy that it
is just a matter of changing configuration. Scalability is really big advantage of
MapReduce model. In the traditional way of data processing, data was moved
from nodes to the master and then the processing happens in master machine. In
this approach, we lose bandwidth and time on moving data to master and parallel
operation cannot happen. Also master can get over-burdened and fail. In
MapReduce approach, Master node distributes the data to the worker machines
which are in themselves a processing unit. So all worker process the data in
parallel and the time taken to process the data is reduced tremendously. (see
Figure 89)
Figure 89: MapReduce Master worker diagram
1. First we divide the input into four parts so that individual nodes can handle
the load.
2. We tokenize each word and assign weightage of value “1” to each word.
3. This way we will have a list of key-value pairs with key being the word and
value as 1.
4. After this mapping phase, shuffling phase starts where all maps with same
key are sent corresponding reducer.
5. Now each reducer will have a unique key and a list of values for each key
which in this case is all 1s.
6. After that, each reducer will count the total number of 1s and assigns final
count to each word.
7. The final output is then written to a file. (see Figure 90)
Figure 90: MapReduce WordCount [68]
Let us see an example of map() and reduce() methods in code for this word
count example.
public static class Map extends Mapper<LongWritable,
Text,
Text,
IntWritable> {
Here we have created a class Map which extends Mapper from MapReduce
framework and we override map() method to declare the key/value pairs. Next,
there will be a reduce method defined inside Reduce class as next and both input
and output here is a key/value pairs:
public static class Reduce extends Reducer<Text,
IntWritable,
Text,IntWritable> {
int sum=0;
for(IntWritable x: values) {
sum+=x.get();
}
context.write(key, new IntWritable(sum));
}
}
There are many big data frameworks available and there is always a question as
to which one is the right one. Leading frameworks are Hadoop MapReduce and
Apache Spark and choice depends on business needs. Let us start comparing
both of these frameworks with respect to their processing capability.
Hadoop MapReduce reads and writes on disk because of this it is a slow system
and that affects the volume of data been processed. But Hadoop is a scalable and
fault tolerant, it us good for linear processing.
10.1.3 References
[70] https://www.ibm.com/analytics/hadoop/mapreduce
[71] https://en.wikipedia.org/wiki/MapReduce
[72] https://www.tutorialspoint.com/hadoop/hadoop_mapreduce.htm
[68] https://www.edureka.co/blog/mapreduce-tutorial/?
utm_source=youtube&utm_campaign=mapreduce-tutorial-161216-
wr&utm_medium=description
[73] https://www.quora.com/What-is-the-difference-between-Hadoop-and-
Spark
[74] https://data-flair.training/blogs/apache-spark-vs-hadoop-mapreduce
[69] https://www.youtube.com/watch?
v=SqvAaB3vK8U&list=WL&index=25&t=2547s
10.2 HADOOP
10.2.1 Hadoop ☁
Hadoop is an open source framework for storage and processing of large datasets
on commodity clusters. Hadoop internally uses its own file system called HDFS
(Hadoop Distributed File System).
In this section we discuss about the Hadoop EcoSystem and the architecture.
In this section we discuss about Yarn resource manager and novel components
added to the Hadoop framework in case of improving the performance and
minimizing fault tolerance.
10.2.1.5 PageRank
In this section we discuss about a real world problem that can be solved using
the MapReduce technique. PageRank is a problem solved by the earliest stages
of the Google.inc. In this section we discuss about the theoretical background
about this problem and we discuss how this can be solved using the map reduce
concepts.
This section is using Hadoop version 3.1.1 in Ubuntu 18.04. We also describe
the installation of the Yarn resource manager. We assume that you have ssh, and
rsync installed and use emacs as editor.
If you use a newer version, and like to update this text please help
10.2.2.1 Releases
https://hadoop.apache.org/releases.html
and verify that you use an up to dat version.If the verison of this instalation is
outdated. we ask you as excrsise to update it.
10.2.2.2 Prerequisites
sudo apt-get install ssh
sudo apt-get install rsync
sudo apt-get install emacs
For security reasons we will install hadoop in a particular user and user group.
We will use the following
sudo addgroup hadoop_group
sudo adduser --ingroup hadoop_group hduser
sudo adduser hduser sudo
These steps will provide sudo privileges to the created hduser user and add the
user to the group hadoop_group.
Here we configure SSH key for the local user to install hadoop with a ssh-key.
This is different from the ssh-key you used for Github, FutureSystems, etc.
Follow this section to configure it for Hadoop installation.
The ssh content is included here because, we are making a ssh key for this
specific user. Next, we have to configure ssh to be used by the hadoop user.
sudo su - hduser
ssh-keygen -t rsa
Follow the instructions as provided in the commandline. When you see the
following console input, press ENTER. Here only we will create password less
keys. IN general this is not a good idea, but for this case we make an exception.
Enter file in which to save the key (/home/hduser/.ssh/id_rsa):
Finally you will see something like this after these steps are finished.
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hduser/.ssh/id_rsa):
Created directory '/home/hduser/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/hduser/.ssh/id_rsa.
Your public key has been saved in /home/hduser/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:0UBCPd6oYp7MEzCpOhMhNiJyQo6PaPCDuOT48xUDDc0 hduser@computer
The key's randomart image is:
+---[RSA 2048]----+
| .+ooo |
| . oE.oo |
|+ .. ...+. |
|X+= . o.. |
|XX.o o.S |
|Bo+ + .o |
|*o * +. |
|*.. *. |
| +.o.. |
+----[SHA256]-----+
If you are already logged into su, you can skip the next command:
su - hduser
Please note that users must accept Oracle OTN license before downloading JDK.
In Ubuntu the environmental variables are setup in a file called bashrc at it can
be accessed the following way
emacs ~/.bashrc
In Emacs to save the file Ctrl-X-S and Ctrl-X-C to exit. After editing you must update
the variables in the system.
source ~/.bashrc
java -version
If you have installed things properly there will be no errors. It will show the
version as follows,
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
If you have successfully installed this, there must be a message shown as next.
Usage: hadoop [--config confdir] COMMAND
where COMMAND is one of:
fs run a generic filesystem user client
version print the version
jar <jar> run a jar file
checknative [-a|-h] check native hadoop and compression libraries availability
distcp <srcurl> <desturl> copy file or directories recursively
archive -archiveName NAME -p <parent path> <src>* <dest> create a hadoop archive
classpath prints the class path needed to get the
credential interact with credential providers
Hadoop jar and the required libraries
daemonlog get/set the log level for each daemon
trace view and modify Hadoop tracing settings
or
CLASSNAME run the class named CLASSNAME
10.2.3.1 Introduction
10.2.3.2 Features
Detect Hardware Failure Hardware failure is the norm rather than the
exception. An HDFS instance may consist of hundreds or thousands of
server machines, each storing part of the file system’s data. Detection of
faults and quick, automatic recovery from them is a core architectural goal
of HDFS.
Support Large Data Sets Applications that run on HDFS have large data
sets. A typical file in HDFS is gigabytes to terabytes in size. Thus, HDFS is
tuned to support large files. It should provide high aggregate data
bandwidth and scale to hundreds of nodes in a single cluster. It should
support tens of millions of files in a single instance.
Internally, a file is split into one or more blocks and these blocks are stored in a
set of DataNodes. The NameNode executes file system namespace operations
like opening, closing, and renaming files and directories. It also determines the
mapping of blocks to DataNodes. The DataNodes are responsible for serving
read and write requests from the file system’s clients. The DataNodes also
perform block creation, deletion, and replication upon instruction from the
NameNode.
10.2.3.4 Usage
10.2.3.4.2 FS Shell
HDFS allows user data to be organized in the form of files and directories. It
provides a commandline interface called FS shell that lets a user interact with the
data in HDFS. The syntax of this command set is similar to other shells
(e.g. bash, csh) that users are already familiar with. Here are some sample
action/command pairs:
bin/hadoop dfs -mkdir /foodir
10.2.3.5 References
10.2.3.6 Exercises
Hadoop Installation on your own Laptop/Desktop
Hadoop MapReduce programming in Python
Hadoop Installation on a cluster (at least two nodes in the cluster)
Run MapReduce in a cluster
10.2.4.1 Introduction
Apache HBase is the Hadoop database, a distributed, scalable, big data store.
Use Apache HBase when you need random, realtime read/write access to your
Big Data. This project’s goal is the hosting of very large tables – billions of rows
X millions of columns – atop clusters of commodity hardware. Apache HBase is
an open-source, distributed, versioned, non-relational database modeled after
Google’s Bigtable: A Distributed Storage System for Structured Data by Chang
et al. Just as Bigtable leverages the distributed data storage provided by the
Google File System, Apache HBase provides Bigtable-like capabilities on top of
Hadoop and HDFS.
10.2.4.2 Features
WARNING: Setting this to false blinds you to potential data loss and
inconsistent system state in the event of process and/or node failures. If
HBase is complaining of an inability to use hsync or hflush it's most
likely not a false positive.
</description>
</property>
</configuration>
10.2.4.4 Usage
Connect to your running instance of HBase using the hbase shell command,
located in the bin/ directory of your HBase install. In this example, some usage
and version information that is printed when you start HBase Shell has been
omitted. The HBase Shell prompt ends with a > character.
$ ./bin/hbase shell
hbase(main):001:0>
describe 'test'
Table test is ENABLED
test
COLUMN FAMILIES DESCRIPTION
{NAME => 'cf', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS =>
'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW'
alse', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE =
=> '65536'}
1 row(s)
Took 0.9998 seconds
10.2.4.4.4 HBase MapReduce job
This example will simply copy data from one table to another.
Configuration config = HBaseConfiguration.create();
Job job = new Job(config,"ExampleReadWrite");
job.setJarByClass(MyReadWriteJob.class); // class that contains mapper
TableMapReduceUtil.initTableMapperJob(
sourceTable, // input table
scan, // Scan instance to control CF and attribute selection
MyMapper.class, // mapper class
null, // mapper output key
null, // mapper output value
job);
TableMapReduceUtil.initTableReducerJob(
targetTable, // output table
null, // reducer class
job);
job.setNumReduceTasks(0);
boolean b = job.waitForCompletion(true);
if (!b) {
throw new IOException("error with job!");
}
10.2.4.5 References
No
This lesson is created and test under the newest version of Cloudmesh client.
Update yours if not.
To manage virtual cluster on cloud, the command is cm cluster. Try cm cluster help to
see what other commands are and what options they supported.
All options will use the default setting if not specified during cluster
define. Try cm cluster help command to see what options cm cluster define has and
means, here is part of the usage information: :
$ cm cluster help
Options:
-A --no-activate Do not activate this cluster
-I --no-floating-ip Do not assign floating IPs
-n NAME --name=NAME Name of the cluster
-c COUNT --count=COUNT Number of nodes in the cluster
-C NAME --cloud=NAME Name of the cloud
-u NAME --username=NAME Name of the image login user
-i NAME --image=NAME Name of the image
-f NAME --flavor=NAME Name of the flavor
-k NAME --key=NAME Name of the key
-s NAME --secgroup=NAME NAME of the security group
-o PATH --path=PATH Output to this path ...
Cluster creation will fail if the floating IPs run out on cloud. When you run into
error like this, use option -I or --no-floating-ip to avoid assigning floating IPs during
cluster creation:
$ cm cluster define --count 3 --no-floating-ip
Then manually assign floating IP to one of the nodes. Use this node
as a logging node or head node to log in to all the other nodes.
We can have multiple specifications defined at the same time. Every time a new
cluster specification is defined, the counter of the default cluster name will
increment. Hence, the default cluster name will be cluster-001, cluster-002, cluster-003 and
so on. Use cm cluster avail to check all the available cluster specifications:
$ cm cluster avail
cluster-001
count : 3
image : CC-Ubuntu14.04
key : xl41
flavor : m1.small
secgroup : default
assignFloatingIP : True
cloud : chameleon
> cluster-002
count : 3
image : CC-Ubuntu14.04
key : xl41
flavor : m1.small
secgroup : default
assignFloatingIP : False
cloud : chameleon
With cm cluster use [NAME], we are able to switch between different specifications with
given cluster name:
$ cm cluster use cluster-001
$ cm cluster avail
> cluster-001
count : 3
image : CC-Ubuntu14.04
key : xl41
flavor : m1.small
secgroup : default
assignFloatingIP : True
cloud : chameleon
cluster-002
count : 3
image : CC-Ubuntu14.04
key : xl41
flavor : m1.small
secgroup : default
assignFloatingIP : False
cloud : chameleon
This will activate specification cluster-001 which assigns floating IP during creation
rather than the latest one cluster-002.
With our cluster specification ready, we create the cluster with command cm cluster
allocate. This will create a virtual cluster on the cloud with the activated
specification:
$ cm cluster allocate
Each specification can have one active cluster, which means cm cluster allocate does
nothing if there is a successfully active cluster.
we just created:
$ cm cluster list
cluster-001
Using cm cluster nodes [NAME], we can also see the nodes of the cluster along with their
assigned floating IPs of the cluster:
$ cm cluster nodes cluster-001
xl41-001 129.114.33.147
xl41-002 129.114.33.148
xl41-003 129.114.33.149
If option --no-floating-ip is included during definition, you will see nodes without
floating IP:
$ cm cluster nodes cluster-002
xl41-004 None
xl41-005 None
xl41-006 None
Then you can log in this node as a head node of your cluster by cm vm ssh [NAME]:
$ cm vm ssh xl41-006
cc@xl41-006 $
Using cm cluster delete [NAME], we are able to delete the cluster we created:
$ cm cluster delete cluster-001
Then we need to undefine our cluster specification with command cm cluster undefine
:
[NAME]
This section is built upon the previous one. Please finish the previous one before
start this one.
To create a Hadoop cluster, we need to first define a cluster with cm cluster define
command:
$ cm cluster define --count 3
on Chameleon. DO NOT use CC-Ubuntu16.04 or any other images. You will need
to specify it if it’s not the default image:
Then we define the Hadoop cluster upon the cluster we defined using cm hadoop define
command:
$ cm hadoop define
Same as cm cluster define, you can define multiple specifications for the Hadoop
cluster and check them with cm hadoop avail:
$ cm hadoop avail
> stack-001
local_path : /Users/tony/.cloudmesh/stacks/stack-001
addons : []
We can use cm hadoop use [NAME] to activate the specification with the given name:
$ cm hadoop use stack-001
May not be available for current version of Cloudmesh Client.
Before deploy, we need to use cm hadoop sync to checkout / synchronize the Big Data
Stack from Github.com:
$ cm hadoop sync
To avoid errors, make sure you are able to connect to Github.com using SSH:
https://help.github.com/articles/connecting-to-github-with-ssh/.
To check Hadoop is working or not. Use cm vm ssh to log into the Namenode of the
Hadoop cluster. It’s usually the first node of the cluster:
$ cm vm ssh node-001
cc@hostname$
To delete the Hadoop cluster we created, use command cm cluster delete [NAME] to
delete the cluster with given name:
$ cm cluster delete cluster-001
To install Spark and/or Pig with Hadoop cluster, we first use command cm hadoop
For example, we create a 3-node Spark cluster with Pig. To do that, all we need
is to specify spark as an ADDON during Hadoop definition:
$ cm cluster define --count 3
$ cm hadoop define spark pig
Using cm hadoop addons, we are able to check the current supported addon:
$ cm hadoop addons
With cm hadoop avail, we can see the detail of the specification for the Hadoop cluster:
$ cm hadoop avail
> stack-001
local_path : /Users/tony/.cloudmesh/stacks/stack-001
addons : [u'spark', u'pig']
Then we use cm hadoop sync and cm hadoop deploy to deploy our Spark cluster:
$ cm hadoop sync
$ cm hadoop deploy
Before we proceed to the next step, there is one more thing we need to, which is
to make sure we are able to ssh from every node to others without password. To
achieve that, we need to execute cm cluster cross_ssh:
$ cm cluster cross_ssh
Now with the cluster ready, let’s run a simple Spark job, Word Count, on one of
William Shakespeare’s work. Use cm vm ssh to log into the Namenode of the Spark
cluster. It should be the first node of the cluster:
$ cm vm ssh node-001
cc@hostname$
Switch to user hadoop and check HDFS is set up or not:
cc@hostname$ sudo su - hadoop
hadoop@hostname$
You can also use any other text file you preferred. Create a new directory wordcount
within HDFS to store the input and output:
$ hdfs dfs -mkdir /wordcount
Save the following code as wordcount.py on the local file system on Namenode:
import sys
if __name__ == "__main__":
10.3 SPARK
10.3.1 Spark Lectures ☁
This section covers an introduction to Spark that is split up into eight parts. We
discuss Spark background, RDD operations, Shark, Spark ML, Spark vs Other
Frameworks.
In this section we discuss about the background of Spark and core components
of Spark.
In this section we discuss about the background of RDD operations along with
other transformation functionality in Spark.
In this section we discuss about the background of DAG (direct acyclic graphs)
operations along with other components like Shark in the earlier stages of Spark.
Spark 10:37 Spark C
In this section we discuss about the real world applications that can be done
using Spark. And also we discuss some comparision results obtained from
experiments done in Spark along with Frameworks like Harp, Harp DAAL, etc.
We discuss the benchmarks and performance obtained from such experiments.
In this section we will discuss how to install Spark 2.3.2 in Ubuntu 18.04.
10.3.2.1 Prerequisites
We assume that you have ssh, and rsync installed and use emacs as editor.
sudo apt-get install ssh
sudo apt-get install rsync
sudo apt-get install emacs
export JAVA_HOME=~/cloudmesh/bin/jdk1.8.0_161
export PATH=$JAVA_HOME/bin:$PATH
Here we use Spark packaged with Hadoop. In this package Spark uses Hadoop
2.7.0 in the packaged version. Note that in Section Hadoop Installation we use
for the vanilla Hadoop installation Hadoop 3.0.1.
Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_151)
Type in expressions to have them evaluated.
Type :help for more information.
Please check the console LOGS and find the port number on which the Spark
Web UI is hosted. It will show something like:
If you see the Spark Dashboard, then you can realize you have installed Spark
successfully.
If you have already installed Spark with Hadoop by following section 1.3 please
update the current SPARK HOME variable with the new path.
emacs ~/.bashrc
Go to the last line and add the following content.
export SPARK_HOME=~/cloudmesh/bin/spark-2.3.2-bin-without-hadoop
export PATH=$SPARK_HOME/bin:$PATH
Now we must add the current Hadoop version that we are using for Spark. Open
up a new terminal and then run the following.
cd $SPARK_HOME
cd conf
cp spark-env.sh.template spark-evn.sh
Now we need to add a new line to show the current path to hadoop installation.
Add the following variable in to the spark-env.sh file.
emacs spark-env.sh
export SPARK_DIST_CLASSPATH=$($HADOOP_HOME/bin/hadoop classpath)
Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_151)
Type in expressions to have them evaluated.
Type :help for more information.
Please check the console LOGS and find the port number on which the Spark
Web UI is hosted. It will show something like: Spark context Web UI available
at the logs folder
Spark Streaming is one of the components extending from Core Spark. Spark
streaming provides a scalable fault tolerant system with high throughput. For
streaming data into spark, there are many libraries like Kafka, Flume, Kinesis,
etc.
Please add a tab when adding the corresponding command for a given
instruction in Makefile. In pdf mode the tab is not clearly shown.
SPARKHOME = ${SPARK_HOME}
run-streaming:
${SPARKHOME}/bin/spark-submit streaming.py localhost 9999
# Create a local StreamingContext with two working thread and batch interval of 1 second
sc = SparkContext("local[2]", "NetworkWordCount")
log4jLogger = sc._jvm.org.apache.log4j
LOGGER = log4jLogger.LogManager.getLogger(__name__)
LOGGER.info("Pyspark script logger initialized")
ssc = StreamingContext(sc, 1)
# Print the first ten elements of each RDD generated in this DStream to the console
wordCounts.pprint()
ssc.start() # Start the computation
ssc.awaitTermination(100) # Wait for the computation to terminate
Terminal 2 :
In this terminal you can see an script running trying to read the stream coming
from the port 9999. You can enter texts in the Terminal 1 and these texts will be
tokenized and the word count is calculated and the result is shown in the
Terminal 2.
In this section we are going to learn how to use Twitter data as the streaming
data source and use Spark Streaming capabilities to process the data. As the first
step you must install the python packages using pip.
10.3.3.3.1 Step 1
10.3.3.3.2 Step 2
Then you need to create an account in Twitter Apps. Go to and sign in to your
twitter account or create a new twitter account. Then you need to create a new
application, let’s name this application as Cloudmesh-Spark-Streaming.
First you need to create an app with the app name we suggested in this section.
The way to create the app is mentioned in +Figure 93.
Next we need to to take a look at the dashboard created for the app. You can see
how your dashboard looks like in +Figure 94.
Figure 94: Go To Twitter App Dashboard
Next the application tokens generated must be reviewed and it can be found in
+Figure 95, you need to go to the Keys and Access Tokens tab.
Figure 95: Create Your Twitter Settings
Now you need to generate the access tokens for the first time if you have not
generated access tokens and this can be done by clicking the Create my access token
button. See +Figure 96
Figure 96: Create Your Twitter Access Tokens
The access tokens and keys are blurred in this section for privacy issues.
10.3.3.3.3 Step 3
Add the following content to the file and make sure you update the
corresponding token keys with your token values.
import tweepy
CONSUMER_KEY = 'your_consumer_key'
CONSUMER_SECRET = 'your_consumer_secret'
ACCESS_TOKEN = 'your_access_token'
ACCESS_TOKEN_SECRET = 'your_access_token_secret'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)
status = "Testing!"
api.update_status(status=status)
python twitterstreaming.py
10.3.3.3.4 Step 4
Let us start the twitter streaming exercise. We need to create a Tweet Listener in
order to retrieve data from twitter regarding a topic of your choice. In this
exercise, we have tried keywords like trump, indiana, messi.
mkdir -p ~/cloudmesh/spark/streaming
cd ~/cloudmesh/spark/streaming
emacs tweetlistener.py
Make your to replace strings related to secret keys and ip addresses by replacing
these values depending on your machine configuration and twitter keys.
CONSUMER_KEY = 'YOUR_CONSUMER_KEY'
CONSUMER_SECRET = 'YOUR_CONSUMER_SECRET'
ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN'
ACCESS_SECRET = 'YOUR_SECRET_ACCESS'
class TweetListener(StreamListener):
def sendData(c_socket):
auth = OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
if __name__ == "__main__":
s = socket.socket()
host = "YOUR_MACHINE_IP"
port = 5555
s.bind((host, port))
s.listen(5)
c, addr = s.accept()
sendData( c )
10.3.3.3.5 step 5
Please replace the local file paths mentioned in this code with a file path of your
preference depending on your workstation. And also IP address must be replaced
with your ip address. The log folder path must be pre-created and make sure to
replace the registerTempTable name with respect to the entity that you are referring.
This will minimize the conflicts among different topics when you need to plot it
in a simple manner.
Open up a terminal,
cd ~/cloudmesh/spark/streaming
jupyter notebook
Then in the browser the jupyter notebook is being loaded. There create a new
IPython notebook called twittersparkstremer.
sc = SparkContext('local[2]','twittersparkstreamer')
ssc = StreamingContext(sc, 10 )
sqlContext = SQLContext(sc)
ssc.checkpoint( "file:///home/<your-username>/cloudmesh/spark/streaming/logs/messi")
lines = socket_stream.window( 20 )
sqlContext
<pyspark.sql.context.SQLContext at 0x7f51922ba350>
ssc.start()
import time
from IPython import display
count = 0
while count < 10:
time.sleep( 20 )
top_10_tweets = sqlContext.sql( 'Select tag, count from tweetsmessi' ) #change table name according to your entity
top_10_df = top_10_tweets.toPandas()
display.clear_output(wait=True)
#sn.figure( figsize = ( 10, 8 ) )
sn.barplot( x="count", y="tag", data=top_10_df)
plt.show()
count = count + 1
ssc.stop()
10.3.3.3.6 step 6
Open Terminal 2
Now we must start the Spark app by running the content in the IPython
Notebook by pressing SHIFT-ENTER in each box to run each command. Make sure not
to run twice the starting command of the SparkContext or initialization of
SparkContext.
Now you will see streams in the Terminal 1 and you can see plots after a while in the
IPython Notebook.
Sample outputs can be seen in +Figure 97, +Figure 98, +Figure 99, +Figure 100.
Figure 97: Twitter Topic Messi
User-defined functions (UDFs) are the functions created by developers when the
built-in functionalities offered in a programming language, are not sufficient to
do the required work. Similarly, Apache Spark UDFs also allow developers to
enable new functions in higher level programming languages by extending built-
in functionalities. It also allows developers to experiment with wide range of
options for integrating UDFs with Spark SQL, MLib and GraphX workflows.
How to run the provided example using a provided docker file and make file.
10.3.4.1 Resources
https://spark.apache.org/
http://www.scala-lang.org/
https://docs.databricks.com/spark/latest/spark-sql/udf-in-python.html
10.3.4.2.1 Linux
http://www.oracle.com/technetwork/java/javase/downloads/index.html
Second, setup environment variables for JDK by adding bin folder path to to
user path variable.
This $ export PATH = $PATH:/usr/local/java8/bin
http://www.scala-lang.org/download/
Then, setup environment variables for Scala by adding bin folder path to the user
path variable.
$ export PATH = $PATH:/usr/local/scala/bin
https://spark.apache.org/downloads.html
Then, setup environment variables for spark by adding bin folder path to the user
path variable.
$ export PATH = $PATH:/usr/local/spark/bin
Finally, for testing the installation, please type the following command.
spark-shell
10.3.4.3 Windows
First, JDK should be installed to a path where there is no space in that path.
Recommended JAVA version is 8.
http://www.oracle.com/technetwork/java/javase/downloads/index.html
Second, setup environment variables for jdk by adding bin folder path to to user
path variable.
set JAVA_HOME=c:\java8
set PATH=%JAVA_HOME%\bin;%PATH%
https://spark.apache.org/downloads.html
Then, setup environment varibale for spark by adding bin folder path to the user
path variable.
set SPARK_HOME=c:\spark
set PATH=%SPARK_HOME%\bin;%PATH%
https://github.com/steveloughran/winutils
Then, change the winutils.exe permission using following command using CMD
with administrator permission.
$ winutils.exe chmod -R 777 C:\tmp\hive
If your system doesnt have hive folder, make sure to create C:\tmp\hive directory.
Next, setup environment variables for hadoop by adding bin folder path to the
user path variable.
set HADOOP_HOME=c:\hadoop\bin
set PATH=%HADOOP_HOME%\bin;%PATH%
Then, install Python 3.6 with anaconda (This is a bundled python installer for
pyspark).
https://anaconda.org/anaconda/python
Finally, for testing the installation, please type the following command.
$ pyspark
10.3.4.4 MacOS
First, JDK should be installed to a path where there is no space in that path.
Recommanded JAVA version is 8.
http://www.oracle.com/technetwork/java/javase/downloads/index.html
Second, setup environment variables for jdk by addding bin folder path to to user
path variable.
$ export JAVA_HOME=$(/usr/libexec/java_home)
Next, install Python 3.6 with anaconda (This is a bundled python installer for
pyspark)
https://anaconda.org/anaconda/python
Finally, for testing the installation, please type the following command.
$ pyspark
10.3.4.5 Instructions for creating Spark User Defined Functions
We will only consider wheather station ID (column 0), entrytype (column 2),
temperature (column 3: it is in 10*Celsius)
First, we need to import the relevent libraries to use Spark sql built in
functionalities listed as follows.
from pyspark.sql import SparkSession
from pyspark.sql import Row
Then, we need create a user defined fuction which will read the text input and
process the data and return a spark sql Row object. It can be created as listed as
follows.
def process_data(line):
fields = line.split(',')
stationID = fields[0]
entryType = fields[2]
temperature = float(fields[3]) * 0.1 * (9.0 / 5.0) + 32.0
return Row(ID=stationID, t_type=entryType, temp=temperature)
Next, we read the raw data using spark build-in function textFile() as shown
next.
lines = spark.sparkContext.textFile("temperature_data.csv")
Alternatively we colud have written the UDF using a python lamda function to
do the same thing as shown next.
parsedLines = lines.map(lambda line: Row(ID=line.split(',')[0],
t_type=line.split(',')[2],
temp=float(line.split(',')[3]) * 0.1 * (9.0
/ 5.0) + 32.0))
Now, we can convert our RDD object to a Spark SQL Dataframe as listed as
follows.
TempDataset = spark.createDataFrame(parsedLines)
Next, we can print and see the first 20 rows of data to validate our work as
shown next.
TempDataset.show()
You can use spark-submit command to run a spark script as shown next.
spark-submit temperature_converter.py
Now we are trying to find what is the maximum temperature reported for a
particluar whether station and print the data in ascending order. We can achieve
this by using where() and orderBy() fundtions as shown next.
TempDatasetProcessed = TempDataset.where(TempDataset['t_type'] == 'TMAX'
).orderBy('temp', ascending=False).cache()
We achieved the filtering using temperature type and it filters out all the data
which is not a TMAX.
Finally, we can print the data to see whether this worked or not using following
statement.
TempDatasetProcessed.show()
Now, it is the time to run the python script again using following command.
spark-submit temperature_converter.py
If everything went well, you should see the following sorted and filtered output.
+-----------+------+-----------------+
| ID|t_type| temp|
+-----------+------+-----------------+
|EZE00100082| TMAX|90.14000000000001|
|ITE00100554| TMAX|90.14000000000001|
|ITE00100554| TMAX| 89.42|
|EZE00100082| TMAX| 88.88|
|ITE00100554| TMAX| 88.34|
|ITE00100554| TMAX|87.80000000000001|
|ITE00100554| TMAX| 87.62|
|ITE00100554| TMAX| 87.62|
|EZE00100082| TMAX| 87.26|
|EZE00100082| TMAX|87.08000000000001|
|EZE00100082| TMAX|87.08000000000001|
|ITE00100554| TMAX| 86.72|
|ITE00100554| TMAX| 86.72|
|ITE00100554| TMAX| 86.72|
|EZE00100082| TMAX| 86.72|
|ITE00100554| TMAX| 86.0|
|ITE00100554| TMAX| 86.0|
|ITE00100554| TMAX| 86.0|
|ITE00100554| TMAX| 85.64|
|ITE00100554| TMAX| 85.64|
+-----------+------+-----------------+
only showing top 20 rows
def process_data(line):
fields = line.split(',')
stationID = fields[0]
entryType = fields[2]
temperature = float(fields[3]) * 0.1 * (9.0 / 5.0) + 32.0
return Row(ID=stationID, t_type=entryType, temp=temperature)
Following link is the home directory for the example explained in this tutorial.
https://github.com/cloudmesh-community/hid-sp18-
409/tree/master/tutorial/spark_udfs
Next, git clone the project . Alternatively you can also download the docker
image from the docker hub. Then you don’t need to do docker build.
$ docker pull kadupitiya/tutorial
Now you should see the same output we saw at the end of the example
explanation.
Learning Objectives
EMR is an Amazon product that allows for the creation of clusters of Elastic
Compute Cloud (EC2) instances [76]. EMR allows user to take advantage of
distributed computing capabilities. As the name suggests this product is designed
to allow users to easily scale their cluster to meet their computing needs.
Amazon EMR facilitates you to analyze and process vast(huge) amounts of data
by distributing the computational work across a cluster of virtual servers running
in the AWS Cloud. The EMR cluster is managed using an open-source
framework called Hadoop. Amazon EMR lets you focus on crunching or
analyzing your data without having to worry about time-consuming setup,
management, and tuning of Hadoop clusters or the compute capacity they rely
on unlike other Hadoop distributors like Cloudera, Hortonworks etc.,
EMR clusters can be created through relatively simple web interfaces or can be
created through code using CLI. EMR Clusters can be configured for size and
can be provisioned with open-source distributed frameworks such as SPARK
and HBase, Presto, Flink and etc. Interact with data in AWS data stores such as
Amazon S3, DynamoDB and etc.
Components Of EMR:
Storage
EC2 instance
Clusters
Security
KMS
Core node: A node with software components that run tasks and store data
in the Hadoop Distributed File System (HDFS) on your cluster. Multi-node
clusters have at least one core node.
Task node: A node with software components that only runs tasks and does
not store data in HDFS. Task nodes are optional.
The following diagram represents a cluster with one master node and four core
nodes.
Figure 101: Cluster and Nodes [77]
10.4.1.1.4 Prerequisites
AWS Account
AWS Key Pair
Install and Configure AWS CLI
AWS Admin Access
Linux Environment
In this example we will use the default EMR security roles. These roles enable
the nodes within the cluster to access each other and to access other AWS
products.
aws emr create-default-roles
Create a json file with the following content and save to a local file:
{
"AuthenticationConfiguration": {
"KerberosConfiguration": {
"Provider": "ClusterDedicatedKdc",
"ClusterDedicatedKdcConfiguration": {
"TicketLifetimeInHours": 24
}
}
}
}
Create the Kerberos configuration using the previously created json file:
aws emr create-security-configuration --name "KerberosSecurityConfiguration" --security-configuration file://MyKerberosSecurityConfig.json
The EMR cluster will run on a subnet so you need to determine the appropriate
subnet for you availability zone. You will need to enter your default zone in the
code next.
aws ec2 describe-subnets --filters "Name=availabilityZone,Values=us-east-2b"
In this example we will create a simple cluster with 3 nodes. One master node
and two slave nodes. We will also specify the EC2 instance type (m4.large).
These parameters are configurable and you can create larger clusters with more
processing power. There are multiple EMR versions available, this example uses
the latest version available at the time of creation.
There are a variety of applications that can be installed on the EMR cluster at
creation, but in this case we will simply install Spark. The Kerberos password
can be used to add users to your cluster once it is created. The KeyName is your
EC2 key pair that is referenced in the Prerequisites section.
aws emr create-cluster --name "Test-Kerberized-Spark-Cluster" \
--release-label emr-5.17.0 \
--instance-type m4.large \
--instance-count 3 \
--use-default-roles \
--ec2-attributes KeyName=your-key,SubnetId=your-subnet-id \
--security-configuration KerberosSecurityConfiguration \
--applications Name=Spark \
--kerberos-attributes Realm=EC2.INTERNAL,KdcAdminPassword=your-password
The cluster may take several minutes to initialize. To check the status of your
cluster use the cluster-id that was returned in the previous step.
aws emr describe-cluster --cluster-id your-cluster-id
To terminate your cluster use the following command (hint: AWS charges apply
while your cluster is up).
aws emr terminate-clusters --cluster-ids your-cluster-id
Go to the AWS Console and ensure that the URL references your default region
(see Figure Figure 102 and Figure 103)
AWS EMR
Go to the AWS Console (ensure that the URL references your default region)
AWS EMR
You can view the status of your cluster or termiate the cluster by naviagting to
>Services>EMR>Clusters within the AWS Console.
When you run a cluster on Amazon EMR, you have several options as to how
you specify the work that needs to be done.
Provide the entire definition of the work to be done in functions that you specify
as steps when you create a cluster. This is typically done for clusters that process
a set amount of data and then terminate when processing is complete.
Create a long-running cluster and use the Amazon EMR console, the Amazon
EMR API, or the AWS CLI to submit steps, which may contain one or more
jobs.
Create a cluster, connect to the master node and other nodes as required using
SSH, and use the interfaces that the installed applications provide to perform
tasks and submit queries, either scripted or interactively.
When you launch your cluster, you choose the frameworks and applications to
install for your data processing needs. To process data in your Amazon EMR
cluster, you can submit jobs or queries directly to installed applications, or you
can run steps in the cluster.
You can submit jobs and interact directly with the software that is installed
in your Amazon EMR cluster. To do this, you typically connect to the
master node over a secure connection and access the interfaces and tools
that are available for the software that runs directly on your cluster. For
more information, see Connect to the Cluster.
You can submit one or more ordered steps to an Amazon EMR cluster.
Each step is a unit of work that contains instructions to manipulate data for
processing by software installed on the cluster.
Generally, when you process data in Amazon EMR, the input is data stored as
files in your chosen underlying file system, such as Amazon S3 or HDFS. This
data passes from one step to the next in the processing sequence. The final step
writes the output data to a specified location, such as an Amazon S3 bucket.
The following diagram represents the step sequence and change of state for the
steps as they are processed.
The following diagram represents the step sequence and default change of state
when a step fails during processing.
Cluser and Nodes
Instance Store - Local storage - Data will be lost on start and stop EC2 instances
EBS - Network attached storage - Data preserved on start and stop - Accessible
only through EC2 instances
AWS Login
S3 – Amazon Storage
Figure 110: Amazon Storage
S3 – Create buckets
Download the. pem file once Key value pair is created. This is needed to
access AWS Hadoop environment from client machine. This need to be
imported in Putty to access your AWS environemnt. See Figure 114
Login to AWS console, go to services and then select EMR. Click on Create
Cluster. The cluster configuration provides details to complete to complete step
execution creation. See: Figure 115, Figure 116, Figure 117, Figure 118,
Figure 119.
Login to AWS console, go to services and then select EMR. Click on Create
Cluster. The cluster configuration provides details to complete. See, Figure 120,
Figure 121, Figure 122.
Login to AWS console, go to services and then select EMR. Click on Create
Cluster. The cluster configuration provides details to complete. See, Figure 123,
Figure 124, Figure 125.
In this example we will execute a simple Python function on a text file using
Spark on EMR. This is a standard word count application that will return the
distinct words in the file along with the count of the number of times the words
are present.
The Python file containing the application will be stored and referenced in a S3
bucket along with the text file being analyzed. The results of the Spark job will
be returned to the same S3 bucket.
You can then sync the folder you stored .py file in to your S3 bucket folder.
aws s3 sync your-local-folder-path s3://test-analysis-bucket/SparkTutorial
Store a text file locally and use the S3 sync function to make it availaable in your
S3 bucket.
aws s3 sync your-local-folder-path s3://test-analysis-bucket/SparkTutorial/Input
Using your cluster id and the paths within your S3 bucket run the following
command (this assumes you have a cluster up and running).
aws emr add-steps --cluster-id your-cluster-id \
--steps Type=spark,Name=SparkWordCountApp,\
Args=[--deploy-mode,cluster,--master,yarn,\
--conf,spark.yarn.submit.waitAppCompletion=false,\
--num-executors,2,--executor-cores,2,--executor-memory,1g,\
s3://your-bucket/SparkTutorial/Python/WordCount.py,\
s3://your-bucket/SparkTutorial/Python/Input/input.txt,\
s3://your-bucket/SparkTutorial/Python/Output/]
We can also run the same Spark step during the creation of a cluster using the
following command (assumes you have already done pre-steps to creating an
EMR cluster).
In this case the EMR cluster will spin up, run the Spark job, persist the results to
your S3 bucket, and then auto terminate.
aws emr create-cluster \
--name "Test-Kerberized-Spark-Cluster" \
--release-label emr-5.17.0 \
--instance-type m4.large \
--instance-count 3 \
--use-default-roles \
--ec2-attributes KeyName=your-key,SubnetId=subnet-d0169eaa \py
--security-configuration KerberosSecurityConfiguration \
--applications Name=Spark \
--kerberos-attributes Realm=EC2.INTERNAL,KdcAdminPassword=your-pw \
--steps Type=spark,Name=SparkWordCountApp,\
Args=[--deploy-mode,cluster,--master,yarn,\
--conf,spark.yarn.submit.waitAppCompletion=false,\
--num-executors,2,--executor-cores,2,--executor-memory,1g,\
s3://your-bucket/SparkTutorial/Python/WordCount.py,\
s3://your-bucket/SparkTutorial/Python/Input/input.txt,\
s3://your-bucket/SparkTutorial/Python/Output/],\
ActionOnFailure=CONTINUE \
--auto-terminate
You can use the AWS Console to view the results of the Spark Job.
Go to the AWS Console (ensure that the URL references your default region)
AWS Console
Navigate to the S3 bucket and folder you specified for the output (see Figure
Figure 126)
10.4.1.1.13 Conclusion
AWS EMR is a powerful tool for distributive processing. It is easy to use from
wither the command line utilizing AWS CLI or through the AWS Console web
interface.
10.4.2 TWISTER
10.4.2.1 Twister2 ☁
10.4.2.1.1 Introduction
Twister2 supports both batch and streaming applications. Unlike other big data
frameworks which either support batch or streaming in the core and develop the
other on top of that, Twister2 natively supports both batch and streaming. Which
allows Twister2 to make separate optimizations for each type.
Twister2 project is still less than 2 years old and still in it’s early stages and
going through rapid development to complete its functionality. It is an Open
Source project which is licenced under the Apache 2.0[79]
Twister2 provides users with 3 levels on API’s which can be used to write
applications. The 3 API levels are shown in Figure Figure 127.
Figure 127: Twister2 API’s
As shown in Figure 127 each API level has different levels of abstraction and
programming complexities. TSet API is the most high level in Twister2 which in
someways is simlar to the RDD API in Apache Spark or DataSet API in Apache
Flink. If the user wants more control over the application development they can
opt to use a more lower level API’s.
TSet API is the most abstract API provided by Twister2. This allows user to
develop their programs at the data layer, similar to the programming model of
Apache Spark. Similar to RDD in Spark users can perform operations on top of
TSet objects which will be automatically parallelized by the framework. To get a
slight understanding of the Tset API take a look at the abstract example given on
how TSet API can be used to implement KMeans algorithm.
public class KMeansJob extends TaskWorker {
//......
@Override
public void execute() {
//.....
TSet<double[][]> points = TSetBuilder.newBuilder(config).createSource(new Source<double[][]>() {
//Code for source function to read data points
}).cache();
for (
int i = 0;
i < iterations; i++) {
TSet<double[][]> KmeansTSet = points.map(new MapFunction<double[][], double[][]>() {
//Code for Kmeans calculation, this will have access to the centroids which are passed in
});
KmeansTSet.addInput("centroids", centroids);
Note: The TSet API is currently under development and has not been released
yet and therefore the API may change from what was discussed in this section,
anyone who is interested can follow the development progress or contribute to
the project through the GitHub repo[79].
The Task API allows developers to create their application at the Task level. The
developer is responsible of managing task level details when developing at this
API level, the upside of using the Task API is that it is more flexible than the
TSet API so it allows developers to add custom optimizations to the application
code. The TSet API is built on top of the Task API therefore the added layer of
abstraction is bound to add slightly more overheads to the runtime, which you
might be able to avoid by directly coding at the Task API level.
To get a better understanding of the Task API take a look at how the classic map
reduce problem word count is implemented at using the Task API in the
following code segment. This is only a portion of the example code, you can find
the complete code for the example at[80].
public class WordCountJob extends TaskWorker {
//.....
@Override
public void execute() {
// source and aggregator
WordSource source = new WordSource();
WordAggregator counter = new WordAggregator();
Reduce
Gather
AllReduce
AllGather
Partition
Broadcast
Keyed Reduce
Keyed Partition
Keyed Gather
Initial Performance comparisons that are discussed in[83] show how Twister2
out performs popular frameworks such Apache Flink, Apache Spark and Apache
Strom in many areas. For example the Figure 128 shows a comparision between
Twister2, MPI and Apache Spark versions of KMeans algorithm, please note
that the graph is in logarithmic scale
Figure 128: Kmeans Performance Comparison[84]
This shows that Twister2 performs around ~10x faster than Apache Spark for
KMeans. And that it is on par with implementations done using OpenMPI which
is a widely used HPC framework.
10.4.2.1.3.1 Resources
http://www.iterativemapreduce.org/
http://www.cs.allegheny.edu/sites/amohan/teaching/CMPSC441/paper10.pdf
https://twister2.gitbook.io/twister2/
http://dsc.soic.indiana.edu/publications/Twister2.pdf
https://www.computer.org/csdl/proceedings/cloud/2018/7235/00/723501a383-
abs.html
10.4.2.2.1 Prerequisites
Because Twister2 is still in the early stages of development a binary release is
not available as of yet, therefore to try out Twister2 users need to first build the
binaries from the source code.
Operating System :
Twister2 is tested and known to work on,
Red Hat Enterprise Linux Server release 7
Ubuntu 14.05, Ubuntu 16.10 and Ubuntu 18.10
source ~/.bashrc
summary, the following commands will build OpenMPI for a Linux system.
cd $OMPI_312
./configure --prefix=$BUILD --enable-mpi-java
make -j 8;make install
If everything goes well mpirun --version will show mpirun (Open MPI) 3.1.2. Execute the
following command to instal $OMPI_312/ompi/mpi/java/java/mpi.jar as a Maven artifact.
mvn install:install-file -DcreateChecksum=true -Dpackaging=jar -Dfile=$OMPI_312/ompi/mpi/java/java/mpi.jar -DgroupId=ompi -DartifactId=ompij
sudo apt-get install g++ git build-essential automake cmake libtool-bin zip
libunwind-setjmp0-dev zlib1g-dev unzip pkg-config python-setuptools -y sudo
apt-get install python-dev python-pip
Now you have successfully installed the required packages. Let us compile
Twister2.
You can compile the Twister2 distribution by using the bazel target as follows.
cd twister2
bazel build --config=ubuntu scripts/package:tarpkgs
If you would like to compile the twister2 without building the distribution
packages use the command
bazel build --config=ubuntu twister2/...
After you’ve build the Twister2 distribution, you can extract it and use it to
submit jobs.
cd bazel-bin/scripts/package/
tar -xvf twister2-0.1.0.tar.gz
In order to run an example users need to submit the example to Twister2 using
the twister command. This command is found inside the bin directory of the
distribution.
For this exercise we are using the standlone mode to submit a job. However
Twister2 does support Kubernetes, Mesos, Slurm and Nomad resource
schedulers if users want to submit jobs to larger cluster deployments.
In this section we will run a batch word count example from Twister2. This
example only uses communication layer and resource scheduling layer. The
threads are managed by the user program.
This will run 4 executors with 8 tasks. So each executor will have two tasks. At
the first phase, the 0-3 tasks running in each executor will generate words and
after they are finished, 5-8 tasks will consume those words and create a count.
Acknowledgement: This section was copied and modified with permission from
https://www.chameleoncloud.org/appliances/17/docs/
link missing
First, launch bare-metal nodes using the RDMA-Hadoop Appliance and select
one of the nodes as the bootstrap node. This node will serve as the host for the
master node of the Hadoop cluster and will also be used to setup the entire
cluster. Now, ssh to this node. Before you can launch the cluster, you have to
download your OpenStack credentials file (see how to download your
credentials file). Then, create a file (henceforth referred to as ips-file) with the ip
addresses of the bare-metal nodes you want to launch your Hadoop cluster on
(excluding the bootstrap node), each on a new line. Next, run these commands as
root:
[root@host]$ cd /home/cc
[root@host]$ ./launch-hadoop-cluster.sh <num-of-vms-per-node> <num-of-MB-per-VM> <num-of-cores-per-VM> <ips-file> <openstack-credentials-fil
The launch cluster script will launch VMs for you, then install and configure
Hadoop on these VMs. Note that when you launch the cluster for the first time, a
lot of initialization is required. Depending on the size of your cluster, it may take
some time to setup the cluster. After the cluster setup is complete, the script will
print an output telling you that the cluster is setup and how you can connect to
the Hadoop master node. Note that the minimum required memory for each VM
is 8,192 MB. The Hadoop cluster will already be setup for use. For more details
on how to use the RDMA-Hadoop package to run jobs, please refer to its user
guide.
Note the MAC address and IP address are in the output of this command. You
should use this MAC address while launching a VM and the IP address to ssh to
the VM. You also need the PCI device ID of the virtual function that you want to
assign to the VM. This can be obtained by running "lspci | grep Mellanox" and
looking for the device ID (with format - XX:XX.X) of one of the virtual
functions as shown next:
[cc@host]$ lspci | grep Mellanox
03:00.0 Network controller: Mellanox Technologies MT27500 Family [ConnectX-3]
03:00.1 Network controller: Mellanox Technologies MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]
...
The PCI device ID of the Virtual Function is 03:00:1 in the previous example.
Now, you can launch a VM on your instance with SR-IOV using the provided
VM startup script and corresponding arguments as follows with the root account.
[root@host]$ ./start-vm.sh <vm-mac> <vm-ifname> <virtual-function-device-id>
Please note that and are the ones you get from the outputs of previous
commands. And is the name of VM virtual NIC interface. For example:
[root@host]$ ./start-vm.sh fa:16:3e:47:48:00 tap0 03:00:1
You can also edit corresponding fields in VM startup script to change the
number of cores, memory size, etc.
You should now have a VM running on your bare metal instance. If you want to
run more VMs on your instance, you will have to create more network ports.
You will also have to change the name of VM virtual NIC interface to different
ones (like tap1, tap2, etc.) and select different device IDs of virtual functions.
After finishing the extra initialization procedure, you should be able to run
Hadoop jobs with SR-IOV support across VMs. Note that this initialization will
be done automatically. For more details about the RDMA-Hadoop package,
please refer to its user guide.
10.4.3.4 Important Note for Tearing Down Virtual Machines and Deleting
Network Ports
Once you are done with your experiments, you should kill all the launched VMs
and delete the created network ports. If you used the launch-hadoop-cluster.sh
script to launch VMs, you can do this by running the kill-vms.sh script as shown
next. This script will kill all launched VMs and also delete all the created
network ports.
[root@host]$ cd /home/cc
[root@host]$ ./kill-vms.sh <ips-file> <openstack-credentials-file>
\end{vernatim}
If you launched VMs using the start-vm.sh script, you should first manually kill all the VMs. Then, delete all the created network ports usi
Learning Objectives
This section covers an introduction to containers that is split up into four parts.
We discuss microservices, serverless computing, Docker, and kubernetes.
We discuss the motivation for containers and contrast them to virtual machines.
Additionally we provide a motivation for containers as they can be used to
microservices.
11.1.3 Docker
In order for us to use containers, we go beyond the historical motivation that was
introduced in a previous section and focus on Docker a predominant technology
for containers on Windows, Linux, and macOS
11.2 DOCKER
11.2.1 Introduction to Docker ☁
Docker is the company driving the container movement and the only container
platform provider to address every application across the hybrid cloud. Today’s
businesses are under pressure to digitally transform but are constrained by
existing applications and infrastructure while rationalizing an increasingly
diverse portfolio of clouds, datacenters and application architectures. Docker
enables true independence between applications and infrastructure and
developers and IT ops to unlock their potential and creates a model for better
collaboration and innovation. An overview of docker is provided at
https://docs.docker.com/engine/docker-overview/
Figure 129: Docker Containers [Image Source] [86]
Figure 129 shows how docker containers fit into the system ## Docker platform
Docker provides users and developers with the tools and technologies that are
needed to manage their application development using containers. Developers
can easily setup different environments for development, testing and production.
The Docker engine can be thought of as the core of the docker runtime. The
docker engine mainly provides 3 services. Figure 130 shows how the docker
engine is composed.
The main concept of the docker architecture is based on the simple client-server
model. Docker clients communicate with the Docker server also known as the
Docker daemon to request various resources and services. THe daemon manages
all the background tasks that need to be performed to complete client requests.
Managing and distributing containers, running the containers, bulding
containers, etc. are responsibilities of the Docker daemon. Figure 131 shows
how the docker architecture is setup. The client module and server can run either
in the same machine or in separate machines. In the latter case the
communication between the client and server are done through the network.
Figure 131: Docker Architecture [Image Source] [86]
In 2016 Docker Inc. surveyed over 500 Docker developers and operations
experts in various phases of deploying container-based technologies. The result
is available in the The Docker Survey 2016 as seen in Figure 132.
https://www.docker.com/survey-2016
Figure 132: Docker Survey Results 2016 [Image Source] [86]
⚠ Please verify if the instructions are still up to date. Rapid changes could mean
they can be outdated quickly. Also we assume the ubuntu instalations may have
changed and may be different between 18.04 and 19.04.
The official installation documentation for docker can be found by visiting the
following Web page:
https://www.docker.com/community-edition
Here you will find a variety of packages, one of which will hopefully suitable for
your operating system. The supported operating systems currently include:
Please chose the one most suitable for you. For your convenience we provide
you with installation instructions for OSX (Section Docker on OSX), Windows
10 (Section Docker on Windows) and Ubuntu (Section Docker on ubuntu).
The docker community edition for OSX can be found at the following link
https://store.docker.com/editions/community/docker-ce-desktop-mac
We recommend that at this time you get the version Docker CE for MAC (stable)
https://download.docker.com/mac/stable/Docker.dmg
Clicking on the link will download a dmg file to your machine, that you than
will need to install by double clicking and allowing access to the dmg file. Upon
installation a whale in the top status bar shows that Docker is running, and you can
access it via a terminal.
In order to install Docker community edition for Ubuntu, you first have to
register the repository from where you can download it. This can be achieved as
follows:
local$ sudo apt-get update
local$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
local$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
local$ sudo apt-key fingerprint 0EBFCD88
local$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
local$(lsb_release -cs) \
stable"
Now that you have configured the repository location, you can install it after you
have updated the operating system. The update and install is done as follows:
local$ sudo apt-get update
local$ sudo apt-get install docker-ce
local$ sudo apt-get update
Once installed execute the following command to make sure the installation is
done properly
local$ sudo systemctl status docker
Docker needs Microsoft’s Hyper-V to be enabled, but it will impact running the
virtual machines
Steps to Install
Client:
Version: 17.03.1-ce
API version: 1.27
Go version: go1.7.5
Git commit: c6d412e
Built: Tue Mar 28 00:40:02 2017
OS/Arch: darwin/amd64
Server:
Version: 17.03.1-ce
API version: 1.27 (minimum version 1.12)
Go version: go1.7.5
Git commit: c6d412e
Built: Fri Mar 24 00:00:50 2017
OS/Arch: linux/amd64
Experimental: true
https://cloud.docker.com/
11.2.3 Dockerfile ☁
In order for us to build containers, we need to know what is in the container and
how to create an image representing a container. To do this a convenient
specification format called Dockerfile can be used. Once a Dockerfile is created, we can
build images from it
https://docs.docker.com/get-started/part2/#publish-the-image
11.2.3.1 Specification
We copy the following contents into the Dockerfile and after that create a simple
REST service
# Use an official Python runtime as a parent image
FROM python:3.7-slim
We also create a requirements.txt file that we need for installing the necessary python
packages
Flask
The example application we use here is a student info served via a RESTful
service implemented using python flask. It is stored in the file app.py
from flask import Flask, jsonify
import os
app = Flask(__name__)
@app.route('/student/albert')
def alberts_information():
data = {
'firstname': 'Albert',
'lastname': 'Zweistsein',
'university': 'Indiana University',
'email': '[email protected]'
}
return jsonify(**data)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=80)
To run the service open a new window and cd into the directory where you code
is located. Now say
local$ docker run -d -p 4000:80 students
Your docker container will run and you can visit it by using the command
local$ curl http://localhost:4000/student/albert
and locate the id of the container, e.g., 2a19776ab812, and then run this
local$ docker stop 2a19776ab812
To delete the docker container image, you must first sop all instances using it
and the remove the image. You can see the images with the command
local$ docker images
Then you can locate all containers using that image while looking in the IMAGE
column or using a simple fgrep in case you have many images. stop the
containers using that image and that you can say
local$ docker rm 74b9b994c9bd
Once you killed all containers using that image, you can remove the image with
the rmi command.
local$ docker rmi 8b3246425402
11.2.3.2 References
https://docs.docker.com/engine/reference/builder/
Docker Hub is integrated into Docker as the default registry. This means that the
docker pull command will initialize the download automatically from Docker
Hub [87]. It allows users to download (pull), build, test and store their images
for easy deployment on any host they may have [86].
A log-in is not necessary for pulling Docker images from the Hub but it is
necessary for pushing images to dockerhub for sharing. Thus to store images on
Docker hub you need to create an account by visiting Docker Hub Web page.
Dockerhub offers in general a free account, but it has restrictions. The free
account allows you to share images that you distriuute publically, but it only
allows one private Docker Hub Repository. In case you need more, you will
need to upgrade to a paid plan.
For the rest of the tutorial we assume that you use the environment variable
DOCKERHUB to indicate yourusername. It is easiset if you set it in your shell
with
local$ export DOCKERHUB=<PUT YOUR DOCKER USERNAME HERE>
There are two ways to search for Docker images on Docker Hub:
One way is to use the Docker command line tool. We can open a terminal and
run the docker search command. For example, the following command searches
for centOS images:
local$ sudo docker search centos
If you do not want to use sudo with docker command each time you need to add
the current user into the docker group. You can do that using the following
command.
local$ sudo usermod -aG docker ${USER}
local$ su - ${USER}
This will prompt you to enter the password for the current user. Now you should
be able to execute the previous command without using sudo.
The other way is to search via the Web Search Box at the top of the Docker web
page by typing the keyword. The search results can be sorted by number of stars,
number of pulls, and whether it is an official image. Then for each search result,
you can verify the information of the image by clicking the details button to
make sure this is the right image that fits your needs.
A particular image (take centos as an example) can be pulled using the following
command:
local$ docker pull centos
Tags can be used to specify the image to pull. By default the tag is latest,
therefore the previous command is the same as the following:
local$ docker pull centos:latest
You can use a different tag:
local$ docker pull centos:6
To check the existing local docker images, run the following command:
local$ docker images
In order to push images to Docker Hub, you need to have a and account and
create a repository.
When you first create a Docker Hub user, you see a Get started with Docker Hub
screen, from which you can click directly into Create Repository. You can also
use the Create menu to Create Repository. When creating a new repository, you
can choose to put it in your Docker ID namespace, or that of any organization
that you are in the owners team [88].
$DOCKERHUB/cloudtechnology
To push an image to the repository created, the following steps can be followed.
First, log into Docker Hub from the command line by specifying the username.
If you encounter permission issues please use sudo in front of the command
$ docker login --username=$DOCKERHUB
Enter the password when prompted. If everything worked you will get a message
similar to:
Login Succeeded
Here, the the image with ID 1f26a5f7a1b4 is the one to push to Docker Hub.
You can choose another image instead if you like.
Here we have used a version number as a tag. However another good way of
adding a tag is to use a keyword/tag that will help you understand what this
container should be used in conjunction with, or what it represents.
Fifth, Now you can see an images under the name $DOCKERHUB/cloudmesh, we now need to
push this image to the repository that we created on the docker hub website. For
that execute the following command.
$ docker push $DOCKERHUB/cloudmesh
It shows something similar to, to make sure you can check on docker hub if the
images that was pushed is listed in the repository that we created.
The push refers to repository [docker.io/$DOCKERHUB/cloudmesh]
18f9479cfc2c: Pushed
e9ddee98220b: Pushed
...
db584c622b50: Mounted from library/ubuntu
a94e0d5a7c40: Mounted from library/ubuntu
...
v1.0: digest: sha256:305b0f911077d9d6aab4b447b... size: 3463
Sixth, now the image is available on Docker Hub. Everyone can pull it since it is
a public repository by using command:
$ docker pull USERNAME/cloudmesh
Please remember that the USERNAME is the username for the user that makes
this image publically available. If you are the user you will see the value being
the one from $DOCKERHUB, If not you will see here the username of the user
uploading the image
11.2.4.6 Resources
11.2.5.1 Introduction
Docker compose is a tool for defining and running multi-container using docker
container to package them as an application. Docker compose uses a YAML file
to specify the dependencies between the containers and their configuration. The
nice feature is taht with a single command you create and start all the services
from your configuration file and can maage the application including shutting it
down.
Using docker compose includes a four-step process:
11.2.5.2 Installation
https://docs.docker.com/docker-for-mac/install/
Please note that you use the newest version which can be found on the download
Web page. After downloading, make sure that you apply executable permissions
to binary:
sudo chmod +x /usr/local/bin/docker-compose
Windows 10 64-bit
Pro, Enterprise, or Education (Build 15063 or later).
Hyper-V and Containers Windows features must be enabled.
https://hub.docker.com/?overlay=onboarding
It is important that you test your instalation before you move forward.This can
be done on the commandline with the command. More involved tests can be
conducted while using the simple example depicted in this section.
$ docker-compose --version
docker-compose version 1.24.1, build 1110ad01
To use docker compose, you will need a file that contains specifications of the
containers and their dependencies. We will demonstrate this concept with a
simple example.
We are starting a redis cache server, a postgresql database server, and containers vote,
result, worker, visualizer to provide frontend an backend services that interacte with the
containers.
After you have reviewed the yaml file, we will explain the different parts in
more detail.
version: "3.7"
services:
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "5000:80"
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "5001:80"
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
frontend:
backend:
volumes:
db-data:
11.2.5.3.1 Configuration
11.2.5.3.1.1 build
The build attribute specifies either a string containing a path to the build context:
version: "3.7"
services:
webapp:
build: ./dir
11.2.5.3.1.2 context
11.2.5.3.1.3 ARGS
The ARGS attribute introduces environment variables accessible only during the
build process.
ARG buildno
ARG gitcommithash
build:
context: .
args:
buildno: 1
gitcommithash: cdc3b19
11.2.5.3.1.4 command
11.2.5.3.1.5 depends_on
The depends_on attribute introduces dependencies between services. The container
that depends on other containers, waits for them to become available. In the
following example the web serviec depends on the db and redis services:
version: "3.7"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
11.2.5.3.1.6 image
The image attribute specifies the image for the container. You can either use a
repository/tag or a partial image ID to identify the image
image: redis
image: ubuntu:14.04
image: mongo
11.2.5.3.1.7 ports
The ports attribute expose ports ports of teh container. However, please note that
the port mapping is incompatible with network_mode: host.
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
11.2.5.3.1.8 volumes
The volume attribute mounts ahost paths or named volumes. A volume is specified
as sub-options to a service.
You can mount a host path as part of a definition for a single service, and there is
no need to define it in the top level volumes key.
11.2.5.4 Usages
By default, web service can reach the mongo service by using the service’s name as
we configured the database URI to be
mongodb://mongo:27017 .
To start the two docker containers you can use the command:
$ docker-compose up
A swarm is a group of machines that are running Docker and are joined into a
cluster. Docker commands are executed on a cluster by a swarm manager. The
machines in a swarm can be physical or virtual. After joining a swarm, they are
referred to as nodes.
11.3.2.1 Terminology
1. run
master$ docker swarm init
to enable swarm mode and make your current machine a swarm manager,
2. then run
worker-1$ docker swarm join
on other machines to have them join the swarm as workers. Choose a tab
described in next to see how this plays out in various contexts. We use VMs
to quickly create a two-machine cluster and turn it into a swarm.
In case you do not have access to multiple physical machines, you can create a
virtual cluster on your machine with the help of virtual box. Instead of using
vagrant we can use the built in docker-machine command to start several virtual
machines.
If you do not have virtualbox installed on your machine install it on your machine.
Additionally you would require docker-machine to be installed on your local machine.
To install docker-machine on please follow instructions at the docker documentation at
Install Docker Machine
To create the virtual machines you can use the command as follows:
local$ docker-machine create --driver virtualbox master
local$ docker-machine create --driver virtualbox worker-1
To list the VMs and get their ip addresses. Use this command to list the
machines and get their IP addresses.
local$ docker-machine ls
11.3.2.4 Initialize the Swarm Manager Node and Add Worker Nodes
The first machine acts as the manager, which executes management commands
and authenticates workers to join the swarm, and the second is a worker.
To instruct the first vm to become the master, first we need to login to the vm
that was named master. To login you can use ssh, execute the following command
on your local machine to login to the master vm.
local$ docker-machine ssh master
Now since we are inside the master vm we can configure this vm as the docker
swarm manager. Execute the following command within the master vm in initialize
swarm
master$ docker swarm init
If you get an error stating something similar to “could not choose an IP address
to advertise since this system has multiple addresses on different interfaces”, use
the following command instead. To find the IP address execute the command
ifconfig and pick the ip address which is most simmilar to 192.x.x.x.
The output wil look like this, where IP-myvm1 is the ip address of the first vm
master$ Swarm initialized: current node (p6hmohoeuggtwqj8xz91zbs5t) is now
a manager.
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Now that we have the docker swarm manager up we can add worker machines to
the swarm. The command that is printed in the output shown previously can be
used to join workers to the manager. Please note that you need to use the output
command that is generated when you run docker swarm init since the token values will
be different.
Now we need to use a separate shell to login to the worker vm that we created.
Open up a new shell (or terminal) and use the following command to ssh into the
worker
Once you are in the worker execute the following command to join worker to the
swam manager.
worker-1$ docker swarm join --token
SWMTKN-1-5c3anju1pwx94054r3vx0v7j4obyuggfu2cmesnx 192.168.99.100:2377
The generic version of the command would be as follows, you need to fill in the
correct values to values marked as ‘<>’ to execute the command.
worker-1$ docker swarm join --token <token> <myvm ip>:<port>
You will see an output stating that this machine joined the docker swarm.
This node joined a swarm as a worker.
If you want to add another node as a manager to the current swarm you can
execute the following command and follow the instructions. However this is not
needed for this exercise.
newvm$ docker swarm join-token manager'
Run docker-machine ls to verify that worker is now the active machine, as indicated by the
asterisk next to it.
local$ docker-machine ls
Then,
master$ vi docker-compose.yml
This command will open an editor. Press the Insert button to enable editing and
then copy paste the following into the document.
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "4000:80"
networks:
- webnet
networks:
webnet:
Then pres the Ecs button and enter :wq to save and close the editor.
Once we have the file we can deploy the test application using the following
command. which will be executed in the master
master$ docker stack deploy -c docker-compose.yml getstartedlab
To verify the services and associated containers have been distributed between
both master and worker, execute the following command.
master$ docker stack ps getstartedlab
This section is for IU students only that take classes with us.
https://portal.futuresystems.org/project/553
If your access to the victor host has been verified, try to login to the docker
swarm head node. To conveniently do this let us define some Linux environment
variables to simplify the access and the material presented here. You can place
them even in your .bashrc or .bash_profile so the information gets populated whenever
you start a new terminal.If you directly edit the files make sure to execute the
source command to refresh the environment variables for the current session using
source .bashrc or source .bash_profile. Or you can close the current shell and reopen a new
one.
local$ export ECHO=149.165.150.76
local$ export FS_USER=<put your futersystem account name here>
Now you can use the two variables that were set to login to the Echo serer, using
the following command
local$ ssh $FS_USER@$ECHO
Note: If you have access to india but not the docker swarm system, your
project may not have been authorized to access the docker swarm cluster.
Send a ticket to FutureSystems ticket system to request this.
While docker run can start a container and you may even attach to its console, the
recommended way to use a docker swarm cluster is to create a service and have
it run on the swarm cluster. The service will be scheduled to one or many
number of the nodes of the swarm cluster, based on the configuration. It is also
easy to scale up the service when more swarm nodes are available. Docker
swarm really makes it easier for service/application developers to focus on the
functionality development but not worrying about how and where to bind the
service to some resources/server. The deployment, access, and scaling up/down
when necessary, are all managed transparently. Thus achieving the new
paradigm of serverless computing.
The command pulls a published image from docker cloud, starts a container and
runs a script to start the service inside the container with necessary parameters.
The option “-p 9001:8888” maps the service port inside the container (8888) to
an external port of the cluster node (9001) so the service could be accessed from
the Internet. In this example, you can then visit the URL:
local$ open http://$ECHO:9001
to access the Jupyter notebook. Using the specified password when you create
the service to login.
This also implies that the external port number used has to be free at the time
when the service was created.
lists the detailed info of the container where the service is running.
echo$ docker node ps NODE
You can create your own service and run it. To do so, start from a base image,
e.g., a ubuntu image from the docker cloud. Then you could:
Run a container from the image and attach to its console to develop the
service, and create a new image from the changed instance using command
‘docker commit’.
Create a dockerfile, which has the step by step building process of the
service, and then build an image from it.
In reality, the first approach is probably useful when you are in the phase of
develop and debug your application/service. Once you have the step by step
instructions developed the latter approach is the recommended way.
https://docs.docker.com/docker-cloud/builds/push-images/
Once the image is published and available to the swarm cluster, you could start a
new service from the image similar to the Jupyter Notebook example.
11.3.3.5 Exercises
E.Docker.Futuresystems.1:
E.Docker.Futuresystems.2:
Create a REST service with swagger codegen and run it on the echo
cloud (see example in this section )
This section is based on the hadoop release 3.1.1 which includes significant
enhancements over the previous version of Hadoop 2.x. Changes include the use
of the following software:
CentOS 7
systemctl
Java SE Development Kit 8
*https://github.com/cloudmesh-
community/book/blob/master/examples/docker/hadoop/3.1.1/Dockerfile
To use the image interactively you can start the container as follows:
$ docker run -it cloudmesh/hadoop:3.1.1 /etc/bootstrap.sh -bash
IN case you need more memory, you can increase it by changing the parameters
in the file mapred-site.xml, for example:
mapreduce.map.memory.mba to 4096
mapreduce.reduce.memory.mb to 8192
A Safemode for HDFS is a read-only mode for the HDFS cluster, where it does
not allow any modifications of files and blocks. Namenode disables safe mode
automatically after starting up normally. If required, HDFS could be forced to
leave the safe mode explicitly by this command:
$ hdfs dfsadmin -safemode leave
11.3.4.5 Examples
https://github.com/cloudmesh-
community/book/tree/master/examples/docker/hadoop/3.1.1/examples
After we launch the container and use the interactive shell, we can run the
statistics Hadoop application which calculates the minimum, maximim, average,
and standard derivation from values stored in a number of input files. Figure
Figure 133 shows the computing phases in a MapReduce job.
To achieve this, this Hadoop program reads multiple files from HDFS and
provides calculated values. We walk through every step from compiling Java
source code to reading a output file from HDFS. The idea of this exercise is to
get you started with Hadoop and the MapReduce concept. You may seen the
WordCount from Hadoop official website or documentation and this example
has a same functions (Map/Reduce) except that you will be computing the basic
statistics such as min, max, average, and standard deviation of a given data set.
The input to the program will be a text file(s) carrying exactly one floating point
number per line. The result file includes min, max, average, and standard
deviation.
10 files contain 55000 lines to process and each line is a random float point
value ranging from 0.2 to 20.0.
11.3.4.5.1.3 Compilation
These commands simply prepare compiling the example code and the compiled
class files are generated at the dest location.
Jar command tool helps archiving classes in a single file which will be used
when Hadoop runs this example. This is useful because a jar file contains all
necessary files to run a program.
$ cd /cloudmesh/examples/statistics
$ jar -cvf stats.jar -C ./dest/ .
The input files need to be uploaded to HDFS as Hadoop runs this example by
reading input files from HDFS.
$ export PATH=$PATH:/HADOOP_HOME/bin
$ hadoop fs -mkdir stats_input
$ hadoop fs -put input_data/* stats_input
$ hadoop fs -ls stats_input/
We are ready to run the program to calculate values from text files. First, we
simply run the program with a single input file to see how it works. data_1000.txt
contains 1000 lines of floats, we use this file here.
$ hadoop jar stats.jar exercise.MinMaxAvgStd stats_input/data_1000.txt stats_output_1000
The command runs with input parameters which indicate a jar file (the program,
stats.jar), exercise.MinMaxAvgStd (package name.class name), input file path
(stats_input/data_1000.txt) and output file path (stats_output_1000).
The sample results that the program produces look like this:
18/02/28 23:48:50 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
18/02/28 23:48:50 INFO input.FileInputFormat: Total input paths to process: 1
18/02/28 23:48:50 INFO mapreduce.JobSubmitter: number of splits:1
18/02/28 23:48:50 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1519877569596_0002
18/02/28 23:48:51 INFO impl.YarnClientImpl: Submitted application application_1519877569596_0002
18/02/28 23:48:51 INFO mapreduce.Job: The url to track the job: http://f5e82d68ba4a:8088/proxy/application_1519877569596_0002/
18/02/28 23:48:51 INFO mapreduce.Job: Running job: job_1519877569596_0002
18/02/28 23:48:56 INFO mapreduce.Job: Job job_1519877569596_0002 running in uber mode: false
18/02/28 23:48:56 INFO mapreduce.Job: map 0% reduce 0%
18/02/28 23:49:00 INFO mapreduce.Job: map 100% reduce 0%
18/02/28 23:49:05 INFO mapreduce.Job: map 100% reduce 100%
18/02/28 23:49:05 INFO mapreduce.Job: Job job_1519877569596_0002 completed successfully
18/02/28 23:49:05 INFO mapreduce.Job: Counters: 49
File System Counters
FILE: Number of bytes read=81789
FILE: Number of bytes written=394101
FILE: Number of read operations=0
FILE: Number of large read operations=0
FILE: Number of write operations=0
HDFS: Number of bytes read=14067
HDFS: Number of bytes written=86
HDFS: Number of read operations=6
HDFS: Number of large read operations=0
HDFS: Number of write operations=2
Job Counters
Launched map tasks=1
Launched reduce tasks=1
Data-local map tasks=1
Total time spent by all maps in occupied slots (ms)=2107
Total time spent by all reduces in occupied slots (ms)=2316
Total time spent by all map tasks (ms)=2107
Total time spent by all reduce tasks (ms)=2316
Total vcore-seconds taken by all map tasks=2107
Total vcore-seconds taken by all reduce tasks=2316
Total megabyte-seconds taken by all map tasks=2157568
Total megabyte-seconds taken by all reduce tasks=2371584
Map-Reduce Framework
Map input records=1000
Map output records=3000
Map output bytes=75783
Map output materialized bytes=81789
Input split bytes=125
Combine input records=0
Combine output records=0
Reduce input groups=3
Reduce shuffle bytes=81789
Reduce input records=3000
Reduce output records=4
Spilled Records=6000
Shuffled Maps =1
Failed Shuffles=0
Merged Map outputs=1
GC time elapsed (ms)=31
CPU time spent (ms)=1440
Physical memory (bytes) snapshot=434913280
Virtual memory (bytes) snapshot=1497260032
Total committed heap usage (bytes)=402653184
Shuffle Errors
BAD_ID=0
CONNECTION=0
IO_ERROR=0
WRONG_LENGTH=0
WRONG_MAP=0
WRONG_REDUCE=0
File Input Format Counters
Bytes Read=13942
File Output Format Counters
Bytes Written=86
The second line of the following logs indicates that the number of input files is
1.
The first run was done pretty quickly (1440 milliseconds took according to the
previous sample result) because the input file size was small (1,000 lines) and it
was a single file. We provides more input files with a larger size (2,000 to
10,000 lines). Input files are already uploaded to HDFS. We simply run the
program again with a slight change in the parameters.
$ hadoop jar stats.jar exercise.MinMaxAvgStd stats_input/ stats_output_all
The command is almost same except that an input path is a directory and a new
output directory. Note that every time that you run this program, the output
directory will be created which means that you have to provide a new directory
name unless you delete it.
The sample output messages look like the following which is almost identical
compared to the previous run except that this time the number of input files to
process is 10, see the line two next:
18/02/28 23:17:18 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
18/02/28 23:17:18 INFO input.FileInputFormat: Total input paths to process: 10
18/02/28 23:17:18 INFO mapreduce.JobSubmitter: number of splits:10
18/02/28 23:17:18 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1519877569596_0001
18/02/28 23:17:19 INFO impl.YarnClientImpl: Submitted application application_1519877569596_0001
18/02/28 23:17:19 INFO mapreduce.Job: The url to track the job: http://f5e82d68ba4a:8088/proxy/application_1519877569596_0001/
18/02/28 23:17:19 INFO mapreduce.Job: Running job: job_1519877569596_0001
18/02/28 23:17:24 INFO mapreduce.Job: Job job_1519877569596_0001 running in uber mode: false
18/02/28 23:17:24 INFO mapreduce.Job: map 0% reduce 0%
18/02/28 23:17:32 INFO mapreduce.Job: map 40% reduce 0%
18/02/28 23:17:33 INFO mapreduce.Job: map 60% reduce 0%
18/02/28 23:17:36 INFO mapreduce.Job: map 70% reduce 0%
18/02/28 23:17:37 INFO mapreduce.Job: map 100% reduce 0%
18/02/28 23:17:39 INFO mapreduce.Job: map 100% reduce 100%
18/02/28 23:17:39 INFO mapreduce.Job: Job job_1519877569596_0001 completed successfully
18/02/28 23:17:39 INFO mapreduce.Job: Counters: 49
File System Counters
FILE: Number of bytes read=4496318
FILE: Number of bytes written=10260627
FILE: Number of read operations=0
FILE: Number of large read operations=0
FILE: Number of write operations=0
HDFS: Number of bytes read=767333
HDFS: Number of bytes written=84
HDFS: Number of read operations=33
HDFS: Number of large read operations=0
HDFS: Number of write operations=2
Job Counters
Launched map tasks=10
Launched reduce tasks=1
Data-local map tasks=10
Total time spent by all maps in occupied slots (ms)=50866
Total time spent by all reduces in occupied slots (ms)=4490
Total time spent by all map tasks (ms)=50866
Total time spent by all reduce tasks (ms)=4490
Total vcore-seconds taken by all map tasks=50866
Total vcore-seconds taken by all reduce tasks=4490
Total megabyte-seconds taken by all map tasks=52086784
Total megabyte-seconds taken by all reduce tasks=4597760
Map-Reduce Framework
Map input records=55000
Map output records=165000
Map output bytes=4166312
Map output materialized bytes=4496372
Input split bytes=1251
Combine input records=0
Combine output records=0
Reduce input groups=3
Reduce shuffle bytes=4496372
Reduce input records=165000
Reduce output records=4
Spilled Records=330000
Shuffled Maps =10
Failed Shuffles=0
Merged Map outputs=10
GC time elapsed (ms)=555
CPU time spent (ms)=16040
Physical memory (bytes) snapshot=2837708800
Virtual memory (bytes) snapshot=8200089600
Total committed heap usage (bytes)=2213019648
Shuffle Errors
BAD_ID=0
CONNECTION=0
IO_ERROR=0
WRONG_LENGTH=0
WRONG_MAP=0
WRONG_REDUCE=0
File Input Format Counters
Bytes Read=766082
File Output Format Counters
Bytes Written=84
11.3.4.5.2 Conclusion
11.3.4.6 Refernces
The details of the new version is available from the official site at
http://hadoop.apache.org/docs/r3.1.1/index.html
PageRank is a popular example algorithm used to display the ability of big data
applications to run parallel tasks. This example will show how the docker
hadoop image can be used to execute the Pagerank example which is available in
/cloudmesh/examples/pagerank
We make the steps of compiling java source, archiving class files, load input
files and run the program into one single script. To execute it with the input file:
PageRankDataGenerator/pagerank5000g50.input.0, using 5000 urls and 1
iteration:
$ cd /cloudmesh/examples/pagerank
$ ./compileAndExecHadoopPageRank.sh PageRankDataGenerator/pagerank5000g50.input.0 5000 1
0 2.9999999999999997E-5
1 2.9999999999999997E-5
2 2.9999999999999997E-5
3 2.9999999999999997E-5
4 2.9999999999999997E-5
5 2.9999999999999997E-5
6 2.9999999999999997E-5
7 2.9999999999999997E-5
8 2.9999999999999997E-5
9 2.9999999999999997E-5
If one wants to generate the java class files and archive them as the previous
exercise, one could use the following code (which is actually inside
compileAndExecHadoopPageRank.sh)
export HADOOP_CLASSPATH=`$HADOOP_PREFIX/bin/hadoop classpath`
mkdir /cloudmesh/examples/pagerank/dist
$ find /cloudmesh/examples/pagerank/src/indiana/cgl/hadoop/pagerank/ \
-name "*.java"|xargs javac -classpath $HADOOP_CLASSPATH \
-d /cloudmesh/examples/pagerank/dist
$ cd /cloudmesh/examples/pagerank/dist
$ jar -cvf HadoopPageRankMooc.jar -C . .
Result
$ hadoop fs -cat output.pagerank/part-r-00000
After a container is launched, we can run Spark in the following two modes: (1)
yarn-client and (2) yarn-cluster. The differences between the two modes can be
found here: https://spark.apache.org/docs/latest/running-on-yarn.html
Let us observe Spark task execution by adjusting the parameter of SparkPi and
the Pi result from the following two commands.
$ spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn-client --driver-memory 1g \
--executor-memory 1g \
--executor-cores 1 $SPARK_HOME/lib/spark-examples-1.6.0-hadoop2.6.0.jar 10
$ spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn-client --driver-memory 1g \
--executor-memory 1g \
--executor-cores 1 $SPARK_HOME/lib/spark-examples-1.6.0-hadoop2.6.0.jar 10000
Let us write our own word-count with Spark RDD. After the shell has been
started, copy and paste the following code in console line by line.
textFile = sc.textFile("file:///etc/hosts")
words = textFile.flatMap(lambda line:line.split())
counts = words.map(lambda word:(word, 1)).reduceByKey(lambda x,y: x+y)
counts.map(lambda x:x[1]).sum()
It will take sometime to download the image. Now we have to run docker spark
image interactively.
$ docker run -i -t -h sandbox sequenceiq/spark-native-yarn /etc/bootstrap.sh -bash
Let us run a sample KMeans example. This is already built with Spark.
Here we specify the data data set from a local folder inside the image and we run
the sample class KMeans in the sample package. The sample data set used is
inside the sample-data folder. Spark has it’s own format for machine learning
datasets. Here the kmeans_data.txt file contains the KMeans dataset.
$ ./bin/spark-submit --class sample.KMeans \
--master execution-context:org.apache.spark.tez.TezJobExecutionContext
\
--conf update-classpath=true \
./lib/spark-native-yarn-samples-1.0.jar /sample-data/kmeans_data.txt
If you run this successfully, you can get an output as shown here.
Finished iteration (delta = 0.0)
Final centers:
DenseVector(0.15000000000000002, 0.15000000000000002, 0.15000000000000002)
DenseVector(9.2, 9.2, 9.2)
DenseVector(0.0, 0.0, 0.0)
DenseVector(9.05, 9.05, 9.05)
In this example the wordcount.txt will used to do the word count using multiple
reducers. Number 1 at the end of the command determines the number of
reducers. As spark can run multiple reducers, we can specify the number as a
parameter to the programme.
$ ./bin/spark-submit --class sample.WordCount --master execution-context:org.apache.spark.tez.TezJobExecutionContext --conf update-classpath
Here we need a new image to work on. Let us run the following command. This
will pull the necessary repositories from docker hub, as we do not have most of
the dependencies related to it. This can take a few minutes to download
everything.
$ docker run -it-p 8888:8888 -v $PWD:/cloudmesh/spark --name spark jupyter/pyspark-notebook
Copy/paste this URL into your browser when you connect for the first time,
to login with a token:
http://(3a3d9f7e2565 or 127.0.0.1):8888/?token=f22492fe7ab8206ac2223359e0603a0dff54d98096ab7930
Please copy the url shown at the end of the terminal output and go to that url in
the browser.
You will see the following output in the browser, (Use Google Chrome)
First navigate to the work folder. Let us create a new python file here. Click
python3 in the new menu.
Create a new python file
Now add the following content in the new file. In Jupyter notebook, you can
enter a python command or python code and press
SHIFT + ENTER
import pyspark
sc = pyspark.SparkContext('local[*]')
rdd = sc.parallelize(range(1000))
rdd.takeSample(False, 5)
In the following stage we configure spark context and import the necessary files.
os.makedirs("data")
Next stage we use sample data set by creating them in form of an array and we
train the kmeans algorithm.
sparse_data = [
SparseVector(3, {1:1.0}),
SparseVector(3, {1:1.1}),
SparseVector(3, {2:1.0}),
SparseVector(3, {2:1.1})
]
model.predict(array([0.,1.,0.]))
model.predict(array([0.,0.,1.]))
model.predict(sparse_data[0])
model.predict(sparse_data[2])
In the final stage we put sample values and check the predictions on the cluster.
In addition to that feed the data using SparseVector format and we add the
kmeans initialization mode, the error margin and the palatalization. We put the
step size as 5 for this example. In the previous one we did not specify any
parameters.
Then in the following way you can check whether two data points belong to one
cluster or not.
isinstance(model.clusterCenters, list)
$ docker rm spark
11.4 KUBERNETES
11.4.1 Introduction to Kubernetes ☁
Learning Objectives
What is Kubernetes?
What are containers?
Cluster components in Kubernetes
Basic Units in Kubernetes
Run an example with Minikube
Interactive online tutorial
Have a solid understanding of Containers and Kubernetes
Understand the Cluster components of Kubernetes
Understand the terminology of Kubernetes
Gain practical experience with kubernetes
With minikube
With an interactive online tutorial
https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/
Kubernetes is
11.4.1.2 Terminology
Pods:
Deployments:
11.4.1.4 Minikube
To try out kubernetes on your own computer you can download and install
minikube. It deploys and runs a single-node Kubernetes cluster inside a VM.
Hence it provide a reasonable environment not only to try it out, but also for
development [cite].
In this section we will first discuss how to install minikube and then showcase an
example.
11.4.1.4.1.0.1 OSX
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.25.0/minikube-darwin-amd64 && chmod +x minikube &&
11.4.1.4.1.0.2 Windows 10
We assume that you have installed Oracle VirtualBox in your machine which
must be a version 5.x.x.
Download Kubectl
Download Minikube
After downloading these two executables place them in the cloudmesh directory
we earlier created. Rename the minikube-windows-amd64.exe to minikube.exe. Make sure
minikube.exe and kubectl.exe lie in the same directory.
11.4.1.4.1.0.3 Linux
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.25.0/minikube-linux-amd64 && chmod +x minikube &&
In this case you must run Windows PowerShell as administrator. For this search
for the application in search and right click and click Run as administrator. If
you are an administrator it will run automatically but if you are not please make
sure you provide the admin login information in the pop up.
$ cd C:\Users\<username>\Documents\cloudmesh
$ .\minikube.exe start --vm-driver="virtualbox"
$ minikube dashboard
You will need an account on FutureSystems and upload the ssh key to the
FutureSystems portal from the computer from which you want to login to echo.
To verify, if you have access try to see if you can log into
victor.futuresystems.org. You need to be a member of a valid FutureSystems
project.
https://portal.futuresystems.org/project/553
If you have verified that you have access to the victor, you can now try to login
to the kubernetes cluster head node with the same username and key. Run these
first on your local machine to set the username and login host:
$ export ECHOK8S=149.165.150.85
$ export FS_USER=<put your futersystem account name here>
NOTE: If you have access to victor but not the kubernetes system, your
project may not have been authorized to access the kubernetes cluster. Send
a ticket to FutureSystems ticket system to request this.
Once you are logged in to the kubernetes cluster head node you can run
commands on the remote echo kubernetes machine (all commands shown in
next except stated otherwise) to use the kubernetes installation there. First try to
run:
$ kubectl get pods
This will let you know if you have access to kubernetes and verifies if the
kubectl command works for you. Naturally it will also list the pods.
The following command runs an image called Nginx with two replicas, Nginx is
a popular web sever which is well known as a high performance load balancer.
$ kubectl run nginx --replicas=2 --image=nginx --port=80
As a result of this one deployment was created, and two PODs are created and
started. If you encounter and error stating that the deployment already exists
when executing the previous command that is because the command has already
been executed. To see the deployment, please use the command, this command
should work even if you noticed the error mentioned.
$ kubectl get deployment
Please note the IP address field. Make sure you are using the IP address that is
listed when you execute the command since the IP address may have changed.
Now if we try to access the nginx homepage with wget (or curl)
$ wget 192.168.56.2
It verifies that the specified image was running, and it is accessible from within
the cluster.
Next we need to start thinking about how we access this web server from outside
the cluster. We can explicitly exposing the service with the following command.
You can change the name that is set using --name to what you want. Given that is
adheres to the naming standards. If the name you enter is already in the system
your command will return an error saying the service already exists.
$ kubectl expose deployment nginx --type=NodePort --name=abc-nginx-ext
For IU students:
You could use your username or if you use one of our classes your hid. The
number part will typically be sufficient. For class users that do not use the hid in
the name we will terminate all instances without notification. In addition, we like
you explicitly to add “-ext” to every container that is exposed to the internet.
Naturally we want you to shut down such services if they are not in use. Failure
to do so may result in termination of the service without notice, and in the worst
case revocation of your privileges to use echo.
In our example you will find the port on which our service is exposed and
remapped to. We find the port 31386 in the value 80:31386/TCP in the ports
column for the running container.
Now if we visit this URL, which is the public IP of the head node followed by
the exposed port number, from a browser on your local machine
http://149.165.150.85:31386
Once you have done all the work needed using the service you can delete it
using the following command.
$ kubectl delete service <service-name>
11.4.2.3 Exercises
E.Kubernetes.fs.1:
E.Kubernetes.fs.2:
E.Kubernetes.fs.3:
https://www.sdsc.edu/support/user_guides/tutorials/singularity.html
and modified. To use it you will need an account on comet which can be
obtained via XSEDE. In case you use this material as part of a class please
contact your teacher for more information.
11.5.1 Background
What is Singularity?
There are numerous good tutorials on how to install and run Singularity on
Linux, OS X, or Windows so we won’t go into much detail on that process here.
In this tutorial you will learn how to run Singularity on Comet. First we will
review how to access a compute node on Comet and provide a simple example
to help get you started. There are numerous tutorial on how to get started with
Singularity, but there are some details specific to running Singularity on Comet
which are not covered in those tutorials. This tutorial assumes you already have
an account on Comet. You will also need access to a basic set of example files to
get started. SDSC hosts a Github repository containing a ’Hello world!" example
which you may clone with the following command:
git clone https://github.com/hpcdevops/singularity-hello-world.git
Why Singularity?
Downloading & Installing Singularity
Building Singularity Containers
Running Singularity Containers on Comet
Running Tensorflow on Comet Using Singularity
Listed next is a typical list of commands you would need to issue in order to
implement a functional Python installation for scientific research:
COMMAND=apt-get -y install libx11-dev
COMMAND=apt-get install build-essential python-libdev
COMMAND=apt-get install build-essentyial openmpi-dev
COMMAND=apt-get install cmake
COMMAND=apt-get install g++
COMMAND=apt-get install git-lfs
COMMAND=apt-get install libXss.so.1
COMMAND=apt-get install libgdal1-dev libproj-dev
COMMAND=apt-get install libjsoncpp-dev libjsoncpp0
COMMAND=apt-get install libmpich-dev --user
COMMAND=apt-get install libpthread-stubs0 libpthread-stubs0-dev libx11-dev libx11-d
COMMAND=apt-get install libudev0:i386
COMMAND=apt-get install numpy
COMMAND=apt-get install python-matplotlib
COMMAND=apt-get install python3`
First we download and upack the source using the following commands
(assuming your user name is test_user and you are working on your local computer
with super user privileges):
[test_user@localhost ~]$ wget https://github.com/singularityware/singularity/
releases/download/2.5.1/singularity-2.5.1.tar.gz tar -zxf singularity-2.5.1.tar.gz
If the file is successfully extracted, you should be able to view the results:
[test_user@localhost ~]$ cd singularity-2.5.1/
[test_user@localhost singularity-2.5.1]$ ls
Next we configure and build the package. To configure, enter the following
command (we will leave out the command prompts):
./configure
Once the installation is completed, you can check to see if it succeeded in a few
different ways:
declare -r SINGULARITY_NAME='singularity'
declare -r SINGULARITY_VERSION='2.5.1'
declare -r SINGULARITY_PREFIX='/usr/local'
declare -r SINGULARITY_CONFIG_DIR='/etc'
cd ../
tar -xzvf "${PWD}/tarballs/${SINGULARITY_NAME}-${SINGULARITY_VERSION}.tar.gz"
cd "${SINGULARITY_NAME}-${SINGULARITY_VERSION}"
./configure --prefix="${SINGULARITY_PREFIX}" --sysconfdir="${SINGULARITY_CONFIG_DIR}"
make
sudo make install
This will create a CentOS 7 container with a default size of ~805 Mb. Depending
on what additional configurations you plan to make to the container, this size
may or may not be big enough. To specify a particular size, such as ~4 Gb,
include the -s parameter, as shown in the following command:
singularity create -s 4096 centos7.img
Next, we will import a Docker image into our empty Singularity container:
singularity import centos7.img docker://centos:7
Once the container actually contains a CentOS 7 installation, you can ‘shell’ into
it with the following:
singularity shell centos7.img
Once you enter the container you should see a different command prompt. At
this new prompt, try typing:
whoami
Your user id should be identical to your user id outside the container. However,
the operating system will probably be different. Try issuing the following
command from inside the container to see what the OS version is:
cat /etc/*-release
You should be prompted for your password, and then you should see something
like the following:
Invoking an interactive shell within the container...
Next, let’s create a script within the container so we can use it to test the ability
of the container to execute shell scripts:
vi hello_world.sh
The previous command assumes you know the vi editor. Enter the following text
into the script, save it, and quit the vi editor:
#!/bin/bash echo "Hello, World!"
You may need to change the permissions on the script so it can be executable:
chmod +x hello_world.sh
Let us say you want to create a container with Ubuntu, but you may want to
create variations on the configurations without having to repeat a long list of
commands manually. First, we need our definitions file. Given next is the
contents of a definitions file which should suffice for our purposes.
Bootstrap: docker
From: ubuntu:latest
%runscript
exec echo "The runscript is the containers default runtime command!"
%files
/home/testuser/ubuntu.def /data/ubuntu.def
%environment
VARIABLE=HELLOWORLD
Export VARIABLE
%labels
AUTHOR [email protected]
%post
apt-get update && apt-get -y install python3 git wget
mkdir /data
echo "The post section is where you can install and configure your container."
Now, we simply need to issue the following command to configure our container
with Ubuntu:
sudo /usr/local/bin/singularity bootstrap ./ubuntu.img ./ubuntu.def
This may take a while to complete. In principle, you can accomplish the same
result by manually issuing each of the commands contained in the script file, but
why do that when you can use bootstrapping to save time and avoid errors.
If all goes according to plan, you should then be able to shell into your new
Ubuntu container.
11.5.12 Running Singularity Containers on Comet
Of course, the purpose of this tutorial is to enable you to use the San Diego
Supercomputer Center’s Comet supercomputer to run your jobs. This assumes
you have an account on Comet already. If you do not have an account on Comet
and you feel you can justify the need for such an account (i.e. your research is
limited by the limited compute power you have in your government-funded
research lab), you can request a ‘Startup Allocation’ through the XSEDE User
Portal:
https://portal.xsede.org/allocations-overview#types-trial
You may create a free account on the XUP if you do not already have one and
then proceed to submit an allocation request at the previously given link.
NOTE: SDSC provides a Comet User Guide to help get you started with Comet.
Learn more about The San Diego Supercomputer Center at http://www.sdsc.edu.
This tutorial walks you through the following four steps towards running your
first Singularity container on Comet:
Once you have created your container on your local system, you will need to
transfer it to Comet. There are multiple ways to do this and it can take a varying
amount of time depending on its size and your network connection speeds.
To do this, we will use scp (secure copy). If you have a Globus account and your
containers are more than 4 Gb you will probably want to use that file transfer
method instead of scp.
Browse to the directory containing the container. Copy the container to your
scratch directory on Comet. By issuing the following command:
scp ./centos7.img comet.sdsc.edu:/oasis/scratch/comet/test_user/temp_project/
Once the file is transferred, login to Comet (assuming your Comet user is named
test_user):
Next, you should submit a request for an interactive session on one of Comet’s
compute, debug, or shared nodes.
[test_user@comet-ln3 ~]$ srun --pty --nodes=1 --ntasks-per-node=24 -p compute -t 01:00:00 --wait 0 /bin/bash
Once your request is approved your command prompt should reflect the new
node id.
Before you can run your container you will need to load the Singularity module
(if you are unfamiliar with modules on Comet, you may want to review the
Comet User Guide). The command to load Singularity on Comet is:
[test_user@comet-ln3 ~]$ module load singularity
You may issue the previous command from any directory on Comet. Recall that
we added a hello_world.sh script to our centos7.img container. Let us try executing
that script with the following command:
[test_user@comet-ln3 ~]$ singularity exec /oasis/scratch/comet/test_user/temp_project/singularity/centos7.img
/hello_world.sh
If all goes well, you should see Hello, World! in the console output. You might
also see some warnings pertaining to non-existent bind points. You can resolve
this by adding some additional lines to your definitions file before you build
your container. We did not do that for this tutorial, but you would use a
command like the following in your definitions file:
# create bind points for SDSC HPC environment mkdir /oasis /scratch/ /comet /temp_project
You will find additional examples located in the following locations on Comet:
/share/apps/examples/SI2017/Singularity
and
/share/apps/examples/SINGULARITY
It is best to avoid working on Comet’s login nodes since they can become a
performance bottleneck not only for you but for all other users. You should
rather allocate resources specific for computationally-intensive jobs. To allocate
a ‘compute node’ for your user on Comet, issue the following command:
[test_user@comet-ln3 ~]$ salloc -N 1 -t 00:10:00
This allocation requests a single node (-N 1) for a total time of 10 minutes (-t
00:10:00). Once your request has been approved, your computer node name
should be displayed, e.g. comet-17-12.
Notice that the command prompt has now changed to reflect the fact that you are
on a compute node and not a login node.
[test_user@comet-06-04 ~]$
Next, load the Singularity module, shell into the container, and execute the
hello_world.sh script:
[test_user@comet-06-04 ~]$ module load singularity [test_user@comet-06-04 ~]$ singularity shell centos7.img
[test_user@comet-06-04 ~]$ ./hello_world.sh
If all goes well, you should see Hello, World! in the console output.
Of course, most users simply want to submit their jobs to the Comet queue and
let it run to completion and go on to other things while waiting. Slurm is the job
manager for Comet.
Given next is a job script (which we will name singularity_mvapich2_hellow.run) which will
submit your Singularity container to the Comet queue and run a program,
hellow.c (written in C using MPI and provided as part of the examples with the
mvapich2 default installation).
#!/bin/bash `` #SBATCH --job-name="singularity_mvapich2_hellow" #SBATCH --output="singularity_mvapich2_hellow.%j.out"
#SBATCH --error="singularity_mvapich2_hellow.%j.err" #SBATCH --nodes=2 #SBATCH --ntasks-per-node=24 #SBATCH --
CONTAINER=/oasis/scratch/comet/$USER/temp_project/singularity/centos7-mvapich2.img
The previous script requests 2 nodes and 24 tasks per node with a wall time of
10 minutes. Notice that two modules are loaded (see the line beginning with
‘module’), one for Singularity and one for MPI. An environment variable
‘CONTAINER’ is also defined to make it a little easier to manage long reusable
text strings such as file paths.
You may need to add a line specifying with allocation to be used for this job.
When you are ready to submit the job to the Comet queue, issue the following
command:
[test_user@comet-06-04 ~]$ sbatch -p debug ./singularity_mvapich2_hellow.run
To view the status of your job in the Comet queue, issue the following:
[test_user@comet-06-04 ~]$ squeue -u test_user
When the job is complete, view the output which should be written to the output
file singularity_mvapich2_hellow.%j.out where %j is the job ID (let’s say the job ID is
1000001):
[test_user@comet-06-04 ~]$ more singularity_mvapich2_hellow.1000001.out
SDSC User Support staff, Marty Kandes, has built several custom Singularity
containers designed specifically for the Comet environment.
An easy way to pull images from the singularity hub on comment is provided in
the next video:
Comet supports the capability to pull a container directly from any properly
configured remote singularity hub. For example, the following command can
pull a container from the hpcdevops singularity hub straight to an empty
container located on Comet:
comet$ singularity pull shub://hpcdevops/singularity-hello-world:master
https://singularity-hub.org/collections
That’s it! Congratulations! You should now be able to run Singularity containers
on Comet either interactively or through the job queue. We hope you found this
tutorial useful. Please contact [email protected] with any questions you might
have. Your Comet-related questions will be routed to the amazing SDSC
Support Team.
One of the more common advantages of using Singularity is the ability to use
pre-built containers for specific applications which may be difficult to install and
maintain by yourself, such as Tensorflow. The most common example of a
Tensorflow application is character recognition using the MNIST dataset. You
can learn more about this dataset at http://yann.lecun.com/exdb/mnist/.
To submit the script to Comet, first you’ll need to request a compute node with
the following command (replace account with your XSEDE account number):
[test_user@comet-ln3 ~]$ srun --account=your_account_code --partition=gpu-shared --gres=gpu:1 --pty --nodes=1 --ntasks-per-node=1 -t 00:30:0
11.5.15 Resources ☁
Several tutorials on docker that can help you understand the concepts in more
detail
https://www.tutorialspoint.com/docker/index.htm
https://www.tutorialspoint.com/docker/docker_tutorial.pdf
https://www.tutorialspoint.com/docker/docker_pdf_version.htm
11.6 EXERCISES ☁
E.Docker.1: MongoDB Container
What are the parameters on the command line that you need to
define?
You are allowed tou sue docker compose, but make sure you read the
password ond username from the yaml file. YoU must not configure it
by hand in the compose yaml file. You can use cloudmesh commands
to read the username and password.
cms config value cloudmesh.data.mongo.MONGO_USERNAME
cms config value cloudmesh.data.mongo.MONGO_PASSWORD
E.Docker.3: Cloudmesh Container
https://github.com/cloudmesh/cloudmesh-
cloud/blob/master/docker/ubuntu-19.04/Dockerfile
https://github.com/cloudmesh/cloudmesh-
cloud/blob/master/docker/ubuntu-19.04/Makefile
Questions:
E.Docker.Swarm.1: Documentation
Develop a section in the handbook that deploys a Docker Swarm
cluster on a number of ubuntu machines. Note that this may actually
be easier as docker and docker swarm are distributed with recent
versions of ubuntu. Just in case we are providing a link to an effort
we found to install docker swarm. However we have not checked it or
identified if it is useful.
https://rominirani.com/docker-swarm-tutorial-b67470cf8872
https://rominirani.com/docker-swarm-on-google-compute-
engine-364765b400ed
E.SingleNodeHadoop:
This includes:
https://hadoop.apache.org/docs/current/hadoop-project-
dist/hadoop-common/SingleCluster.html
E.MultiNodeHadoop:
https://hadoop.apache.org/docs/r3.0.0/hadoop-project-
dist/hadoop-common/ClusterSetup.html
You can use this set of instructions or identify other resources on the
internet that allow the creation of a hadoop cluster on kubernetes.
Alternatively you can use docker compose for this exercise.
E.SparkCluster: Documentation
You may want to get inspired from the talk Scalable Spark
Deployment using Kubernetes:
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-1/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-2/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-3/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-4/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-5/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-6/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-7/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-8/
http://blog.madhukaraphatak.com/scaling-spark-with-
kubernetes-part-9/
12.1 FAAS ☁
12.1.1 Introduction
Generally FaaS specifies a set of constraints on what a function can be. The
constraints include storage constraints such as a maximum size for the function,
maximum memory allowed, execution time, etc. The exact constraints differ
from provider to provider. AWS Lambda is considered as one of first FaaS
offerings. Now most cloud providers offer their own version of FaaS. Several
popular FaaS providers are listed next.
In Serverless Computing, servers are still there, its just that we dont need to
manage them.
Other than the providers there are also several open source FaaS offerings that
are available to be used. One of the most complete and popular open source
option would be Apache OpenWhisk, which was developed by IBM and later
open sourced. IBM currently deploys OpenWhisk in IBM cloud and offers it as a
IBM Cloud functions.
OpenWhisk https://github.com/apache/incubator-openwhisk
Funktion https://github.com/funktionio/funktion
Iron Functions https://github.com/iron-io/functions
Kubeless https://github.com/kubeless/kubeless
Fission https://github.com/fission/fission
FaaS-netes https://github.com/alexellis/faas-netes
There are many articles and tutorials online that provide very good information
regarding FaaS. Given next are some such resources that provide introductions
and some example usecase’s of FaaS
12.1.4 Resources
https://stackify.com/function-as-a-service-serverless-architecture
https://en.wikipedia.org/wiki/Serverless_computing
https://azure.microsoft.com/en-us/overview/serverless-computing
https://aws.amazon.com/serverless
https://aws.amazon.com/lambda
https://www.infoworld.com/article/3093508/cloud-computing/what-
serverless-computing-really-means.html
https://techbeacon.com/aws-lambda-serverless-apps-5-things-you-need-
know-about-serverless-computing
https://blog.alexellis.io/introducing-functions-as-a-service
12.1.5 Usage Examples
https://aws.amazon.com/solutions/case-studies/netflix-and-aws-lambda
https://blog.alexellis.io/first-faas-python-function
Learning Objectives
AWS does not share how the internals of AWS Lambda work in detail but as
with any general FaaS framework it should be leveraging various container
technologies underneath. You can get a better understanding on how the
internals of a FaaS framework is organized by looking at the OpenWhisk Section
AWS Lambda provides many features that allows the creation of an FaaS
application to be straight forward. An FaaS application normally consist of a set
of functions and a set of events that activate or invoke those functions. AWS
Lambda supports several programing languages that allow developers to develop
the function they require in any of the programming languages that are
supported. The following list show the programming languages that are currently
supported by AWS Lambda for function creation.
Node.js (JavaScript)
Python
Java (Java 8 compatible)
C# (.NET Core)
Go
Other than the functions the most important requirement for a good FaaS
framework is a rich set of function invocation methods which allow users to tie
together different events that happen in the echo system with the FaaS
application. In this regard AWS Lambda supports many event sources, mainly
from the AWS echo system. AWS documentation provides a complete list of
supported event sources at AWS Lambda event sources. For example a
developer can configure an function to be invoked when a S3 bucket is updated,
or configure an function to be invoked based on inputs received by Amazon
Alexa, etc.
AWS Lambda also sets several memory and storage limits for functions.
Currently the maximum memory allocated to a function is 3008MB and the
maximum allocated storage space is 512MB. However it is good to keep in mind
that monetary charge for function execution increases with the amount of
memory that is specified for the function.
If new users want to experiment with AWS lambda, AWS does provide a free
tier for AWS Lambda, which include 1 million function invocations per month.
You can find a more detailed description of the free tier in the AWS docs AWS
Lambda Pricing.
With the GUI interface it is relatively easy to try out your first Serverless
function with AWS Lambda. Please follow the steps defined at How to run your
first AWS Lambda function in the cloud (this link does not exsit any longer)
One key point to note here is that Amazon charges only when the functions are
executed. So, The Seattle Times is charged for this service only when the images
are been resized. Lambda can be used for Analytics. So lets say, there has been a
purchase of a house on zillow, this data can be saved into a NoSQL database and
this entry into the database is an event which can trigger Lambda function to
load the order information into Amazon Redshift. Then we can run Analytics on
top of this data. We can also build serverless applications composed of functions
that are triggered by events and automatically deploy them using AWS
CodePipeline and AWS CodeBuild. For more information, see Deploying
Lambda-based Applications.
There are development groups or companies mainly startups, where they want to
just focus on their application development without wanting to care about their
infrastructure and they also want that they pay for what they use. Hence, AWS
Lambda comes into play which satisfies all their needs.
Ironically, Lambda could be a threat to one of the Amazon’s most popular EC2.
Developers can build apps that run entirely on Lambda functions instead of
spinning up EC2 VMs. Amazon may be out-innovating itself with Lambda.
Step 1: The very first thing we need is an AWS account. (There is already a
section on this, please go through that to understand how to create an AWS
account - Creating AWS account
Step 2: We will be writing a function that we call isPalindrome, which will check if
the string is palindrome or not.
function isPalindrome(string) {
const reverse = string.split('').reverse().join('');
const isPalindrome = (string === reverse);
const result = isPalindrome ? `${string} is a Palindrome` : `${string} is not a Palindrome`;
return result;
}
document.write(isPalindrome('abcd'));
Step 4: Now we will select AWS Lambda from console and then click on Get
Started Now (see Figure 138)
Step 5: For runtime, we will select Node.js 6.10 and then press “Blank
Function.” (see Figure 139).
Figure 139: Blank Function
Step 6: We will skip this step and press Next . (see Figure 140)
Lambda function is just a function, named as handler here and the function takes
three parameter - event, context and a callback function. The callback will run
when the Lambda function is done and will return a response or an error
message. For the Blank Lambda blueprint, response is hard-coded as the string
Hello from Lambda.
Step 8: Please scroll down for choosing the Role “Create new Role from
template”, and for Role name we are going to use isPalindromeRole in our case.
For Policy templates, we will choose “Simple Microservice” permissions. (see
Figure 142)
Figure 142: Policy
Step 9: For Memory, 128 megabytes is more than enough for our simple
function. As for the 3 second timeout, this means that — should the function not
return within 3 seconds - AWS will shut it down and return an error. Three
seconds is also more than enough. Leave the rest of the advanced settings
unchanged (see @#fig:aws-lambda-settings).
Figure 143: Advanced Settings Source
Step 10: Let’s click on the “Create function” button now to create our first
Lambda function. (see Figure 144)
Figure 144: Create
Step 11: Now that we have created our first Lambda function, let’s test it by
clicking Test (see Figure 145)
Figure 145: Test
The output will be the hard-coded response of Hello from Lambda. from the created
Lambda function. (see Figure 146)
Step 12: Now let us add our isPalindrome.js function code here to Lambda function
but instead of return result use callback(null, result). Then add a hard-coded string
value of abcd on line 3 and press Test. (see Figure 147)
Similarly, let us try with string abcdcba and in this case output should return abcdcba is
a Palindrome. Thus, our Lambda function is behaving as expected.
this section includes many refernces to other tools, that need bibtex
refernces.
Apache OpenWhisk is a Function as a Service (FaaS), aka Serverless computing,
platform used to execute code in response of an events via triggers by managing
the infrastructure, servers and scaling. The advantage of OpenWhisk over
traditional long-running VM or container approach is that there is lack of
resiliency-related overhead in OpenWhisk. OpenWhisk is inherently scalable
since the actions are executed on demand. OpenWhisk also helps the developers
to focus only on coding by taking care of infrastructure-related tasks like
monitoring and patching.
The developers provide the code written in the desired programming language
for the desired action and this code will be executed in response to the events.
The triggering can be invoked using HTTP requests or external feeds. The
events invoking the triggers ranges from database modification to new variables
in IoT sensors. Actions that response to these events could also range from a
Python code snippet to a binary code in a container and it is as well possible to
chain the actions. Note that these actions are deployed and executed
instantaneously and can be invoked not only by triggers but also using the
OpenWhisk API or CLI.
The wsk command is what is known as OpenWhisk CLI, which we will show how
to install in the next sections. Note that OpenWhisk’s API is RESTful and fully
HTTP based. In other words, the previously-mentioned wsk action command is
basically a HTTP request equivalent to the following:
POST /api/v1/namespaces/$userNamespace/actions/HelloAction
Host: $openwhiskEndpoint
The userNamespace variable defines the namespace in which the HelloAction is put into.
Accordingly, nginx is the entering point of the OpenWhisk system and it plays
an important role as a HTTP server as well as a reverse proxy server, mainly
used for SSL termination and HTTP request forwarding.
We learned that nginx does not do any processing on the HTTP request except
decrypting it (SSL Termination). The main processing of the request starts in the
Controller. The controller plays the role of the interface for user both for actions
and Create, Read, Update, and Delete (CRUD) requests, translating the user’s
POST request to action invocation. The controller has an essential role in
OpenWhisk workflow and its role is not finished here and is partially involved in
next steps as well.
12.3.1.3 CouchDB
After authentication and authorization using the subjects database, the record for
the action HelloAction is load from whisks database. This record contains the code, the
parameters consist of default parameters merged with user parameters, as well as
the resource limits, e.g. maximum memory. The HelloAction record in whisk contains
its code (listed previously) and no parameters as the code does not get any
parameters.
Next comes the load balancer which is technically part of the controller and it is
load balancer’s responsibility to check the health status of the executors, known
as Invokers, continuously. Load balancer is aware of the available invokers and
select them for the actions accordingly.
12.3.1.5 Kafka
For a request user sends, there are two scenarios where things can go bad:
Both of this scenarios can be handled with Kafka distributed messaging system.
The action invocation mechanism with Kafka is as follows:
The Action example is a node.js action and therefore the invoker will start a node.js
container, inject our previsouly-mentioned code to it, runs the code and gets the
results, save the logs and terminates the node.js container.
HelloAction example containing the log in JSON format, would look like this:
{
"activationId": "31809ddca6f64cfc9de2937ebd44fbb9",
"response": {
"statusCode": 0,
"result": {
"hello": "world"
}
},
"end": 1474459415621,
"logs": [
"2016-09-21T12:03:35.619234386Z stdout: Hello World"
],
"start": 1474459415595,
}
Similar to the same API call used for submitting the action, we can use
OpenWhisk’s API to retrieve the result using the ActivationId:
wsk activation get 31809ddca6f64cfc9de2937ebd44fbb9
Make sure you do not have any services running on the following ports
otherwise the docker compose will fail starting some of the containers:
In case you have services running on any of the previous ports, you can either
stop the local services that are using these ports or alternatively you can modify
the docker-compose.yml and change the source port number in the port number mapping.
The latter option is, however, more tricky because you have to make sure the
change does not affect the communication between the containers. For instance
if you have Apache service running on Port 80, then open docker-compose.yml, search for
the keyword 80: to find the port mapping with source port of 80: bash ports: - "80:80"
After that, you should be able to run make quick-start successfully and then you can
check the status of the running docker containers using:
$ docker ps --format "{{.ID}}: {{.Names}} {{.Image}}"
16e7746c4af1: wsk0_9_prewarm_nodejs6 openwhisk/nodejs6action:latest
dd3c4c2d4947: wsk0_8_prewarm_nodejs6 openwhisk/nodejs6action:latest
6233ae715cf7: openwhisk_apigateway_1 openwhisk/apigateway:latest
3ac0938aecdd: openwhisk_controller_1 openwhisk/controller
e1bb7272a3fa: openwhisk_kafka-topics-ui_1 landoop/kafka-topics-ui:0.9.3
6b2408474282: openwhisk_kafka-rest_1 confluentinc/cp-kafka-rest:3.3.1
9bab823a891b: openwhisk_invoker_1 openwhisk/invoker
98ebd5b4d605: openwhisk_kafka_1 wurstmeister/kafka:0.11.0.1
65a3b2a7914f: openwhisk_zookeeper_1 zookeeper:3.4
9b817a6d2c40: openwhisk_redis_1 redis:2.8
e733881d0004: openwhisk_db_1 apache/couchdb:2.1
6084aec44f03: openwhisk_minio_1 minio/minio:RELEASE.2018-07-13T00-09-07Z
It is always possible that something goes wrong in the process of deploying the
12 dockers. If the make quick-start process stuck at some point, the best way to find
the issue is to use the docker ps -a command to check which of the containers is
causing the issue. Then you can try to fix the issue of that container separately.
This fix could possibly happen in docker-compose.yml file. For instance, there was some
issue with the openwhisk/controller docker at some point and it turns out the issue was
the following line in the docker-compose.yml:
command: /bin/sh -c "exec /init.sh --id 0 >> /logs/controller-local_logs.log 2>&1"
this line is indicating that the following command should be run after the
container is started:
$ /init.sh --id 0 >> /logs/controller-local_logs.log 2>&1
However, starting another instance of the docker image with this command
outputted a Permission Denied error which could be fixed either by changing the logs
folder permission in the docker image or container (followed by a commit) or
saving the log file in another folder. In this case replacing that line with the
following line would temporarily fix the issue:
command: /bin/sh -c "exec /init.sh --id 0 >> /home/owuser/controller-local_logs.log 2>&1"
Running the wsk without any command or flag, will print its help:
~/incubator-openwhisk-devtools/docker-compose/openwhisk-src/bin$ ./wsk
____ ___ _ _ _ _ _
/\ \ / _ \ _ __ ___ _ __ | | | | |__ (_)___| | __
/\ /__\ \ | | | | '_ \ / _ \ '_ \| | | | '_ \| / __| |/ /
/ \____ \ / | |_| | |_) | __/ | | | |/\| | | | | \__ \ <
\ \ / \/ \___/| .__/ \___|_| |_|__/\__|_| |_|_|___/_|\_\
\___\/ tm |_|
Usage:
wsk [command]
Available Commands:
action work with actions
activation work with activations
package work with packages
rule work with rules
trigger work with triggers
sdk work with the sdk
property work with whisk properties
namespace work with namespaces
list list entities in the current namespace
api work with APIs
You can then re-invoke the built-in Hello World example using:
~/incubator-openwhisk-devtools/docker-compose$ make hello-world
creating the hello.js function ...
invoking the hello-world function ...
adding the function to whisk ...
ok: created action hello
invoking the function ...
invocation result: { "payload": "Hello, World!" }
{ "payload": "Hello, World!" }
creating an API from the hello function ...
ok: updated action hello
invoking: http://192.168.2.2:9090/api/23bc46b1-71f6-4ed5-8c54-816aa4f8c502/hello/world
"payload": "Hello, World!"
ok: APIs
Action Verb API Name URL
/guest/hello get /hello http://192.168.2.2:9090/api/23bc46b1-71f6-4ed5-8c54-816aa4f8c502/hello/world
deleting the API ...
ok: deleted API /hello
deleting the function ...
ok: deleted action hello
We already invoked the built-in hello world action. Now, we try to build a new
custom action. First create a file called greeter.js:
function main(input) {
return {payload: 'Hello, ' + input.user.name + ' from ' + input.user.location + '!'};
}
Afterwards you can get the list of actions to make sure your desired action is
created:
$ wsk -i action list
actions
/guest/greeter private nodejs:6
The result of the previous command is showing that the hello action has been
invoked twice and the greeter action was invoked once. You can get more
information about each of the activation using the wsk -i activation get [ACTIVATION_ID]:
$ wsk -i activation get 976a7d02dab7460eaa7d02dab7760e9a
ok: got activation 976a7d02dab7460eaa7d02dab7760e9a
{
"namespace": "guest",
"name": "greeter",
"version": "0.0.1",
"subject": "guest",
"activationId": "976a7d02dab7460eaa7d02dab7760e9a",
"start": 1539980284774,
"end": 1539980284886,
"duration": 112,
"response": {
"status": "success",
"statusCode": 0,
"success": true,
"result": {
"payload": "Hello Vafa from Indiana!"
}
},
...
Finally, after you are finished using the OpenWhisk Devtools, you can stop
platform using:
~/incubator-openwhisk-devtools/docker-compose$ make destroy
Stopping openwhisk_apigateway_1 ... done
Stopping openwhisk_controller_1 ... done
Stopping openwhisk_kafka-topics-ui_1 ... done
Stopping openwhisk_kafka-rest_1 ... done
Stopping openwhisk_invoker_1 ... done
Stopping openwhisk_kafka_1 ... done
Stopping openwhisk_zookeeper_1 ... done
Stopping openwhisk_redis_1 ... done
Stopping openwhisk_db_1 ... done
Stopping openwhisk_minio_1 ... done
...
12.4 KUBELESS ☁
add bibtex
12.4.1 Introduction
The Functions API provides a REST Endpoint to create, read, update and delete
functions. This is developed as a Kubernetes Custom Resource Definitions
(CRD). CRD is an extension point provided by Kubernetes that can be used to
create custom resources. A custom resource exposes a REST endpoint and
makes it available as any other REST API that is embedded with Kubernetes.
Once created, Functions custom resource exposes the REST API that can be
used for function CRUD operations. The Kubeless-controller is a custom
controller that is deployed with the Kubernetes installation. This controller
continuously monitors invocations that occur at the functions REST API and
performs the required tasks according to the invocation. For example, if the
invocation is for a function creation, the controller will create a Deployment for
the function and a Service to expose the function. The Deployment will contain
information on what runtime the function is intended to use, therefore the
deployment will make sure to spin up Pods which will host containers of that
runtime when a function execution is requested. Kafka is deployed within the
Kubernetes installation as an event source which can be used to trigger the
functions.
Because the container image that is used to execute the function is generic, it
does not have any specific dependencies that are required by the function and the
function code itself. These two need to be injected into the Pod when the Pod is
created. For the application logic/function code, Kubless uses a configuration
resource provided by Kubernetes API named ConfigMap. The code segment is
attached to the ConfigMap which can be read from within a Pod once the Pod is
created. In order to install all the required dependencies, another Kubernetes
resource named Init containers are utilized. Init containers are a special kind of
container which can be configured to run when a Pod is created. Kubernetes also
guarantees that all init containers specified for a Pod will run till completion
before the application containers ( in this case function container) are executed.
Kubless runs an init container which will install all the required dependencies for
the function before invoking the function. The function dependencies must be
specified at function creation time.
12.5 MICROSOFT AZURE FUNCTION ☁
fa18-516-08
Learning Objectives
https://cloud.google.com/functions/use-cases/
gives more detail about the use cases such as Serverless application backends,
Real-time data processing, Intelligent applications - all without the need of
provisioning a server instance or the overhead of managing a server instance.
The functions are invoked as services whenever needed for a business
requirement and the cost is billed as per the minutes of usage just for the
function execution time. The Google Cloud Functions can be written in Node.js
or Python. For Python runtime environment refer to the page
https://cloud.google.com/functions/docs/concepts/python-runtime
https://cloud.google.com/functions/docs/concepts/nodejs-6-runtime
For Node.js 8 runtime environment refer to the page
https://cloud.google.com/functions/docs/concepts/nodejs-8-runtime>
Following from the example as presented in AWS Lambda section, we will look
into a simple example of building a Google Cloud Function to check if a string is
Palindrome or not. The implementation will be in Python and we will use Python
runtime environment. We will use HTTP trigger to invoke the function using
HTTP request. We will also use the Google Cloud Console to build, deploy and
test the function. Finally we will use HTTP url to send request to the function to
get the result of our query.
Let us begin:
Step 1: Login to Google Cloud Platform with your GCP account. We are using
free tier for this demonstration. Refer to the section for Google Cloud in the
epub for creting a free tier GCP account.
Step 6: In the next page, give a name to the function. In our case we are giving
function name as isPalindrome. Specify the memory (128 mb is good for this
demo). Select the function trigger as HTTP. Choose inline editor for the source
code and finally Python 3.7 as the run time environment.(see Figure 154)
Figure 154: Name Function
Step 7: In the inline source editor, write a Python function and then click Create.
We have written a Python function to check for Palindrome string. NOTE: This
is not an optimized Python code, it is just used here for demonstration purpose.
This function can be optimized further with Python standards style writing.(see
Figure 155)
Figure 155: :Write Python Function
Step 8: The function is created and deployed in the next page (see Figure 156)
and Figure 157)
Figure 156: Function is Deployed
Step 10: In the Trigger event box, write a HTTP message request in JSON
format and click Test the Function (see Figure 159)
Figure 159: Trigger Event
Step 11: The response box will show the result of the test as expected (see
Figure 160)
Figure 160: Result
Step 12: Let us run one more Test (see Figure 161)
Figure 161: Another Test
Step 13: You will get the expected result (see Figure 162)
Figure 162: Expected Result For Test
Step 14: Let us test our function deployment using url. Click on the function
name (see Figure 163)
Step 16: In a web browser type the url and add the HTTP request to it and hit
enter
https://us-central1-test-functions-12345.cloudfunctions.net/isPalindrome?
message=abcd
Step 17: You will get a response back from the function(see Figure 165)
Figure 165: Test Http
This completes our demo for Google Cloud Function offered as Function as
Service. To learn more about Google Cloud Functions and trigger options
available alongwith triggers using command line - visit
https://cloud.google.com/functions/
To learn about creating and deploying functions using command line instead of
GCP console - visit
https://cloud.google.com/functions/docs/quickstart
12.7 OPENFAAS ☁
OpenFaas is a framework for building serverless functions on docker containers
and follows the same workflow as micro services. Since, OpenFaas uses Docker
and Kubernetes technologies, it will give lot of hosting options ranging from a
laptop to large-scale cloud systems Any program written in any language can be
packaged as a function within in a container which gives a best approach to
convert all the old code to run on cloud-based infrastructure
Easy to Use
Deployable to private or public clouds in container
Simplicity in architecture and design
Open and extensible platform
Language agnostic
There are three components which include API Gateway, Function Watchdog
and the instance of Prometheus. All the functions run on Docker containers
orchestrated by either Docker Swarm or Kubernetes. The function watchdog is
part of the function containers, whereas the API Gateway and Promoethues
instance are services.
It is a tiny HTTP server, encolsed along with the app in the docker image. It
receives request from the API Gateway, triggers the app. It provide args and
catch result through STDIN/STDOUT
12.7.1.4 Monitoring
OpenFaas makes monitoring simple with the use of Prometheus. The end users
can install Grafana Dashboard and connect point to the Promotehus data source.
This provides quick access to the dashboard to monitor the OpenFaas functions
Figure 168: faas - OpenFaas - Grafana [91]
12.7.2.1 Prerequistics
1. Docker
2. Git Bash (for Windows)
OpenFaas gives the option to use yaml(.yml) file for configuring the functions
and the image will be built by OpenFaas automatically. Alternatively, custom
docker image can be built and passed as an argument to the OpenFaas CLI. This
gives the flexibility for the developers to extend further which is not in the
standard yaml file.
$ git clone https://github.com/openfaas/faas
$ cd faas
$ git checkout master
$ ./deploy_stack.sh --no-auth
$ cd <test function folder>
$ docker build -t <test function image>
$ faas-cli deploy --image <test function image> --name <test function name
OpenFaas can be tested via curl, faas-cli, or any HTTP-based client to connect to
the API gateway to invoke a function
Once the function is deployed, the functions can be verified in the following url
http://127.0.0.1:8080
This section illustrates how to create a simple Python function with OpenFaaS.
Following are the the steps involved in creating and deploying a function with
OpenFaaS
Install OpenFaas
Install the OpenFaaS CLI
Build the function
Deploy the function
Installing OpenFaas:
https://docs.openfaas.com/deployment
Installing CLI:
functions:
func-python:
lang: python
handler: ./func-python
image: func-python
Docker engine builds the function into an image in the docker library and images
will appear as follows
$ docker images | grep func-python
func-python latest <image ID> one minute ago
Function can be tested either through the OpenFaas portal UI or with curl
command
$ curl 127.0.0.1:8080/function/func-python -d "Test Successfull"
Python Function: Test Successfull
faas-cli commands can also be used to list and invoke the functions
faas-cli list
echo "Test" | faas-cli invoke func-python
12.8 OPENLAMDA ☁
Cloud computing is evolving. All major public cloud providers now support
serverless computing such as AWS Lambda, Google Cloud Functions (Alpha)
and Azure Function. Serverless computing introduces many new research
challenges in the areas of sandboxing, session management, load balancing, and
databases. To facilitate work in these areas, OpenLambda is building an open-
source serverless computing platform.
https://open-lambda.org/resources/slides/ol-first-meeting.pdf.
https://open-lambda.slack.com/.
Wat: https://www.destroyallsoftware.com/talks/wat.
History of Containers: https://www.youtube.com/watch?v=hgN8pCMLI2U.
AFS benchmarking: http://www.cs.cmu.edu/~coda/docdir/s11.pdf.
12.8.2 Development
OpenLambda source code it available on github (all material below have been
sourced from github): https://github.com/open-lambda/open-lambda.
12.8.3 OpenLambda
First, run the dependency script to install necessary packages (e.g., Golang,
Docker, etc.)
$ ./quickstart/deps.sh
Now, build the OpenLambda worker & its dependencies and run integration
tests. These tests will spin up clusters in various configurations and invoke a few
lambdas.
$ make test-all
To manage a cluster, we will use the admin tool. This tool manages state via a cluster
directory on the local file system. More details on this tool can be found below.
First, we need to create a cluster. Ensure that the path to the cluster directory
exists, and it does not.
$ ./bin/admin new -cluster my-cluster
Cluster containers:
The default configuration uses a local directory to store handler code, so creating
new lambda functions is as simple as writing files to the ./my-cluster/registry directory.
Now send a request for the hello lambda to the worker via curl. Handlers are passed
a Python dictionary corresponding to the JSON body of the request. hello will
echo the "name" field of the payload to show this.
$ curl -X POST localhost:8080/runLambda/hello -d '{"name": "Alice"}'
To create your own lambda named <NAME>, write your code in ./my-
Now, kill the worker process and (optionally) remove the cluster directory.
$ ./bin/admin kill -cluster=my-cluster
$ rm -r my-cluster
12.8.5 Administration
The admin tool is used to manage OpenLambda clusters. This tool manages state
via a cluster directory on the local file system. Note that only a single
OpenLambda worker per machine is currently supported.
While the process is running, you may ping it from another terminal with the
following command:
$ curl http://localhost:8080/status
If the worker is ready, the status request will return a “ready” message.
Of course, you will typically want to run one (or maybe more) workers as
servers in the background on your machine. Most of the remaining admin
commands allow you to manage these long-running workers.
For OpenLambda, a local cluster’s name is the same as the file location. Thus,
<ROOT> should refer to a local directory that will be created for all OpenLambda
files. The layout of these files in the <ROOT> directory is described in detail below.
You will need to pass the cluster name/location to all future admin commands
that manage the cluster.
The <ROOT>/config/template.json file in the cluster located at <ROOT> will contain many
configuration options specified as keys/values in JSON. These setting will be
used for every new OpenLambda worker. You can modify these values by
specifying override values (again in JSON) using the setconf command. For
example:
$ ./admin setconf --cluster=<ROOT> '{"sandbox": "sock", "registry": "local"}'
In the above example, the configuration is modified so that workers will use the
local registry and the “sock” sandboxing engine.
This will create a specified number of workers listening on ports starting at the
given value. For example, suppose <NUM>=3 and <PORT>=8080. The workers command will
create three workers listening on ports 8080, 8081, and 8082. The workers
command is basically a convenience wrapper around the worker-exec command. The
workers command does three things for you: (1) creates a config file for each
worker, based on template.json, (2) invokes worker-exec for each requested worker
instance, and (3) makes the workers run in the background so they continue
executing even if you exit the terminal.
When you want to stop a local OpenLambda cluster, you can do so by executing
the of kill command:
$ ./admin kill --cluster=<NAME>
This will halt any processes or containers associated with the cluster.
The registry will start listening on the designated port. You may generate the
KEY and SECRET randomly yourself if you wish (or you may use some other
hard-to-guess SECRET). Keep these values handy for later uploading handlers.
The <ROOT>/config/template.json file specifies registry mode and various registry options.
You may manually set these, but as a convenience, the registry command will
automatically populate the configuration file for you when you launch the
registry process. Thus, to avoid manual misconfiguration, we recommend
running ./admin registry before running ./admin workers. Or, if you wish to use the local-
directory mode for your registry, simply never run ./admin registry (the default
configs use local-directory mode).
After the registry is running, you may upload handlers to it via the following
command:
$ ./admin upload --cluster=<NAME> --handler=<HANDLER-NAME> \
--file=<TAR> --access-key=<KEY> \
--secret-key=<SECRET>
The above command should use the KEY/SECRET pair used when you
launched the registry earlier. The <TAR> can refer to a handler bundle. This is just a
.tar.gz containing (at a minimum) a lambda_func.py file (for the code) and a
packages.txt file (to specify the Python dependencies).
You will find six subdirectories in the my-cluster' directory: config,logs,base,packages,registry, and
workers.
The config directory will contain, at a minimum, a template.json file. Once you start
workers, each worker will have an additional config file in this directory named
worker-<N>.json (the admin tool creates these by copying first copying template.json, then
Each running worker will create two files in the logs directory: worker-<N>.out and worker-
<N>.pid. The “.out” files contain the log output of the workers; this is a good place
to start if the workers are not reachable or if they are returning unexpected
errors. The “.pid” files each contain a single number representing the process ID
of the corresponding worker process; this is mostly useful to the admin kill tool
for identifying processes to halt.
All OpenLambda handlers run on the same base image, which is dumped via
Docker into the my-cluster/base directory. This contains a standard Ubuntu image
with additional OpenLambda-specific components. This base is accessed on a
read-only basis by every handler when using SOCK containers.
The ./my-cluster/packages directory is mapped (via a read-only bind mount) into all
containers started by the worker, and contains all of the PyPI packages installed
to workers on this machine.
Each worker has its own directory for various state. The storage for worker N is
rooted at ./my-cluster/workers/worker-<N>. Within that directory, handler containers will
have scratch space at ./handlers/<handler-name>/<instance-number>. For example, all containers
created to service invocations of the “echo” handler will have scratch space
directories inside the ./handlers/echo directory. Additionally, there is a directory ./my-
cluster/workers/worker-<N>/import-cache that contains the communication directory mapped
Suppose there is an instance of the “echo” handler with ID “3”. That container
will have it’s scratch space at ./handlers/echo/3 (within the worker root, ./my-
cluster/workers/worker-<N>). The handler may write temporary files in that directory as
necessary. In addition to these, there will be three files: server_pipe sock file (used
by the worker process to communicate with the handler) and stdout and stderr files
(handler output is redirected here). When debugging a handler, checking these
output files can be quite useful.
Note that the same directory can appear at different locations in the host and in a
guest container. For example, containers for two handlers named “function-A”
and “function-B” might have scratch space on the host allocated at the following
two locations:
$ ./my-cluster/workers/worker-0/handlers/function-A/123
$ ./my-cluster/workers/worker-0/handlers/function-B/321
As a developer debugging the functions, you may want to peek in the above
directories to look for handler output and generated files. However, in order to
write code for a handler that generates output in the above locations, you will
need to write files to the /host directory (regardless of whether you’re writing code
for function-A or function-B) because that is where scratch space is always
mapped within a lambda container.
12.8.6 Configuration
document the configuration parameters and how they interact. Also describe
how to use the packages.txt file in a handler directory to specify dependencies.
12.8.7 Architecture
13.1 MQTT ☁
Learning Objectives
With the increase importance of cloud computing and the increased number of
edge devices and their applications, such as sensor networks, it is crucial to
enable fast communication between the sensing devices and actuators, which
may not be directly connected, as well as cloud services that analyze the data. To
allow services that are built on different software and hardware platforms to
communicate, a data agnostic, fast and service is needed. In addition to
communication, the data generated by these devices, services, and sensors must
be analyzed. Security aspects to relay this data is highly important. We will
introduce a service called MQTT, which is a common, easy to use, queuing
protocol that helps meet these requirements.
13.1.1 Introduction
MQTT was first developed in 1999 to connect oil pipelines [93]. The protocol
has been designed to be used on top of TCP/IP protocol in situations where
network bandwidth, and available memory are limited allowing low power
usage. However, as it is implemented on top of TCP/IP it is reliable in contrast
to other protocols such as UDP. It allows efficient transmission of data to
various devices listening for the same event, and is scalable as the number of
devices increase [94][95].
MQTT is becoming more popular than ever before with the increasing use of
mobile device and smartphone applications such as Facebook’s Messenger and
Amazon Web Services. This protocol is used in WIFI or low bandwidth
network. MQTT does not require any connection with the content of the
message.
The current support for MQTT is conducted as part of the Eclipse Phao project
[96]. As MQTT is a protocol many different clients in various languages exist.
This includes languages such as Python, C, Java, Lua, and many more.
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf
This allows for decoupling of functionality at various levels. The publisher and
subscriber do not need to be close to each other and do not need to know each
others identity. They need only to know the broker, as the publisher and the
subscribers do not have to be running either at the same time nor on the same
hardware [98].
13.1.2.1 Topics
MQTT implements a hierarchy of topics that are relates to all messages. These
topics are recognised by strings separated by a forward-slash (/), where each part
represents a different topic level. This is a common model introduced in file
systems but also in internet URLs.
Subscribers can subscribe to different topics via the broker. Subscribing to topic-
allows the subscriber to receive all messages that are associated with topics
level0
that start with topic-level0. This allows subscribers to filter what messages to receive
based on the topic hierarchy. Thus, when a publisher publishes a message related
to a topic to the broker, the message is forwarded to all the clients that have
subscribed to the topic of the message or a topic that has a lower depth of
hierarchy [98] [97].
13.1.2.2 Callbacks
For example, the paho-mqtt package for python provides callbacks methods
including on-connect(), on-message() and on-disconnect(), which are invoked when the
connection to the broker is complete, a message is received from the broker, and
when the client is disconnected from the broker respectively. These methods are
used in conjunction with the loop-start() and loop-end() methods which start and end an
asynchronous loop that listens for these events invoking the relevant callbacks.
Hence it frees the services to perform other tasks [99] when no messages are
available, thus reducing overhead.
MQTT has been designed to be flexible allowing for the change of quality of
service (QoS) as desired by the application. Three basic levels of QoS are
supported by the protocol: Atmost-once (QoS level 0), Atleast-once (QoS level
1) and Atmost-once (QoS level 2) [99], [100].
QoS level 0:
The QoS level of 0 is used in applications where some dropped messages
may not affect the application. Under this QoS level, the broker forwards a
message to the subscribers only once and does not wait for any
acknowledgement [100][99].
QoS Level 1:
The QoS level of 1 is used in situations where the delivery of all messages
is important and the subscriber can handle duplicate messages. Here the
broker keeps on resending the message to a subscriber after a certain
timeout until the first acknowledgement is received.
QoS Level 3:
A QoS level of 3 is used in cases where all messages must be delivered and
no duplicate messages should be allowed. In this case the broker sets up a
handshake with the subscriber to check for its availability before sending
the message [99], [100].
The various levels of quality of service allow the use of this protocol with
different service level expectations.
MQTT specification uses TCP/IP to deliver the messaged to the subscribers, but
it does not provide security by default to enable resource constrained IoT
devices. “It allows the use of username and password for authentication, but by
default this information is sent as plain text over the network, making it
susceptible to man-in-the middle attacks” [101], [102]. Therefore, to support
sensitive applications additional security measures need to be integrated through
other means. This may include for example the use of Virtual Private Networks
(VPNs), Transport Layer Security, or application layer security [102].
Transport Layer Security (TLS) and Secure Sockets Layer (SSL) are
cryptographic protocols that establish a the identity of the server and client with
the help of a handshake mechanism which uses trust certificates to establish
identities before encrypted communication can take place [103]. If the
handshake is not completed for some reason, the connection is not established
and no messages are exchanged [102]. “Most MQTT brokers provide an option
to use TLS instead of plain TCP and port 8883 has been standardized for secured
MQTT connections” [101].
When connecting to the broker this token can be used to check whether the client
is authorised to connect at this time or not. Additionally the same validations can
be used when publishing or subscribing to the broker. The broker may use a
third party resource such as LDAP (lightweight directory access protocol) to
look up authorizations for the client [104]. Since there can be a large number of
clients and it can become impractical to authorize everyone, clients may be
grouped and the authorizations may be checked for each group [103].
As the individual IoT devices perform their respective functions in the sensor
network, a lot of data is generated which needs to be processed. MQTT allows
easy integration with other services, that have been designed to process this data.
Let us provide some examples of MQTT integration into other Services.
Apache Storm.
ELK stack.
When using optimized MQTT broker services, MQTT can be utilized for
enterprise and production environments. A good example is the use of EMQ
(Erlang MQTT Broker) that provides a highly scalable, distributed and reliable
MQTT broker for enterprise-grade applications [111].
13.1.6 Installation
On OSX yo need to first install mosquito, which is easiest to install with brew
Open a terminal and use homebrew to install mosquito and than you can install
paho with pip
brew install mosquitto
pip install paho-mqtt
You need to start the mosquito service buy hand to use it.
You can integrate mosquito service on boot, while adding it via LaunchAgents.
This can be achieved by linking it as follows:
ln -sfv /usr/local/opt/mosquitto/*.plist ~/Library/LaunchAgents
Now you can test the installation and ensure the server is running successfully.
Open a new command window and start a listener.
mosquitto_sub -t topic/state
To test teh setup you can in another window, send a message to the listener.
mosquitto_pub -t topic/state -m "Hello World"
On ubuntu you need to first install mosquito, than with pip you install paho-mqt
$ sudo apt-get install mosquitto mosquitto-clients
$ pip install paho-mqtt
If you have experimented with the Raspberry P and MQTT, you can contribute
to this section.
13.1.6.4.1 Broker
You will need to add the mosquito repository to the known repositories as
follows:
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
apt-get update
13.1.6.4.2 Client
In this example we are demonstrating how to set up a MQTT broker, a client and
a subscriber while just using regular servers and clients. The code of this
example is located at:
https://github.com/bigdata-i523/sample-hid000/tree/master/experiment/mqtt
A test program that starts a MQTT broker and client showcases how simple the
interactions between the publisher and subscribers are while using a higher level
API such as provided through the python client library of Paho.
import paho.mqtt.client as mqtt
import time
broker_address="localhost"
# broker_address="test.mosquitto.org"
# broker_address="broker.hivemq.com"
# broker_address="iot.eclipse.org"
print("creating new instance")
client = mqtt.Client("i523") #create new instance
client.on_log=on_log
client.on_message=on_message #attach function to callback
print("connecting to broker")
client.connect(broker_address) #connect to broker
client.loop_start() #start the loop
print("Subscribing to topic","robot/leds/led1")
client.subscribe("robot/leds/led1")
time.sleep(4) # wait
client.loop_stop() #stop the loop
https://github.com/bigdata-i523/hid201/tree/master/experiment/mqtt
The setup used three different machines. A laptop or a desktop running the
MQTT broker, and two raspberry pis configured with raspbian operating system.
Eclipse Paho MQTT client was setup on each of the raspberry pis [99].
Additionally all three devices were connected to an isolated local network.
GrovePi shields for the raspberry pis, designed by Dexter Industries were used
on each of the raspberry pis to connect the actuators as they allow easy
connections ot the raspberry pi board [112]. The actuators used were Grove
relays [113] and Grove LEDs [114] which respond to the messages received via
MQTT.
To control the leds and relays, the python library cloudmesh-pi [115], developed
at Indiana University was used. The library consists of interfaces for various IoT
sensors and actuators and can be easily used with the grove modules.
13.1.8.2 Results
The two Raspberry Pis subscribe connect to the broker and subscribe with
different topics. The raspberry pis wait for any messages from the broker. A
publisher program that connects to the broker publishes messages to the broker
for the topics that the two raspberry pis had registered. Each raspberry pi
receives the corresponding message and turns the LEDs or relays on or off as per
the message.
On a local network this process happens in near real time and no delays were
observed. Eclipse IoT MQTT broker (iot.eclipse.org) was also tried which also
did not result in any significant delays.
Thus it is observed that two raspberry pis can be easily controlled using MQTT.
This system can be extended to include arbitrary number of raspberry pis and
other devices that subscribe to the broker. If a device fails, or the connection
from one device is broken, other devices are not affected and continue to
perform the same.
This project can be extended to include various other kinds of sensors and
actuators. The actuators may subscribe to topics to which various sensors publish
their data ans respond accordingly. The data of these sensors can be captured
with the help of a data collector which may itself be a different subscriber, that
performs analytics or visualizations on this data.
13.1.9 Conclusion
We see that as the number of connected devices increases and their applications
become commonplace, MQTT allows different devices to communicate with
each other in a data agnostic manner. MQTT uses a publish-subscribe model and
allows various levels of quality of service requirements to be fulfilled. Although
MQTT does not provide data security by default, most brokers allow the use of
TLS/SSL to encrypt the data. Additional features may be provided by the broker
to include authorization services. MQTT can be easily integrated with other
services to allow collection and analysis of data. A small environment was
simulated that used MQTT broker and clients running on raspberry pis to control
actuators
13.1.10 Exercises
E.MQTT.1:
E.MQTT.2:
Develop a CPU load broker, that collects the cpu load from a number
of machines and clients can subscribe to the data and visualize it.
E.MQTT.3:
E.MQTT.4:
E.MQTT.5:
The following steps illustrate using Avro to serialize and deserialize data with
example modified from Apache Avro 1.8.2 Getting Started (Python) [117].
to:
schema = avro.schema.Parse(open("student.avsc", "rb").read())
13.2.4 Deserializing
13.2.5 Resources
The steps and instructions are modified from Apache Avro 1.8.2 Getting
Started (Python) [117].
The Avro Python library does not support code generation, while Avro used
with Java supports code generation, see Apache Avro 1.8.2 Getting Started
(Java) [118].
Avro provides a convenient way to represent complex data structures within
a Hadoop MapReduce job. Details about Avro are documented in Apache
Avro 1.8.2 Hadoop MapReduce guide [119].
For more information on schema files and how to specify name and type of
a record can be found at record specification [120].
14 GO
Learning Objectives
Go Logo
The language Go has at its goal to be expressive, concise, clean, and efficient. It
includes concurrency mechanisms with the goal to make it easy to write
programs that can utilize multicore and networked features of modern computer
systems and infrastructure easily with language features. However in contrast to
languages such as python and ruby, it introduces in addition to static types
explicitly types supporting concurrent programming such as channels that have
already been used in the early days of programming for example as part of CSP
[122] and OCCAM [123] [124].
Legend
The material presented in this chapter introduces the reader first to the basic
concepts and features of the Go language and system. This includes installation
(see Section 14.2) and compiling (see Section 14.4), have a basic understanding
of the programming language (see Section 14.4), use standard library and
become familiar with package management (see Section 14.5). Next we will
focus on aspects of the Go language that are especially useful for Cloud
computing. This includes the review of how to develop REST services with
various frameworks such as Gorilla (see ) and OpenAPI (see Section 14.8). You
will than be introduced on how to access virtual machines (see Section 14.10)
and containers (see Section 14.10).
14.1.2 References
The following references may be useful for you to find out more about go. We
have not gone to the list in detail, but want to make you are of some of them that
we found through simple searches in Google search. If you find others or you
have a favorite, let us know and we will add them and mark them appropriately.
golang.org [121].
Go cheat sheet [127].
The Little Go Book [128].
Learn Go in an Hour - Video 2015-02-15
Learning to Program in Go, a multi-part video training class.
Go By Example provides a series of annotated code snippets [129].
Learn Go in Y minutes is a top-to-bottom walk-through of the language
[130].
Workshop-Go - Startup Slam Go Workshop - examples and slides [131].
Go Fragments - A collection of annotated Go code examples [132].
50 Shades of Go: Traps, Gotchas, Common Mistakes for New Golang Devs
[133]
Golang Tutorials - A free online class [134].
The Go Bridge Foundry [135] - A member of the Bridge Foundry [136]
family, offering a complete set of free Go training materials with the goal of
bringing Go to under-served communities.
Golangbot - Tutorials to get started with programming in Go [137].
Algorithms to Go - Texts about algorithms and Go, with plenty of code
examples [138].
Go Language Tutorials - List of Go sites, blogs and tutorials for learning
Go language [139].
Golang Development Video Course - A growing list of videos focused
purely on Go development 2019-02-10.
14.2 INSTALLATION ☁
In case Go is not installed on your computer it is iease to install. Up to date
informtion about the install process for your acitecture is available from
https://golang.org/doc/install
We recommend that you use the tarball for Linux, and MacOS, that you can
obtain for your platform here:
https://golang.org/dl/
Packaged installers are also available for macOS, and Windows. They may
provide you with the familiar platform specific instalation methods.
https://github.com/golang/go/wiki/IDEsAndTextEditorPlugins
We recommend that you identify an editor form that list that will work for you.
Due to the universality of emacs and its use for managing LaTeX as ewll as
bibtex, we recommend that you use emacs, Important is that the editor supports
lin breaks at the 80 character limit so the code is no=icely formatted for github.
If your editor does not support this feature use emacs.
If your version of emacs does not yet have support for go, yo ucan find the go
mode at
https://www.emacswiki.org/emacs/GoMode [?]
http://dominik.honnef.co/posts/2013/03/writing_go_in_emacs/ [?]
Other editors may include
Please help us complete this section while letting us know how each editor
supports 80 chracter line wrap mode.
14.4 GO LANGUAGE ☁
Go is a computer language developed by Google with the goal to “build simple,
reliable, and efficient software”. The language is open source and the main Web
page is https://golang.org/
The following program from the https://golang.org/ web page shows the
customary Hello World example:
package main
import "fmt"
func main() {
/* This is a very easy program. */
fmt.Println("Hello World!")
}
14.4.1 Concurrency in Go
import "fmt"
func main() {
go f(0)
var input string
fmt.Scanln(&input)
}
This program consists of two goroutines. The first goroutine is implicit and is the main
function itself. The second goroutine is created when we call go f(0). Normally
when we invoke a function our program will execute all the statements in a
function and then return to the next line following the invocation. With a goroutine
we return immediately to the next line and don’t wait for the function to
complete.
Goroutines are lightweight and we can easily create thousands of them. We can
modify our program to run 10 goroutines by doing this:
func main() {
for i := 0; i < 10; i++ {
go f(i)
}
var input string
fmt.Scanln(&input)
}
import (
"fmt"
"time"
)
func main() {
var c chan string = make(chan string)
go pinger(c)
go printer(c)
This program will print “ping” forever (hit enter to stop it). A channel type is
represented with the keyword chan followed by the type of the things that are
passed on the channel (in this case we are passing strings). The <- (left arrow)
operator is used to send and receive messages on the channel. c <- "ping" means
send “ping”. msg := <- c means receive a message and store it in msg.
The Select statement in Go lets you wait and watch multiple operations on a
channel. Combining GoRoutines and channels will show off the true power of
concurrency in Go.
go func() {
for {
c1 <- "from 1"
time.Sleep(time.Second * 2)
}
}()
go func() {
for {
c2 <- "from 2"
time.Sleep(time.Second * 3)
}
}()
go func() {
for {
select {
case msg1 := <- c1:
fmt.Println(msg1)
case msg2 := <- c2:
fmt.Println(msg2)
}
}
}()
picks the first channel that is ready and receives from it (or sends to it). If
select
more than one of the channels are ready then it randomly picks which one to
receive from. If none of the channels are ready, the statement blocks until one
becomes available.
14.5 LIBRARIES ☁
Golang comes with a list of standard libraries in the following table, and more
libraries can be found on this page: https://golang.org/pkg/
Name Synopsis
archive
Package tar implements access to tar
tar
archives.
Package zip provides support for
zip
reading and writing ZIP archives.
Package bufio implements buffered I/O.
It wraps an io.Reader or io.Writer
object, creating another object (Reader
bufio
or Writer) that also implements the
interface but provides buffering and
some help for textual I/O.
builtin Package builtin provides documentation
for Go’s predeclared identifiers.
Package bytes implements functions for
bytes
the manipulation of byte slices.
compress
Package bzip2 implements bzip2
bzip2
decompression.
Package flate implements the
flate DEFLATE compressed data format,
described in RFC 1951.
Package gzip implements reading and
gzip writing of gzip format compressed files,
as specified in RFC 1952.
Package lzw implements the Lempel-
Ziv-Welch compressed data format,
described in T. A. Welch, ``A
lzw
Technique for High-Performance Data
Compression’’, Computer, 17(6) (June
1984), pp 8-19.
Package zlib implements reading and
zlib writing of zlib format compressed data,
as specified in RFC 1950.
container
Package heap provides heap operations
heap for any type that implements
heap.Interface.
Package list implements a doubly
list
linked list.
Package ring implements operations on
ring
circular lists.
Package context defines the Context
type, which carries deadlines,
context cancelation signals, and other request-
scoped values across API boundaries
and between processes.
Package crypto collects common
crypto
cryptographic constants.
Package aes implements AES
encryption (formerly Rijndael), as
aes
defined in U.S. Federal Information
Processing Standards Publication 197.
Package cipher implements standard
block cipher modes that can be
cipher
wrapped around low-level block cipher
implementations.
Package des implements the Data
Encryption Standard (DES) and the
Triple Data Encryption Algorithm
des
(TDEA) as defined in U.S. Federal
Information Processing Standards
Publication 46-3.
Package dsa implements the Digital
dsa Signature Algorithm, as defined in
FIPS 186-3.
Package ecdsa implements the Elliptic
ecdsa Curve Digital Signature Algorithm, as
defined in FIPS 186-3.
index
Package suffixarray implements
suffixarray substring search in logarithmic time
using an in-memory suffix array.
Package io provides basic interfaces to
io
I/O primitives.
Package ioutil implements some I/O
ioutil
utility functions.
Package log implements a simple
log
logging package.
syslog Package syslog provides a simple
interface to the system log service.
Package math provides basic constants
math
and mathematical functions.
Package big implements arbitrary-
big
precision arithmetic (big numbers).
Package bits implements bit counting
bits and manipulation functions for the
predeclared unsigned integer types.
Package cmplx provides basic constants
cmplx and mathematical functions for
complex numbers.
Package rand implements pseudo-
rand
random number generators.
Package mime implements parts of the
mime
MIME spec.
Package multipart implements MIME
multipart multipart parsing, as defined in RFC
2046.
Package quotedprintable implements
quotedprintable quoted-printable encoding as specified
by RFC 2045.
14.6 GO CMD ☁
14.6.1 CMD
In pthon we have the CMD5 package that allows us to create command shells
with plugins. In Go we find a community developed package called gosh (or Go
shell). It uses the Go plugin system to create interactive console-based shell
programs. A shell created with gosh contains a collection of Go plugins, each of
which which implement one or more commands. Upon start gosh starts, searches
the directory ./plugins and loads them so they become available within gosh.
https://github.com/vladimirvivien/gosh
14.6.2 DocOpts
https://github.com/docopt/docopt.go
https://github.com/docopt/docopt.go/blob/master/examples/options/
A sample program of using doc opts for our purposes loks as follows.
package main
import (
"fmt"
"github.com/docopt/docopt-go"
)
func main() {
usage := `cm-go.
Usage:
cm-go vm start NAME [--cloud=CLOUD]
cm-go vm stop NAME [--cloud=CLOUD]
cm-go set --cloud=CLOUD
cm-go -h | --help
cm-go --version
Options:
-h --help Show this screen.
--version Show version.
--cloud=CLOUD The name of the cloud.
--moored Moored (anchored) mine.
--drifting Drifting mine.
ARGUMENTS:
NAME The name of the VM`
arguments, _ := docopt.ParseDoc(usage)
fmt.Println(arguments)
}
14.7 GO REST ☁
Go is a new powerful language and there are many frameworks from lightweight
to full featured that support building RESTful APIs.
2. Gin The fastest full-featured web framework for Golang. Crystal clear.
https://nordicapis.com/7-frameworks-to-build-a-rest-api-in-go/
with mongo https://hackernoon.com/build-restful-api-in-go-and-mongodb-
5e7f2ec4be94
https://tutorialedge.net/golang/consuming-restful-api-with-go/
https://thenewstack.io/make-a-restful-json-api-go/
Making a RESTful JSON API in Go
14.7.1 Gorilla
https://www.codementor.io/codehakase/building-a-restful-api-with-golang-
a6yivzqdo
1. Uniform Interface
2. Cacheable
3. Client-Server
4. Stateless
5. Code on Demand
6. Layered System
14.7.3 Router
The name mux stands for “HTTP request multiplexer”. Like the standard
http.ServeMux, mux.Router matches incoming requests against a list of
registered routes and calls a handler for the route that matches the URL or other
conditions. The main features are:
We’ll need to use a mux to route requests, so we need a Go package for that
(mux stands for HTTP request multiplexer which matches an incoming request
to against a list of routes (registered)). In the rest-api directory, let’s require the
dependency (package rather). More examples are here:
https://github.com/gorilla/mux#examples
rest-api$ go get github.com/gorilla/mux
package main
import (
"encoding/json"
"log"
"net/http"
"github.com/gorilla/mux"
)
Packages are explained here: * fmt is what we will be using to print to STDOUT
(the console) * log is used to log when the server exits * encoding/json is for
creating our JSON responses * net/http will give us the representations of HTTP
requests, responses, and be responsible for running our server *
github.com/gorilla/mux will be our router that will take requests and decide what
should be done with them
import (
"encoding/json"
"github.com/gorilla/mux"
"log"
"net/http"
)
// Delete an item
func DeletePerson(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
for index, item := range people {
if item.ID == params["id"] {
people = append(people[:index], people[index+1:]...)
break
}
json.NewEncoder(w).Encode(people)
}
}
14.9.1 Dependencies
github.com/go-swagger/go-swagger/cmd/swagger
github.com/go-openapi/runtime
github.com/docker/go-units
github.com/go-openapi/loads
github.com/go-openapi/validate
Create a new folder named hello-swagger under ~/go/src, and a folder named swagger under
hello-swagger. Create main.go under hello-swagger and swagger.yml under swagger folder. The
The command will generate Go code and put them under the swagger folder. Once
there is a new folder named restapi, this step is successful.
Now we can create our restapi server and implement the request handler in Go.
import (
"github.com/go-openapi/loads"
"github.com/go-openapi/runtime/middleware"
"hello-swagger/swagger/restapi"
"hello-swagger/swagger/restapi/operations"
"log"
)
func main() {
log.Println("Starting...")
if err != nil {
log.Fatalln(err)
}
api := operations.NewEchoAPI(swaggerSpec)
server := restapi.NewServer(api)
defer server.Shutdown()
server.Port = 8080
api.EchoHandler = operations.EchoHandlerFunc(
func(params operations.EchoParams) middleware.Responder {
response := params.Msg
payload := operations.EchoOKBody{Msg: response}
return operations.NewEchoOK().WithPayload(&payload)
})
if err := server.Serve(); err != nil {
log.Fatalln(err)
}
}
We use go command to run, which compile the code and run the program. Once
the program is been started, some logs are print out in the console like:
2019/02/04 17:06:24 Starting...
2019/02/04 17:06:24 Serving echo at http://[::]:8080
Once the server is listening at 8080, we can run curl command to do some tests:
curl http://localhost:8080/echo\?msg\=Hello
# {"msg":"Hello"}
curl http://localhost:8080/echo\?msg\=World
# {"msg":"World"}
14.9.6 References
go-swagger documentation
OpenAPI.Tools
14.10 GO CLOUD ☁
14.10.1 Golang Openstack Client
https://github.com/openstack/golang-client
Authentication
Images
ObjectStore
This file reads in some configurations form a json file, however we want to
develop one for our ~/.cloudmesh/cloudmesh.yaml file. For the json example see: json
setup
Volume
There are multiple API interfaces that allow direct access to elementary
functionality to controll for example virtual machines in Go. This includes
GopgerCloud, and GolangClient. We describe them next.
14.10.2.1 GohperCloud
GopherCloud is located at
https://github.com/gophercloud/gophercloud
14.10.2.1.1 Authentication
use the same format and obtain the information from that file. Your task will be
to write a yaml file reader in go, get the information and modify the program
accordingly while improving this section with a pull request.
opts := gophercloud.AuthOptions{
IdentityEndpoint: "https://openstack.example.com:5000/v2.0",
Username: "{username}",
Password: "{password}",
}
Natirally you can also obtain the values from environment variables as pointed
out by gopher cloud:
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/utils"
)
To start a virtual machine you need to first identify the location of the client for
the region you will use. This can be achieved wit the command:
client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
Now that we know we can authenticate to the cloud, we can create our first
virtual machine, where flavor_id and image_id are the approriate flavors and image ids:
import "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
14.10.2.1.3 Resources
However, if we just want to provide a list of all servers, we can simply use the
AllPages() method as follows:
https://github.com/gophercloud/gophercloud/blob/master/doc.go
14.11 GO LINKS ☁
In this section we list some potentially useful as well as links to research Go
further. If you find other very useful links, please let us know. YOu can shaoe
this section with us.
https://cse.sc.edu/~mgv/csce330f16/pres/330f15_BarnhartReevesLee_Go.pptx
http://www.cis.upenn.edu/~matuszek/cis554-
2016/Talks/Golang_Presentation.ppt
https://talks.golang.org/2015/go-for-java-programmers.slide#1
https://github.com/golang/go/wiki/GoTalks
http://courses.cs.vt.edu/cs5204/fall11-kafura/Overheads/Go.pptx
https://en.wikipedia.org/wiki/Kahn_process_networks
http://devcodegeek.com/best-cloud-programming-languages.html
https://webdesignledger.com/top-4-cloud-computing-languages-learn-now/
https://techlog360.com/top-10-cloud-programming-languages/
https://www.techrepublic.com/article/10-of-the-coolest-cloud-
programming-languages/
Often we find refrences to how popular a programming language is. Some ways
of identifying this is with analysis of the Tiobe index
http://www.zdnet.com/article/which-programming-languages-are-most-
popular-and-what-does-that-even-mean/
https://www.tiobe.com/tiobe-index/
http://pypl.github.io/PYPL.html
https://www.infoworld.com/article/2610933/cloud-computing/article.html
The following links are useful to research aspects related to creating REST
services or clients form specifications in Go.
https://swagger.io/
https://nordicapis.com/top-specification-formats-for-rest-apis/
https://www.npmjs.com/package/raml-python
https://github.com/Jumpscale/go-raml
https://en.wikipedia.org/wiki/Overview_of_RESTful_API_Description_Languages
14.12 EXERCISES ☁
E.Go.1:
Write a REST service with OpenAPI that exposes the cpu load
E.GO.2:
Write a REST service with Gorilla that exposes the cpu load
E.GO.3:
E.GO.4:
[2] domo.com, “Data never sleeps 7.0.” Image, Jun-2019 [Online]. Available:
https://www.domo.com/learn/data-never-sleeps-7
[3] domo.com, “Data never sleeps 6.0.” Image, Jun-2018 [Online]. Available:
https://www.domo.com/blog/wp-content/uploads/2018/06/18-domo-data-never-
sleeps-6.png
[4] L. Lewis, “This is what happens in an internet minute.” Web Page, Apr-2018
[Online]. Available: https://www.allaccess.com/merge/archive/28030/2018-
update-what-happens-in-an-internet-minute
[6] K. Heslin, “Proper data center staffing is key to reliable operations.” Web
Page, Mar-2015 [Online]. Available: https://journal.uptimeinstitute.com/data-
center-staffing/
[8] Indiana State, “Indiana - state energy profile overview - u.s. Energy
information.” Web Page, Apr-2018 [Online]. Available:
https://www.eia.gov/state/?sid=IN
[9] Joe Powell and Associates, “4 steps to better data center cooling.” Web Page,
Jan-2019 [Online]. Available: https://www.joepowell.com/4-steps-to-better-data-
center-cooling/
[14] Amazon, “Amazon data centers.” Web Page, Jan-2019 [Online]. Available:
https://aws.amazon.com/compliance/data-center/data-centers/
[19] A. Shehabi et al., “United states data center energy usage report,” Lawrence
Berkeley National Laboratory, Report DE-AC02-05CH1131, LBNL-1005775,
Jun. 2016 [Online]. Available: https://escholarship.org/uc/item/84p772fc
[22] New York times, “Microsoft underwater datacenter.” Web Page, Aug-2019
[Online]. Available: https://www.nytimes
.com/2016/02/01/technology/microsoft-plumbs-oceans-depths-to-test-
underwater-data-center.html
[23] I. Foster and C. Kesselman, Eds., The grid: Blueprint for a new computing
infrastructure. San Francisco, CA, USA: Morgan Kaufmann Publishers Inc.,
1999.
[25] J. Varia, “Architecting for the cloud: Best practices,” Amazon Web Services,
vol. 1, pp. 1–21, 2010.
[28] O. Orgeron, “Top 10 list for success in the cloud.” Oracle Corporation;
Presentation, 2012 [Online]. Available:
https://www.oracle.com/technetwork/articles/entarch/orgeron-top-10-cloud-
1957407.pdf
[29] A. K. Anbarasu, “Cloud reference architecture.” Oracle Corporation; White
Paper, Nov-2012 [Online]. Available:
https://www.oracle.com/technetwork/topics/entarch/oracle-wp-cloud-ref-arch-
1883533.pdf
[31] National Institute of Standars, “NIST big data public working group.” Aug-
2019 [Online]. Available: https://bigdatawg.nist.gov/
[37] RAML, “RAML version 1.0: RESTful api modeling language.” Web Page
[Online]. Available: https://github.com/raml-org/raml-
spec/blob/master/versions/raml-10/raml-10.md
[45] OpenAPI Initiative, “Announcing the official release of openapi 3.0.” Web
Page, 2017 [Online]. Available: https://swagger.io/blog/news/announcing-
openapi-3-0/
[46] OpenAPI Initiative, “The openapi docs.” Web Page [Online]. Available:
https://swagger.io/docs/specification/about/
[55] Django Software Foundation, “Django web framework.” Web Page, Aug-
2019 [Online]. Available: https://www.djangoproject.com/
[56] João Angelo, “JWT tokens.” Web Page, Aug-2019 [Online]. Available:
https://stackoverflow.com/a/39914013
[58] Github, “Github api v4.” Web Page, Aug-2019 [Online]. Available:
https://developer.github.com/v4/
[60] S. J. Bigelow, “Full virtualization vs. Paravirtualization: What are the key
differences?” Wegb page, Sep-2018 [Online]. Available:
https://searchservervirtualization.techtarget.com/answer/Full-virtualization-vs-
paravirtualization-What-are-the-key-differences
[63] Suse, “Virtualization with kvm,” in Virtualization with kvm, Suse, 2016
[Online]. Available:
https://www.suse.com/documentation/sles11/book_kvm/data/cha_libvirt_overview.html
[64] J. Guerrag, “Difference between kvm and qemu.” Forum Post, Dec-2010
[Online]. Available: https://serverfault.com/questions/208693/difference-
between-kvm-and-qemu
[67] Stackoverflow, “What are the differences between qemu and virtualbox?”
Forum Post, Sep-2018 [Online]. Available:
https://stackoverflow.com/questions/43704856/what-are-the-differences-
between-qemu-and-virtualbox
[92] P. Caponetti, “Why mqtt is the protocol of choice for the iot.” Blog, Nov-
2017 [Online]. Available: http://blog.xively.com/why-mqtt-is-the-protocol-of-
choice-for-the-iot/
[93] The HiveMQ Team, “Introducing the mqtt protocol - mqtt essentials: Part
1.” Web Page, Nov-2017 [Online]. Available:
https://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt
[95] Mqtt, “Mqtt official website.” mqtt official website, Nov-2017 [Online].
Available: http://mqtt.org/
[97] Random nerds tutorial, “What is mqtt and how it works.” Web Page, Nov-
2017 [Online]. Available: https://randomnerdtutorials.com/what-is-mqtt-and-
how-it-works/
[98] H. MQ, “MQTT essentials part 2: Publish & subscribe.” Web Page, Nov-
2017 [Online]. Available: https://www.hivemq.com/blog/mqtt-essentials-part2-
publish-subscribe
[100] H. MQ, “MQTT essentials part 6: Quality of service 0, 1 and 2.” Web
Page, Nov-2017 [Online]. Available: https://www.hivemq.com/blog/mqtt-
essentials-part-6-mqtt-quality-of-service-levels
[101] T. Ouska, “Transport-level security tradeoffs using mqtt.” Web Page, Nov-
2017 [Online]. Available: http://iotdesign.embedded-computing.com/guest-
blogs/transport-level-security-tradeoffs-using-mqtt/
[102] H. Mq, “MQTT security fundamentals: TLS / ssl.” Web Page, Nov-2017
[Online]. Available: https://www.hivemq.com/blog/mqtt-security-fundamentals-
tls-ssl
[103] I. Craggs, “MQTT security: Who are you? Can you prove it? What can
you do?” Web Page, Nov-2013 [Online]. Available:
https://www.ibm.com/developerworks/community/blogs/c565c720-fe84-4f63-
873f-607d87787327/entry/mqtt_security?lang=en
[104] hive mq, “MQTT security fundamentals: OAuth 2.0 and mqtt.” Web Page,
Nov-2017 [Online]. Available: https://www.hivemq.com/blog/mqtt-security-
fundamentals-oauth-2-0-mqtt
[109] Smart Factory, “Storing iot data using open source. MQTT and
elasticsearch - tutorial.” Web Page, Oct-2016 [Online]. Available: https://smart-
factory.net/mqtt-elasticsearch-setup/
[110] Smart Factory, “MQTT and kibana - open source graphs and analysis for
iot.” Web Page, Nov-2017 [Online]. Available: https://smart-factory.net/mqtt-
and-kibana-open-source-graphs-and-analysis-for-iot/
[114] seed studio, “Grove led socket kit.” Seed studio website, Oct-2017
[Online]. Available: http://wiki.seeed.cc/Grove-LED_Socket_Kit/
[115] G. von Laszewski, Cloud computing with the raspberry pi, Fall 2018.
Bloomington, Indiana: Indiana University, 2018 [Online]. Available:
https://github.com/cloudmesh-community/book/vonLaszewski-pi.epub?raw=true
[116] Apache Avro, “Apache avro 1.8.2 documentation.” Web Page, Feb-2017
[Online]. Available: http://avro.apache.org/docs/1.8.2/index.html
[117] Apache Avro, “Apache avro 1.8.2 getting started (python).” Web Page,
Feb-2017 [Online]. Available:
http://avro.apache.org/docs/1.8.2/gettingstartedpython.html
[118] Apache Avro, “Apache avro 1.8.2 getting started (java).” Web Page, Feb-
2017 [Online]. Available:
http://avro.apache.org/docs/1.8.2/gettingstartedjava.html
[119] Apache Avro, “Apache avro 1.8.2 hadoop mapreduce guide.” Web Page,
Feb-2017 [Online]. Available: http://avro.apache.org/docs/1.8.2/mr.html
[120] Apache Avro, “Apache avro 1.8.2 specification.” Web Page, Feb-2017
[Online]. Available: http://avro.apache.org/docs/1.8.2/spec.html#schema_record
[126] G. von Laszewski, Linux for cloud computing, Fall 2019. Bloomington,
Indiana: Indiana University, 2019 [Online]. Available:
https://laszewski.github.io/book/linux/
[127] A. Mashraki, “Go cheat sheet.” Web Page, Sep-2015 [Online]. Available:
https://github.com/a8m/go-lang-cheat-sheet/blob/master/golang_refcard.pdf
[128] K. Seguin, “The little go book.” Web Page, Jan-2018 [Online]. Available:
https://github.com/karlseguin/the-little-go-book
[133] K. Quest, “50 shades of go: Traps, gotchas, common mistakes for new
golang devs.” Web Page, Jan-2018 [Online]. Available:
http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/
[139] Many, “Go language tutorials.” Web Page, Jan-2018 [Online]. Available:
https://www.cybrhome.com/topic/go-language-tutorials