<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: StevenMcGown</title>
    <description>The latest articles on Forem by StevenMcGown (@stevenmcgown).</description>
    <link>https://forem.com/stevenmcgown</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F657912%2Faf317a8c-03a4-424f-a63c-9b52cb3e6ca2.png</url>
      <title>Forem: StevenMcGown</title>
      <link>https://forem.com/stevenmcgown</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stevenmcgown"/>
    <language>en</language>
    <item>
      <title>Data Science Zero to Hero - 2.2: Data ETF (Extract, Transform, Load)</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Sat, 12 Aug 2023 14:46:22 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/data-science-zero-to-hero-22-data-etf-extract-transform-load-349l</link>
      <guid>https://forem.com/stevenmcgown/data-science-zero-to-hero-22-data-etf-extract-transform-load-349l</guid>
      <description>&lt;h2&gt;
  
  
  Where does data come from?
&lt;/h2&gt;

&lt;p&gt;Data can come from many different sources - it might be generated by users, collected from sensors, retrieved from databases, even scraped from websites. The methods of data collection may depend on the nature of the data source, and the process of managing this data and making it usable for analysis often involves ETL (Extract, Transform, Load). In many cases, &lt;em&gt;extracted&lt;/em&gt; raw data is not &lt;em&gt;loaded&lt;/em&gt; directly into a database; It has to be cleaned and &lt;em&gt;transformed&lt;/em&gt; before it is suitable for machine learning.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extract:&lt;/strong&gt; Data is pulled from various sources like databases, sensors, or online services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transform:&lt;/strong&gt; The extracted data is then cleaned and transformed into a suitable format. This might include handling inconsistencies, converting data types, aggregating information, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load:&lt;/strong&gt; Finally, the cleaned and structured data is loaded into a destination system such as a database where it can be accessed and analyzed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffh3gzmxk0czgenn73uu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffh3gzmxk0czgenn73uu8.png" alt="etl"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Extraction Tools
&lt;/h2&gt;

&lt;p&gt;The choice of an ETL tool should be guided by the specific needs of a project. For example, Amazon Kinesis is a powerful tool for real-time data streaming and analytics, often used in the extraction phase of ETL for AWS environments. It's designed to handle large-scale data like video, audio, application logs, and more. Kinesis can ingest massive amounts of information at high speed. This real-time processing allows for immediate insights and responsiveness, distinguishing Kinesis from traditional batch-based ETL tools. &lt;/p&gt;

&lt;p&gt;Kinesis is an ETL tool that might be best used in an AWS environment, but there are other options depending on your needs. To name a couple, you might consider Apache Kafka, a great fit for high-throughput real-time data processing or Microsoft SQL Server Integration Services (SSIS), designed for businesses embedded in the Microsoft ecosystem. There's tons of tools out there, each with their own benefits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8da6mlj7ndmqwl21c5zl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8da6mlj7ndmqwl21c5zl.png" alt="catmeme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Transformation Tools
&lt;/h2&gt;

&lt;p&gt;The choice for a transformation tool is again dependent on your needs.&lt;br&gt;
Apache Spark excels in rapid transformations with in-memory processing, while Microsoft's Power Query is favored for Excel and Power BI with its graphical interface. AWS Glue, a fully managed ETL service, offers a serverless data integration service that simplifies and automates the transformation process. Again with benefits and drawbacks for each, the choice hinges on data size and complexity, processing speed, and user expertise.&lt;/p&gt;

&lt;h2&gt;
  
  
  File Formats and Storage Solutions
&lt;/h2&gt;

&lt;p&gt;So far we've covered extracting and transforming data, but what exactly are we trasnforming it into? Well data comes in various formats, each catering to different requirements and use-cases. The chosen file format often influences the way data is stored and managed in databases. Here's a look at some common file formats and corresponding storage solutions:&lt;/p&gt;

&lt;h3&gt;
  
  
  CSV, Excel, Parquet, and ORC Files
&lt;/h3&gt;

&lt;p&gt;For structured data, CSV, Excel, Parquet, and ORC files are popular choices. CSV and Excel are simple, human-readable, and can be easily manipulated using spreadsheet software. Parquet and ORC are columnar storage formats designed for efficiency. These file formats are often used for storing tabular data in &lt;strong&gt;Relational Databases&lt;/strong&gt; like MySQL and PostgreSQL, which provide robust querying capabilities, data integrity, and scalability.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON, XML, Avro, and Protobuf
&lt;/h3&gt;

&lt;p&gt;JSON (JavaScript Object Notation), XML (eXtensible Markup Language), Avro, and Protobuf are commonly used for semi-structured data. These formats allow hierarchical data representation, making them suitable for complex data structures. They are widely used in web development, API responses, and configuration files, and can be stored in &lt;strong&gt;NoSQL Databases&lt;/strong&gt; like MongoDB, DynamoDb, or Cassandra, offering more flexibility in data models and allowing for horizontal scaling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Images, Audio, Video Files, and HDF5
&lt;/h3&gt;

&lt;p&gt;Unstructured data often takes the form of multimedia files like images, audio, videos, and large numerical data like HDF5. They may require specialized preprocessing techniques such as feature extraction, image recognition, or natural language processing (NLP) to be utilized in machine learning models. These types of files are typically stored in Object Storage Systems like AWS S3, Azure Blob Storage, or Google Cloud Storage. These systems are commonly used for large, &lt;strong&gt;unstructured datasets&lt;/strong&gt; and provide scalability, particularly useful when working with big data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The world of data isn't just about having it; it's about molding it in a way that extracts its maximum potential. This requires both a deep understanding of the available tools and an intricate knowledge of the data itself. Each transformation step can potentially unlock new insights or, if done incorrectly, can lead to misguided conclusions.&lt;/p&gt;

&lt;p&gt;We now know the basic flow of ETF and its place in the ML Cycle, but there are still questions to be answered. What kind of transformations are most impactful for specific datasets? How do these transformations vary when dealing with structured versus unstructured data? And, are there transformations that universally benefit every dataset or are some uniquely tailored for specific contexts? These are all questions that I am to explain in the following posts in section 2 of this series.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>beginners</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Data Science Zero to Hero - 2.1: The Machine Learning Cycle</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Wed, 09 Aug 2023 21:15:40 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/data-science-zero-to-hero-21-the-machine-learning-cycle-13ag</link>
      <guid>https://forem.com/stevenmcgown/data-science-zero-to-hero-21-the-machine-learning-cycle-13ag</guid>
      <description>&lt;h1&gt;
  
  
  Data Collection and Preparation: ML Concepts
&lt;/h1&gt;

&lt;p&gt;Data, data, data! If there's one thing you should take away from this series, it's that data is &lt;strong&gt;super important&lt;/strong&gt; to data scientists and Machine Learning Engineers alike. In the previous posts, we talked about different ways of transforming and visualizing data with Python and those libraries are certainly powerful tools, but where does this data come from anyway? How do we collect it? Where do we store it? What other steps might need to be taken? Furthermore, what do we do with that data once we have it? Questions like these are best answered with the steps in the &lt;em&gt;Machine Learning Cycle.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I8CC4xeL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06lk5mkb7bmf0g5gpbxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I8CC4xeL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06lk5mkb7bmf0g5gpbxu.png" alt="mlcycle" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You see, the process of machine learning is cyclical because its purpose is to improve a machine learning model's performance on a &lt;em&gt;specific task&lt;/em&gt; as new data becomes available. These models should be flexible enough to incorporate that new data so that it doesn't become &lt;em&gt;biased&lt;/em&gt;. This includes understanding how the data was collected and ensuring that it represents the problem space without inherent biases related to factors like gender, ethnicity, or socioeconomic status.&lt;/p&gt;

&lt;p&gt;Depending on who you ask, the Machine Learning Cycle may vary, but the basic idea is this: Get the data, train a model, and then evaluate the results to do the process over again. Let's break the graphic above step by step.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Collection:&lt;/strong&gt; This is the initial phase where all relevant data is gathered from various sources, whether structured or unstructured. It may include collecting data from databases, sensors, online sources, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Transformation:&lt;/strong&gt; Here, the data is cleaned and transformed into a suitable format for training models. It might involve handling missing values, encoding categorical variables, or normalizing numerical features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exploratory Data Analysis (EDA):&lt;/strong&gt; Before diving into modeling, EDA helps in understanding the data's characteristics, distribution, and patterns. This step often includes visualizations, statistical tests, and preliminary insights. &lt;em&gt;Note: A preliminary or light EDA might be performed on the raw data **before transformation,&lt;/em&gt;* especially if you are dealing with an entirely new dataset, to get an initial sense of the data and to identify the transformations that might be needed.*&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Training and Evaluation:&lt;/strong&gt; This phase includes selecting the appropriate algorithm, training the model on the training dataset, and evaluating its performance using techniques like cross-validation on a validation dataset. Adjustments may be made to optimize performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Deployment:&lt;/strong&gt; Once the model is trained and validated, it's deployed into a production environment where it can start making predictions or decisions based on new data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Monitoring:&lt;/strong&gt; Continuous monitoring ensures that the model performs well with the real-world data it encounters. Monitoring can detect issues like drifts in data or degraded performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Retraining:&lt;/strong&gt; Models are not static; they might need to be retrained as new data becomes available or if the underlying data patterns change. Retraining ensures that the model remains accurate and relevant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these steps plays a critical role in creating a robust machine learning model. They collectively contribute to a cyclical process of continuous improvement and adaptation. In the next posts, we'll expand on each of these concepts in much more detail.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>ai</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Data Science Zero to Hero - 1.3: Matplotlib, Seaborn &amp; Jupyter Notebooks</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Thu, 27 Jul 2023 23:05:48 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/python-for-mlai-13-matplotlib-seaborn-jupyter-notebooks-2a76</link>
      <guid>https://forem.com/stevenmcgown/python-for-mlai-13-matplotlib-seaborn-jupyter-notebooks-2a76</guid>
      <description>&lt;p&gt;&lt;em&gt;You like python programs, don't you Squidward?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dq0bu2dmljjder8lh8u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dq0bu2dmljjder8lh8u.jpg" alt="meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*crickets*&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'll be here all week!&lt;/p&gt;

&lt;p&gt;Jokes aside, if you're like me, you're getting excited about learning new tools for your Data Science/ML/AI journey. So far we've covered Numpy and Pandas, where we learned how to manipulate, process, and analyze numerical and tabular data. These libraries gave us a solid foundation in handling and preparing data for further analysis or modeling, and as we delve into Matplotlib and Seaborn inside of Jupyter Notebooks, we're now stepping into the fascinating world of data visualization. Trust me, it only gets better from here!&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Line Plot&lt;/li&gt;
&lt;li&gt;Using Pandas with Matplotlib&lt;/li&gt;
&lt;li&gt;Scatter Plot&lt;/li&gt;
&lt;li&gt;Bar Plot&lt;/li&gt;
&lt;li&gt;Pie Plot&lt;/li&gt;
&lt;li&gt;Histogram&lt;/li&gt;
&lt;li&gt;Box Plot&lt;/li&gt;
&lt;li&gt;Violin Plot&lt;/li&gt;
&lt;li&gt;Strip Plot&lt;/li&gt;
&lt;li&gt;Pair Plot&lt;/li&gt;
&lt;li&gt;Distribution Plot&lt;/li&gt;
&lt;li&gt;Count Plot&lt;/li&gt;
&lt;li&gt;Heat Map&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Data Visualization with Matplotlib and Seaborn in Jupyter Notebooks
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Matplotlib&lt;/strong&gt; is one of the most widely used libraries for creating static, animated, and interactive visualizations in Python. Its extensive functionality and versatility make it a powerful tool for any data scientist or analyst to perform &lt;strong&gt;Exploratory Data Analysis (EDA)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once imported, Matplotlib provides a wide variety of plots and charts to visualize data, from simple line and bar plots to more complex scatter plots and histograms. Whether you're trying to spot trends over time, distributions of data, or relationships between variables, Matplotlib has the flexibility to meet your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seaborn&lt;/strong&gt;, while built on Matplotlib, enhances its capabilities and introduces more sophisticated visualization tools. It's designed to work seamlessly with Pandas dataframes and makes creating complex plots from dataframes quite straightforward.&lt;/p&gt;

&lt;p&gt;With Seaborn, you can create a range of informative and attractive statistical graphics. Heat maps, violin plots, pair plots, and swarm plots are just a few of the more advanced visualizations available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3les5k1g0y4i4p8mvwx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3les5k1g0y4i4p8mvwx.jpg" alt="matplotlibseabornmeme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both Matplotlib and Seaborn work exceptionally well in &lt;strong&gt;Jupyter Notebooks&lt;/strong&gt;, a popular open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. Jupyter Notebooks provide an interactive and intuitive interface for conducting data analysis and visualization.&lt;/p&gt;

&lt;p&gt;To use Matplotlib or Seaborn in Jupyter Notebooks, you simply need to import the required libraries and execute your code. The outputs, including all graphs and plots, are then displayed directly under each code cell, making it easy to view and interpret your results in a structured and clear manner.&lt;/p&gt;

&lt;p&gt;Typically when people use these libraries, they do the imports with the following aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the fun. Let's see what these libraries can do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Line Plot
&lt;/h2&gt;

&lt;p&gt;Lets start with a simple example. A line plot is used to display information as a series of data points connected by straight line segments. It's useful for visualizing data over time, also known as time series data. In this example, we can show the unemployment rate each year. In the code we can see that we have two arrays with an equal number of values in each, and we plot an unemployment rate with a corresponding year.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;year = [1920, 1930, 1940, 1950, 1960, 1970, 1980, 1990, 2000, 2010]
unemployment_rate = [9.8, 12, 8, 7.2, 6.9, 7, 6.5, 6.2, 5.5, 6.3]

plt.plot(year, unemployment_rate)
plt.title('unemployment rate vs year')
plt.xlabel('year')
plt.ylabel('unemployment rate')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1rtva1zkhxw7o6eat5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1rtva1zkhxw7o6eat5b.png" alt="lineplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Side note: Don't ask me where this data came from, it could be wrong for all I know and should only be used for demonstration purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Pandas with matplotlib
&lt;/h2&gt;

&lt;p&gt;Now that we have taken a stab at using matplotlib, let's load a dataset from a csv file into a pandas dataframe. We can take the information from this dataframe and plot it with a variety of different methods. You can download the dataset that I'm using from here:&lt;br&gt;
&lt;a href="https://www.kaggle.com/code/sanjanabasu/tips-dataset/input" rel="noopener noreferrer"&gt;https://www.kaggle.com/code/sanjanabasu/tips-dataset/input&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, recall that above we defined pandas as 'pd'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df=pd.read_csv('tips.csv')

# Print DataFrame
print(df.head())

# Outputs:

   total_bill   tip     sex smoker  day    time  size
0       16.99  1.01  Female     No  Sun  Dinner     2
1       10.34  1.66    Male     No  Sun  Dinner     3
2       21.01  3.50    Male     No  Sun  Dinner     3
3       23.68  3.31    Male     No  Sun  Dinner     2
4       24.59  3.61  Female     No  Sun  Dinner     4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scatter Plot
&lt;/h2&gt;

