<?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>DEV Community: Vasco Ramos</title>
    <description>The latest articles on DEV Community by Vasco Ramos (@vascoalramos).</description>
    <link>https://dev.to/vascoalramos</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%2F325980%2F05f84796-7065-4430-8194-5b758d1b67a3.jpg</url>
      <title>DEV Community: Vasco Ramos</title>
      <link>https://dev.to/vascoalramos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vascoalramos"/>
    <language>en</language>
    <item>
      <title>Learning Kubernetes - Part II: Pods, Labels, and Services</title>
      <dc:creator>Vasco Ramos</dc:creator>
      <pubDate>Mon, 22 Mar 2021 00:00:55 +0000</pubDate>
      <link>https://dev.to/vascoalramos/learning-kubernetes-part-ii-pods-labels-and-services-36jj</link>
      <guid>https://dev.to/vascoalramos/learning-kubernetes-part-ii-pods-labels-and-services-36jj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Welcome to the second part of my Learning Kubernetes series. This second post builds on the concepts introduced in the &lt;a href="https://dev.to/vascoalramos/learning-kubernetes-concepts-part-1-pb0"&gt;previous one&lt;/a&gt; and explores a new (&lt;em&gt;better&lt;/em&gt;) way of defining objects. We will also explore what &lt;strong&gt;Services&lt;/strong&gt; are and how they can help you better expose your applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  But first... a quick recap!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Kubernetes is an orchestration tool that allows us to manage containerized applications across a group of nodes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the previous post, we talked about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Kubernetes&lt;/li&gt;
&lt;li&gt;What it's used for&lt;/li&gt;
&lt;li&gt;Some simple concepts and tools around it: &lt;em&gt;Pods&lt;/em&gt; and &lt;em&gt;kubectl&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To review what a Pod is, this is what we saw in the previous post:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A pod is the smallest unit inside the Kubernetes cluster, and it represents a collection of application containers and volumes running in the same isolated execution environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, not to forget that all containers inside the same Pod share:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP address&lt;/li&gt;
&lt;li&gt;Namespace&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One last thing, we saw how to create objects (more precisely, Pods) using &lt;strong&gt;kubectl&lt;/strong&gt;. In this post, I want to introduce you to the &lt;em&gt;de facto&lt;/em&gt; way of creating and managing objects in Kubernetes and some new concepts.&lt;/p&gt;

&lt;p&gt;So, let's jump right in! 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  The brave "new" declarative world!
&lt;/h2&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%2Fimgur.com%2F0u5glcX.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%2Fimgur.com%2F0u5glcX.png" alt="Brave new world banner"&gt;&lt;/a&gt;&lt;br&gt;
The declarative approach to Infrastructure is natural to DevOps and has gained even more relevance with the surge of GitOps. Immutability is a core concept in the declarative approach. In the case of Kubernetes, as it's said in &lt;a href="https://www.amazon.com/Kubernetes-Running-Dive-Future-Infrastructure/dp/1492046531/" rel="noopener noreferrer"&gt;Kubernetes: Up and Running&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Immutable container images are at the core of everything that you will build in Kubernetes. It is possible to imperatively change running containers, but this is an &lt;strong&gt;anti-pattern&lt;/strong&gt; [...] And even then, the changes must also be recorded through a declarative configuration update later, after the fire is out.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So... how do we do this? Let's go back to the example in &lt;a href="https://dev.to/vascoalramos/learning-kubernetes-concepts-part-1-pb0"&gt;Part I&lt;/a&gt;. When we created the Pod, we did so by running the following (imperative) command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl run kubernetes-hello-world &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;paulbouwer/hello-kubernetes:1.9 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will do the same thing but with a declarative configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;                                            &lt;span class="c1"&gt;# 1&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes-hello-world&lt;/span&gt;                       &lt;span class="c1"&gt;# 2&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                                &lt;span class="c1"&gt;# 3&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;paulbouwer/hello-kubernetes:1.9&lt;/span&gt;         &lt;span class="c1"&gt;# 4&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-kubernetes&lt;/span&gt;                         &lt;span class="c1"&gt;# 5&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;                        &lt;span class="c1"&gt;# 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this YAML manifest is equivalent to the previous command. Now let's see the most important concepts in this definition:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Kind:&lt;/strong&gt; specifies the kind of Kubernetes object to be created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: defines the name for the object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spec&lt;/strong&gt; is the specification of the object's desired state. The main specification here, at least in the case of Pods, is the array of containers (in our case, there's only 1 container in that array).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image&lt;/strong&gt; is the container's image to be executed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(Containers) Name&lt;/strong&gt; is the name for the container in the pod (it must be unique).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Port&lt;/strong&gt; is the port on which the container is listening.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, to create the Pod we need to "send" the manifest to the Kubernetes API. We do this by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# assume the manifest is stored in a file named 'pod.yml'&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; pod.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see an output stating the object was created. If you describe the object with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl describe pod/kubernetes-hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and compare it to the description of the object created with the previous method, you will see they are similar in every way. &lt;/p&gt;