&lt;p&gt;A scatter plot uses dots to represent values for two different numeric variables. The position of each dot represents the value of data point, and this is useful for visualizing the relationship between two variables. Many scatter plots simply use one color of dots to illustrate the relationship between two variables, but in this example I've shown that you can describe the characteristics of your data points better with a little bit of creativity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Prepare df for plotting
total_bill = df['total_bill']
tip = df['tip']
sex = df['sex']
smoker = df['smoker']

# Create a scatter plot
plt.figure(figsize=(10, 6))
colors = {'Male': 'blue', 'Female': 'red'}
smoker_markers = {'Yes': 'x', 'No': 'o'}

for i in range(len(total_bill)):
    plt.scatter(total_bill[i], tip[i], c=colors[sex[i]], marker=smoker_markers[smoker[i]], s=100)

# Set plot labels and title
plt.xlabel('Amount Due')
plt.ylabel('Gratuity')
plt.title('Scatter Plot of Amount Due vs. Gratuity')

# Add legend for gender and smoker status
for gender_label, color in colors.items():
    plt.scatter([], [], c=color, label=gender_label)
for smoker_label, marker in smoker_markers.items():
    plt.scatter([], [], marker=marker, label='Smoker: ' + smoker_label)

plt.legend(loc='upper right')

plt.grid(True)
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g7gqbwuqpow06kdplh6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g7gqbwuqpow06kdplh6.png" alt="scatterplot"&gt;&lt;/a&gt;&lt;br&gt;
We can see from the plot of the following example that there is a positive correlation between the x and y variables. This positive correlation implies that the higher the bill is, the higher the tip will be. This makes sense if you think about how many people tip based on the percentage of the bill.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bar Plot
&lt;/h2&gt;

&lt;p&gt;Bar plots are used to display and compare the number, frequency or other measure (like mean) for different categories. Each bar's height is proportional to the value it represents. In this plot we can see that there are 4 days recorded, Friday, Saturday, Sunday and Thursday. I suppose we can assume that the person who recorded this data only worked and recorded tips on those days.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Group the data by 'day' and calculate the average 'total_bill' for each day
average_total_bill_by_day = df.groupby('day')['total_bill'].mean()

# Create the bar plot
plt.bar(average_total_bill_by_day.index, average_total_bill_by_day.values)
plt.xlabel('Day of the Week')
plt.ylabel('Average Total Bill')
plt.title('Average Total Bill by Day of the Week')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpolwjeb77o5bd1ua37lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpolwjeb77o5bd1ua37lw.png" alt="barplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pie Plot
&lt;/h2&gt;

&lt;p&gt;Pie plots represent the size of items (out of 100%) in one data series, proportional to the sum of the items. We've all seen a pie plot before; it's useful when you want to visualize percentage breakdown of categories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Group the data by 'sex' and calculate the total count for each category
sex_counts = df['sex'].value_counts()

# Create the pie plot
plt.figure(figsize=(6, 6))
plt.pie(sex_counts, labels=sex_counts.index, autopct='%1.1f%%', startangle=90)
plt.title('Distribution of Sex')
plt.axis('equal')  # Equal aspect ratio ensures that the pie plot is circular.
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhfr0qldc0zswultbcrl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhfr0qldc0zswultbcrl.png" alt="pieplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Histogram
&lt;/h2&gt;

&lt;p&gt;Histograms show the distribution of numeric data by dividing the data into bins of equal width. Each bin is plotted as a bar whose height corresponds to how many data points are in that bin. We'll get more into distributions in the future, they're important to understanding nature of your data.&lt;/p&gt;

&lt;p&gt;You may also notice in the code that an argument 'kde' is set to true. This is known as the Kernel Density Estimation, and it allows us to visualize the data distribution in a smooth and continuous manner, avoiding the limitations of discrete binning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plt.figure(figsize=(8, 6))
sns.histplot(df['total_bill'], kde=True)
plt.xlabel('Total Bill')
plt.ylabel('Frequency')
plt.title('Total Bill Histogram')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjgh5d15ocmghbhvzjp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjgh5d15ocmghbhvzjp3.png" alt="histogram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Box Plot
&lt;/h2&gt;

&lt;p&gt;A box plot, also known as a box and whisker plot, shows the quartiles of the dataset and is useful to visualize the distribution and skewness of your data. It also identifies outliers in your data. We'll go deeper into quartiles in future posts about distributions as well. For now, think of it this way:&lt;/p&gt;

&lt;p&gt;A box plot divides your data into four equal parts, with each part representing a &lt;em&gt;quarter&lt;/em&gt; of the data points. The "box" in the plot represents the middle 50% of the data, where the lower boundary of the box is the first quartile (Q1) and the upper boundary is the third quartile (Q3). The line inside the box represents the median (Q2), which is the middle value of the dataset.&lt;/p&gt;

&lt;p&gt;Additionally, the "whiskers" extend from the box and indicate the range of the data, excluding outliers. Typically, the whiskers encompass data within 1.5 times the interquartile range (IQR), which is the difference between Q3 and Q1. Data points outside this range are considered outliers and are represented as individual points beyond the whiskers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plt.figure(figsize=(8, 6))
sns.boxplot(data=df[['A', 'B']])
plt.title('Box Plot')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fikph1bp2s66d5daohvn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fikph1bp2s66d5daohvn1.png" alt="boxplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Violin Plot
&lt;/h2&gt;

&lt;p&gt;A violin plot plays a similar role as a box and whisker plot. It shows the distribution of quantitative data across several levels of one (or more) categorical variables such that those distributions can be compared.&lt;/p&gt;

&lt;p&gt;The real value in using a violin plot is that it not only displays the quartile information like a box plot, but it also provides a more detailed view of the data distribution by showing the probability density of the data at different values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plt.figure(figsize=(10, 6))
sns.violinplot(x='day', y='total_bill', hue='sex', data=df, split=True, palette='muted')
plt.xlabel('Day of the Week')
plt.ylabel('Total Bill')
plt.title('Total Bill Distribution by Day and Sex')
plt.legend(title='Sex', loc='upper right')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fag1qpg3h4am53au6qvoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fag1qpg3h4am53au6qvoh.png" alt="stripplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Strip Plot
&lt;/h2&gt;

&lt;p&gt;Strip plots are used to represent the distribution of data. It's a good complement to a box or violin plot in cases where all observations along each category can be shown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plt.figure(figsize=(8, 6))
sns.stripplot(data=df, x='D', y='A', jitter=True)
plt.title('Strip Plot')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91knawse6wdci0t749ii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91knawse6wdci0t749ii.png" alt="stripplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pair Plot
&lt;/h2&gt;

&lt;p&gt;Pair plots are used to visualize the pairwise relationship between the columns. They are an effective way to visualize the relationships between different columns in a dataset, allowing you to quickly identify patterns, correlations, and trends. It is a useful exploratory data analysis tool when dealing with datasets containing multiple numerical variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sns.pairplot(df, hue='D')
plt.title('Pair Plot')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl631ge3pzc222oh3mpjt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl631ge3pzc222oh3mpjt.png" alt="pairplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Distribution Plot
&lt;/h2&gt;

&lt;p&gt;Distribution plot visualizes the distribution of a univariate set of observations. In seaborn, it is mainly done through the histplot function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Distribution Plot
plt.figure(figsize=(8, 6))
sns.histplot(data=df, x='A', kde=True)
plt.title('Distribution Plot')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2me9t3bl7m7nv66ra8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2me9t3bl7m7nv66ra8k.png" alt="distributionplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Count Plot
&lt;/h2&gt;

&lt;p&gt;Count plot can be thought of as a histogram across a categorical variable, instead of a quantitative one. It shows the counts of observations in each categorical bin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Count Plot
plt.figure(figsize=(8, 6))
sns.countplot(data=df, x='D')
plt.title('Count Plot')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7qfzy071c1rnxkc0k5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7qfzy071c1rnxkc0k5i.png" alt="countplot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Heat Map
&lt;/h2&gt;

&lt;p&gt;A heat map is a two-dimensional representation of information with the help of colors. In the context of data visualization, it is used to represent the correlation between different features.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Heatmap
corr = df.corr()
plt.figure(figsize=(8, 6))
sns.heatmap(corr, annot=True, cmap='coolwarm')
plt.title('Heat Map')
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktbm7z3yc66nwd3ex4bv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktbm7z3yc66nwd3ex4bv.png" alt="heatmap"&gt;&lt;/a&gt;&lt;br&gt;
Heat maps are exceptionally powerful as they provide an intuitive and visually striking representation of data. By using a color-coded system to display values on a 2D matrix, heat maps allow us to grasp complex patterns, trends, and relationships within the data at a glance.&lt;/p&gt;

&lt;p&gt;We can see a few different things in this plot, and the first thing that might stick out to you is the red, diagonal line of boxes of 1's. These all indicate a 100% correlation, which makes sense when you see that it is being shown to correlate with itself.&lt;/p&gt;

&lt;p&gt;If you look in the first column where total_bill is being compared with tip, we can see that there is a relatively strong correlation. This is in line with our assumption earlier that larger bill totals tend to garner larger tips. We can also see that there's a relatively strong correlation between large party size and tips, as well as total bill, which makes sense.&lt;/p&gt;

&lt;p&gt;On the flip side, there's the cool blue size of the spectrum, which indicates negative correlation. If we look where time_Dinner and day_Thur is, we can see there is a very strong negative correlation between the two variables. Saturday and Sunday seem to follow opposite trends.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Well, we've made it to the end. I hope you have enjoyed this post on data visualization with matplotlib and seaborn! I highly recommend using these plots for your data science projects &lt;br&gt;
as they will not only make your analyses more insightful and compelling but also enable you to effectively communicate your findings to others. &lt;/p&gt;

&lt;p&gt;Happy visualizing and exploring the exciting world of data science! &lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Data Science Zero to Hero - 1.2: Pandas</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Wed, 26 Jul 2023 22:59:45 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/data-science-zero-to-hero-12-pandas-5hb0</link>
      <guid>https://forem.com/stevenmcgown/data-science-zero-to-hero-12-pandas-5hb0</guid>
      <description>&lt;p&gt;Pandas are nature's adorable, bamboo-munching- wait, not that kind of panda...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvtw7205qir18dzywdg7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvtw7205qir18dzywdg7.jpg" alt="panda" width="660" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Much less cute but much more useful for data science, Pandas is a popular open-source Python library that provides powerful data manipulation and analysis tools. The name "Pandas" is derived from "Panel Data," reflecting its original focus on handling and analyzing financial data with panel data structures. &lt;/p&gt;

&lt;p&gt;It is built on top of NumPy and offers easy-to-use data structures and data analysis functionalities. In this blog post, we will explore various features and capabilities of Pandas, including Series, DataFrames, reading data, manipulation techniques, merging and joining, reshaping data, pivot tables, duplication, mapping and replacing values, and grouping data.&lt;/p&gt;

&lt;p&gt;This one's going to be long, so put on your seat belts!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pandas Series: Foundations of Data Manipulation&lt;/li&gt;
&lt;li&gt;DataFrames: Tabular Data Made Easy&lt;/li&gt;
&lt;li&gt;Reading Data into Pandas&lt;/li&gt;
&lt;li&gt;Concatenation, Merge, and Joining: Combining DataFrames&lt;/li&gt;
&lt;li&gt;Reshaping Data: Pivoting and Melting&lt;/li&gt;
&lt;li&gt;Duplication: Identifying and Handling Duplicate Data&lt;/li&gt;
&lt;li&gt;Map and Replace: Modifying Values in DataFrames&lt;/li&gt;
&lt;li&gt;GroupBy: Aggregating and Analyzing Data&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Pandas Series: Foundations of Data Manipulation
&lt;/h2&gt;

&lt;p&gt;At the core of Pandas lies the concept of a &lt;strong&gt;Series&lt;/strong&gt;. A Series is a one-dimensional labeled array that can hold any data type, such as integers, strings, or even Python objects. It consists of two main components: the index and the data.&lt;/p&gt;

&lt;p&gt;The index is an array-like structure that holds labels for each element in the Series, allowing for fast and efficient data access. The data component contains the actual values associated with each index label.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a series
&lt;/h3&gt;

&lt;p&gt;We can create a series from a list like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

# Creating a Series from a list
my_list = [10, 20, 30, 40, 50]
my_series = pd.Series(my_list)
print(my_series)

# Outputs:
0    10
1    20
2    30
3    40
4    50
dtype: int64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Indexing and slicing a Series
&lt;/h3&gt;

&lt;p&gt;To index a series, we simply put the index of the series that we want to retrieve in brackets. Like we have seen before in numpy, we can slice the series by indexing with an inclusive start value and a exclusive end value separated by a colon.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(my_series[2])
print(my_series[1:4])

# Outputs:
30
1    20
2    30
3    40
dtype: int64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filtering values in a Series
&lt;/h3&gt;

&lt;p&gt;...is as simple as this. Remember that our series contains the values 10, 20, 30, 40 and 5. So it makes sense that we only see the values greater than 30 here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(my_series[my_series &amp;gt; 30])

# Outputs:
3    40
4    50
dtype: int64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Performing arithmetic operations on a Series
&lt;/h3&gt;

&lt;p&gt;In this example, we're multiplying all of the values in the series by 2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(my_series * 2)

# Outputs:
0     20
1     40
2     60
3     80
4    100
dtype: int64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manipulating Series is a fundamental task in Pandas. You can create a Series from various data sources, such as Python lists or dictionaries. Additionally, you can perform operations like indexing, slicing, filtering, and arithmetic operations on Series, enabling powerful data transformations.&lt;/p&gt;

&lt;h2&gt;
  
  
  DataFrames: Tabular Data Made Easy
&lt;/h2&gt;

&lt;p&gt;It's worth noting at this point that Pandas isn't really great for manipulating &lt;em&gt;large&lt;/em&gt; datasets for a number of reasons (not parallelizing operations, loading the whole data set in memory, etc). There are other data manipulation libraries like Dask and Vaesk that may work better with larger data sets, and you may be waiting a while if you try to do these operations on a very large dataset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fys1qasil30kcdf7fvcba.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fys1qasil30kcdf7fvcba.jpg" alt="skeleton" width="193" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have learned about series which are 1-dimensional, we will look at &lt;strong&gt;Data Frames&lt;/strong&gt;.&lt;br&gt;
DataFrames are two-dimensional labeled data structures in Pandas, inspired by the concept of tables in relational databases. They are essentially a collection of Series that share a common index, allowing for intuitive and efficient data handling.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating a Pandas data frame from a python dictionary
&lt;/h3&gt;

&lt;p&gt;Pandas easily transforms Python dictionaries into data frames for efficient data manipulation and analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

### Creating a DataFrame from a dictionary
data = {'Name': ['John', 'Emma', 'Ryan'],
        'Age': [25, 30, 35],
        'City': ['New York', 'London', 'Sydney']}
df = pd.DataFrame(data)
print(df)

# Outputs:
   Name  Age       City
0  John   25   New York
1  Emma   30     London
2  Ryan   35     Sydney
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Selecting specific columns in a DataFrame
&lt;/h3&gt;

&lt;p&gt;Just like you can index a series, you can index the columns of a data frame as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(df['Name'])
print(df[['Name', 'Age']])

# Outputs:
0    John
1    Emma
2    Ryan
Name: Name, dtype: object

   Name  Age
0  John   25
1  Emma   30
2  Ryan   35
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filtering rows based on conditions
&lt;/h3&gt;

&lt;p&gt;This works exactly like filtering on series.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(df[df['Age'] &amp;gt; 28])

# Outputs:
   Name  Age      City
1  Emma   30    London
2  Ryan   35    Sydney
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sorting a DataFrame
&lt;/h3&gt;

&lt;p&gt;You can sort the rows of a dataframe on the names of the columns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(df.sort_values('Age'))

# Outputs:
   Name  Age       City
0  John   25   New York
1  Emma   30     London
2  Ryan   35     Sydney

# Applying aggregate functions
print(df['Age'].mean())

# Outputs:
30.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manipulating DataFrames offers a wide range of possibilities for data analysis. You can create DataFrames from various data sources, including CSV files, Excel spreadsheets, and SQL databases. Once you have a DataFrame, you can perform operations like selecting specific columns, filtering rows based on conditions, sorting data, and applying aggregate functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading Data into Pandas
&lt;/h3&gt;

&lt;p&gt;Pandas provides several functions to read data from different file formats. Some commonly used methods include &lt;code&gt;read_csv()&lt;/code&gt;, &lt;code&gt;read_excel()&lt;/code&gt;, and &lt;code&gt;read_sql()&lt;/code&gt;. These functions allow you to load data into DataFrames, making it easy to analyze and manipulate the data using Pandas' powerful functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

## Reading data from a CSV file
df = pd.read_csv('data.csv')
print(df.head())

# Outputs:
   Column1  Column2  Column3
0        1        2        3
1        4        5        6
2        7        8        9
3       10       11       12
4       13       14       15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Concatenation, Merge, and Joining: Combining DataFrames
&lt;/h2&gt;

&lt;p&gt;Concatenation, merging, and joining are techniques used to combine multiple DataFrames into a single DataFrame, allowing for comprehensive data analysis. Concatenation is the process of stacking DataFrames vertically or horizontally. Merging involves combining DataFrames based on common columns, similar to SQL joins. Joining is the process of combining DataFrames based on their index.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concatenating Dataframes
&lt;/h3&gt;

&lt;p&gt;You can concatenate along two axes - axis 0 (rows) or axis 1 (columns). The default is axis 0. During concatenation, make sure the column names and index labels match correctly. If they don't, Pandas will create NaN values for non-matching elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

# Concatenating DataFrames vertically
df1 = pd.DataFrame({'A': [1, 2, 3],
                    'B': [4, 5, 6]})
df2 = pd.DataFrame({'A': [7, 8, 9],
                    'B': [10, 11, 12]})
result = pd.concat([df1, df2])
print(result)

# Outputs:
   A   B
0  1   4
1  2   5
2  3   6
0  7  10
1  8  11
2  9  12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Merging DataFrames based on a common column
&lt;/h3&gt;

&lt;p&gt;You need a common key or set of keys to merge DataFrames. These keys serve as the basis for matching and combining rows. Pandas supports different types of merges - 'inner', 'outer', 'left', and 'right'. Each type specifies how the rows are combined based on the keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df1 = pd.DataFrame({'Key': ['A', 'B', 'C'],
                    'Value': [1, 2, 3]})
df2 = pd.DataFrame({'Key': ['B', 'C', 'D'],
                    'Value': [4, 5, 6]})
result = pd.merge(df1, df2, on='Key')
print(result)

# Outputs:
  Key  Value_x  Value_y
0   B        2        4
1   C        3        5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These operations provide flexibility in data integration and enable the user to perform more complex analyses by leveraging data from multiple sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reshaping Data: Pivoting and Melting
&lt;/h2&gt;

&lt;p&gt;Reshaping data is a common task in data analysis, and Pandas provides functions to pivot and melt DataFrames. Pivoting involves transforming data from a "long" format to a "wide" format, creating new columns based on unique values in an existing column. Melt, on the other hand, transforms data from a "wide" format to a "long" format, unpivoting the data.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvgfs6xh87nxb7dfvj49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvgfs6xh87nxb7dfvj49.png" alt="pivot" width="698" height="536"&gt;&lt;/a&gt;&lt;br&gt;
So they're just the inverse operation of each other. Changing the structure from wide to long or long to wide is often necessary to adapt the data to different analysis, modeling, or visualization requirements. Each format has its advantages and is suitable for specific scenarios. For this section, I would highly suggest paying close attention to the outputs of these examples to see  they're doing. Not sure why, but it took me some time to understand these concepts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pivoting
&lt;/h3&gt;

&lt;p&gt;Again, pivoting is used to turn dataframes long to wide. Here's some examples of when that might be useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Redundancy Reduction:&lt;/strong&gt; Wide-format data can help reduce redundancy, especially when dealing with sparse data. By pivoting, you can consolidate related information into a more compact representation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualization:&lt;/strong&gt; In some cases, a wide-format presentation may be more intuitive or easier to understand for certain types of visualizations, especially when there are fewer categorical variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exporting Data:&lt;/strong&gt; For some specific use cases or external tools, a wide-format might be the preferred format for data export.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

# Pivoting a DataFrame
df = pd.DataFrame({'Date': ['2023-01-01', '2023-01-02', '2023-01-03'],
                   'City': ['New York', 'London', 'Sydney'],
                   'Temperature': [32, 28, 35]})
pivot_table = df.pivot(index='Date', columns='City', values='Temperature')
print(pivot_table)

# Outputs:
City        London  New York  Sydney
Date                               
2023-01-01    NaN      32.0     NaN
2023-01-02   28.0       NaN     NaN
2023-01-03    NaN       NaN    35.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Melting
&lt;/h3&gt;

&lt;p&gt;Once more, melting is for making dataframes wide to long.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aggregation and Analysis:&lt;/strong&gt; When you need to perform aggregate functions or statistical analysis on multiple related columns, melting the data into a long format is often more convenient. It allows you to treat the column names as data values, making it easier to apply operations uniformly across different groups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualization:&lt;/strong&gt; Certain visualization libraries or tools work better with data in a long format. For example, tools like Seaborn or Plotly often expect data in a long format for categorical data plotting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalization:&lt;/strong&gt; Long-format data can help in data normalization and provide a standardized way to handle repeated measures.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df = pd.DataFrame({'Name': ['John', 'Emma', 'Tom'],
                   'Math': [95, 87, 92],
                   'Science': [88, 90, 85]})
melted_df = pd.melt(df, id_vars='Name', var_name='Subject', value_name='Score')
print(melted_df)

# Outputs:
   Name  Subject  Score
0  John     Math     95
1  Emma     Math     87
2   Tom     Math     92
3  John  Science     88
4  Emma  Science     90
5   Tom  Science     85
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These reshaping techniques are particularly useful when working with datasets that require restructuring for better analysis and visualization.&lt;/p&gt;
&lt;h2&gt;
  
  
  Duplication: Identifying and Handling Duplicate Data
&lt;/h2&gt;

&lt;p&gt;Data duplication is a common issue in real-world datasets. Pandas offers functions to identify and handle duplicate data effectively. You can use methods like &lt;code&gt;duplicated()&lt;/code&gt; and &lt;code&gt;drop_duplicates()&lt;/code&gt; to detect and remove duplicate rows from DataFrames. By addressing duplication, you can ensure data integrity and obtain accurate insights from your analysis.&lt;/p&gt;
&lt;h3&gt;
  
  
  Duplicating
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

# Identifying duplicate rows
df = pd.DataFrame({'Name': ['John', 'Jane', 'John'],
                   'Age': [25, 30, 25]})
duplicated_rows = df.duplicated()
print(duplicated_rows)

# Outputs:
0    False
1    False
2     True
dtype: bool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Dropping duplicate rows
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df = df.drop_duplicates()
print(df)

# Outputs:
   Name  Age
0  John   25
1  Jane   30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Map and Replace: Modifying Values in DataFrames
&lt;/h2&gt;

&lt;p&gt;Pandas provides convenient methods for mapping and replacing values in DataFrames. The &lt;code&gt;map()&lt;/code&gt; function allows you to create new columns based on existing values or apply custom transformations to existing columns. The &lt;code&gt;replace()&lt;/code&gt; function is useful for substituting specific values or patterns in a DataFrame with new values.&lt;/p&gt;
&lt;h3&gt;
  
  
  Mapping Values
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

# Mapping values using a dictionary
df = pd.DataFrame({'Grade': ['A', 'B', 'C']})
grades_mapping = {'A': 'Excellent', 'B': 'Good', 'C': 'Average'}
df['Grade'] = df['Grade'].map(grades_mapping)
print(df)

# Outputs:
       Grade
0  Excellent
1       Good
2    Average
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Replacing Values
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df = pd.DataFrame({'Age': [25, 30, 35, 40]})
df['Age'] = df['Age'].replace({30: 31, 35: 36})
print(df)

# Outputs:
   Age
0   25
1   31
2   36
3   40

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These operations help in cleaning and transforming data, enabling you to make data more consistent and suitable for further analysis.&lt;/p&gt;
&lt;h2&gt;
  
  
  GroupBy: Aggregating and Analyzing Data
&lt;/h2&gt;

&lt;p&gt;GroupBy operations in Pandas allow you to split data into groups based on specified criteria, apply aggregation functions to each group, and combine the results. This functionality is invaluable for statistical analysis, as it enables you to compute summary statistics, perform group-level calculations, and gain insights into the data distribution.&lt;/p&gt;
&lt;h3&gt;
  
  
  GroupBy
&lt;/h3&gt;

&lt;p&gt;In this example, we create a DataFrame 'df' with population data for cities 'A' and 'B.' We then group the data by city and calculate the mean population for each group, creating a new DataFrame 'grouped_df' with the results. The output shows the average population for cities 'A' and 'B.'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pandas as pd

# Grouping and calculating mean
df = pd.DataFrame({'City': ['A', 'B', 'A', 'B'],
                   'Population': [100000, 200000, 150000, 250000]})
grouped_df = df.groupby('City').mean()
print(grouped_df)

# Outputs:
      Population
City            
A         125000
B         225000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Applying multiple aggregations
&lt;/h3&gt;

&lt;p&gt;We can do multiple aggregations like so. This gives us both the sum and mean of the population for city A and B&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df = pd.DataFrame({'City': ['A', 'B', 'A', 'B'],
                   'Population': [100000, 200000, 150000, 250000]})
aggregations = {'Population': ['sum', 'mean']}
grouped_df = df.groupby('City').agg(aggregations)
print(grouped_df)

# Outputs:
     Population          
            sum      mean
City                     
A        250000  125000.0
B        450000  225000.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GroupBy operations are particularly useful when working with large datasets, as they allow you to analyze data at different granularities and identify patterns or trends within each group.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Whew! You made it!! You're ready to go out into the world and confidently manipulate DataFrames with Pandas 🐼&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8adln1xnzymfnjghyhwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8adln1xnzymfnjghyhwm.png" alt="Image description" width="800" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By leveraging Pandas' Series and DataFrame data structures, as well as various functions and operations, you can effectively handle, transform, and analyze data for a wide range of use cases.&lt;/p&gt;

&lt;p&gt;In this blog post, we explored key aspects of Pandas, including Series manipulation, DataFrame operations, data reading, concatenation, merging, reshaping, duplication handling, mapping and replacing values, and GroupBy analysis. Armed with this knowledge, you can confidently dive into data analysis tasks and unleash the full potential of Pandas in your Python projects!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Data Science Zero to Hero - 1.1: Numpy</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Mon, 24 Jul 2023 23:17:46 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/data-science-zero-to-hero-11-numpy-26p0</link>
      <guid>https://forem.com/stevenmcgown/data-science-zero-to-hero-11-numpy-26p0</guid>
      <description>&lt;p&gt;Numpy is a Python library used for working with arrays, linear algebra, matrices, and much more. It’s a fantastic tool for anyone who wants to work with numerical data in Python, particularly in the context of data science and machine learning. Numpy is used extensively in machine learning algorithms, so it’s good to have some experience with it if you want to be able to create any ML solutions.&lt;/p&gt;

&lt;p&gt;This post will assume that you already have some programming experience with Python. In the future I might put out some posts on Python programming, but there are plenty of great videos and websites that can teach you how to program with Python.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefdxbre05d686zqmn3li.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefdxbre05d686zqmn3li.png" alt="Numpy Meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most basic thing to know about Numpy is a numpy array. You may be familiar with arrays already; in its most basic form, a 1 dimensional array is just a row of data. This can be anything, but most of the time we use these arrays for numbers, strings, or even a mix of both. &lt;/p&gt;

&lt;p&gt;For example, let's create a Numpy array with the following values:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import numpy as np
mixed_array = np.array(['Apple', 10, 'B', 5, 'Banana', 7.5, 'D', 3])


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can see that we have an array that contains a mix of strings, characters, integers and floating point numbers. We can reference items in the array like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mixed_array[0]
# Outputs "Apple"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will give us the value stored in the second compartment of the array, which is 4.&lt;/p&gt;

&lt;p&gt;Like an egg carton, a 2D array has compartments, or cells, that can hold values. An array with 2 or dimensions is also called a matrix. Each cell is identified by an index, which is like the number of the compartment in the egg carton. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48e6wr7b4orr5i7dzrx5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48e6wr7b4orr5i7dzrx5.jpg" alt="eggs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just like we did in the previous example, we can take an element out of the array. An important thing to notice with this is that because it is a 2D array, each element is an array. So when we index the first element in the array (0), we will get the first row in our array.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

egg_array = np.array([['egg1','egg2','egg3','egg4','egg5','egg6'],
                      ['egg7','egg8','egg9','egg10','egg11','egg12']])

print(egg_array[0])

# Outputs: ['egg1' 'egg2' 'egg3' 'egg4' 'egg5' 'egg6']


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can also slice a NumPy array, just like we can take out a row of eggs from an egg carton. For example, let's say we want to get the second and third values from the array:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

egg_array = np.array([['egg1','egg2','egg3','egg4','egg5','egg6'],
                      ['egg7','egg8','egg9','egg10','egg11','egg12']])


print(egg_array[0][1:3])

# Outputs: ['egg2' 'egg3']


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This outputs a new array with the values in the second and third compartments. Taking a closer look, we can see that we index the first array in the matrix with [0] and then the 2nd through 3rd elements in the array with [1:3].&lt;/p&gt;

&lt;p&gt;You might be wondering why is it that the 2nd and 3rd elements are selected with [1:3] and not [2:3]? In Python, when using slicing notation start:end, the start index is inclusive, while the end index is exclusive. It means that the range of elements selected includes the element at the start index but excludes the element at the end index.&lt;/p&gt;

&lt;p&gt;Great! Now that we understand how to index and slice arrays, let’s simplify our array just a little bit, so that each egg is represented as a number instead of a string. &lt;/p&gt;

&lt;p&gt;Just like you can add or subtract eggs from an egg carton, you can perform operations on a NumPy array. For example, let's say we want to multiply all the values in our array by 2:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

print(egg_carton * 2) 
# Outputs: [4, 8, 12, 16]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will give us a new array with the values doubled.&lt;/p&gt;

&lt;p&gt;You can also concatenate, or combine, two or more arrays together, just like you can stack multiple egg cartons on top of each other. For example, let's say we have two arrays:&lt;/p&gt;