&lt;h3&gt;
  
  
  Health Checks
&lt;/h3&gt;

&lt;p&gt;When you run your app as a container, Kubernetes automatically keeps it alive through a health check. This process guarantees that your app is always running, and if the app fails, Kubernetes restarts it immediately.&lt;/p&gt;

&lt;p&gt;This default behavior is helpful in simple scenarios. However, in most cases, it's not enough. &lt;/p&gt;

&lt;p&gt;That's the utility of health checks for application liveness. It allows you to run customized health checks to verify that your app is running and working.&lt;/p&gt;

&lt;p&gt;The following manifest builds on the previous one by adding a custom health check capability, using what is called a &lt;strong&gt;Liveness Probe&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes-hello-world-health&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                       
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;paulbouwer/hello-kubernetes:1.9&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-kubernetes&lt;/span&gt;                         
      &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;                       &lt;span class="c1"&gt;# 1&lt;/span&gt;
        &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;                            &lt;span class="c1"&gt;# 2&lt;/span&gt;
        &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;                            &lt;span class="c1"&gt;# 3&lt;/span&gt;
        &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;                          &lt;span class="c1"&gt;# 4&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8080&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;This first field specifies the number of seconds to delay the probe's first execution.&lt;/li&gt;
&lt;li&gt;Specifies that the probe must respond within the X-second timeout (in our case: 1-second timeout).&lt;/li&gt;
&lt;li&gt;Specifies that the probe will be called every X seconds (in our case: 10 seconds).&lt;/li&gt;
&lt;li&gt;Specifies that the container will fail and restart if the probe fails more than X times in a row (in our case: 3 times).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we create the pod by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# assume the manifest is stored in a file named 'pod-health.yml'&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; pod-health.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run &lt;code&gt;kubectl get pods&lt;/code&gt;, you will have the following output (or something similar):&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%2Fimgur.com%2FzY9a54J.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%2Fimgur.com%2FzY9a54J.png" alt="Pods list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This shows you the two pods we created. the first one without a custom health check, and the second one with a custom health check that restarts the Pod if the container fails more than 3x in a row.&lt;/p&gt;
&lt;h2&gt;
  
  
  Labels and Annotations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Labels&lt;/strong&gt; and &lt;strong&gt;Annotations&lt;/strong&gt; are cornerstone concepts in Kubernetes that let you work in sets of objects that represent how &lt;em&gt;you&lt;/em&gt; think about your app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Labels&lt;/strong&gt; are key/value pairs that can be attached to Kubernetes objects such as Pods and Deployments. They can be arbitrary and are useful for attaching semantic information used to group Kubernetes objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Annotations&lt;/strong&gt; are key/value pairs designed to hold non-semantic information that can be used by tools and libraries.&lt;/p&gt;

&lt;p&gt;As we will see, labels are essential to the definition of some Kubernetes objects such as Services and Deployments.&lt;/p&gt;

&lt;p&gt;To exemplify the usage of labels, and following &lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/" rel="noopener noreferrer"&gt;the recommend usage of labels in Kubernetes&lt;/a&gt;, we will create different versions of our 2 Pods by adding labels. Here you have the manifests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes-hello-world-labeled&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                     &lt;span class="c1"&gt;# label section&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world&lt;/span&gt;
    &lt;span class="na"&gt;part-of&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;labeled&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;paulbouwer/hello-kubernetes:1.9&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-kubernetes&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes-hello-world-health-labeled&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                     &lt;span class="c1"&gt;# label section&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world-health&lt;/span&gt;
    &lt;span class="na"&gt;part-of&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;labeled&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;paulbouwer/hello-kubernetes:1.9&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-kubernetes&lt;/span&gt;
      &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
        &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By creating these two pods following a similar approach as in the others, we get this 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%2Fimgur.com%2FpSzfJSS.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%2Fimgur.com%2FpSzfJSS.png" alt="Get all pods"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Label Selectors
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Show Labels
&lt;/h4&gt;

&lt;p&gt;The first interaction with labels is to quickly see all the labels associated with the objects when we list them, just as we can see in the following 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%2Fimgur.com%2FmDjDW8U.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%2Fimgur.com%2FmDjDW8U.png" alt="Get Pods (show labels)"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Selector
&lt;/h4&gt;

&lt;p&gt;The other, more handy interaction, is to list the objects that have the specified labels. The following image shows two different ways to do this.&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%2Fimgur.com%2Fk9cmBjd.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%2Fimgur.com%2Fk9cmBjd.png" alt="Label selector"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Services
&lt;/h2&gt;