&lt;p&gt;egg_carton1 = np.array([1, 2, 3])&lt;br&gt;
egg_carton2 = np.array([4, 5, 6])&lt;br&gt;
We can concatenate them together like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

print(np.concatenate([egg_carton1, egg_carton2])) 
# Outputs: [1, 2, 3, 4, 5, 6]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will give us a new array with all the values from both arrays.&lt;/p&gt;

&lt;p&gt;Finally, just like you can split an egg carton into two or more parts, you can split a NumPy array into smaller arrays. For example, let's say we have an array with six values:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

egg_carton3 = np.array([1, 2, 3, 4, 5, 6])


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can split it into two arrays of equal size like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

print(np.split(egg_carton3, 2)) 
# Outputs: [array([1, 2, 3]), array([4, 5, 6])]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will give us a list of two new arrays, each containing half of the values from the original array.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There are plenty of other concepts to learn about numpy, but for the sake of brevity, I'm going to cover the essentials in this post. If you would like to know more, please explore the numpy documentation!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So there you have it – a NumPy array is like an egg carton for numbers, with compartments that can be indexed, sliced, operated on, concatenated, and split! There are many useful things that you can do with Numpy that are more advanced and won’t be covered in this post. After you read this, I encourage you to dive deeper into the documentation if you’re interested in learning more.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Data Science Zero to Hero - Foreword</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Mon, 24 Jul 2023 23:04:20 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/data-science-zero-to-hero-foreword-3c2p</link>
      <guid>https://forem.com/stevenmcgown/data-science-zero-to-hero-foreword-3c2p</guid>
      <description>&lt;p&gt;Wow, it's been such a long time since I made a post here. I've been working hard, learning a lot, and I'm pleased to share that I have made sizeable strides into the world of Data Science!&lt;/p&gt;

&lt;p&gt;Since I've been gone, I saw that according to my post statistics I have totaled over 100k views! That's so amazing. Speaking of statistics, they have been on my mind for the past year! You might be wondering though, why? Well, statistics is truly the heart of the scientific method, and plays an integral role in Artificial Intelligence, Machine Learning and Data Science.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F079ozabzallkr4316khb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F079ozabzallkr4316khb.png" alt="scoobydoomeme" width="544" height="733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today I'll be starting a new series called "Data Science Zero to Hero" where I will be breaking down popular concepts so that those who are interested in learning about ML, AI and data science can learn in a guided way without any prior knowledge. It's also worth noting that these terms are often used interchangeably, but are not necessarily the same things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1u70yhw9z3ucb6m4m4pc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1u70yhw9z3ucb6m4m4pc.png" alt="Image description" width="730" height="776"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Artificial Intelligence (AI) is a broad concept focused on creating machines that can mimic human thinking, reasoning, and behavior. On the other hand, Machine Learning (ML) is a subset of AI where computer systems learn from their environment, using these learnings to enhance experiences and processes. It's important to note that all ML is AI, but not all AI involves ML.&lt;/p&gt;

&lt;p&gt;Data Science, in contrast, involves processing, analyzing, and extracting relevant insights from data. Data Scientists utilize machine learning techniques to predict future events by uncovering hidden patterns in the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  A little bit about myself...
&lt;/h2&gt;

&lt;p&gt;Just a little bit of background into what I learned so far - I took MIT's online Applied Data Science course and learned tons. If anyone is interested in an introduction to learning Data Science, I would definitely recommend it.&lt;/p&gt;

&lt;p&gt;My goal is to learn by teaching, and to help those who are intimidated by complex technical concepts. I hope that you're as excited as I am! Thanks for reading!&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>ai</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Terraform for Dummies - Part 2: Getting Started</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Wed, 08 Jun 2022 23:17:35 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/terraform-for-dummies-part-2-2lfj</link>
      <guid>https://forem.com/stevenmcgown/terraform-for-dummies-part-2-2lfj</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlhxa6ysjc7ou7qly1vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlhxa6ysjc7ou7qly1vg.png" alt="terraformaws"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome to the second part in the “Terraform for Dummies” series 😃 In the last post, we learned about instructure as code and got a high level overview of how terraform works in a DevOps environment. If you haven’t already, please learn the basics in the previous post before reading further. In this post, we will get our environment set up so we can start creating Terraform code!&lt;/p&gt;

&lt;p&gt;If you haven't already, please read &lt;a href="https://dev.to/stevenmcgown/terraform-for-dummies-part-1-eap"&gt;part 1&lt;/a&gt; of this series to have the best info going forward 👍&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Setting Up&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
Before we go any further, we will need to do three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have an active AWS account&lt;/li&gt;
&lt;li&gt;Install an IDE of your choice (I use VSCode)&lt;/li&gt;
&lt;li&gt;Install terraform&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create an AWS account:&lt;br&gt;
&lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/" rel="noopener noreferrer"&gt;https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install VSCode:&lt;br&gt;
&lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;https://code.visualstudio.com/download&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install Terraform:&lt;br&gt;
&lt;a href="https://learn.hashicorp.com/tutorials/terraform/install-cli" rel="noopener noreferrer"&gt;https://learn.hashicorp.com/tutorials/terraform/install-cli&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have done these three things, we will need to open up our IDE. I recommend using VSCode because of its wide array of extensions. One of the extensions I will be using is the Hashicorp Terraform extension, which will do things like syntax highlighting and autocompletion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdluochh35zzbfj3zs90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdluochh35zzbfj3zs90.png" alt="terraformextensions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open up a terminal in VSCode and type &lt;code&gt;$ terraform version&lt;/code&gt;. If you get an error message, you may have missed a step in the terraform installation step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1d1g4c8ayimkl7oodyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1d1g4c8ayimkl7oodyh.png" alt="terrformversion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Getting Started&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
Create a project folder and a new file called &lt;code&gt;main.tf&lt;/code&gt;. Inside of this file, we are going to add our aws provider found on &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest" rel="noopener noreferrer"&gt;hashicorp’s website&lt;/a&gt;. If you have programmed before, you are probably familiar with ‘main’ as a special keyword for compilers to find as a starting point for code execution. This is actually not the case with Terraform; Terraform treats all files with the &lt;code&gt;.tf&lt;/code&gt; extension as one single file, so any file names that you specify are just logical groups. It’s also a best practice to keep your naming conventions and file structure consistent across your projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdaue9taqsoowl8c6g58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdaue9taqsoowl8c6g58.png" alt="terraformmain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that we have a terraform block which is our terraform settings configuration. We need at least one provider in this block, so in our case we have aws. Notice that the provider is actually Hashicorp and not AWS themselves, although it is the official aws provider. At the time I am creating this post, the current version of terraform is 4.16.0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej8l43yzb11q038i3ryd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej8l43yzb11q038i3ryd.png" alt="terraformkeys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also see we have a provider block named “aws”. In this provider block, you can specify our region, access key and secret key. &lt;b&gt;It is important to know that you should NEVER share these keys with ANYONE!&lt;/b&gt; &lt;/p&gt;

&lt;p&gt;While it is possible to configure these credentials directly in the terraform code, &lt;b&gt;you should not do this&lt;/b&gt;. A better way is to store them in an AWS profile, which is what we will do for this tutorial. The best practice would be to store these keys in a secret manager like Hashicorp’s Vault. For the sake of simplicity and as to not deviate from focusing on Terraform itself, we will not be storing these secrets in Vault, but again in an AWS profile.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Generating AWS Keys&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
To generate our keys, we will first need to navigate to Identity Access Management in the AWS console.&lt;/p&gt;

&lt;p&gt;Once in IAM, create a User with any name that you want. In this case I will simply call it “Terraform.” Since we will only be using it from the terminal, only give it programmatic access and attach the &lt;b&gt;PowerUserAccess&lt;/b&gt; policy. This policy essentially gives the same permissions as the AdministratorAccess policy minus management of users and groups. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1j3rrvjxngcr6qlz6d8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1j3rrvjxngcr6qlz6d8.png" alt="Power user"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have created your user, you should see your Access key ID and Secret access key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhq1dp6r4qly3xnba106g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhq1dp6r4qly3xnba106g.png" alt="keys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again… &lt;b&gt;DO NOT SHOW YOUR access_key OR secret_key TO ANYONE OR PUSH THEM TO ANY REPOSITORY.&lt;/b&gt; Doing so could cause your AWS Account to be compromised!! That being said, I am not responsible for any wrongdoing that may come as a result of exposing secret keys.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Configuring an AWS Profile&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
Depending on how experienced you are with AWS CLI, you may have already configured your default aws profile to have access to AWS. We can configure AWS CLI to have multiple profiles which will allow us to have an IAM user dedicated to this terraform tutorial.&lt;/p&gt;

&lt;p&gt;To configure these credentials, edit the .aws/credentials file using your favorite text editor:&lt;br&gt;
~/.aws/credentials (Linux &amp;amp; Mac) or %USERPROFILE%.aws\credentials (Windows)&lt;/p&gt;

&lt;p&gt;In this file we can see the default credentials and we can add our own set of credentials to use. AWS specifies that you &lt;b&gt;cannot&lt;/b&gt; use the word “profile” when creating an entry in the credentials file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

[terraform_tutorial]
aws_access_key_id=ACCESS_KEY
aws_secret_access_key=SECRET_ACCESS_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have configured your credentials, you can now reference that credentials profile in your terraform code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzz0pyz7tlu4ga2zswbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzz0pyz7tlu4ga2zswbj.png" alt="awsprovider"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Terraform Code&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
Now that we have taken care of the credentials configuration, we can write a small piece of terraform code called a &lt;b&gt;resource block&lt;/b&gt;. A resource block describes one or more infrastructure objects, such as virtual networks, compute instances, or higher-level components such as DNS records. In our case, we can start by creating a sample S3 bucket so we don’t run up charges on our AWS account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2arcyfbfsv7h62kgyt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2arcyfbfsv7h62kgyt5.png" alt="s3bucket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that this resource block declares &lt;b&gt;resource type&lt;/b&gt; &lt;code&gt;"aws_s3_bucket"&lt;/code&gt; with a given &lt;b&gt;local name&lt;/b&gt; &lt;code&gt;"test-terraform-bucket"&lt;/code&gt;. The local name is used to refer to the s3 bucket resource from elsewhere in the same Terraform module, but has no significance outside that module's scope.&lt;/p&gt;

&lt;p&gt;Within the block body (between the &lt;code&gt;{&lt;/code&gt; and &lt;code&gt;}&lt;/code&gt;) are the &lt;b&gt;configuration arguments&lt;/b&gt;, &lt;code&gt;bucket&lt;/code&gt; and &lt;code&gt;tags&lt;/code&gt;, for &lt;code&gt;aws_s3_bucket&lt;/code&gt;.&lt;br&gt;
For &lt;code&gt;bucket&lt;/code&gt;, we must give a string that will create an s3 bucket with a globally unique name.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tags&lt;/code&gt; are optional, but I have added this argument to demonstrate that many configuration arguments can also have arguments from within themselves.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Terraform init&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
Recall from the previous post that “init” is the second stage of the terraform lifecycle, right after code. To recap, terraform init is used to initialize a working directory containing Terraform configuration files. This is the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control.&lt;/p&gt;

&lt;p&gt;We can initialize terraform using &lt;code&gt;$ terraform init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Terraform plan&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
The next step in the terraform lifecycle is plan. This step creates an execution plan, like a blueprint for a house. Unless explicitly disabled, terraform does a refresh and then declaratively determines what needs to be done in order to reach the desired configuration state.&lt;/p&gt;

&lt;p&gt;Run the terraform plan for this with &lt;code&gt;$ terraform plan&lt;/code&gt;. If successful, the following output and more will print out: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnkolendp6kmzp7acs7d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnkolendp6kmzp7acs7d.png" alt="plan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that the bucket and tags are listed in the output, and that everything else will be known after the apply. If you are receiving an error, you may have given invalid values or there might be a syntax error. At this point, terraform has not applied any changes to the AWS environment.&lt;/p&gt;

&lt;p&gt;You may have also noticed 2 new files generated in your project folder: “terraform-provider-aws_v4.16.0_x5” and “.terraform.lock.hcl”&lt;/p&gt;

&lt;p&gt;“terraform-provider-aws_v4.16.0_x5”  is nothing but the aws provider binary for terraform 4.16 and “.terraform.lock.hcl” is known as the dependency lock file which allows terraform to “remember” which exact version of each provider you used before.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Terraform apply&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
Once your plan is successful, you can run &lt;code&gt;$ terraform apply&lt;/code&gt;. This will apply all of the configuration changes which were made in the plan stage.&lt;/p&gt;

&lt;p&gt;When you run this command, you will be greeted with the following message asking if you want to perform the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2mrzf0f9wpbogdaaaum9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2mrzf0f9wpbogdaaaum9.png" alt="apply"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now your changes will be visible in the AWS console. Alternatively, you can run the following command to list your bucket. Make sure to use the profile that we configured earlier.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ aws s3 ls –profile &amp;lt;profile-name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will also see a new file called “terraform.tfstate”. This file unsurprisingly stores the state of your terraform configuration. While the format of the state files are just JSON, direct file editing of the state is discouraged. Terraform provides the terraform state command to perform basic modifications of the state using the CLI.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;b&gt;Terraform destroy&lt;/b&gt;&lt;/u&gt;&lt;br&gt;
At this point you have everything you need to deploy an s3 bucket solely using terraform. You might be seeing how powerful terraform can be now, since you can create and manage cloud infrastructure with some code and a few simple commands.&lt;/p&gt;

&lt;p&gt;At the end of every lifecycle, in our case terraform, there is an end. If you wish to tear down all of the infrastructure that you created, it's an easy task for terraform. Please note that you should only do this if you wish to delete the infrastructure that you provisioned.&lt;/p&gt;

&lt;p&gt;Once again, we are greeted with a similar message upon running &lt;code&gt;$ terraform destroy&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rfwk3g4ifsxo8phu945.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rfwk3g4ifsxo8phu945.png" alt="destroy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we allow terraform to destroy our resources by typing “yes”, we will no longer be able to see our s3 bucket in the aws console. And of course, you can again list your buckets by using the command: &lt;br&gt;
&lt;code&gt;$ aws s3 ls –profile &amp;lt;profile-name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foeeh8phh4jjgnyqwmvhq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foeeh8phh4jjgnyqwmvhq.png" alt="tf-lifecycle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This concludes part 2 of this series! Thank you for reading, and stay tuned for part 3 of this series. In the next post, we will be taking an even deeper dive into terraform.&lt;/p&gt;

&lt;p&gt;Please comment below if you’re enjoying these posts, and let me know if there’s anything I can improve!😊&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Terraform for Dummies - Part 1: What is Terraform?</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Tue, 31 May 2022 22:37:51 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/terraform-for-dummies-part-1-eap</link>
      <guid>https://forem.com/stevenmcgown/terraform-for-dummies-part-1-eap</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xxbvlvs531kq8by535n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xxbvlvs531kq8by535n.png" alt="terraform"&gt;&lt;/a&gt;&lt;br&gt;
Welcome to this first part of Terraform for Dummies! In this series, you will learn about what Terraform is and how DevOps engineers use it to provision, deploy and orchestrate both on-prem and cloud infrastructure in a reliable and easy way.&lt;/p&gt;

&lt;p&gt;If you’re a DevOps engineer, odds are you have at least heard of Terraform. In this series, we will use Terraform as an Infrastructure as Code (IaC) tool for provisioning Amazon Web Services (AWS) resources. We will also touch on important DevOps concepts along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Infrastructure as Code?
&lt;/h2&gt;

&lt;p&gt;IaC is pretty much exactly what it sounds like. Using IaC tools like terraform, you can do away with manual configuration all together by defining your infrastructure in a code template. There are a few reasons why IaC champions over manual configuration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;People are imperfect and get it wrong - misconfiguration becomes more likely as infrastructure scales due to human error.&lt;/li&gt;
&lt;li&gt;Transferring knowledge to teammates is difficult when environments are manually configured, especially across multiple projects. IaC allows any team member to read/edit IaC with little KT.&lt;/li&gt;
&lt;li&gt;Configuration compliance is also difficult. Enforcing compliance according to customer/company standards is easier with IaC.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Terraform uses their own configuration language called HCL, which we will dive into more in up-coming posts. You can use configuration scripts to automate creating, updating and destroying cloud infrastructure. Think of these configuration files as blueprints, much like a blueprint an architect would use to build a house.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz6v8mi8svg7btzb8r6p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz6v8mi8svg7btzb8r6p.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terraform supports a variety of providers outside of GCP, AWS and Azure and sometimes it’s the only provider available. It’s also open-source and extendable so any API can be used to create IaC tooling for any kind of cloud platform technology. E.g. Heroku, Spotify Playlists.&lt;/p&gt;

&lt;p&gt;Terraform is also &lt;strong&gt;cloud-agnostic&lt;/strong&gt;, meaning that it allows a single configuration to be used to manage multiple providers and even handle cross-cloud dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declarative vs. Imperative
&lt;/h2&gt;

&lt;p&gt;Immutability, or the inability to change the object state, is an important concept to grasp for understanding declarative vs imperative programming. Immutable types are safer from bugs, easier to understand, and more ready for change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Declarative programming&lt;/em&gt;&lt;/strong&gt; is a paradigm describing WHAT the program does, without explicitly specifying its control flow. There is zero chance of misconfiguration with declarative programming.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declarative languages don't have looping control structures, e.g. for and while, because &lt;strong&gt;due to immutability&lt;/strong&gt;, the loop condition would never change.&lt;/li&gt;
&lt;li&gt;Declarative languages don't express control-flow other than nested function order (a.k.a logical dependencies), because &lt;strong&gt;due to immutability&lt;/strong&gt;, other choices of evaluation order do not change the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Declarative programming uses scripting languages such as JSON, YAML, XML&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Imperative programming&lt;/em&gt;&lt;/strong&gt; is a paradigm describing HOW the program should do something by explicitly specifying each instruction (or statement) step by step, which &lt;strong&gt;mutate&lt;/strong&gt; the program's state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imperative programming is less verbose; you could end up with misconfiguration&lt;/li&gt;
&lt;li&gt;AWS CDK and Pulumi use imperative &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imperative programming uses scripting languages such as Python, Ruby and Javascript.&lt;br&gt;
So is Terraform declarative or imperative? Well, Terraform is declarative but it has imperative-like features like for loops, dynamic blocks, locals and complex data structures like maps and collections.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6h25pt6y4xivx9grlen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6h25pt6y4xivx9grlen.png" alt="declarativevsimperative"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Idempotent vs non-idempotent
&lt;/h2&gt;

&lt;p&gt;Idempotency is a principle of IaC that refers to the state of a configuration after applying changes.&lt;/p&gt;

&lt;p&gt;Non-idempotent configurations will add the specified resources each time they are applied whereas idempotent configurations can be applied multiple times without changing the results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-idempotent example:&lt;/strong&gt;&lt;br&gt;
Your configuration file specifies that you need three virtual machines. Each time you apply your configuration, you have 3 more virtual machines. So each time you apply, the number of VMs will increment by 3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Idempotent example:&lt;/strong&gt;&lt;br&gt;
Your configuration file specifies that you need three virtual machines. Each time you apply your configuration, the number of virtual machines is always 3 virtual machines. So no matter how many times you apply, you will always have the same number of VMs in your configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Drift
&lt;/h2&gt;

&lt;p&gt;Configuration drift is simply unexpected changes to your infrastructure. This can happen for a number of different reasons, including manual adjustments to configurations, side effects of SDKs, CLIs, or APIs or even from malicious actors.&lt;/p&gt;

&lt;p&gt;Terraform prevents configuration drift with the state file (.tfstate) which show what the configuration of files should be. To correct the drift, you can utilize the terraform plan and refresh commands which we will look to more in depth in the coming posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitOps
&lt;/h2&gt;

&lt;p&gt;Terraform goes hand-in-hand with GitOps. In collaborative environments, you can use a git repository as a formal process to review and accept changes to IaC. Once those changes are accepted, a deployment is triggered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkojvf512geafz2o7ho4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkojvf512geafz2o7ho4p.png" alt="gitops"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, Terraform code is pushed to a git repo such as Github or Bitbucket. The person who made the push can continue to commit until they are ready to create a pull request to the main branch. Once the pull request is approved by a reviewer, a CI/CD pipeline such as Jenkins, Concourse or Github Actions is triggered to deploy changes to your cloud environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgjzpkp9yzwc7yg2tmst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgjzpkp9yzwc7yg2tmst.png" alt="tfcloud"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terraform cloud also has their own version of this where you have a git repo, PR, and Terraform cloud takes care of the CI/CD.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform Lifecycle
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;At the start, you will update the &lt;strong&gt;code&lt;/strong&gt; of your terraform configuration file&lt;/li&gt;
&lt;li&gt;Then you will initialize your project or pull the latest providers using terraform &lt;strong&gt;init&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Next, the &lt;strong&gt;plan&lt;/strong&gt; allows you to speculate what your changes will be&lt;/li&gt;
&lt;li&gt;Validation happens automatically when your run plan but you can also &lt;strong&gt;validate&lt;/strong&gt; manually&lt;/li&gt;
&lt;li&gt;Finally, you will execute the terraform plan to provision infrastructure using &lt;strong&gt;apply&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You can also &lt;strong&gt;destroy&lt;/strong&gt; terraform infrastructure using apply or the destroy command&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05he41m3bbpl7h2a6f27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05he41m3bbpl7h2a6f27.png" alt="tflifecycle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now know the basics of Terraform! In the next post, we will set up a development environment for terraform and begin to start using terraform with AWS. &lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>OpenShift for Dummies - Part 2</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Wed, 04 Aug 2021 23:47:31 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/openshift-for-dummies-part-2-2eg4</link>
      <guid>https://forem.com/stevenmcgown/openshift-for-dummies-part-2-2eg4</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vomn5j6jtz8s58ki8kl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vomn5j6jtz8s58ki8kl.png" alt="openshiftlogo"&gt;&lt;/a&gt;&lt;br&gt;
Thank you for reading part two of OpenShift for Dummies! In this article, I will briefly outline advantages and use cases of OpenShift. Additionally, I will go into technical detail of how you can get started using OpenShift. As a reminder, OpenShift is open source and has a free tier intended for experimentation and development, which is perfect for beginners. If you haven’t read OpenShift for Dummies - Part 1, please read it here before continuing. In the last post, we talked about containers and their advantages over VM’s, but these important questions still remain: why should you use OpenShift and how do you get started using it?&lt;/p&gt;

&lt;h1&gt;Why Should I Use OpenShift?&lt;/h1&gt;

&lt;p&gt;In Kubernetes for Dummies, we talked about the need for a container orchestration system. In 2015, there were many different orchestration systems that people were using including cloud foundry, mesosphere, docker swarm, and kubernetes to name a few. Today, the market has consolidated and kubernetes has come out on top. Red Hat bet early on K8s and is now the second largest contributor and influencer of its direction, only next to Google. K8s is the kernel of distributed systems, while OpenShift is a distribution of it. What this means for developers is that whenever there is a new version of Kubernetes available, Red Hat can take K8s from upstream, secure it, test it and certify it with hardware and software vendors. In addition, Red Hat patches 97% of all security vulnerabilities within 24 hours and 99% within the first week, showing the difference between Red Hat and their competition.&lt;/p&gt;

&lt;h3&gt;OpenShift, the Platform of the Future&lt;/h3&gt;

&lt;p&gt;OpenShift is a platform that can run on premise, in a virtual environment, in a private cloud, or in a public cloud. You can migrate all of your traditional applications to OpenShift so you can get all of the advantages of containerization, as well as software from independent software vendors. You can also build cloud-native greenfield applications (greenfield describes a completely new project that has to be executed from scratch) as well as integrate Machine Learning and Artificial Intelligence functions. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8aae747uxd9rgumloub.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8aae747uxd9rgumloub.jpg" alt="openshiftfancy"&gt;&lt;/a&gt;&lt;br&gt;
OpenShift also provides automated operations, multi-tenancy, secure by default capabilities, network traffic control, and the option for chargeback and showback. OpenShift is also pluggable so you can introduce third party security vendors if you wish. Developers also get a self service provisioning portal so operations teams can define what is available for developers and developers can request controls as authorized by the operations team. The OpenShift platform is very versatile in that it runs on most public cloud services such as AWS, Azure, Google Cloud Platform, IBM Cloud, and of course it runs on-premises as well.&lt;/p&gt;

&lt;h1&gt;OpenShift Demo&lt;/h1&gt;

&lt;p&gt;You can use the trial version of OpenShift by visiting:&lt;br&gt;
&lt;a href="https://www.redhat.com/en/products/trials?products=hybrid-cloud" rel="noopener noreferrer"&gt;https://www.redhat.com/en/products/trials?products=hybrid-cloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this demo, you will need a Red Hat account. We will be selecting the option that plainly says ‘Red Hat OpenShift - An enterprise-ready Kubernetes container platform’&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttqv4q50uxghy21or7e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttqv4q50uxghy21or7e0.png" alt="tryit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select ‘Start your trial’ under ‘Developer Sandbox.’ The developer sandbox will suffice for this walkthrough. Please note that the account created will be active for 30 days. At the end of the active period, your access will be deactivated and all your data on the Developer Sandbox will be deleted. Upon logging in, you should be brought to this webpage:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1z8r2nimglrqog0zlwjb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1z8r2nimglrqog0zlwjb.png" alt="devscreen"&gt;&lt;/a&gt;&lt;br&gt;
If you are not brought here, visit &lt;a href="https://developers.redhat.com/developer-sandbox" rel="noopener noreferrer"&gt;https://developers.redhat.com/developer-sandbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Click ‘Get started in the Sandbox’ and then ‘Launch your Developer Sandbox for Red Hat OpenShift’ and then ‘Start using your sandbox.’ You may also need to verify your email address to continue. &lt;/p&gt;

&lt;h3&gt;Welcome to OpenShift!&lt;/h3&gt;

&lt;p&gt;On the side bar you can see different options to select from...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frp7cbyki55n5212xr3pr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frp7cbyki55n5212xr3pr.png" alt="devview"&gt;&lt;/a&gt;&lt;br&gt;
&lt;b&gt;Perspective Switcher&lt;/b&gt;&lt;br&gt;
You can toggle between Developer and Administrator perspectives using the perspective switcher. &lt;/p&gt;

&lt;p&gt;The Administrator perspective can be used to manage workload storage, networking, cluster settings, and more. This may require additional user access.&lt;/p&gt;

&lt;p&gt;Use the Developer perspective to build applications and associated components and services, define how they work together, and monitor their health over time.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Add&lt;/b&gt;&lt;br&gt;
You can select a way to create an application component or service from one of the options.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Monitor&lt;/b&gt;&lt;br&gt;
The monitoring tab allows you to monitor application metrics, create custom metrics queries, and view &amp;amp; silence alerts in your project.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Search&lt;/b&gt;&lt;br&gt;
Search for resources in your Project by simply starting to type or by scrolling through a list of existing resources.&lt;/p&gt;

&lt;p&gt;Now, switch to the Administrator perspective and look under projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3sklqizyaih3fnpqckr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3sklqizyaih3fnpqckr.png" alt="adminview"&gt;&lt;/a&gt;&lt;br&gt;
Under &lt;b&gt;projects&lt;/b&gt;, you may see two different projects, one for development and one for staging. The projects section allows you to create projects based on domains within IT (Developers, Operations, Security, Network, Infrastructure, Storage, etc) and isolate their functions from one another. Normally these teams would have their own systems, but through OpenShift they all have one singular console where they can have control for their respective roles. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60qvv38eupu25slj0y9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60qvv38eupu25slj0y9v.png" alt="oneplatform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, change back to the developer perspective. Under topology, we can see that we currently do not have any workloads. OpenShift gives us many options to create applications, components and services using the options listed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6xqnzobinyb2647vv79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6xqnzobinyb2647vv79.png" alt="catalog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s explore the catalog to see what we can choose from. Through the developer catalog, the developer does not need to request from the infrastructure team that they need a new developing environment, database, runtime, etc. Rather, the developer can choose from a list of pre-approved apps, services or source-to-image builders. For our purposes, we will be using python to create a front end. I will be using a sample random background color generator to demonstrate the use of python in OpenShift. This app will randomly generate a color and a welcome message to the user who opens the website. Simply type in ‘Python’ in the developer catalog or find it under Languages &amp;gt; Python and click the option that plainly says ‘Python.’&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6iar6r1uoxjx50rvgkz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6iar6r1uoxjx50rvgkz.png" alt="devcatalog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click ‘Create Application’&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzise0any50k0f9noboh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzise0any50k0f9noboh.png" alt="createapplication"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, we will paste the link from the github repository that holds the python script we will use for our webpage: &lt;a href="https://github.com/StevenMcGown/OpenShift_Demo" rel="noopener noreferrer"&gt;https://github.com/StevenMcGown/OpenShift_Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also change the name of the application if you wish. For our purposes, we will leave everything in default settings. Once you click ‘Create’, OpenShift will begin to build the application. You can see the build process from the side bar by navigating Builds &amp;gt; open-shift-demo &amp;gt; Builds &amp;gt; open-shift-demo-1 &amp;gt; Logs. In this screenshot, we can see that OpenShift goes to the location of the source code, and copies the source code. Once the source code is copied, it is analyzed and it will build an application binary. Next, OpenShift creates a &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;dockerfile&lt;/a&gt; which will install all of the app dependencies needed to run the application binary. The application dependencies are layered to make a container image, where it will be stored in a registry which is built into OpenShift. Finally, from that registry it will deploy an application file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4piggcgwtstkqhzk5rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4piggcgwtstkqhzk5rv.png" alt="build"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click on the Topology tab in the sidebar. We can see our python application in a bubble with 3 smaller bubbles attached. The green check mark shows that the build was successful, and we can actually check the build log we just saw by clicking on it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2uj5g0t6c0kon4vrfho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2uj5g0t6c0kon4vrfho.png" alt="withoutcoderw"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bubble on the bottom right with a red C allows us to edit our source code with CodeReady Workspaces. CodeReady Workspaces allows you to edit the code within the browser. Opening CodeReady Workspaces will take some time to open, but when it opens you should see an IDE similar to that of VSCode. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxtwafjag418ym2kxkak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxtwafjag418ym2kxkak.png" alt="codereadyworkspaces"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking back at the Topology of our application, we can now see that a CodeReady Workspaces icon is now added to our project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uc4qj3l3m0762bgvuf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uc4qj3l3m0762bgvuf6.png" alt="withcoderw"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking the bubble on the top-right on the python icon will open the container application. In this instance, it took green as the random color and we are welcomed with a message from the application open-shift-demo hosted on the ‘hkqbv’ container under the ‘7c749ff559’ replica set. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpqp2183ocota25hh345.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpqp2183ocota25hh345.png" alt="green"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an administrator, we are interested in giving the application high availability by scaling, control routing, etc. Let’s look at the application from an administrator’s perspective now. In the admin perspective, we can view our application pods by navigating to Workloads &amp;gt; Pods. Here we can see that only one pod is serving our application. If we want to increase our availability, we can navigate to Workloads &amp;gt; Deployments and increase the number of pods to serve our application. As a reminder, a deployment is a set of pods and ensures that a sufficient number of pods are running at one time to service an application. If you need to brush up on &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;Kubernetes&lt;/a&gt; concepts such as deployments and pods, please read &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;Kubernetes for Dummies.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1v0u0voouti6iamdevo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1v0u0voouti6iamdevo.png" alt="increasepods"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traditionally, if you wanted to increase the availability of your app, you would have to create an additional VM, create a load balancer, install the application and only then would you be set to have high availability. In OpenShift, increasing the availability is as simple as incrementing or decrementing the pod counter under ‘Deployment Details,’ which is done in seconds. Increasing the number of pods means an application will be hosted on each pod, meaning that the application we have will use 3 pods and thus 3 random colors.&lt;/p&gt;