&lt;p&gt;As we saw, we currently have four Pods: two of them are labeled and the other two are not.&lt;/p&gt;

&lt;p&gt;Imagine that we want to expose the two pods that are labeled. How do we do that? The answer is &lt;strong&gt;Services&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Services provide an abstract way to &lt;strong&gt;expose&lt;/strong&gt; an app running on a &lt;strong&gt;logical set of Pods&lt;/strong&gt; and a policy by which to access them. The set of Pods targeted by a Service is usually determined by a &lt;strong&gt;LabelSelector&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Services provide three policies to expose your app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ClusterIP&lt;/strong&gt; (default type): exposes the service on an internal IP in the cluster. This makes the Service only reachable from within the cluster. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NodePort&lt;/strong&gt;: exposes the service on the same port of each node by forwarding traffic to that port to the service. It's a superset (an expansion) of ClusterIP. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LoadBalancer&lt;/strong&gt;: creates an external load balancer in the current cloud (if supported) and assigns a fixed, external IP to the Service. The load balancer directs traffic to the nodes in your cluster using NodePort, so it's a superset of NodePort.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As my Kubernetes Cluster is in a cloud setup (GCP), I will expose my application with a service of type LoadBalancer by creating and applying the following YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LoadBalancer&lt;/span&gt;      &lt;span class="c1"&gt;# service type: ClusterIP (default), NodePort, LoadBalancer&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;               &lt;span class="c1"&gt;# label selector (of pods)&lt;/span&gt;
    &lt;span class="na"&gt;part-of&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;labeled&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;            &lt;span class="c1"&gt;# the port in which the service gets requests&lt;/span&gt;
      &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;       &lt;span class="c1"&gt;# the communication protocol&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;    &lt;span class="c1"&gt;# the port at which incoming requests are forward&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you will have 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%2Fimgur.com%2FRaIhYHs.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%2Fimgur.com%2FRaIhYHs.png" alt="Service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the service is exposed in IP &lt;code&gt;35.197.19.160&lt;/code&gt;, at port 80. So if I access &lt;code&gt;http://35.197.19.160:80&lt;/code&gt;, I see my app up and running:&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%2Fimgur.com%2Fg3KD7dA.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%2Fimgur.com%2Fg3KD7dA.png" alt="app view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;That's all for this post! As of a summary, we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transitioned from imperative object definitions to declarative ones;&lt;/li&gt;
&lt;li&gt;explored how to define custom health checks to our pods;&lt;/li&gt;
&lt;li&gt;learned the basics of how labels and annotations work;&lt;/li&gt;
&lt;li&gt;understood how to expose applications using services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next post, I will address how to create true deployments with dynamic pod creation and destruction, and also how to use Ingress as a way to expose and load balance our applications.&lt;/p&gt;




&lt;p&gt;If you liked my post, you can follow me, see my other posts or check my &lt;a href="https://github.com/vascoalramos/kubernetes-playground" rel="noopener noreferrer"&gt;Kubernetes repo&lt;/a&gt; with additional resource examples.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Learning Kubernetes - Part I: Introduction</title>
      <dc:creator>Vasco Ramos</dc:creator>
      <pubDate>Wed, 10 Mar 2021 19:04:38 +0000</pubDate>
      <link>https://dev.to/vascoalramos/learning-kubernetes-concepts-part-1-pb0</link>
      <guid>https://dev.to/vascoalramos/learning-kubernetes-concepts-part-1-pb0</guid>
      <description>&lt;p&gt;This post is the first part of a series about Kubernetes. Rather than a series of tutorials, this is meant to be a periodic log of my journey learning the concepts and tools regarding orchestration using Kubernetes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Installation
&lt;/h4&gt;

&lt;p&gt;As I intended to learn how to use Kubernetes (not managing it), I started a Kubernetes cluster in Google Cloud Platform and worked from there. Hence, I will not address Kubernetes cluster installation and configuration in this series. For more details on how to use the GCP Kubernetes cluster, click &lt;a href="https://cloud.google.com/kubernetes-engine/docs/quickstart" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  First: the concepts
&lt;/h4&gt;

&lt;p&gt;One thing that always helps me better understand and learn a new technology or tool is to understand what is the purpose of the tool or technology, what it is used for, and &lt;strong&gt;get the concepts right&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Making sure you understand the basic concepts is a great help in the road ahead of improving your knowledge of the tool/technology you're learning. &lt;/p&gt;

&lt;p&gt;So, let's start by understanding &lt;strong&gt;what is Kubernetes&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes
&lt;/h2&gt;