&lt;p&gt;After refreshing your page, you may notice that the app does not ever change color… What gives? From a networking perspective, the default configuration is to have a sticky session, meaning that the user will always be hosted by the same container once they connect to the application. To change this, we will navigate to Networking &amp;gt; Routes and click on the 3 dots to edit annotations.&lt;/p&gt;

&lt;p&gt;We will add these key-value pairs to our existing annotations:&lt;br&gt;
haproxy.router.openshift.io/balance : roundrobin&lt;br&gt;
haproxy.router.openshift.io/disable_cookies : true&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjq9ifjlfqy2wglie2dw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjq9ifjlfqy2wglie2dw.png" alt="edit annotations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information on the round robin scheduling algorithm and cookies, visit these links:&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Round-robin_scheduling#Network_packet_scheduling" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Round-robin_scheduling#Network_packet_scheduling&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HTTP_cookie" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/HTTP_cookie&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you refresh the page, you will receive a new message each time indicating that you are being serviced by a different pod for the application. The background color, however, might be the same as another container since the app is initialized with a random color from an array of 7 colors. &lt;/p&gt;

&lt;h3&gt;Simulating a Crash&lt;/h3&gt;

&lt;p&gt;Let’s simulate one of the pods crashing to test our availability. In the administrator view, navigate  to Workloads &amp;gt; Pods. You should see 3 pods running under the Replica Set tag, indicating that the pods are created using the same data set. If we delete one of these pods, it would mean that the pod immediately fails. In doing so, Kubernetes will simultaneously create a container to replace the pod that failed. This shows that the controller is always looking at how many pods are running vs. how many are needed. In this case, K8s will detect that there are only 2 pods running and immediately create a new pod to replace the failed pod.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w3qoddve75y4nua0plv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w3qoddve75y4nua0plv.png" alt="afterdelete"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the old pod was deleted, a new pod was created with a container ID ‘hxghh’ and purple background.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftldv65vt6zwe05f95kh4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftldv65vt6zwe05f95kh4.png" alt="purple"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Developer Updates&lt;/h3&gt;

&lt;p&gt;Let's suppose the developer of the application updates the source code. When this happens, OpenShift needs to reflect the changes made by the developer. We can do this by building the project again by going into the developer perspective, clicking on the python icon, and clicking 'Start Build.' In this case, I added black to the array of colors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qwj84trp0i667m7pi9q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qwj84trp0i667m7pi9q.png" alt="new build"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing to note is a feature OpenShift uses called 'rolling updates.' Rolling updates ensure seamless transitions from one update to another. With rolling updates, new pods are commissioned while old ones are decommissioned one at a time until completion. This way, there is never a service loss for the end user. With some luck, we can now see a new color background for our web page as given by the developers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdhkq9ul9oatlnkcdrr6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdhkq9ul9oatlnkcdrr6a.png" alt="black"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;That's all I have for now! Thank you so much for reading part 2 of OpenShift for Dummies. I plan on making more of these in the future, but please let me know if you have any questions or concerns for these posts!&lt;/p&gt;

&lt;p&gt;I hope you have enjoyed reading. If you did, please leave a like and a comment! Also, follow me on LinkedIn at &lt;a href="https://www.linkedin.com/in/steven-mcgown/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/steven-mcgown/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>python</category>
    </item>
    <item>
      <title>OpenShift for Dummies - Part 1</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Sat, 24 Jul 2021 19:20:12 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/openshift-for-dummies-part-1-39f4</link>
      <guid>https://forem.com/stevenmcgown/openshift-for-dummies-part-1-39f4</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxw43n0qsszvu7myk9db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxw43n0qsszvu7myk9db.png" alt="OpenShift"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The best way to bring value to an existing business is with the development of new applications, whether they be cloud-native applications, AI &amp;amp; machine learning, analytics, IoT, or any other innovative application. OpenShift, created by Red Hat, is the platform large enterprises use to deliver container-based applications. If you have read my previous posts about &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;Docker&lt;/a&gt; and &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;Kubernetes&lt;/a&gt;, you understand the importance of containerization in the cloud. OpenShift claims to be “the industry's most secure and comprehensive enterprise-grade container platform based on industry standards.” To put it bluntly, OpenShift is like &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;Kubernetes&lt;/a&gt; on steroids.&lt;/p&gt;

&lt;p&gt;In this post, I will cover a brief history of IT infrastructure, summarize the role of a DevOps engineer and why they use OpenShift, how OpenShift works, and in part 2 I will show how to use OpenShift. Having a good grasp of the evolution of IT infrastructure is important to fully understand why DevOps engineers use OpenShift and appreciate the impact OpenShift on the cloud computing industry.&lt;/p&gt;

&lt;p&gt;If you have already read part 1, please stay tuned for part 2!&lt;/p&gt;

&lt;h1&gt;How IT Infrastructure Has Changed Over Time&lt;/h1&gt;

&lt;p&gt;Moore’s law is the observation that the number of transistors on a chip doubles every two years. This means that we can expect the speed and capability of computers to increase every couple of years, and that we will pay less for them. Increasingly powerful microchips have consistently brought forth sweeping changes to business and life in general ever since the advent of the internet. It is hilarious how wrong some people were about how the internet would affect our lives.&lt;/p&gt;

&lt;p&gt;In 1995, scientist Clifford Stoll was promoting his book, “Silicon Snake Oil.” At the same time, he published an article in Newsweek titled, “The Internet? Bah!,” in which he stated that services like e-commerce would not be viable, and that “no online database will replace your daily newspaper.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdd1oduroxjkjry4lehne.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdd1oduroxjkjry4lehne.gif" alt="petergriffin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perhaps it's just that hindsight is 20/20. After all, Clifford Stoll managed computers at Lawrence Berkeley National Laboratory in California, so it’s not like his opinion was coming from a place of ignorance. Today, most people know how ubiquitous internet technology is to some degree, but where did that process start, and where are we now? Let's begin with the development process. There are 3 pertinent development processes that you may be familiar with:&lt;/p&gt;

&lt;h3&gt;Development Processes&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;Waterfall:&lt;/b&gt; The waterfall process is named for its one-way approach. Progress is typically only made in mode direction, like a waterfall. A project is broken down into linear sequential phases and each phase depends on the deliverables of the previous phase. The main issue with this is if a client decides that their needs have changed, it is difficult to go back and make changes. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Agile:&lt;/b&gt; From the waterfall method, the agile method was born. Instead of delivering 100% to the client at each stage, you may deliver about 20% of a functionality. At that point, the client gives their feedback and while you continue to work on the deliverable, you begin the process of creating another functionality. After 5 iterations, developers have a product that they are satisfied with and will continue to use. But what about IT operations; those who run existing servers, websites and databases?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;DevOps:&lt;/b&gt; Since development and operation teams can have different goals and skills, the division of these two teams often creates an environment where they do not trust each other. The DevOps approach combines these two teams so they have shared passion and common goals. I will touch more on this later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vibo1ht1pd6zeei1ahy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vibo1ht1pd6zeei1ahy.jpg" alt="devevolution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next aspect of IT evolution is application architecture, which refers to the software modules and components, internal and external systems, and the interactions between them.&lt;/p&gt;

&lt;h3&gt;Application Architecture&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;Monolithic:&lt;/b&gt; A monolithic architecture is the traditional unified model for the design of a software program. Monoliths had a main frame that held the entire application stack, so if the mainframe hardware crashed, the entire system was down. These were then broken down over the years into separate tiers.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;3-tier:&lt;/b&gt; Three-tier systems break down the model of the mainframe into a web tier, an application tier, and a database tier. This is known as service-oriented architecture (SOA). The reality remains, however, if one of these tiers goes down, you have downtime. And still, all of the application logic remains in the app tier. People have moved on from this architecture to a microservice architecture. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Microservices:&lt;/b&gt; In this architecture, you build your services not by the tier, but rather by the business functionality. I will go into more detail about microservices later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcm3hg42wy16d3x34qkuy.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcm3hg42wy16d3x34qkuy.jpeg" alt="MonolithicvsMicroservices"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next aspect is application infrastructure, which is the software platform for the delivery of business applications.&lt;/p&gt;

&lt;h3&gt;Application Infrastructure&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;Data Centers:&lt;/b&gt; These are giant rooms filled with large, powerful computers that make a lot of noise. To put it in perspective, many data centers are larger than 100,000 sq feet and require specially designed air conditioning systems to make sure they do not overheat. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Hosted:&lt;/b&gt; Collections of organizations all underneath one umbrella host their computing and storage power for other businesses to use. This is the precursor of cloud computing.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Cloud computing:&lt;/b&gt; Cloud computing uses a network of remote servers to take care of storing, managing, and processing data. There are many cloud providers out there, namely Amazon Webservices, Azure and Google Cloud Platform, which dominate the global market. With cloud computing, hosting, availability, redundancy, etc. are taken care of by a cloud provider. Many businesses are wanting to move to cloud computing, but there are logistical challenges that people have to consider and overcome to do so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhrcc72yoh4n8lmmki90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhrcc72yoh4n8lmmki90.png" alt="infrastrucure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not only is how applications are developed important, but how they are delivered is also important. The evolution of deployment and packaging is as follows:&lt;/p&gt;

&lt;h3&gt;Deployment and Packaging&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;Physical servers:&lt;/b&gt; At one point, one physical server hosted one application. By today's standards, this is very inefficient. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Virtual servers:&lt;/b&gt; On one physical server you can have many virtual machines, which can host an application.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Containers:&lt;/b&gt; Containerization is the next step that businesses are adopting for application development. With containers, multiple applications with all their dependencies can be hosted on a single server without having the OS layer in between. &lt;/p&gt;

&lt;p&gt;You should be familiar with containers! If you are not, please read &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;“Docker for Dummies”&lt;/a&gt; and &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;"Kubernetes for Dummies"&lt;/a&gt;. The rest of this post assumes you understand the basics behind containerization and container orchestration.&lt;/p&gt;

&lt;h1&gt;DevOps Best Practices&lt;/h1&gt;

&lt;p&gt;We have seen that new technology gives rise to new ways of creating applications. As stated before, there are often issues between development and operation teams, which is why companies are adopting DevOps practices to streamline their development. DevOps engineers use OpenShift because it makes cloud deployments easy and enables them to follow these DevOps best practices:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Everything as Code:&lt;/b&gt; The practice of treating all parts of a system as code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Infrastructure as Code:&lt;/b&gt; Simple workflows to auto-provision infrastructure in minutes. (e.g. Terraform, AWS CloudFormation)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Environments as Code:&lt;/b&gt; Single workflows to build and deploy virtual machine environments in minutes. (e.g. Vagrant, &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;Docker&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Configuration as Code:&lt;/b&gt; Simple, model-based workflows to scale app deployment and configuration management. (Ansible, Puppet, Chef)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Data Pipelines as Code:&lt;/b&gt; Programmatically author, schedule and monitor data pipeline workflows as code. (e.g. Apache Airflow, Jenkins)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Security Configuration as Code:&lt;/b&gt; Detect and remediate build &amp;amp; production security misconfigurations at scale. (e.g. Checkov)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;b&gt;Encryption Management as Code:&lt;/b&gt; Programmatically secure, store and tightly control access across cloud and data center (e.g. Vault, AWS KMS)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Application is always “releasable”:&lt;/b&gt; Because everything is code, it is always releasable at any point in time.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Rebuild vs. Repair:&lt;/b&gt; This is precisely the point between developers and operations that causes friction (AKA integration hell). For example, someone on the development team changes something in the development environment of the application. Or maybe someone in operations changes something in staging of production. Either way, you have an end product which does not reflect either side. What you should do is instead of tweaking the end product, you should have a golden image that everyone tweaks and can be released at any time. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Continuous Monitoring:&lt;/b&gt; You should ensure there is no malware or security vulnerabilities in your application stack, and that any sensitive information like passwords or keys are not exposed to the public.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Automate Everything:&lt;/b&gt; Don’t do things manually which can be done automatically like configuration management and testing. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Rapid Feedback:&lt;/b&gt; Rapid feedback loops are what make good development teams. The goal behind having rapid feedback is to continuously remove bottlenecks. A simple example of a rapid feedback loop is a CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Delivery pipeline:&lt;/b&gt; A delivery pipeline automates the continuous deployment of a project. In a project's pipeline, sequences of stages retrieve input and run jobs, such as builds, tests, and deployments.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Continuous Integration/Continuous Delivery or Deployment(CI/CD):&lt;/b&gt; CI/CD is a method to frequently deliver apps to customers.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Continuous Integration:&lt;/b&gt; New code changes to an app are regularly built, tested and merged to a shared repository. This solves the problem of having too many branches or an app in development at once that could possibly conflict with one another.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Continuous Delivery:&lt;/b&gt; Applications are automatically bug tested and uploaded to a repository (e.g. GitHub, &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;DockerHub&lt;/a&gt;) where they can then be deployed to a live production environment.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Continuous Deployment:&lt;/b&gt; Automatically testing a developer’s changes from the repository to production where it is usable by customers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fps3l43tt6gehhln8dv3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fps3l43tt6gehhln8dv3d.png" alt="devopsbestpractices"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Developing Applications With Monoliths vs. Microservices&lt;/h1&gt;

&lt;p&gt;Consider the following application: An airline company wants to create an application to book flights. There are three major areas of the application that should be created: Registration, Payment and Service Inquiry. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;Monolithic:&lt;/b&gt;&lt;br&gt;
With a monolithic architecture, there are some serious drawbacks. All three major areas must be tightly coupled in order to run.&lt;/p&gt;

&lt;p&gt;In the monolithic model, all of the modules and programs only work on one type of system and are dependent on one another. This makes new changes a challenge and drives up cost to scale. There is also low resilience in this system because if anything fails, the whole system fails, which can happen for any number of reasons. Maybe there is a hardware issue, or maybe the application receives more traffic than it is designed to handle. In both cases, the application crashes and the whole system is down.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Microservices:&lt;/b&gt;&lt;br&gt;
In a microservices architecture, you split your business function so each function has its own set of independent resources. Each function might have its own application and its own database. This means you can independently scale these services and that you are not limited to the technology that you use for your application stack. Autonomous services (microservices) make systems more resilient, flexible to changes, easy to scale and highly available. With cloud platforms like AWS, you can automate these processes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zlmlbq6nzve05jd7k56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zlmlbq6nzve05jd7k56.png" alt="microvsmacro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Moving to the Cloud&lt;/h1&gt;

&lt;p&gt;A notable issue with using virtual machines in infrastructure is that they are not portable across the hypervisor and thus do not provide portable packaging for applications. So in practice, there is no guarantee that applications will migrate smoothly from, say, an employee’s laptop to a virtual machine or to a public cloud. There are different OS layers, different stacks for each environment, so the portability is nonexistent. As explained before in &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;“Docker for Dummies”&lt;/a&gt;, containerization software like &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;Docker&lt;/a&gt; offers a solution for this. OpenShift uses Red Hat Enterprise Linux which has their own container daemon built into the kernel, eliminating the need for containerization applications like &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;Docker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2thpkpdmbmfvg6vdcix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2thpkpdmbmfvg6vdcix.png" alt="rhelcoreos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A conceptual way of thinking about it is in terms of microservices. If you have hundreds of microservices, you are not going to want to have hundreds of virtual machines for each service because there would be too much overhead. This is why containerization is necessary if businesses want to adopt a microservice architecture. Here is a simple view of the advantages of using containers vs. virtual machines:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo5ejsh7rlb30j575gse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo5ejsh7rlb30j575gse.png" alt="VMvsContainer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve talked about IT infrastructure, DevOps practices and how OpenShift is used to manage containers. We also discussed some advantages of using OpenShift, but how does OpenShift differ from &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;Kubernetes&lt;/a&gt;, and how do you get started?&lt;/p&gt;

&lt;p&gt;Please stay tuned for part 2 to learn more!&lt;/p&gt;

&lt;p&gt;If you are enjoying this series, please leave a like and a comment. Writing these posts takes a lot of work and I love to hear your feedback! Also, feel free to follow me here on &lt;a href="https://dev.to/stevenmcgown"&gt;Dev.to&lt;/a&gt; for more posts like these, and on &lt;a href="https://www.linkedin.com/in/steven-mcgown/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to get in contact with me!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>linux</category>
    </item>
    <item>
      <title>Kubernetes for Dummies</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Tue, 13 Jul 2021 14:58:08 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/kubernetes-for-dummies-5hmh</link>
      <guid>https://forem.com/stevenmcgown/kubernetes-for-dummies-5hmh</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtw4rwv0m4u30x3n1uwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtw4rwv0m4u30x3n1uwz.png" alt="k8slogo"&gt;&lt;/a&gt;&lt;br&gt;
After receiving much positive feedback on my post &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;“Docker for Dummies”&lt;/a&gt;, I wanted to create a post about Docker’s often-paired technology Kubernetes. If you haven’t read Docker for Dummies yet, please read it &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;here&lt;/a&gt;, and if you are already familiar with Kubernetes, consider reading my post about &lt;a href="https://dev.to/stevenmcgown/openshift-for-dummies-part-1-39f4"&gt;OpenShift&lt;/a&gt;. Understanding a container service like Docker is fundamental to having a good grasp of Kubernetes. In fact, Kubernetes is capable of managing other container runtimes that will not be covered in this post. In this post I will explain what Kubernetes is, what problems it solves with containers, and how you can get started using it today.&lt;/p&gt;

&lt;h3&gt;An Introduction to Kubernetes&lt;/h3&gt;

&lt;p&gt;Kubernetes is derived from the Greek word κυβερνήτης (kubernḗtēs), which means pilot or helmsman. The Kubernetes logo of a ship's steering wheel further enforces the idea of piloting or managing, which is exactly what Kubernetes does with Docker containers. Kubernetes manages Docker containers in a variety of ways so it does not have to be done manually. Kubernetes is often referred to as K8s for simplicity because of the 8 letters in between “K” and “s”. I will be referring to Kubernetes as K8s from here on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqa8y75sy1i4d8etqnw0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqa8y75sy1i4d8etqnw0.jpeg" alt="k8scomic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using K8s further abstracts machines, storage and networks from their physical implementation. As described in the last post, manually managing numerous containers can create similar issues to managing virtual machines. However, managing containers is especially important because cloud companies bill you for things like computing time and storage. You don’t want to have many running containers doing nothing for this reason. In addition, you also don’t want one container taking a network load it cannot handle by itself. K8s is designed to solve problems like these. &lt;/p&gt;

&lt;h3&gt;What services does K8s provide?&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;Service discovery and load balancing: &lt;/b&gt; K8s can locate a container using a DNS name or IP address and can distribute network traffic to other containers to stabilize deployments.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Storage orchestration: &lt;/b&gt;You can automatically mount a storage system of your choice, whether it be locally, with a cloud provider such as AWS or GCP, or a network storage system such as NFS iSCSI, Gluster, Ceph, Cinder, or Flocker.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Automated rollouts and rollbacks: &lt;/b&gt;You can define the desired state of deployed containers and change the state at a controlled rate. For example, you can automate Kubernetes to create new containers for your deployment, remove existing containers and adopt all their resources to the new container.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Automatic bin packing: &lt;/b&gt;You can provide K8s with a cluster of nodes to run containerized tasks and specify how much CPU and memory each container needs. Kubernetes can automatically fit containers onto nodes to make the best use of resources.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Self-healing: &lt;/b&gt;K8s restarts containers that fail, replaces containers, kills containers that don't respond to your user-defined health check, and doesn't advertise them to clients until they are ready to serve.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Secret and configuration management: &lt;/b&gt;K8s lets you store sensitive information such as SSH keys, OAuth tokens and passwords. You can update these secrets and app configuration without rebuilding your container images and without exposing secrets in your stack configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will only scratch the surface of these features in this post.&lt;/p&gt;

&lt;h3&gt;Some Definitions&lt;/h3&gt;

&lt;p&gt;It is important to understand these basic K8s concepts. Again, you should also be familiar with container services such as &lt;a href="https://dev.to/stevenmcgown/docker-for-dummies-2bff"&gt;Docker&lt;/a&gt; before continuing.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Pods&lt;/b&gt; are groups of one or more containers. Pods have shared storage and network resources which have specifications on how to run the containers. They are the smallest deployable units of computing that you can create and manage using K8s. Pods run on &lt;strong&gt;&lt;em&gt;nodes&lt;/em&gt;&lt;/strong&gt; together as a logical unit, so they all share the same IP address but can reach each other via localhost. Pods can also share storage but do not have to run on the same machine since containers can span multiple machines.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Nodes&lt;/b&gt; are physical or virtual machines that are not created by K8s. Typically, you would have several nodes in a cluster but you may have just one node in a learning or resource-limited environment. Nodes are created manually or with public cloud services such as AWS EC2 or OpenStack, so you need to have basic infrastructure laid down before you use K8s to deploy applications. From this point you can define virtual networks, storage, etc. One node can run multiple pods.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Deployments&lt;/b&gt; are a set of Pods. A Deployment ensures that a sufficient number of Pods are running at one time to service the app. Deployments can also shut down Pods that are not needed by looking at metrics such as CPU utilization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx4juywf3ih7dajimdrx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx4juywf3ih7dajimdrx.png" alt="kubernetesmodel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Let's Get Started Using K8s&lt;/h1&gt;

&lt;p&gt;To run K8s locally, I will be using Minikube and Kubectl. You can install the latest version of Minikube at &lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;https://minikube.sigs.k8s.io/docs/start/&lt;/a&gt; and Kubectl at &lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/tools/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please note that you must also have Docker installed to move forward with this tutorial.&lt;/p&gt;

&lt;h3&gt;1) Install prerequisites&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;docker --version&lt;/code&gt; and &lt;code&gt;minikube version&lt;/code&gt; and &lt;code&gt;kubectl version&lt;/code&gt; Don't worry about the message stating the connection to localhost:8080 was refused, we will address this later. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6zjri8deatfiq84551s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6zjri8deatfiq84551s.png" alt="version"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;2) Create nodes with Minikube&lt;/h3&gt;

&lt;p&gt;To create nodes, start up Minikube. For example, starting Minikube with 2 nodes:&lt;br&gt;
&lt;code&gt;minikube start --nodes=2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will take a while the first time around, so be patient. The first time I ran this it easily took 5-10 minutes to complete.&lt;/p&gt;

&lt;p&gt;We can check the status of our nodes using &lt;code&gt;minikube status&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzab7bdmf42qddwdqq0r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzab7bdmf42qddwdqq0r9.png" alt="minikube status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first node is the master node. You can see that it has the control plane, running host, kubelet, API, and kubeconfig configured. The second node is the work node.&lt;/p&gt;

&lt;p&gt;We can see that we have 2 containers running if we run:&lt;br&gt;
&lt;code&gt;docker ps&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnghjs7gp9qdcv6s8hrkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnghjs7gp9qdcv6s8hrkt.png" alt="dockerps"&gt;&lt;/a&gt;&lt;br&gt;
This image shows the master node as ce3359246578 and the work node as 44697ff120e4  with relevant information for both nodes.&lt;/p&gt;

&lt;p&gt;We can view our nodes using:&lt;br&gt;
&lt;code&gt;kubectl get nodes&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7r7op750n5z6zeubn1x5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7r7op750n5z6zeubn1x5.png" alt="kubectlgetnodes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By running &lt;code&gt;kubectl get pods -A&lt;/code&gt;, we can retrieve all pods in all namespaces.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgren5pqjatamdf9uiddz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgren5pqjatamdf9uiddz.png" alt="allpods"&gt;&lt;/a&gt;&lt;br&gt;
All of the these pods make up the control plane. For example, kube-apiserver-minikube is the API which is exposed for external and internal communications. So when we type kubectl, this is the API server that handles the request for it. &lt;/p&gt;

&lt;h3&gt;3) Creating a deployment&lt;/h3&gt;

&lt;p&gt;We can check the Pods by typing &lt;code&gt;kubectl get pod&lt;/code&gt;. At this point, you should not have any Pods and it will read “No resources found in default namespace”&lt;/p&gt;

&lt;p&gt;Pods are the smallest unit of the K8s cluster but in practice, you don’t create Pods but rather deployments. To create a kubernetes deployment, the usage is &lt;code&gt;kubectl create deployment &amp;lt;NAME&amp;gt; --image=&amp;lt;image&amp;gt;&lt;/code&gt;. For this particular deployment, we will be creating a nginx deployment:&lt;br&gt;
&lt;code&gt;kubectl create deployment nginx-depl --image=nginx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For those who don't know, NGINX is an open-source webserver that is used to develop server-side applications.&lt;/p&gt;

&lt;p&gt;Now when we run &lt;code&gt;kubectl get deployment&lt;/code&gt; and &lt;code&gt;kubectl get pod&lt;/code&gt; we get the following output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek3bwq8hlplrg438d8e1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek3bwq8hlplrg438d8e1.png" alt="getpodanddeployment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our usage of &lt;code&gt;kubectl create deployment &amp;lt;NAME&amp;gt; --image=&amp;lt;image&amp;gt;&lt;/code&gt; is the most minimalistic way to create a deployment. The rest of the deployment uses default configuration. Between the deployment and Pod there is another layer which is automatically manages by K8s deployment called &lt;strong&gt;&lt;em&gt;ReplicaSet&lt;/em&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;The ReplicaSet specifies how to identify Pods that it can acquire, a number of replicas indicating how many Pods it should be maintaining, and a Pod template specifying the data of new Pods it should create to meet the number of replicas criteria. A ReplicaSet then fulfills its purpose by creating and deleting Pods as needed to reach the desired number. When a ReplicaSet needs to create new Pods, it uses its Pod template.&lt;/p&gt;

&lt;p&gt;We can view the ReplicaSet with &lt;code&gt;kubectl get replicaset&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2corya2vobwofgnlwrd0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2corya2vobwofgnlwrd0.png" alt="replicaset"&gt;&lt;/a&gt;&lt;br&gt;
We can see the ID for the ReplicaSet appended to the deployment name: 5c8bf76b5b. You may notice that the ReplicaSet ID is included in the ID for the Pod; like stated before the ReplicaSet is a layer that sits between the Deployment and the Pod.&lt;/p&gt;

&lt;p&gt;So all together, this is how the layers of Abstraction work. A Deployment manages a ReplicaSet,a ReplicaSet manages all the replicas of the Pod, and a Pod is an abstraction of a container. &lt;/p&gt;

&lt;h3&gt;4) Edit the Deployment&lt;/h3&gt;

&lt;p&gt;Edit your deployment using:&lt;br&gt;
&lt;code&gt;kubectl edit deployment nginx-depl&lt;/code&gt;&lt;br&gt;
This will show the auto-generated configuration file. Don't worry, you don't need to understand everything in the config file at this time. For the sake of this tutorial, we will only edit the image version which can be found somewhere in the middle of the file.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9afk2q9rl8g3fd1chs5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9afk2q9rl8g3fd1chs5e.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
When you are finished editing, type :wq for write &amp;amp; quit. This will terminate the old image and create a new one.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0022ap79ut2ff86qi362.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0022ap79ut2ff86qi362.png" alt="new"&gt;&lt;/a&gt;&lt;br&gt;
Upon invoking &lt;code&gt;kubectl get replicaset&lt;/code&gt;, we can see that the old one has no pods in it and a new one has been created as well.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0yq7n3moroyujwnqv6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0yq7n3moroyujwnqv6g.png" alt="newreplicaset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;5) Debugging Pods&lt;/h3&gt;

&lt;p&gt;Another useful command is &lt;code&gt;kubectl logs &amp;lt;Pod Name&amp;gt;&lt;/code&gt;.&lt;br&gt;
If you run this on nginx, you will get nothing because nginx did not log anything. To demonstrate logs we can use MongoDB, which is a document database.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl create deployment mongo-depl --image=mongo&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib5w6v7kqlkzjrzt4ui1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib5w6v7kqlkzjrzt4ui1.png" alt="created"&gt;&lt;/a&gt;&lt;br&gt;
Executing &lt;code&gt;kubectl logs mongo-depl-5fd6b7d4b4-vbf2t&lt;/code&gt; will produce concise logs and &lt;code&gt;kubectl describe pod mongo-depl-5fd6b7d4b4-vbf2t&lt;/code&gt; will produce a more verbose output.&lt;/p&gt;

&lt;p&gt;Logging will help with debugging if something goes wrong, and describe produces something a little more intelligible.&lt;/p&gt;

&lt;p&gt;Another useful command to see whats going on inside the Pod is &lt;code&gt;kubectl exec -it &amp;lt;Pod Name&amp;gt; -- bin/bash&lt;/code&gt;. (-it stands for interactive terminal)&lt;/p&gt;