&lt;p&gt;Kubernetes is an orchestration tool that allows us to manage containerized applications across a group of nodes. Not only providing mechanisms to quickly run those but also how to update, deploy and provide access to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pod: the atom in the Kubernetes universe
&lt;/h2&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%2Fi1uekt1ooync59oschot.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%2Fi1uekt1ooync59oschot.jpg" alt="Kubernetes - Pods"&gt;&lt;/a&gt;&lt;br&gt;
A pod is the smallest unit inside the Kubernetes cluster and it represents a collection of application containers and volumes running in the same isolated execution environment. Each container in the same Pod shares the same IP address, namespace, and storage.&lt;/p&gt;

&lt;p&gt;Although I described a pod as a collection of containers, the most common pattern is to have one container per pod. If you need to think twice about group multiple containers in the same pod, ask yourself&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Will these containers work properly if they land on different machines?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is "no", you should indeed group those containers in the same pod, otherwise, just don't do it. &lt;/p&gt;
&lt;h2&gt;
  
  
  Kubectl: the basics
&lt;/h2&gt;

&lt;p&gt;Before going any further, let's see some basic capabilities of kubectl (Kubernetes command-line tool).&lt;/p&gt;
&lt;h3&gt;
  
  
  Version and Status
&lt;/h3&gt;

&lt;p&gt;To ensure kubectl and Kubernetes is working properly, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you should see something like the image below, where it's listed the version of your Kubernetes cluster and client.&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%2Fi.imgur.com%2FtYBkfqt.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%2Fi.imgur.com%2FtYBkfqt.png" alt="kubectl version output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, you can also check the status of your Kubernetes cluster main components with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get componentstatuses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should provide you with an output similar to this one: &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%2Fi.imgur.com%2FdEgud9u.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%2Fi.imgur.com%2FdEgud9u.png" alt="kubectl get componentstatuses&amp;lt;br&amp;gt;
 output"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Nodes
&lt;/h3&gt;

&lt;p&gt;To get information about the nodes that make up the Kubernetes cluster and can be scheduled with work run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command, as you can see in the following image, gives you a list with some basic information for every node of your cluster. As I said earlier, my cluster is on Google Cloud Platform, so, depending on your setup (a local cluster or a cluster in another cloud provider), the output may be a little different.&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%2Fimgur.com%2FyeWwMFh.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%2Fimgur.com%2FyeWwMFh.png" alt="kubectl get nodes&amp;lt;br&amp;gt;
 output"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Pods
&lt;/h3&gt;

&lt;p&gt;Now, to quickly show you about pods, let's create one by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl run kubernetes-hello-world &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;paulbouwer/hello-kubernetes:1.9 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;kubectl run&lt;/code&gt; is not the ideal way to do things, but let's do it for the sake of the example. In the next post, we will explore the right way to define resources (the declarative way). You should see an output similar to this one:&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%2Fimgur.com%2Fht9EIZK.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%2Fimgur.com%2Fht9EIZK.png" alt="kubectl run&amp;lt;br&amp;gt;
 output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get the following output, where you can see the pod that was created with the &lt;code&gt;kubectl run&lt;/code&gt; command.&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%2Fimgur.com%2FbvJt4tm.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%2Fimgur.com%2FbvJt4tm.png" alt="kubectl get pods&amp;lt;br&amp;gt;
 output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also check more details with other commands such as &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;logs&lt;/code&gt;, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl describe pods kubernetes-hello-world
kubectl logs kubernetes-hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first gives you a detailed description of the specified pod, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;kubernetes-hello-world&lt;/span&gt;
&lt;span class="na"&gt;Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;Priority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;Node&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;gke-kuar-cluster-default-pool-41051aa0-hs4q/10.138.15.194&lt;/span&gt;
&lt;span class="na"&gt;Start Time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;Thu, 11 Mar 2021 17:44:41 +0000&lt;/span&gt;
&lt;span class="na"&gt;Labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;run=kubernetes-hello-world&lt;/span&gt;
&lt;span class="na"&gt;Annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;&amp;lt;none&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;Status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;Running&lt;/span&gt;
&lt;span class="na"&gt;IP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;10.96.14.3&lt;/span&gt;
&lt;span class="na"&gt;IPs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;IP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;10.96.14.3&lt;/span&gt;
&lt;span class="na"&gt;Containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kubernetes-hello-world&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Container ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;docker://db09b9c745c03f3e757f1f386f5df8e04e48faaace587cfa72ed1f3e6a751300&lt;/span&gt;
    &lt;span class="na"&gt;Image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;paulbouwer/hello-kubernetes:1.9&lt;/span&gt;
    &lt;span class="na"&gt;Image ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;docker-pullable://paulbouwer/hello-kubernetes@sha256:be6b5ba3abdca6e01689e0d1d27b41410fb5bf5793da407108a89ef355f362f0&lt;/span&gt;
    &lt;span class="na"&gt;Port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;8080/TCP&lt;/span&gt;
    &lt;span class="na"&gt;Host Port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;0/TCP&lt;/span&gt;
    &lt;span class="na"&gt;State&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;Running&lt;/span&gt;
      &lt;span class="s"&gt;Started&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;Thu, 11 Mar 2021 17:44:50 +0000&lt;/span&gt;
    &lt;span class="na"&gt;Ready&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;True&lt;/span&gt;
    &lt;span class="na"&gt;Restart Count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;&amp;lt;none&amp;gt;&lt;/span&gt;
    &lt;span class="na"&gt;Mounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="s"&gt;/var/run/secrets/kubernetes.io/serviceaccount from default-token-dzc9f (ro)&lt;/span&gt;
&lt;span class="na"&gt;Conditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;Type              Status&lt;/span&gt;
  &lt;span class="s"&gt;Initialized       True&lt;/span&gt; 
  &lt;span class="s"&gt;Ready             True&lt;/span&gt; 
  &lt;span class="s"&gt;ContainersReady   True&lt;/span&gt; 
  &lt;span class="s"&gt;PodScheduled      True&lt;/span&gt; 
&lt;span class="na"&gt;Volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;default-token-dzc9f&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;Secret (a volume populated by a Secret)&lt;/span&gt;
    &lt;span class="na"&gt;SecretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;default-token-dzc9f&lt;/span&gt;
    &lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;QoS Class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;BestEffort&lt;/span&gt;
&lt;span class="na"&gt;Node-Selectors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;&amp;lt;none&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;Tolerations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;node.kubernetes.io/not-ready:NoExecute op=Exists for 300s&lt;/span&gt;
                 &lt;span class="s"&gt;node.kubernetes.io/unreachable:NoExecute op=Exists for 300s&lt;/span&gt;
&lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;Type    Reason     Age   From               Message&lt;/span&gt;
  &lt;span class="s"&gt;----    ------     ----  ----               -------&lt;/span&gt;
  &lt;span class="s"&gt;Normal  Scheduled  23m   default-scheduler  Successfully assigned default/kubernetes-hello-world to gke-kuar-cluster-default-pool-41051aa0-hs4q&lt;/span&gt;
  &lt;span class="s"&gt;Normal  Pulling    23m   kubelet            Pulling image "paulbouwer/hello-kubernetes:1.9"&lt;/span&gt;
  &lt;span class="s"&gt;Normal  Pulled     23m   kubelet            Successfully pulled image "paulbouwer/hello-kubernetes:1.9"&lt;/span&gt;
  &lt;span class="s"&gt;Normal  Created    23m   kubelet            Created container kubernetes-hello-world&lt;/span&gt;
  &lt;span class="s"&gt;Normal  Started    23m   kubelet            Started container kubernetes-hello-world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second option gives you the logs related to the running container(s). These methods of debugging and inspection are available in every resource available in Kubernetes (Pods, Deployments, Services, etc).&lt;/p&gt;

&lt;p&gt;One final way to debug your application besides the logs is to inspect and interact with the running container(s) with &lt;code&gt;exec&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; kubernetes-hello-world &lt;span class="nt"&gt;--&lt;/span&gt; sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see one example of this interaction in the following 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%2Fimgur.com%2FahVtNcI.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%2Fimgur.com%2FahVtNcI.png" alt="kubectl get pods&amp;lt;br&amp;gt;
 output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, to delete the created pod, run:&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%2Fimgur.com%2FLjLiu6O.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%2Fimgur.com%2FLjLiu6O.png" alt="kubectl delete pod&amp;lt;br&amp;gt;
 output"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you like my explanation, you can follow me, I will publish the following parts of this series in the coming weeks.&lt;/p&gt;

&lt;p&gt;Click &lt;a href="https://dev.to/vascoalramos/learning-kubernetes-part-ii-pods-labels-and-services-36jj"&gt;here&lt;/a&gt; for the &lt;strong&gt;next part&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Get Started with Java Logging (and some tips to easily learn new libraries)</title>
      <dc:creator>Vasco Ramos</dc:creator>
      <pubDate>Mon, 10 Aug 2020 14:36:40 +0000</pubDate>
      <link>https://dev.to/vascoalramos/get-started-with-java-logging-and-some-tips-to-easily-learn-new-libraries-4c83</link>
      <guid>https://dev.to/vascoalramos/get-started-with-java-logging-and-some-tips-to-easily-learn-new-libraries-4c83</guid>
      <description>&lt;p&gt;When I started my journey in computer science 3 years ago as a CS undergraduate student, I began to learn the basics of programming in python (attribution statements, conditions, loops, functions, recursion, others). Then, I moved to Java with OOP (Object-Oriented Programming) and, during all that time, I never used logging to debugging or monitoring purposes... I would always use print statements. Only if I knew better, it would have saved me a lot of time.&lt;/p&gt;