&lt;p&gt;Suppose we want to use this to enter our MongoDB Pod:&lt;br&gt;
&lt;code&gt;kubectl exec -it mongo-depl-5fd6b7d4b4-vbf2t --bin/bash&lt;/code&gt; and if we type &lt;code&gt;ls&lt;/code&gt; we can see our directories. To exit this, simply type &lt;code&gt;exit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugafn2aw5h0yeyrcrcer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugafn2aw5h0yeyrcrcer.png" alt="root"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;6) Deleting deployments&lt;/h3&gt;

&lt;p&gt;Deleting a Deployment will delete all of the Pods inside of the Deployment. For example, to delete the MongoDB Deployment type:&lt;br&gt;
&lt;code&gt;kubectl delete deployment mongo-depl&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;The following commands are useful, but you should be careful not to delete anything important&lt;/h1&gt;

&lt;p&gt;You can delete all the pods in a single namespace with this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl delete --all pods --namespace=foo&lt;/code&gt;&lt;br&gt;
You can also delete all deployments in namespace which will delete all pods attached with the deployments corresponding to the namespace&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl delete --all deployments --namespace=foo&lt;/code&gt;&lt;br&gt;
You can delete all namespaces and every object in every namespace (but not un-namespaced objects, like nodes and some events) with this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl delete --all namespaces&lt;/code&gt;&lt;br&gt;
However, the latter command is probably not something you want to do, since it will delete things in the kube-system namespace, which will make your cluster not usable.&lt;/p&gt;

&lt;p&gt;This command will delete all the namespaces except kube-system, which might be useful:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;for each in $(kubectl get ns -o jsonpath="{.items[*].metadata.name}" | grep -v kube-system);&lt;br&gt;
do&lt;br&gt;
  kubectl delete ns $each&lt;br&gt;
done&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;7) Apply configuration files&lt;/h3&gt;

&lt;p&gt;To apply a configuration file, we must first create one. In a directory you can refer back to, create a config file for the nginx Deployment.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch nginx-deployment.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, copy and paste this configuration to the file:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;br&gt;
apiVersion: apps/v1&lt;br&gt;
kind: Deployment&lt;br&gt;
metadata:&lt;br&gt;
  name: myapp&lt;br&gt;
  labels:&lt;br&gt;
    app: nginx&lt;br&gt;
spec:&lt;br&gt;
  replicas: 1&lt;br&gt;
  selector:&lt;br&gt;
    matchLabels:&lt;br&gt;
      app: nginx&lt;br&gt;
  template:&lt;br&gt;
    metadata:&lt;br&gt;
      labels:&lt;br&gt;
        app: nginx&lt;br&gt;
    spec:&lt;br&gt;
      containers:&lt;br&gt;
      - name: nginx&lt;br&gt;
        image: nginx:1.16&lt;br&gt;
        ports:&lt;br&gt;
        - containerPort: 80&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Everything under "template" is the blueprint for the Pods. The first spec tag is specification for Deployments, and the second spec tag is specification for the Pods.&lt;/p&gt;

&lt;p&gt;This config file basically states we want one container inside of the pod with an NGINX image and we are going to bind that on port 80.&lt;/p&gt;

&lt;p&gt;When we use &lt;code&gt;kubectl apply -f nginx-deployment.yaml&lt;/code&gt;, it creates a deployment using the configuration. Lets say that in the config file we changed the Deployment to create 4 replicas instead of 1.&lt;/p&gt;

&lt;p&gt;After typing &lt;code&gt;kubectl get pod&lt;/code&gt; and &lt;code&gt;kubectl get deployment&lt;/code&gt; we get the following output:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxttnadsogw1zlycjkwy6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxttnadsogw1zlycjkwy6.png" alt="afterchange"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, K8s knows when to create or update deployment.&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;By following this article you should gain a good understanding of the fundamentals of Kubernetes. In summary, we learned what Kubernetes is and what it can do at a high level. We learned what services K8s provides as well as some important definitions. We then used Docker, Minikube and Kubectl to explore CRUD commands for Deployments. Finally, we learned how to debug Pods and use configuration files for Deployments. It should be mentioned that you can also use kubectl for services, volumes, any other K8s component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkplzmfqfc03jnqvklv9m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkplzmfqfc03jnqvklv9m.jpg" alt="k8scomic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Final thoughts&lt;/h3&gt;

&lt;p&gt;I hope you enjoyed following along, and I hope you learned something! Kubernetes is a very useful tool for managing containers, so I'm glad you made it this far. You can always find much more thorough documentation at &lt;a href="https://kubernetes.io/docs/home/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/home/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you would like for me to expand on this lesson in the future, if you have any questions or if I missed something please let me know. I really value your feedback, so please leave me a comment!&lt;/p&gt;

&lt;p&gt;P.S.&lt;br&gt;
I am currently looking for a job in DevOps! If you know someone who is hiring entry-level DevOps engineers please send them my resume which can be found at &lt;a href="https://smcgown.com" rel="noopener noreferrer"&gt;https://smcgown.com&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/steven-mcgown/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/steven-mcgown/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>beginners</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>Docker for Dummies</title>
      <dc:creator>StevenMcGown</dc:creator>
      <pubDate>Fri, 09 Jul 2021 00:23:18 +0000</pubDate>
      <link>https://forem.com/stevenmcgown/docker-for-dummies-2bff</link>
      <guid>https://forem.com/stevenmcgown/docker-for-dummies-2bff</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4psm82g8sqb647mi83kr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4psm82g8sqb647mi83kr.png" alt="dockerlogo"&gt;&lt;/a&gt;&lt;br&gt;
Docker is one of those services that you always hear about but may have never used. I never used Docker in college, and I actually never heard of it until I began researching the field of DevOps. Knowing how to use Docker is a quintessential element of becoming a part of a modern development team. My goal of this post is to help the reader gain an understanding of what Docker is, to learn why enterprise teams are adopting it today, and how to get started using Docker. &lt;/p&gt;

&lt;p&gt;If you already know how to use Docker, consider reading my post about &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;managing containers using Kubernetes&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;Questions to answer:&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;What problems does Docker solve?&lt;/li&gt;
&lt;li&gt;What are containers?&lt;/li&gt;
&lt;li&gt;What is the difference between a container and a VM?&lt;/li&gt;
&lt;li&gt;What is the difference between images and containers?&lt;/li&gt;
&lt;li&gt;How does Docker help create applications?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Why Docker?&lt;/h3&gt;

&lt;p&gt;The need for Docker arises from virtual machines on servers being used at large scales. Take a large business for example. For a business that uses hundreds of servers with a cluster of virtual machines for each of their platforms, maintaining these machines is a full-time job. Each server has to have an OS installed, it needs upgrades and patches from time to time, and then dependencies for the applications each machine uses also have to be installed. &lt;/p&gt;

&lt;p&gt;You can see why this quickly becomes very complex. Manually configuring these servers is not feasible, so many companies keep a list of servers that they programmatically update. This can work, however the list of servers is shared between a team of people, and this list does not always stay up to date. Some servers never receive updates and consequentially errors may arise which impact system performance. Finding one faulty server in a room of hundreds can also be a troubleshooting nightmare. How does Docker solve this?&lt;/p&gt;

&lt;h3&gt;Docker to the rescue!&lt;/h3&gt;

&lt;p&gt;Rather than running applications on virtual machines, you can upload Docker images to your server. When an image fails, you just upload a new one. There is no need to worry about configuration because the image exists as an exact replica of the original configuration. In this way, you do not have to worry about installing application dependencies or OS patches because they have already been configured in your Docker image. The Docker setup frees you from treating servers as pets, constantly monitored and cared for, to something more ephemeral; It is okay if the image fails, you can just replace it. "What is an image, and why can it be a better fit than virtual machines? You might ask." This term will make more sense as we move forward.&lt;/p&gt;

&lt;p&gt;Docker is also great for developers. It means no more "It works on my machine" since all the developers are developing with the same stack maintained in the Docker file.&lt;/p&gt;

&lt;h3&gt;How does Docker streamline the development process?&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;CI/CD:&lt;/b&gt; You can consistently test and deploy your code to different environments in the development process (staging, user acceptance testing, production) without the hassle of configuring various testing environments.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Versioning:&lt;/b&gt; Docker also helps with versioning, as you can save different versions of software on repositories and check them out later if needed. This eliminates the need for changing versions of software when running an older version of an application.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Roll Forward:&lt;/b&gt; When defects are found, there is no need to patch or update the application. You just need to use a new image.&lt;/p&gt;

&lt;h3&gt;What is the difference between an image and a container?&lt;/h3&gt;

&lt;p&gt;Docker images and containers are closely related, however they are distinct. Docker images are immutable, meaning they cannot be changed. I have explained previously that these images can be uploaded to servers in place of running applications directly on an OS. Images contain the source code, libraries, dependencies, tools and other files that the application needs to run. When using Docker, we start with a base image. Because images can become quite large, images are designed to be composed of layers of other images to allow a minimal amount of data to be sent when transferring images over the network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jxn6fjons4ggrfrnxek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jxn6fjons4ggrfrnxek.png" alt="imageandcontainer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The instance of an image is called a container. Containers are running instances with top writable layers, and they run the actual applications. When the container is deleted, the writable layer is also deleted but the underlying image remains the same. The main takeaway from this is that you can have many running containers off of the same image. A good way to think about images and containers is with this metaphor: Images are the recipe to make a cake, and containers are the cakes you bake. You can make as many cakes as your resources allow you with a recipe; you can make as many containers as your resources will allow you with an image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9t7fkz3s61nzd1t34px5.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9t7fkz3s61nzd1t34px5.jpeg" alt="docker cake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;What is the difference between virtual machines and containers?&lt;/h3&gt;

&lt;p&gt;Consider the layout of a typical VM fleet: Virtual machines are managed through a hypervisor, which runs on a host OS that is installed on server hardware. The hypervisor virtualizes hardware that virtual machines use to run their operating systems (Guest OS). So basically the server has a host OS, and the virtual machines themselves have a complete operating system installed.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabs51w3ej6bhe3hzxv1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabs51w3ej6bhe3hzxv1s.png" alt="helloworld"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What makes a container different is that the container does not have a Guest OS. Instead, the container actually virtualizes the operating system. Inside this container you can build whatever you want. The advantages to using containers over virtual machines are the fast boot up time and their portability. &lt;/p&gt;

&lt;h3&gt;Building images with Dockerfiles&lt;/h3&gt;

&lt;p&gt;As you can see, Docker helps ease the hassle of installation and configuration. Let's look at a sample Docker command:&lt;br&gt;
&lt;code&gt;sudo docker run docker/whalesay cowsay Hello-World!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f426u44863qi5wy9hjf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f426u44863qi5wy9hjf.png" alt="images"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the docker image did not initially exist locally so it had to be pulled from docker/whalesay. You can also see that the image consists of multiple layers e190868d63f8, 909cd34c6fd7, etc. To create an image, we can create a Dockerfile. Once this file is completed, we will use &lt;code&gt;docker build [OPTIONS] PATH | URL | -&lt;/code&gt; to create our image.&lt;/p&gt;

&lt;p&gt;A Dockerfile can be created using &lt;code&gt;touch Dockerfile&lt;/code&gt; and can be edited using your favorite text editor. Notice that this file is created without an extension, this is intentional.&lt;/p&gt;

&lt;p&gt;In your Dockerfile, type the following code:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4cdf79op8zdso1wbt0zq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4cdf79op8zdso1wbt0zq.png" alt="dockerfile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The FROM statement declares what image your new image will be based on. For this sample project, I will be using the ubuntu image. However if you want to create a Docker image from scratch, you can simply write &lt;code&gt;FROM scratch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;LABEL is used to apply meta data to Docker objects. In this case, you can use LABEL to specify the maintainer of the Docker image. MAINTAINER was once used but this is since deprecated. &lt;/p&gt;

&lt;p&gt;RUN is used to execute commands during the building of the image, while CMD is executed only when the container is created out of the image.&lt;/p&gt;

&lt;p&gt;In the directory of your Dockerfile, type &lt;code&gt;docker build .&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfgovtflb64shwx535x4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfgovtflb64shwx535x4.png" alt="dockerbuild"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first time each command is executed, each command will be executed. Each command in the Dockerfile is cached, so if you edit the file it will only need to build for edited command. After editing the echo command of our Dockerfile, we will also give the Docker image a name and the 'latest' tag. &lt;br&gt;
&lt;code&gt;docker build -t helloworld:latest .&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkxhwrf7leudhcytr591.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkxhwrf7leudhcytr591.png" alt="built"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run your image, first find the image name by running &lt;code&gt;docker images&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihsb09q9vjalops1fhuk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihsb09q9vjalops1fhuk.png" alt="dockerimages"&gt;&lt;/a&gt;&lt;br&gt;
Note that you can run a Docker image by its image ID or its name and tag. If you run by name only, Docker will automatically run by the 'latest' tag.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run helloworld:latest&lt;/code&gt; and &lt;code&gt;docker run 4d6c8eea04c9&lt;/code&gt;&lt;br&gt;
produce the same output in this case.&lt;/p&gt;

&lt;p&gt;And there you have it! You have created your first Docker image. You can find other images on &lt;a href="https://hub.docker.com" rel="noopener noreferrer"&gt;https://hub.docker.com&lt;/a&gt; and documentation at &lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;https://docs.docker.com/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Extra Credit!&lt;/h3&gt;

&lt;p&gt;I suggest pushing your newly created docker image to DockerHub if you would like to share your Docker images. First, create a DockerHub account at &lt;a href="https://hub.docker.com" rel="noopener noreferrer"&gt;https://hub.docker.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Log in to your DockerHub account using the CLI:&lt;br&gt;
&lt;code&gt;docker login&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can also log out from your CLI using:&lt;br&gt;
&lt;code&gt;docker logout&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, you can push your newly created docker image by first tagging it.&lt;br&gt;
&lt;code&gt;docker tag &amp;lt;image&amp;gt; helloworld:latest &amp;lt;DOCKER_HUB_USERNAME&amp;gt;/dockerhub:myfirstimagepush&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, push the docker image:&lt;br&gt;
&lt;code&gt;docker push &amp;lt;DOCKER_HUB_USERNAME&amp;gt;/dockerhub:myfirstimagepush&lt;/code&gt;&lt;br&gt;
You should receive a SHA-256 hash indicating the push was successful.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbqmblkzy4lvpu6wf4pf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbqmblkzy4lvpu6wf4pf.png" alt="dockerpush"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you think you're ready to manage your Docker containers using Kubernetes, read my post about &lt;a href="https://dev.to/stevenmcgown/kubernetes-for-dummies-5hmh"&gt;Kubernetes&lt;/a&gt; and then read about &lt;a href="https://dev.to/stevenmcgown/openshift-for-dummies-part-1-39f4"&gt;OpenShift&lt;/a&gt;, the industry's most secure and comprehensive enterprise-grade container platform!&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;I hope that this post can help anyone who feels like they aren't ready to learn about Docker. Often times, the most difficult part of getting something done is starting it. Please let me know if this helped or if I missed anything!&lt;/p&gt;

&lt;p&gt;P.S.&lt;br&gt;
I am currently looking for a job in DevOps! If you know someone who is hiring entry-level DevOps engineers please send them my resume which can be found at &lt;a href="https://smcgown.com" rel="noopener noreferrer"&gt;https://smcgown.com&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/steven-mcgown/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/steven-mcgown/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>beginners</category>
      <category>devops</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