&lt;p&gt;Before going to implementation details, I will give a quick overview of logging and its &lt;em&gt;levels&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging Levels
&lt;/h2&gt;

&lt;p&gt;The most common levels in logging frameworks are &lt;strong&gt;Debug&lt;/strong&gt;, &lt;strong&gt;Info&lt;/strong&gt;, &lt;strong&gt;Warn&lt;/strong&gt;, &lt;strong&gt;Error&lt;/strong&gt; and &lt;strong&gt;Fatal&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debug
&lt;/h3&gt;

&lt;p&gt;This is usually the most verbose log level. It allows you to understand the core code execution path in certain important processes. As the name implies, these messages help debug tasks since it allows us to trace what's going on in the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Info
&lt;/h3&gt;

&lt;p&gt;This level is usually used to highlight when something has happened. It's active by default, as opposed to Debug. It's usually used as an "assertion" that everything is operating smoothly, and since this messages use to contain little notes related to performed actions, at the end of the day, info messages are, essentially, just noise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warn
&lt;/h3&gt;

&lt;p&gt;It's used to report harmful situations that aren't relevant enough to require immediate action and can be fixed later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error
&lt;/h3&gt;

&lt;p&gt;At ERROR level, are logged error events that might still allow the application to continue running, but still, require immediate or close to immediate response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fatal
&lt;/h3&gt;

&lt;p&gt;As stated in &lt;a href="https://www.tutorialspoint.com/log4j/log4j_logging_levels.htm" rel="noopener noreferrer"&gt;Tutorials Point&lt;/a&gt;, Fatal-level messages are used to report very severe error events that will presumably lead the application to abort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Java Logging
&lt;/h2&gt;

&lt;p&gt;Passed the overview, let's get started with Java logging. When you are finished reading, you will know how to approach logging in your Java source code, and better yet, how to learn and approach a new library in the scope of your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assumptions
&lt;/h3&gt;

&lt;p&gt;For the sake of focus and simplicity, I'm going to use &lt;a href="https://www.jetbrains.com/idea" rel="noopener noreferrer"&gt;IntelliJ IDEA&lt;/a&gt; and I'm also going to assume that you already have the  &lt;a href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html" rel="noopener noreferrer"&gt;Java JDK&lt;/a&gt; installed on your machine.&lt;/p&gt;

&lt;p&gt;I am going to use a simple "dummy" project to explain logging in java, but you can include this code and config directly into your project.&lt;/p&gt;

&lt;p&gt;My project structure looks like this:&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%2Fi%2Frzz336yzx6om8comebix.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%2Fi%2Frzz336yzx6om8comebix.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a Logging Framework
&lt;/h3&gt;

&lt;p&gt;In this tutorial, I'm going to use &lt;a href="https://logging.apache.org/log4j/2.x" rel="noopener noreferrer"&gt;Apache Log4j 2&lt;/a&gt; because it is a widely used framework and I quite like it, but there are a bunch of other Java Logging Frameworks (see more &lt;a href="https://www.loggly.com/ultimate-guide/java-logging-basics" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In this project, I am using Maven so, to add log4j to the project, I need to add the following XML to my &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.logging.log4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;log4j-api&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.13.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.logging.log4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;log4j-core&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.13.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring the Logger (a different approach)
&lt;/h3&gt;

&lt;p&gt;This bit is where I present to you a different approach from so many others logging config tutorials. Following the line of thought from Robert C. Martin in &lt;a href="https://amzn.to/3gsNbcS" rel="noopener noreferrer"&gt;Clean Code&lt;/a&gt;, I decided to explain the learning and configuration process of a third-party library through learning testing. As the author elaborates in the book, using learning tests to approach third-party code that is going to be introduced into your project is a good practice because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can test the library capabilities and specificities in a controlled environment with a series of objective and precise experiments.&lt;/li&gt;
&lt;li&gt;The tests you write in this learning process are a good tool to test new releases of the third-party package, where you can easily see if something changed which enables you to make an informed decision whether to upgrade the package version or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That being said, our journey begins. The first step is to add testing capabilities to our project. To do so, we need to add this XML to &lt;code&gt;pom.xml&lt;/code&gt; (I'm going to use JUnit 5):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.junit.jupiter&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit-jupiter-api&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.6.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.junit.jupiter&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit-jupiter-engine&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.6.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Testing Default Behaviour
&lt;/h4&gt;

&lt;p&gt;Next, without configuring anything, we will test our third-party package (log4j). The tests I wrote are fairly simple but are enough to test the basic capabilities of our logging framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LogTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@BeforeEach&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LogManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TestLogger"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testSimpleMessage&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello World!"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fatal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testFormattedMessage&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;formattedMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello {}, this is my current grade {}!"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;17.64&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formattedMessage&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formattedMessage&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formattedMessage&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formattedMessage&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formattedMessage&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fatal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formattedMessage&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tests are not going to fail, instead, they are going to show us what is the default behaviour of our logger.&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%2Fi%2F6mnklncuuzse4e997hl0.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%2Fi%2F6mnklncuuzse4e997hl0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The output implies the format that is being used and what is the upper level that is enabled by default (&lt;code&gt;ERROR&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration
&lt;/h4&gt;

&lt;p&gt;First, go to "Project" tool window in IntelliJ and expand the folders till you locate the "resources" folder (java -&amp;gt; src -&amp;gt; main), just like in the image I showed earlier.&lt;/p&gt;

&lt;p&gt;Now, create a file name &lt;code&gt;log4j2.properties&lt;/code&gt; inside that folder.&lt;/p&gt;

&lt;p&gt;After the file is created, insert the following specifications in the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Log4j2PropertiesConfig&lt;/span&gt;

&lt;span class="py"&gt;appenders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;console&lt;/span&gt;

&lt;span class="c"&gt;# configuration of console logging
&lt;/span&gt;&lt;span class="py"&gt;appender.console.type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Console&lt;/span&gt;
&lt;span class="py"&gt;appender.console.name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;STDOUT&lt;/span&gt;
&lt;span class="py"&gt;appender.console.layout.type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;PatternLayout&lt;/span&gt;
&lt;span class="py"&gt;appender.console.layout.pattern&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;%highlight{%-21d{yyyy-MM-dd HH:mm:ss} %-12c %-8level %m%n}&lt;/span&gt;

&lt;span class="c"&gt;# default root logging config
&lt;/span&gt;&lt;span class="py"&gt;rootLogger.level&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;debug&lt;/span&gt;
&lt;span class="py"&gt;rootLogger.appendRefs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;stdout&lt;/span&gt;
&lt;span class="py"&gt;rootLogger.appenderRef.stdout.ref&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;STDOUT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you insert these configurations, the result of re-running the tests is the one you can see below:&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%2Fi%2Fjhhcaq9igbldwme4pk28.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%2Fi%2Fjhhcaq9igbldwme4pk28.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some detail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: just specifies the name of that specific configuration layout.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;appenders&lt;/code&gt;: the name of the different &lt;strong&gt;appender&lt;/strong&gt; components (the ones that effectively writes the message to some medium).&lt;/li&gt;
&lt;li&gt;The remaining configuration follows the same line of thought and for more detail see &lt;a href="https://logging.apache.org/log4j/log4j-2.2/manual/configuration.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Happy Learning!
&lt;/h2&gt;

&lt;p&gt;What I've tried to show you today is just an over-simplified introduction to the path of understanding logging usage and configuration with &lt;strong&gt;log4j2&lt;/strong&gt;. If you want, there is a lot more to learn!&lt;/p&gt;

&lt;p&gt;Here are some suggestions on what you can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn how to have multiple appenders, each with a different type of output (console, file, etc).&lt;/li&gt;
&lt;li&gt;Learn how to configure different loggers, one for each log level.&lt;/li&gt;
&lt;li&gt;Play with the options available for the "layout" entry.&lt;/li&gt;
&lt;li&gt;Learn about the other ways you can configure log4j.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Furthermore, as I said, there are lots of options for logging frameworks; when you feel confident enough with log4j, try some of them.&lt;/p&gt;

</description>
      <category>java</category>
      <category>logging</category>
      <category>beginners</category>
      <category>log4j</category>
    </item>
    <item>
      <title>My Experience with Java Debugger - Beginner Tips</title>
      <dc:creator>Vasco Ramos</dc:creator>
      <pubDate>Tue, 28 Jul 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/vascoalramos/my-experience-with-java-debugger-beginner-tips-3pj4</link>
      <guid>https://dev.to/vascoalramos/my-experience-with-java-debugger-beginner-tips-3pj4</guid>
      <description>&lt;p&gt;Recently, while working on a Java project with &lt;a href="http://bioinformatics.ua.pt" rel="noopener noreferrer"&gt;IEETA Bioinformatics - UA&lt;/a&gt;, I needed to do some serious debugging in the code. As I was new to the project and didn't have a strong knowledge of the project's codebase, I decided to use the Java debugger to inspect the behavior of the code and better understand the flow where the specific bug was occurring. That too was a challenge because I had never used a debugger. &lt;/p&gt;

&lt;p&gt;Hence, I decided to write this article to help other programmers that, like I, are beginners at proper debugging and also to help me structure the knowledge I have recently learned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This article uses visual examples from &lt;a href="https://www.jetbrains.com/idea" rel="noopener noreferrer"&gt;IntelliJ IDEA&lt;/a&gt;, but the same concepts can be found and applied across most alternative JAVA IDEs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breakpoints
&lt;/h2&gt;

&lt;p&gt;A breakpoint allows you to specify where the program should stop when debugging so you can analyze the state of the program (inspect existing fields and variables, change its values, and more) and find what is wrong with your code.&lt;/p&gt;

&lt;p&gt;Every debugger offers several types of breakpoints such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Line breakpoints:&lt;/strong&gt; Halt the program upon reaching the line of code where the breakpoint was set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method breakpoints:&lt;/strong&gt; Halt the program upon entering (or exiting) the specified method. This allows you to check the entry or exit conditions of a particular method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional breakpoints:&lt;/strong&gt; Halt the program when a certain criterion (condition) is met&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exception breakpoints:&lt;/strong&gt; Halt the program when &lt;code&gt;Throwable&lt;/code&gt; or its subclasses are thrown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch points:&lt;/strong&gt; Halt the program when the specified field is read or written to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an example of a condition breakpoint on the IntelliJ IDE, set on line number 73.&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%2Fi%2Fg3tokntmtukarrr2gocq.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%2Fi%2Fg3tokntmtukarrr2gocq.png" alt="Conditional Breakpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition to setting breakpoints, you can also &lt;strong&gt;remove&lt;/strong&gt;, &lt;strong&gt;mute&lt;/strong&gt;, &lt;strong&gt;enable&lt;/strong&gt; and &lt;strong&gt;disable&lt;/strong&gt; them. Mute a breakpoint is extremely helpful when you don't need to stop at some specific breakpoint for a while. Another helpful possibility is to enable/disable breakpoints, which is useful because when you delete a breakpoint, its internal configuration is lost, so enabling/disabling breakpoints it's a less terminal operation that allows you to temporarily turn an individual breakpoint off without losing its parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Actions
&lt;/h2&gt;

&lt;p&gt;Every Java debugger provides a set of features (stepping actions) that allow you to navigate through different sections of your code when debugging, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Step Over:&lt;/strong&gt; Steps over the current line and takes you to the next line, even if the current line has method calls in it (the implementation of the methods is skipped).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step Into:&lt;/strong&gt; Steps into the method to inspect what happens inside it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Force Step Into:&lt;/strong&gt; Steps in the method even if this method is skipped by the regular Step Into.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step Out:&lt;/strong&gt; Steps out of the current method and takes you to the caller method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drop Frame:&lt;/strong&gt; Allows you to undo the last frame and restore the previous frame in the stack. This can be useful if you've mistakenly stepped too far or want to re-enter a function where you missed a critical spot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step Filter:&lt;/strong&gt; Allows you to skip certain packages during debugging. You don’t have to navigate through all classes of the JDK system when you can simply filter out types you don’t need.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Variables Pane
&lt;/h2&gt;

&lt;p&gt;Although the inline debugger is extremely helpful, the variables pane shows a lot more details. With its help, you can see the exact state and value of each variable in the selected stack and can even change the value of those variables, if you need to better understand what effect a specific change in your variable has in the execution of your code.&lt;/p&gt;

&lt;p&gt;If you want a more hands-on approach to this topic, there is this great video from &lt;a href="https://www.jetbrains.com/" rel="noopener noreferrer"&gt;JetBrains&lt;/a&gt; that walks you through the concepts I described and its implementation/application in IntelliJ UI.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lAWnIP1S6UA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Finally, remember that debugging might sometimes take more time than the actual implementation. As you improve your Java debugging skills, always try to write clean, efficient code - it makes an enormous difference when it comes to debugging.&lt;/p&gt;

&lt;p&gt;When you do need to do some debugging, remember that you only need to have to be creative and use the right tools.&lt;/p&gt;

&lt;p&gt;And even with the right tools, when things seem to get out of hand, it’s always worth taking a break. A bug is nothing more than a programming puzzle, and sometimes you just need a break from the code to solve the bug.&lt;/p&gt;

</description>
      <category>java</category>
      <category>debugging</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Hello World</title>
      <dc:creator>Vasco Ramos</dc:creator>
      <pubDate>Sun, 14 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/vascoalramos/hello-world-14de</link>
      <guid>https://dev.to/vascoalramos/hello-world-14de</guid>
      <description>&lt;p&gt;This is the first post of my new personal blog. This blog will be a digital registry of some of my findings and experiences with software development and different technologies. Feel free to check out my other posts and to reach out on my social presence.&lt;/p&gt;

</description>
      <category>hello</category>
    </item>
  </channel>
</rss>
