<?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: Okteto</title>
    <description>The latest articles on Forem by Okteto (@okteto).</description>
    <link>https://forem.com/okteto</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%2Forganization%2Fprofile_image%2F1034%2F3a48ac62-975a-4dd0-b1c9-f6434bfc63a7.png</url>
      <title>Forem: Okteto</title>
      <link>https://forem.com/okteto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/okteto"/>
    <language>en</language>
    <item>
      <title>Container Orchestration and Kubernetes</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Mon, 19 Dec 2022 07:28:47 +0000</pubDate>
      <link>https://forem.com/okteto/container-orchestration-and-kubernetes-9c1</link>
      <guid>https://forem.com/okteto/container-orchestration-and-kubernetes-9c1</guid>
      <description>&lt;p&gt;Containers quickly became the norm for how we built and packaged our applications. They made the software delivery and development cycle easy by providing a convenient way to run applications anywhere - without having to worry about setting the environment up from scratch every time. But, to run our containerized applications in production, we still needed to solve a few pieces of the puzzle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Containers in Production
&lt;/h2&gt;

&lt;p&gt;Since we shifted to a microservices based architecture, we started having a separate container for each microservice. But containers are meant to be ephemeral, and things can and do go wrong in production. This can lead to containers going down unexpectedly. And this is just one of the many problems associated with running containers in production. Long story short, we couldn’t just run containers directly to serve our applications. We needed something to manage these running containers - a container orchestrator.&lt;/p&gt;

&lt;p&gt;Managing a few containers to serve your application might still be possible with manual effort, but to run containers at scale, we needed some way to automate all the operational tasks associated with container management. Container orchestrators take care of all this. They are responsible for managing the complete container lifecycle and ensuring your applications are always up and running for users to access. They remove the manual effort of monitoring and managing containers by automating the whole process. Some of the tasks they generally take care of are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying containers with the correct application images&lt;/li&gt;
&lt;li&gt;Monitoring provisioned containers and checking if they are healthy&lt;/li&gt;
&lt;li&gt;Scaling up or down the number of containers based on the application traffic&lt;/li&gt;
&lt;li&gt;Balancing load between different running containers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it came to container orchestrators, two prominent names appeared: &lt;a href="https://docs.docker.com/get-started/swarm-deploy/" rel="noopener noreferrer"&gt;Docker Swarm&lt;/a&gt; and &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;. Let’s see how they differ and which one might be ideal for your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Swarm vs Kubernetes
&lt;/h2&gt;

&lt;p&gt;Both Docker Swarm and Kubernetes can help you orchestrate your containers. Deciding between the two primarily depends on your use case. Docker Swarm is an easy to set up and maintain solution when you want to manage simple workloads. It has a lower learning curve and is lightweight. If you have a relatively simple application and don’t have the time to invest in a complex solution, Docker Swarm might be the better choice for you. Kubernetes, on the other hand, offers a lot more features and should be the choice if you want to run complex workloads at scale effectively. It has a lot larger open source community than Docker Swarm and is offered by all the major cloud providers. It also has a vast ecosystem of tools built around it which extend its capabilities and make it the ideal choice for enterprises managing their microservices based applications. But the problem with Kubernetes is that it can be tough to learn and set up when getting started initially.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you’re looking to get started with Kubernetes, check out our &lt;a href="https://www.okteto.com/blog/kubernetes-basics/" rel="noopener noreferrer"&gt;Kubernetes for Beginners&lt;/a&gt; blog to get learning!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Migrating your existing applications and development workflows to containers running on Kubernetes can be a tough task. If you’re struggling with that, Okteto can help make the migration easy and simplify how you develop cloud native applications! &lt;a href="https://www.okteto.com/get-demo/" rel="noopener noreferrer"&gt;Reach out to us&lt;/a&gt; to talk more :)&lt;/p&gt;

&lt;h2&gt;
  
  
  How Kubernetes Works As Container Orchestrator
&lt;/h2&gt;

&lt;p&gt;Now that you have an idea of what a container orchestrator is, you might be wondering how exactly do they work. Let’s understand this by taking the example of Kubernetes. K8s works on a declarative system to manage your containerized applications. You tell it how you want things configured by writing a YAML file, and then it will work towards bringing up all the required containers and other needed things.&lt;/p&gt;

&lt;p&gt;Then it also continuously monitors the resources it has created and checks that they still match the state we had described in the configuration file. If that’s not the case, it takes the necessary actions required to get to that state. This is how K8s functions as a container orchestrator and avoids application downtime.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now that you recognize the usefullness of Kubernetes and will be using it to deliver, deploy, and run containers, &lt;a href="https://www.okteto.com/try-free/" rel="noopener noreferrer"&gt;give Okteto a try&lt;/a&gt; and immediately get the development environment to the K8s level and save development time and resources!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Developing Containerized Applications With Okteto
&lt;/h2&gt;

&lt;p&gt;Kubernetes has become the go-to tool for running containers at scale. It has changed how we deploy our applications. But the &lt;strong&gt;development&lt;/strong&gt; of these microservices based applications has still been an area that is lacking behind. Mainly because we’ve been using the same old tools for development that we used before containers came into the picture. Okteto simplifies the development of containerized applications by allowing you to write code in an environment that is exactly like production. This is done by leveraging Kubernetes during development as well! Check out our &lt;a href="https://www.okteto.com/docs/getting-started/" rel="noopener noreferrer"&gt;Getting Started Guide&lt;/a&gt; and learn how to simplify the development of your containerized applications.&lt;/p&gt;

</description>
      <category>css</category>
      <category>discuss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Kubernetes Cheat Sheet: Must-Know Commands and Examples</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Mon, 05 Dec 2022 13:00:07 +0000</pubDate>
      <link>https://forem.com/okteto/kubernetes-cheat-sheet-must-know-commands-and-examples-2d1k</link>
      <guid>https://forem.com/okteto/kubernetes-cheat-sheet-must-know-commands-and-examples-2d1k</guid>
      <description>&lt;p&gt;Things can be overwhelming when you are new to Kubernetes. You’d think that understanding all the &lt;a href="https://www.okteto.com/blog/kubernetes-basics/#fundamental-kubernetes-concepts-everyone-needs-to-know" rel="noopener noreferrer"&gt;different objects&lt;/a&gt; Kubernetes has to offer would be the end of it. But no, when it comes to actually interacting with K8s clusters, things get even more confusing for beginners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to kubectl
&lt;/h2&gt;

&lt;p&gt;The most common tool to interact with a Kubernetes cluster is &lt;a href="https://kubernetes.io/docs/tasks/tools/#kubectl" rel="noopener noreferrer"&gt;kubectl&lt;/a&gt;. This allows you to interact with the objects you create, view logs, etc. But as anyone who’s just starting to learn K8s will agree, THERE ARE JUST TOO MANY KUBECTL COMMANDS TO KEEP TRACK OF!&lt;/p&gt;

&lt;p&gt;But don’t worry; this blog is going to be my attempt to simplify things. We’ll go over the most common commands you’d find yourself using throughout your K8s journey. Here’s a meme to ease you in before getting started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqxmhgjq5hpwdtj2eveli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqxmhgjq5hpwdtj2eveli.png" alt="kubectl meme" width="720" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, if you’re completely new to Kubernetes, you might want to check out our Kubernetes for Beginners blog before proceeding!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cluster Info and Configuration
&lt;/h2&gt;

&lt;p&gt;Often you need to get information, not about the application but the cluster itself. Here are a few commands which help with that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl version&lt;/code&gt;: Gives information about what version of Kubernetes the client and server are on.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl cluster-info&lt;/code&gt;: Displays the endpoint of the Kubernetes control plane.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl config get-contexts&lt;/code&gt;: Lists all the contexts present in the current kubeconfig.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl config use-context &amp;lt;context name&amp;gt;&lt;/code&gt;: Allows you to set the default context for all the kubectl commands you’ll run.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Namespaces
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.okteto.com/blog/kubernetes-basics/#namespaces" rel="noopener noreferrer"&gt;Namespaces&lt;/a&gt; play a very important role in clusters. They act as a way to organize and isolate the different resources your application might need. By default, you’re in the &lt;code&gt;default&lt;/code&gt; namespace (surprise, surprise!), and the resources Kubernetes needs for its functioning are in the &lt;code&gt;kube-system&lt;/code&gt; namespace. Here are some other commands related to namespaces you’ll find yourself using frequently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl get namespaces&lt;/code&gt;: Often, you’ll find that you’ve lost track of all the namespaces you’ve created. This command will help you out by listing them all.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl create namespace &amp;lt;namespace name&amp;gt;&lt;/code&gt;: This command would create a new namespace for you. Note that it will not set that namespace as the default one, though. So all resources you create will still be created in the &lt;code&gt;default&lt;/code&gt; namespace unless you specify the &lt;code&gt;--namespace&lt;/code&gt; flag explicitly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl config set-context --current --namespace=&amp;lt;namespace name&amp;gt;&lt;/code&gt;: This allows you to change the default namespace for all the commands you’ll run while still keeping the same context. Just remember that the default namespace is called &lt;code&gt;default&lt;/code&gt; in case you ever want to switch back.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl delete namespace &amp;lt;namespace name&amp;gt;&lt;/code&gt;: This deletes the specified namespace and &lt;strong&gt;all resources under the namespace!&lt;/strong&gt; The deletion of resources is an asynchronous process, so don’t be surprised if you see your namespace in the “Terminating” state for a while before it’s completely gone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pods, Deployments, Secrets, etc
&lt;/h2&gt;

&lt;p&gt;Now there is a certain set of commands which you’ll find yourself using a lot when interacting with most of the Kubernetes resources. Just put in the resource name instead of &lt;code&gt;X&lt;/code&gt;, and you should be good to go with these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl get X&lt;/code&gt;: Lists all resources of that particular type &lt;strong&gt;in the current namespace&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl create X &amp;lt;name&amp;gt; &amp;lt;other properties&amp;gt;&lt;/code&gt;: Creates the “X” resource in the current namespace with the specified name. In most cases, you would have to specify some additional flags to actually create that particular resource.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl delete X &amp;lt;name&amp;gt;&lt;/code&gt;: Deletes the “X” resource with the given name in the current namespace.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl describe X &amp;lt;name&amp;gt;&lt;/code&gt;: You’ll find yourself using this one a lot when debugging things. This provides details and events related to the resource you specify.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl edit X &amp;lt;name&amp;gt;&lt;/code&gt;: This command will allow you to edit the specified resource directly without having to deal with any YAML. Remember to make the changes to your YAMLs once you’re satisfied with your edits because the edits don’t persist once the resource gets deleted!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nodes
&lt;/h2&gt;

&lt;p&gt;Nodes are what build your cluster, so it’s no surprise that you’ll often find yourself interacting with them. The following commands are worth keeping a note of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl get nodes&lt;/code&gt;: Shows a list of all the nodes along with their role (control-plane, worker, etc.) and the version of K8s they are running.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl top node &amp;lt;node name&amp;gt;&lt;/code&gt;: Shows the CPU and memory usage of the specified node.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl cordon/uncordon node &amp;lt;node name&amp;gt;&lt;/code&gt;: Cordoning nodes means marking them as unschedulable; that is, no pods will be placed on that particular node. This is useful when you want to isolate a node for something like updating its version or debugging.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl drain node &amp;lt;node name&amp;gt;&lt;/code&gt;: You’ll find yourself using this command when doing maintenance tasks for your cluster. Draining a node, cordons it as well, and deletes all pods running on it. If those pods are being managed by a Deployment, DaemonSet, etc., they will be recreated on the remaining nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Other Common Commands
&lt;/h2&gt;

&lt;p&gt;These are some commands which don’t exactly fit into any single category, but you’ll find yourself using them a lot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl apply -f &amp;lt;filename.yaml&amp;gt;&lt;/code&gt;: If you’re creating K8s resources using YAML files, then this is the command you should be using to apply those YAMLs. If the resource specified in the YAML already exists, then this command would update that resource with the latest configuration specified in the YAML file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl delete -f &amp;lt;filename.yaml&amp;gt;&lt;/code&gt;: This command deletes all the resources specified in the particular YAML file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl port-forward &amp;lt;pod name&amp;gt; &amp;lt;local port&amp;gt;:&amp;lt;remote port&amp;gt;&lt;/code&gt;: Relying on services to expose your application to external traffic isn’t always convenient, especially when you’re debugging. The &lt;code&gt;port-forward&lt;/code&gt; subcommand provides you with a simple way to do this by letting you forward a local port to a specified port in the mentioned pod.&lt;/li&gt;
&lt;li&gt;kubectl logs : This is a very useful command for debugging your deployed application. This command prints the logs for the container running in the specified pod. If your pod is running more than one container, you can additionally specify the &lt;code&gt;--container&lt;/code&gt; flag to mention which container’s logs you want to see.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Abstract Away the Complexities of Kubernetes From Developers
&lt;/h2&gt;

&lt;p&gt;While we discussed some common commands you’d find yourself using when working with K8s, I believe that it is not developers who should be taking care of these K8s related tasks. Having developers deal with the infrastructure and deployment side of things during the development process takes a massive hit on productivity and also leads to a poor developer experience. With Okteto, you can define all the things you need to spin up your dev environment in a YAML and have developers skip right to the code-writing phase by running just one single command. Try our &lt;a href="https://www.okteto.com/docs/getting-started/" rel="noopener noreferrer"&gt;Getting Started Guide&lt;/a&gt; to see the magic for yourself!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>beginners</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Beginner’s Guide to Network Policies in Kubernetes</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Mon, 28 Nov 2022 14:55:20 +0000</pubDate>
      <link>https://forem.com/okteto/beginners-guide-to-network-policies-in-kubernetes-49fk</link>
      <guid>https://forem.com/okteto/beginners-guide-to-network-policies-in-kubernetes-49fk</guid>
      <description>&lt;p&gt;Everyone agrees that Kubernetes clusters are not secure by default. But the good thing is that Kubernetes gives you the tools to make it so. In this article, we’re going to learn about one of such resources K8s provides right out of the box to make your deployed applications a bit more secure: Network Policies.&lt;/p&gt;

&lt;p&gt;If you’re completely new to Kubernetes, I would recommend you go through our &lt;a href="https://www.okteto.com/blog/kubernetes-basics/" rel="noopener noreferrer"&gt;Kubernetes Basics&lt;/a&gt; tutorial first before proceeding with this!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Network Policies Are Important
&lt;/h2&gt;

&lt;p&gt;When learning about something new, I often find it easier to understand if I start with learning the “why” it was needed, even before knowing “what” it actually is. Let’s do the same with Network Policies, and I’m sure you’ll have a much easier time understanding them! :)&lt;/p&gt;

&lt;p&gt;By default, Kubernetes allows traffic from all pods to reach all other pods. But this isn’t something you’d want in production. Why? Because this way, if a pod gets compromised, it will be able to affect other pods and potentially compromise the security of your entire application. Network Policies provide a way to restrict traffic in your cluster so that only legitimate traffic can flow - where the term “legitimate traffic” is for you to decide based on your application.&lt;/p&gt;

&lt;p&gt;For example, if you’ve deployed a full-stack application by default, the frontend pods will be able to communicate with the backend as well as the database pods. But we know that the frontend pods don’t actually need to talk to the database pods directly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkqbgvfilvi17w1bc03fs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkqbgvfilvi17w1bc03fs.png" alt="Networking without Network Policies" width="671" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this scenario, it would be ideal for us to leverage Network Policies to allow traffic from the frontend pods only to the backend pods. This way, even if the frontend pods get compromised, we can be sure that our database won’t be affected!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fex3cxdq3ig0ip42cr2rt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fex3cxdq3ig0ip42cr2rt.png" alt="Networking with Network Policies" width="671" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have an understanding of what utility Network Policies serve let’s start learning about them in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly Are Network Policies
&lt;/h2&gt;

&lt;p&gt;Network Policies are a resource in Kubernetes responsible for controlling traffic &lt;em&gt;to and from&lt;/em&gt; &lt;a href="https://www.okteto.com/blog/kubernetes-basics/#pods" rel="noopener noreferrer"&gt;pods&lt;/a&gt; running in a cluster. With Network Policies, you select pods using labels and then specify rules for these selected pods. You can utilize a combination of the following three to precisely control traffic:&lt;/p&gt;

&lt;p&gt;Other pods: You can select other pods using labels that should be allowed to talk to the selected pods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.okteto.com/blog/kubernetes-basics/#namespaces" rel="noopener noreferrer"&gt;Namespaces&lt;/a&gt;: You can select complete namespaces as well. In this case, all pods in the namespace would be able to communicate with the selected pods.&lt;/p&gt;

&lt;p&gt;IP blocks: You can specify CIDR ranges from or to which traffic is allowed for the selected pods.&lt;/p&gt;

&lt;h3&gt;
  
  
  The NetworkPolicy Resource
&lt;/h3&gt;

&lt;p&gt;Let’s look at a sample NetworkPolicy resource and then understand all the fields in a bit more detail. Warning: things aren’t as scary as they might look at first glance! :P&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;networking.k8s.io/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;NetworkPolicy&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;sample-network-policy&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;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Egress&lt;/span&gt;
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;firstproject&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client&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;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&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;4614&lt;/span&gt;
  &lt;span class="na"&gt;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secondproject&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;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&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;1010&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like most other K8s resources, the &lt;code&gt;NetworkPolicyresource&lt;/code&gt; also has the usual &lt;code&gt;apiVersion&lt;/code&gt;, &lt;code&gt;kind&lt;/code&gt;, &lt;code&gt;metadata&lt;/code&gt;, and &lt;code&gt;spec&lt;/code&gt; fields. The &lt;code&gt;spec&lt;/code&gt; field is where things get interesting! You’ll mostly see the following things under this field:&lt;/p&gt;

&lt;h4&gt;
  
  
  podSelector
&lt;/h4&gt;

&lt;p&gt;This is where we select the pods we want the policy to get applied to.&lt;/p&gt;

&lt;h4&gt;
  
  
  policyType
&lt;/h4&gt;

&lt;p&gt;NetworkPolicies have two types: Ingress and Egress. A NetworkPolicy resource can be of any of the two types (or even both!). Ingress refers to the traffic entering the pods we select under the &lt;code&gt;podSelector&lt;/code&gt;, whereas Egress refers to the traffic leaving the pods. The &lt;code&gt;policyType&lt;/code&gt; field indicates whether we will specify ingress rules or egress rules, or both for the pods we’ve selected in our NetworkPolicy resource.&lt;/p&gt;

&lt;h4&gt;
  
  
  ingress
&lt;/h4&gt;

&lt;p&gt;This is where we list rules for what traffic is allowed to enter the selected pods. All the listed rules get &lt;code&gt;OR&lt;/code&gt;ed.&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;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;firstproject&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above section in a network policy would allow traffic to the selected pods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;from all pods in the namespace with the label "project: firstproject" and,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;from all pods with the label "role: client" regardless of which namespace they are present in.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In case you wanted a combination of both of these rules, your ingress section would look something like this:&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;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;firstproject&lt;/span&gt;
      &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this would allow traffic only from pods with the “role: client” label present in the namespace with the “project: firstproject” label.&lt;/p&gt;

&lt;p&gt;The selection capabilities are quite powerful, no?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ports&lt;/code&gt; section simply specifies the ports on which the selected traffic is allowed.&lt;/p&gt;

&lt;h4&gt;
  
  
  egress
&lt;/h4&gt;

&lt;p&gt;Similar to ingress in terms of selecting things, the only difference being that this is where we select where traffic is allowed to go from our selected pods.&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;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secondproject&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in the above example, the selected pods are allowed to send traffic to all pods in the namespace with the label “project: secondproject”. The selection rules for egress get ANDed and ORed, similar to ingress rules. The portssection, too, like in the case of ingress, specifies what ports the rules are valid on.&lt;/p&gt;

&lt;p&gt;Now that you have a general idea of what a NetworkPolicy does and looks like let’s see things in action!&lt;/p&gt;

&lt;h2&gt;
  
  
  Working With Network Policies
&lt;/h2&gt;

&lt;p&gt;We’ll keep things simple in this section but, at the same time, ensure that you’re able to understand Network Policies in detail. We’ll work with two pods: frontend and backend, and test the connectivity between them before and after creating some Network Policies.&lt;/p&gt;

&lt;p&gt;Let’s first create both our pods:&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="nv"&gt;$ &lt;/span&gt;kubectl run frontend &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx
&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl run backend &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let’s just expose both these pods by creating cluster internal services so that its easier for us to check the connectivity between them:&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="nv"&gt;$ &lt;/span&gt;kubectl expose pod frontend &lt;span class="nt"&gt;--port&lt;/span&gt; 80
&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl expose pod backend &lt;span class="nt"&gt;--port&lt;/span&gt; 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm that everything is working as expected by running kubectl get all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NAME           READY   STATUS    RESTARTS   AGE
pod/backend    1/1     Running   0          3m10s
pod/frontend   1/1     Running   0          3m18s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;   AGE
service/backend      ClusterIP   10.120.37.122   &amp;lt;none&amp;gt;        80/TCP    67s
service/frontend     ClusterIP   10.120.39.94    &amp;lt;none&amp;gt;        80/TCP    72s
service/kubernetes   ClusterIP   10.120.32.1     &amp;lt;none&amp;gt;        443/TCP   257d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you remember, at the start, I mentioned that by default, all pods in K8s are allowed to interact with each other. Let’s confirm this by trying to ping the backend pod, using the cluster IP of its service, from the frontend pod by running the &lt;code&gt;exec&lt;/code&gt; 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="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec &lt;/span&gt;frontend &lt;span class="nt"&gt;--&lt;/span&gt; curl 10.120.37.122
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Welcome to nginx!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;35em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tahoma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Verdana&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to nginx!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;For online documentation and support please refer to
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;http://nginx.org/&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;nginx.org&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;.&lt;span class="nt"&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
Commercial support is available at
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;http://nginx.com/&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;nginx.com&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&lt;/span&gt;Thank you for using nginx.&lt;span class="nt"&gt;&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see the HTML output for the NGINX starter page, which confirms that we were successfully able to ping the backend pod.&lt;/p&gt;

&lt;p&gt;You can also try this the other way around as well 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="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec &lt;/span&gt;backend &lt;span class="nt"&gt;--&lt;/span&gt; curl 10.120.39.94
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s now create a very common policy called “Default deny”. Once this is created, it will restrict ALL traffic for ALL pods in your cluster. This is a very convenient and common way to begin thinking about networking rules in your cluster. You begin by stopping all traffic and then create more network policies only for the traffic you want to allow.&lt;/p&gt;

&lt;p&gt;Create the following default deny policy:&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;networking.k8s.io/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;NetworkPolicy&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;default-deny&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;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Egress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specifying &lt;code&gt;{}&lt;/code&gt; for &lt;code&gt;podSelectors&lt;/code&gt; selects all pods and not writing an ingress or egress section while mentioning them both under &lt;code&gt;policyTypes&lt;/code&gt; blocks all traffic.&lt;/p&gt;

&lt;p&gt;Try running the kubectl execcommands we ran before now. You’ll notice that it doesn’t show the HTML and just keeps loading. This is because of the Network Policy that we just created!&lt;/p&gt;

&lt;p&gt;Now let’s make sure our frontend pod is able to communicate with the backend pod. For this, we would need to create two rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One egress rule which allows outgoing traffic from the frontend to the backend&lt;/li&gt;
&lt;li&gt;One ingress rule which allows incoming to the backend from the frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following policy will select the frontend pods and allow outgoing traffic from them to reach the backend pods:&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;networking.k8s.io/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;NetworkPolicy&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;frontend-policy&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;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Egress&lt;/span&gt;
  &lt;span class="na"&gt;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try rerunning the following command to test if things are working or not:&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="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec &lt;/span&gt;frontend &lt;span class="nt"&gt;--&lt;/span&gt; curl 10.120.37.122
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll notice that it still doesn’t work. And that’s expected! Right now, we’ve only created a policy that allows traffic to leave from the frontend pods to the backend pods. The backend pods still need an ingress rule to allow incoming traffic from the frontend pods. Let’s create another policy to achieve this:&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;networking.k8s.io/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;NetworkPolicy&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;backend-policy&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;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you’ve created both of these policies, try pinging the backend pods again, and it should work! You can also try pinging the frontend pods from the backend ones and confirm that it still does not work because of our default deny policy.&lt;/p&gt;

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

&lt;p&gt;I think you can now start to appreciate how Network Policies can play a crucial role in helping you ship secure applications. We learned why Network Policies are needed and how they work and then saw them in action. If there is one piece of advice I want to leave you with before concluding, it's that when managing traffic in your clusters, it is best to &lt;strong&gt;only&lt;/strong&gt; allow the required traffic and &lt;strong&gt;block everything else&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Okteto allows developers to work on their applications in a production-like environment. This means you can use Kubernetes resources like Network Policies right &lt;strong&gt;during the development phase&lt;/strong&gt;. This allows developers to be sure that the code they write is secure and won’t break in production. Check out our &lt;a href="https://www.okteto.com/docs/getting-started/" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt; guide to learn more!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>beginners</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Beginner’s Guide to Kubernetes Deployments</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Thu, 22 Sep 2022 08:19:39 +0000</pubDate>
      <link>https://forem.com/okteto/beginners-guide-to-kubernetes-deployments-4bjl</link>
      <guid>https://forem.com/okteto/beginners-guide-to-kubernetes-deployments-4bjl</guid>
      <description>&lt;p&gt;Over the last five years, &lt;a href="https://dev.to/okteto/getting-started-with-kubernetes-as-a-developer-2jea"&gt;Kubernetes&lt;/a&gt; has seen rapid adoption as a container orchestrator. And for a good reason too. &lt;a href="https://dev.to/rinkiyakedad/introduction-to-docker-1hp2"&gt;Containers&lt;/a&gt; solved the problem of being unable to run applications easily on different environments and systems. But there were a lot of problems when running containers at scale:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do you ensure a minimum number of containers are always running?&lt;/li&gt;
&lt;li&gt;What happens when a container goes down?&lt;/li&gt;
&lt;li&gt;How do you update your application without any downtime?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kubernetes solved all these and many more problems for us. But its architecture has always been an object of mystery when looked at from far. How is it managing all these containers for us? What inputs does it need from us to do this? All of this can be scary if you haven’t gotten the basics of Kubernetes right. In this article, we will focus on one of the basic objects it has to offer: Deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Bit About Pods First
&lt;/h2&gt;

&lt;p&gt;Learning about Deployments directly before knowing about Pods is like learning to read without knowing the alphabet. We won’t go into much detail about pods here, but I’ll cover enough so the rest of the article makes sense.&lt;/p&gt;

&lt;p&gt;Pods are the most fundamental unit in the K8s world. The simplest way to understand pods without getting confused is to think of them as a wrapper for containers. Kubernetes doesn’t run containers directly. Instead, it runs Pods, where we specify which containers we want to run. Another thing to remember about pods, which we’ll get back to later, is that in the K8s world, pods are meant to be ephemeral: a single pod runs a single instance of your application, and that’s all there is to it. A running pod is only responsible for ensuring an instance of your application is running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes vs Docker Deployments
&lt;/h2&gt;

&lt;p&gt;When we talk of Deployments in Kubernetes, it is very different from what we mean when we refer to deploying your application using just Docker. This is why I wanted to have a separate section to clarify the difference, so you don’t get confused.&lt;/p&gt;

&lt;p&gt;When we talk about deploying using Docker, we usually mean the process of building container images from our Dockerfiles, pushing them to a registry, and then running our application containers.&lt;/p&gt;

&lt;p&gt;In the world of Kubernetes, however, Deployments are an object. As per the &lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#kubernetes-objects" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A Kubernetes object is a "record of intent"--once you create the object, the Kubernetes system will constantly work to ensure that object exists.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These objects are accompanied by controllers. So for the Deployment object, there is a Deployment controller. The controllers ensure that the object's current state matches the desired state we specified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployments in Kubernetes
&lt;/h2&gt;

&lt;p&gt;So now we know two things: Pods are the fundamental unit in the world of K8s, and Deployments are a type of Kubernetes object. With this, we’re ready to understand the Deployment object in more detail. Let’s consider the following scenario:&lt;/p&gt;

&lt;p&gt;You run a bunch of pods to serve your application to the users. Now let’s say there’s a sudden increase in traffic, and your pods start running out of resources. What should Kubernetes do in this case? If you recall, I mentioned that Pods only have the single function of running your application. They alone can’t bring up more pods if existing pods run out of resources.&lt;/p&gt;

&lt;p&gt;To help manage pods, we need another Kubernetes object. And that’s where Deployments kick in. Instead of creating individual pods to serve our application, we create a Deployment object. The Deployment controller is then responsible for the management of these pods. All we have to do is create our Deployment object, and then the controller will handle the task of making sure that our specified number of pods is always running. What’s more, is that it also allows us to do other useful things like scale the number of pods, update the version of our application (without any downtime!), and even roll back to a previous app version if we discover a bug. We’ll soon see all of these in action. But let’s now learn how we can create them.&lt;/p&gt;

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

&lt;p&gt;I'll assume you have a K8s cluster ready to work with. If this is your first time interacting with Kubernetes, I will recommend you read our &lt;a href="https://dev.to/okteto/getting-started-with-kubernetes-as-a-developer-2jea"&gt;Beginners’ Guide to Kubernetes&lt;/a&gt; before continuing with this.&lt;/p&gt;

&lt;p&gt;Let us look at what the YAML for a typical Deployment object would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the &lt;code&gt;spec&lt;/code&gt; section, you’ll notice we have a property called &lt;code&gt;replicas&lt;/code&gt;. This refers to the number of pods we want our Deployment to run. The Deployment controller will continuously check if these many pods are up and running at any given time. If that’s not the case, it will work towards reaching this number by creating more pods or deleting existing ones.&lt;/p&gt;

&lt;p&gt;Then under the &lt;code&gt;selector&lt;/code&gt;, we specify the labels of the pods for the Deployment controller. This is so that it knows which pods it is supposed to manage. Let’s say in our Deployment object, we specify that we want three replicas, but two pods with the label &lt;code&gt;app: nginx&lt;/code&gt; already exist before we create the object. In this case, the controller will only create one additional pod for us. Had we not specified any labels, then the controller wouldn’t have been able to identify that two of the needed pods were already running.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;template&lt;/code&gt; section is nothing but a Pod template's metadata and specification section. The &lt;code&gt;metadata&lt;/code&gt; section lets the Deployment controller know what labels to attach to any new pods it creates, and the &lt;code&gt;spec&lt;/code&gt; section has information about the containers which would run in the pod.&lt;/p&gt;

&lt;p&gt;You can create this Deployment just like you would any other object by using the &lt;code&gt;kubectl apply&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f nginx-deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the Deployment, if you now look at all the objects in our K8s cluster by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;you’ll notice that we not only have the Deployment, but we also see the three pods which the Deployment created for us!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
NAME                                   READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-877f48f6d-2zp4p   1/1     Running   0          15s
pod/nginx-deployment-877f48f6d-8tf9g   1/1     Running   0          15s
pod/nginx-deployment-877f48f6d-ptgz8   1/1     Running   0          15s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
service/kubernetes   ClusterIP   10.120.32.1     &amp;lt;none&amp;gt;        443/TCP     223d

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           16s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-877f48f6d   3         3         3       16s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Performing Rolling Updates
&lt;/h3&gt;

&lt;p&gt;Let’s say you updated your container image and now want all your pods serving your application using the new image. If you were to manually delete and recreate them, you would face downtime. To avoid this, Kubernetes supports something called Rolling Updates. Rolling updates are the default strategy K8s uses whenever you make any updates to your Deployment. When doing a Rolling update, K8s doesn’t bring down all the pods at once and then bring up all the new ones. Instead, it brings down some pods, then brings up some, and then repeats this process until all old pods have been replaced. This ensures that there are always pods available serving the application to the users.&lt;/p&gt;

&lt;p&gt;Let’s see this in action by changing the image used in our nginx deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl set image deployment nginx-deployment nginx=nginx:1.19.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see the rollout process in action as it proceeds, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl rollout status deployment nginx-deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you do this, you’ll notice exactly what I described taking place in the logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rolling Back Deployments
&lt;/h3&gt;

&lt;p&gt;Now let’s say we realize there’s a bug in the latest container image we just updated &lt;code&gt;nginx&lt;/code&gt; to. In this case, we would ideally like to return to the last version of our deployment, which we knew was working. K8s allows us to do exactly that using the &lt;code&gt;undo&lt;/code&gt; subcommand.&lt;/p&gt;

&lt;p&gt;If you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl rollout history deployment nginx-deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you should be able to see all the updates we made to our Deployment. We can go back to any previous version (in the case the first one) by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl rollout undo deployment nginx-deployment --to-revision=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like with Rolling Updates, when rolling back, Kubernetes will ensure that all the pods aren’t brought down all at once to avoid downtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scaling Deployments
&lt;/h3&gt;

&lt;p&gt;The number of pods we mention in the replicassection of our Deployment can be updated. This is very useful when we want the number of pods to be changed based on the load. If at some point, there are a lot of users trying to access our application, we would obviously want more pods so there is no overload.&lt;/p&gt;

&lt;p&gt;Let’s say we want Kubernetes to increase the number of pods for our deployment if the CPU load of the node exceeds 80%. But we still want the max number of pods it scales up to to be 7. The autoscalesubcommand helps us achieve exactly that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl autoscale deployment nginx-deployment --min=3 --max=7 --cpu-percent=80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on this, when the load decreases to less than 80%, it will also automatically start scaling down the number of pods until there are just three running pods.&lt;/p&gt;

&lt;p&gt;I hope you found this introduction to Kubernetes Deployments useful. There is much more to Deployments, but this should be enough to get you started!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Services and Ingresses in Kubernetes</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Thu, 17 Feb 2022 15:05:26 +0000</pubDate>
      <link>https://forem.com/okteto/services-and-ingresses-in-kubernetes-1pjp</link>
      <guid>https://forem.com/okteto/services-and-ingresses-in-kubernetes-1pjp</guid>
      <description>&lt;p&gt;Before starting this post, I want to congratulate you all for making it till here! Kubernetes is intimidating, especially if you come from a developer background. The fact that you were able to understand the concepts we talked about in the previous articles is a huge feat. Wrapping your head around so many Kubernetes objects is no easy deal!&lt;/p&gt;

&lt;p&gt;In the &lt;a href="//okteto.com/blog/configuration-and-storage-in-kubernetes"&gt;last post&lt;/a&gt; we looked at configuration and storage in Kubernetes. We saw how &lt;a href="//okteto.com/blog/configuration-and-storage-in-kubernetes/#configmaps-and-secrets"&gt;Secrets&lt;/a&gt; help provide sensitive configuration data to our app and how &lt;a href="//okteto.com/blog/configuration-and-storage-in-kubernetes/#persistent-volumes"&gt;Persistent Volumes&lt;/a&gt; can be used to make sure we don’t lose our data in case some Pods crash. In the final post of this series, we’re going to take a look at how networking works in Kubernetes. &lt;/p&gt;

&lt;p&gt;We will see how we can expose Pods running our application using the &lt;a href="//okteto.com/blog/services-and-ingresses-in-kubernetes/#services"&gt;Service&lt;/a&gt; object. This would help us ensure that different parts of our application (backend, frontend, etc) are able to communicate with each other within the cluster. Then we will see how we can ease external access to our application by setting up routing using the &lt;a href="//okteto.com/blog/services-and-ingresses-in-kubernetes/#ingresses"&gt;Ingress&lt;/a&gt; object. Lots to cover in this one, so let’s begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Services
&lt;/h2&gt;

&lt;p&gt;To understand Services, let’s look at what problem they solve. If you recall our discussion of &lt;a href="//okteto.com/blog/fundamental-kubernetes-concepts-everyone-needs-to-know/#deployments"&gt;Deployments&lt;/a&gt; you’ll remember that deployments create and manage multiple pods for us. &lt;/p&gt;

&lt;p&gt;So we would have a deployment for the frontend of our application which would manage multiple pods running our containerized frontend code. Now this code would need to interact with the backend pods. But how does it do that? What IP address should it ping? It clearly can’t be the IP address of a particular backend pod because we know pods are ephemeral so we can’t rely on their IP addresses.&lt;/p&gt;

&lt;p&gt;This is where Services come into the picture. Services allow us to send traffic to Pods that match the labels we specify when creating the Service. Let us look at the YAML for a simple service to understand things better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;​​apiVersion: v1
kind: Service
metadata:
  name: database-service
spec:
  selector:
    app: database
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above YAML should be pretty easy to understand - it creates a Service that will route all traffic to Pods that have the label &lt;code&gt;app: database&lt;/code&gt; on them. Coming to the &lt;code&gt;ports&lt;/code&gt; section which might not be so obvious, we specify a &lt;code&gt;port&lt;/code&gt; and a &lt;code&gt;targetPort&lt;/code&gt;. &lt;code&gt;targetPort&lt;/code&gt; is the port on which the selected pods will be listening. The Service will send requests to the Pods on this particular port. &lt;code&gt;port&lt;/code&gt;, on the other hand, is simply the port within the cluster on which we want the Service to be exposed. This is needed because we might have different services in our cluster, which we would then expose on different ports. Another thing worth mentioning is that while TCP is the default network protocol for services in Kubernetes, you can use any of the &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/#protocol-support" rel="noopener noreferrer"&gt;following&lt;/a&gt; instead too. &lt;/p&gt;

&lt;p&gt;So far, so good, right? Looking at the movies app &lt;a href="//okteto.com/docs/getting-started/#step-1-deploy-the-movies-app"&gt;we deployed&lt;/a&gt; on Okteto Cloud, we have a service created which is exposing the database for our backend pods to talk to. You can confirm that this Service exists by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;To see what the YAML for this Service looks like, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get service mongodb -o yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see that we have specified &lt;code&gt;3940&lt;/code&gt; as the value of the &lt;code&gt;port&lt;/code&gt;, which is arbitrarily chosen. For the &lt;code&gt;targetPort&lt;/code&gt;, we specify &lt;code&gt;27017&lt;/code&gt; because that is the default port a MongoDB database listens on.&lt;/p&gt;

&lt;p&gt;Now, if you look at the &lt;a href="https://github.com/okteto/movies/blob/ce27d64bd17762559eea6cbdebc28592065790d6/api/server.js#L6" rel="noopener noreferrer"&gt;backend code&lt;/a&gt; you’ll see that we use the name of this Service, which is &lt;code&gt;mongodb&lt;/code&gt;, to connect to the database. The &lt;code&gt;url&lt;/code&gt; used to connect to the database is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const url = `mongodb://${process.env.MONGODB_USERNAME}:${encodeURIComponent(process.env.MONGODB_PASSWORD)}@${process.env.MONGODB_HOST}:3940/${process.env.MONGODB_DATABASE}`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is using the &lt;code&gt;MONGODB_HOST&lt;/code&gt; environment variable, which is &lt;a href="https://github.com/okteto/movies/blob/a60756c8122643ac65fec2cee837d95a60b02210/chart/templates/api-deployment.yaml#L52-L53" rel="noopener noreferrer"&gt;set to&lt;/a&gt; the name of the Service, that is, &lt;code&gt;mongodb&lt;/code&gt;. After that, we also specify the port which we arbitrarily chose when creating our Service (&lt;code&gt;3940&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;And voila! This is all the K8s magic we need in order to make different microservices in our application talk to each other. Let’s now take our discussion further and see how we can route incoming traffic to various services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ingresses
&lt;/h2&gt;

&lt;p&gt;So you’ve containerized your application, you’ve set up your Deployments and configured Services to enable communication between parts of your application, but what’s next? If your application is deployed on a cloud provider, you would set up a load balancer pointing to your services. The load balancer would provide you with a static IP address accessible from outside the cluster. &lt;/p&gt;

&lt;p&gt;But is it cost-effective and manageable to set up different load balancers for each of your services? This is where Ingresses come to the rescue. Think of an Ingress object as a sort of signboard for vehicles at a cross-section of roads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fng9238mgtwkxnwut5lnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fng9238mgtwkxnwut5lnl.png" alt="sign board" width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The roads in this metaphor are different services in our cluster and the vehicles are the requests coming to our cluster. An Ingress object we create will tell the incoming requests to the cluster which Service they should go to. Ingresses don’t enable external access to our app by themselves, but they make it easy. You would now just need one load balancer from your cloud provider, which would point to the Ingress, and then the Ingress will take care of handling the routing of all incoming traffic. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fynt1txvvp6y9oilo7zms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fynt1txvvp6y9oilo7zms.png" alt="ingress flow" width="800" height="847"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s see what the Ingress object for our movies app looks like by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get ingress movies -o yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output you get should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec:
  rules:
  - host: movies-rinkiyakedad.cloud.okteto.net
    http:
      paths:
      - backend:
          service:
            name: frontend
            port:
              number: 80
        path: /
        pathType: Prefix
      - backend:
          service:
            name: api
            port:
              number: 8080
        path: /api
        pathType: Prefix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see that under the &lt;code&gt;spec&lt;/code&gt; section, we set up two paths for different services in our application which we wanted to expose: the frontend service and the backend service. So requests sent to our cluster at &lt;code&gt;/api&lt;/code&gt; will be redirected to the backend service, which further directs them to the backend pods serving our application. All other requests will be redirected to the frontend pods via the frontend service. This simplifies the management of different routes significantly when compared to the traditional way of doing this - setting up an NGINX proxy per application. Very convenient, right? :)&lt;/p&gt;

&lt;p&gt;To sum our discussion up, Ingress isn’t something complicated - it’s just a Kubernetes object which allows us to specify routing rules!&lt;/p&gt;

&lt;p&gt;However, there is another part to Ingresses that we didn’t touch in this article. The K8s objects we’ve seen so far (Pods, Deployments, etc) come with their &lt;a href="//okteto.com/blog/getting-started-with-kubernetes-as-a-developer/#kubernetes-under-the-hood"&gt;controllers&lt;/a&gt; preinstalled in the cluster. This is not true for Ingresses. To create an Ingress object, you will need your cluster admin to install an &lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/" rel="noopener noreferrer"&gt;ingress controller&lt;/a&gt; in your cluster. I won’t be covering how to do that since as developers we rarely have to do it ourselves. If you’re using &lt;a href="https://cloud.okteto.com/" rel="noopener noreferrer"&gt;Okteto Cloud&lt;/a&gt;, the cluster provided to you would already have an Ingress controller installed :)&lt;/p&gt;

&lt;p&gt;Well, that wraps up our discussion for this article. We learned that different microservices in our application can talk to each other with the help of the &lt;a href="//okteto.com/blog/services-and-ingresses-in-kubernetes/#services"&gt;Service&lt;/a&gt; K8s object. Then we went ahead and looked at &lt;a href="//okteto.com/blog/services-and-ingresses-in-kubernetes/#ingresses"&gt;Ingresses&lt;/a&gt;, which allow us to route incoming traffic to our cluster to the different Services which we’ve created. &lt;/p&gt;

&lt;p&gt;I hope this discussion not only enables you to learn more about this topic but also sparks your curiosity enough so you go give things a try yourself. A very easy way to tinker with all this could be to &lt;a href="https://github.com/okteto/movies" rel="noopener noreferrer"&gt;fork the movies app&lt;/a&gt;, edit the &lt;a href="https://github.com/okteto/movies/tree/main/chart/templates" rel="noopener noreferrer"&gt;YAMLs&lt;/a&gt; and deploy on Okteto Cloud using a &lt;a href="//okteto.com/docs/getting-started/#step-1-deploy-the-movies-app"&gt;single click&lt;/a&gt;! &lt;/p&gt;

&lt;p&gt;This post also concludes our Kubernetes for Developer series. There will, however, be one &lt;a href="//okteto.com/blog/kubernetes-for-developers-blog-series-by-okteto/"&gt;final brief post&lt;/a&gt; to wrap things up and point you to resources that would be helpful for you on your Kubernetes journey ahead. Until then, happy hacking! 😄&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The "Kubernetes for Developers" blog series has now concluded, and you can find all the posts in this series &lt;a href="//okteto.com/blog/kubernetes-for-developers-blog-series-by-okteto/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>beginners</category>
      <category>docker</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Configuration and Storage in Kubernetes</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Thu, 10 Feb 2022 15:11:09 +0000</pubDate>
      <link>https://forem.com/okteto/configuration-and-storage-in-kubernetes-7ae</link>
      <guid>https://forem.com/okteto/configuration-and-storage-in-kubernetes-7ae</guid>
      <description>&lt;p&gt;Hello fellow developers! By this point in the series, I hope you’re now much less scared of Kubernetes. So far we’ve explored its architecture, some essential K8s objects, and even deployed an app on a Kubernetes cluster using Okteto! Pat yourselves on the back for making it till here :)&lt;/p&gt;

&lt;p&gt;In this article, we’ll first look at two somewhat similar Kubernetes objects which help with providing configuration to our application running in the cluster - ConfigMaps and Secrets. Then we’ll move on to look at how storage is handled in Kubernetes using Volumes and Persistent Volumes. So strap on and let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  ConfigMaps and Secrets
&lt;/h2&gt;

&lt;p&gt;To inject configuration data into a container, Kubernetes provides us with two objects: ConfigMaps and Secrets. It is highly recommended to separate configuration data from your application code so you’ll see these two objects being used in almost all Kubernetes clusters. &lt;/p&gt;

&lt;p&gt;If you see the YAML for a &lt;a href="https://kubernetes.io/docs/concepts/configuration/configmap/#configmaps-and-pods" rel="noopener noreferrer"&gt;ConfigMap&lt;/a&gt; or a &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets" rel="noopener noreferrer"&gt;Secret&lt;/a&gt; you’ll notice that both of them are almost similar. They both have a &lt;code&gt;data&lt;/code&gt; key under which the configuration data is provided in key-value pairs. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data:
  key1: value1
  key2: value2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference is in the fact that secrets are meant for holding sensitive data. When writing the YAML for a secret we wouldn’t specify &lt;code&gt;value1&lt;/code&gt; and &lt;code&gt;value2&lt;/code&gt; directly like we would for ConfigMaps. Instead, we would specify the &lt;a href="https://en.wikipedia.org/wiki/Base64" rel="noopener noreferrer"&gt;base64&lt;/a&gt; encoded versions of these values. &lt;/p&gt;

&lt;p&gt;Pods can refer to a particular ConfigMap and/or Secret and specify a key and then they would have an environment variable in their container with the corresponding value. This would enable you to refer to these environment variables in your application code.&lt;/p&gt;

&lt;p&gt;For the &lt;a href="https://okteto.com/docs/getting-started/index.html#step-1-deploy-the-movies-app" rel="noopener noreferrer"&gt;movies app&lt;/a&gt; which we deployed, our api pod needed the credentials for the MongoDB database in order to connect to it. We provided these using a secret. If you see the YAML for the api deployment you’ll see that we’re getting an environment variable called &lt;code&gt;MONGODB_PASSWORD&lt;/code&gt; for our container from a secret called &lt;code&gt;mongodb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fe9hxjn1nre9vl9citdjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fe9hxjn1nre9vl9citdjq.png" alt="Secret being used in pod" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to see how the YAML for this secret looks, head over to the terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get secret mongodb -o yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-o yaml&lt;/code&gt; flag gets the YAML for a particular Kubernetes object. You’ll see that under the &lt;code&gt;data&lt;/code&gt; key for the returned object, we have the &lt;code&gt;mongodb-password&lt;/code&gt; key which we were referring to in our api deployment. To see the actual value for this key you’ll have to decode the base64 encoded value shown. &lt;/p&gt;

&lt;p&gt;Now that you have an idea of how configuration data is handled in Kubernetes clusters, let’s move on and take a look at how data is shared between K8s objects using Volumes and Persistent Volumes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Storage in Kubernetes
&lt;/h2&gt;

&lt;p&gt;If you recall, in the &lt;a href="//okteto.com/blog/fundamental-kubernetes-concepts-everyone-needs-to-know/#deployments"&gt;second article&lt;/a&gt; I mentioned that Pods are meant to be ephemeral. This means that any data generated by containers running in the Pod also gets destroyed when the pod is destroyed. In Kubernetes, Volumes and Persistent Volumes help us solve this problem of data loss. Apart from this they also solve another problem - sharing of data between different containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Volumes
&lt;/h3&gt;

&lt;p&gt;There are a lot of &lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/#volume-types" rel="noopener noreferrer"&gt;volume types&lt;/a&gt; offered by Kubernetes. But thankfully as developers we mostly never have to worry about all this stuff. In this section, we’ll just cover a common volume type which you might run into - &lt;code&gt;emptyDir&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;emptyDir&lt;/code&gt; type has two important use cases. The first is that it allows us to share data between two containers running in the same pod. The second is that if our container ever crashes, it enables us to still retain all the data created previously. Do note that this volume only exists as long as the Pod is running. So if your pod is destroyed for any reason, you &lt;strong&gt;WILL&lt;/strong&gt; lose all the data. Let’s look at how volumes are configured for Pods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  volumes:
  - name: cache-volume
    emptyDir: {}
  containers:
  - image: nginx
    name: my-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the Pod &lt;code&gt;spec&lt;/code&gt; we first define our volumes in a list - in the above example we have one volume called &lt;code&gt;cache-volume&lt;/code&gt; which is of type &lt;code&gt;emptyDir&lt;/code&gt;. Then while specifying our containers we refer to this volume under &lt;code&gt;volumeMounts&lt;/code&gt;. &lt;code&gt;mountPath&lt;/code&gt; is where in the filesystem of the container the data from the volume should be loaded into.&lt;/p&gt;

&lt;h3&gt;
  
  
  Persistent Volumes
&lt;/h3&gt;

&lt;p&gt;We just learned that &lt;code&gt;emptyDir&lt;/code&gt; volumes won’t save our data if our Pod goes down. So you must be wondering how does one store data which persists regardless of any changes to the Pod. This is where Persistent Volumes come to save the day.&lt;/p&gt;

&lt;p&gt;A Persistent Volume (PV) is a cluster level storage object. What this means is that just like &lt;a href="//okteto.com/blog/getting-started-with-kubernetes-as-a-developer/#kubernetes-under-the-hood"&gt;nodes&lt;/a&gt;, it too is a resource present in the cluster. It is an administrator’s job to provision this so don’t worry too much about how it’s created. However, what we as developers should be familiar with is how to use this provisioned storage. &lt;/p&gt;

&lt;p&gt;To use a Persistent Volume, we create a Persistent Volume Claim (PVC) object and then refer to this claim under the &lt;code&gt;volumes&lt;/code&gt; key of the Pod YAML like we saw above. A PVC is nothing but a request for storage. This is how a basic PVC object would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you create this PVC, the Kubernetes control plane will &lt;em&gt;bind&lt;/em&gt; this claim to a suitable persistent volume for you. The above YAML should be pretty simple to understand, we’re requesting 3 Gigabyte of storage with the &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes" rel="noopener noreferrer"&gt;access mode&lt;/a&gt; of &lt;code&gt;ReadWriteOnce&lt;/code&gt;. What this means is that the volume can be mounted as a read-write storage but only by a single node. &lt;/p&gt;

&lt;p&gt;After you create the PVC, all that you need to do is refer to it in your Pod’s YAML as we did for &lt;code&gt;emptyDir&lt;/code&gt; above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec:
  volumes:
    - name: pv-storage
      persistentVolumeClaim:
        claimName: pv-claim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voilà! You now have a persistent storage solution for your application. Okteto gives you the ability to do a lot more with volumes including creating a data clone of your application's database and using it with your development environment. You can read up more on how to do that &lt;a href="https://okteto.com/blog/how-to-create-and-use-data-clones-in-okteto-cloud/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This concludes our discussion on configuration and storage in Kubernetes. We started by taking a look at ConfigMaps and Secrets and saw how they help provide us configuration data to our application. Then we looked at how we can leverage Volumes to safeguard our application data in case our container restarts. Finally, we looked at Persistent Volumes which provide us a way to persist data in a separate resource present in the cluster - thus ensuring that even Pod deletion doesn't lead to a loss of data. &lt;/p&gt;

&lt;p&gt;All of this does look intimidating at first but remember that you don’t have to fight these battles alone as a developer. If you’re using a managed Kubernetes environment like Okteto, most of this is already taken care of for you. If not, even then, you should be receiving support from the infra team. But like I said earlier, even as a developer it is good to have an idea of things so you’re not totally lost! In the &lt;a href="//okteto.com/blog/services-and-ingresses-in-kubernetes/"&gt;final article&lt;/a&gt; of this series, we’ll be taking a look at how networking works in Kubernetes so make sure to keep an eye out for that one! :D&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The "Kubernetes for Developers" blog series has now concluded, and you can find all the posts in this series &lt;a href="//okteto.com/blog/kubernetes-for-developers-blog-series-by-okteto/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>beginners</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Developing and Deploying a Helm Chart Application in Okteto</title>
      <dc:creator>Abdulazeez Abdulazeez</dc:creator>
      <pubDate>Mon, 07 Feb 2022 18:17:43 +0000</pubDate>
      <link>https://forem.com/okteto/developing-and-deploying-a-helm-chart-application-in-okteto-418c</link>
      <guid>https://forem.com/okteto/developing-and-deploying-a-helm-chart-application-in-okteto-418c</guid>
      <description>&lt;p&gt;Deploying applications in Kubernetes can be complicated. Even the simplest application could require creating a series of interdependent components (e.g., namespaces, RBAC rules, ingress, services, deployments, pods, secrets, etc.), each with one or more YAML manifests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://helm.sh/"&gt;Helm&lt;/a&gt; is the de-facto package manager for &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt; applications that allows developers and operators to easily package, configure, and deploy applications onto Kubernetes clusters. If you're building an application that will run in Kubernetes, you should really look into leveraging Helm.&lt;/p&gt;

&lt;p&gt;In this article, we'll show you how you can deploy a Helm chart powered application to Okteto, a Kubernetes powered service. We'll also show you how to push your application images to the &lt;a href="https://dev.to/docs/cloud/registry/"&gt;Okteto container registry&lt;/a&gt;, create and configure a helm chart, and then develop the deployed application using Okteto's remote development environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're a beginner to Kubernetes, check out our &lt;a href="https://dev.to/blog/getting-started-with-kubernetes-as-a-developer"&gt;Kubernetes For Developers series&lt;/a&gt; aimed at beginners. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;In order to follow this tutorial, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An Okteto Cloud Account (It's free!)&lt;/li&gt;
&lt;li&gt;Some &lt;a href="https://dev.to/blog/getting-started-with-kubernetes-as-a-developer"&gt;familiarity with Kubernetes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install Helm
&lt;/h2&gt;

&lt;p&gt;We'll be needing the Helm command line tool to create and deploy our application. &lt;/p&gt;

&lt;h3&gt;
  
  
  For MacOS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For Linux
&lt;/h3&gt;

&lt;p&gt;Debian/Ubuntu&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl https://baltocdn.com/helm/signing.asc | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;apt-transport-https &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb https://baltocdn.com/helm/stable/debian/ all main"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/helm-stable-debian.list
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For Windows
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;choco &lt;span class="nb"&gt;install &lt;/span&gt;kubernetes-helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building a helm powered application
&lt;/h2&gt;

&lt;p&gt;In this section, we'll create a helm chart to enable us to deploy an already built application. Unlike a docker-compose powered application, helm chart powered applications can not be deployed using the &lt;code&gt;okteto stack deploy&lt;/code&gt; command. Helm powered applications also depend on prebuilt container images, so we'll have to build and push our images to a registry too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clone the application
&lt;/h3&gt;

&lt;p&gt;In your terminal, clone the GitHub repository and make it the working directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git clone &lt;span class="nt"&gt;-b&lt;/span&gt; default https://github.com/okteto/recipe-app
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;recipe-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the folder, we have an application prebuilt alongside a Dockerfile. As it stands, there is no manifest readily available for deploying the application to Kubernetes. We are going to create a helm chart for the application but before then, let's build the image and push it to Okteto's build registry.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the application image
&lt;/h3&gt;

&lt;p&gt;We will be building the image for this application from the Dockerfile to &lt;a href="https://dev.to/docs/cloud/registry/"&gt;Okteto's container registry&lt;/a&gt;. Before building the image, set the Okteto context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;okteto context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, run the command to build the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;okteto build &lt;span class="nt"&gt;-t&lt;/span&gt; okteto.dev/recipe-app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command above builds and pushes the application's image allowing us to pull this image from our namespace easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a helm chart
&lt;/h3&gt;

&lt;p&gt;To create a helm chart, we'll use the Helm command-line tool. In the application directory, run the command to create the helm chart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;helm create charts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command above creates a new folder containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;chart/
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│     └── test-connection.yaml
└── values.yaml
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Chart.yaml&lt;/code&gt; contains basic information about the Helm Chart. Change the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; to:&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;recipe-app&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;A recipe application built on FastAPI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the list of files above, we're majorly concerned with &lt;code&gt;_helpers.tpl&lt;/code&gt;, &lt;code&gt;service.yaml&lt;/code&gt;, &lt;code&gt;deployment.yaml&lt;/code&gt; and &lt;code&gt;values.yaml&lt;/code&gt; in this article.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;_helpers.tpl&lt;/code&gt; contains variables to be defined in our normal k8s manifest. Instead of repeating variables such as annotations, labels, etc., in multiple manifests, they are placed in the &lt;code&gt;_helpers.tpl&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Update the &lt;code&gt;_helpers.tpl&lt;/code&gt; file to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{/*
Expand the name of the chart.
*/}}
{{- define "chart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "chart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "chart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "chart.labels" -}}
helm.sh/chart: {{ include "chart.chart" . }}
app.kubernetes.io/name: {{ include "chart.name" . }}
{{ include "chart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "chart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "chart.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "chart.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;deployment.yaml&lt;/code&gt; manifest contains the instructions for deploying your application to Kubernetes. It comes prefilled and fetches the values from the &lt;code&gt;_helpers.tpl&lt;/code&gt; and &lt;code&gt;values.yaml&lt;/code&gt; file. Update the &lt;code&gt;containerPort&lt;/code&gt; in the &lt;code&gt;container&lt;/code&gt; section to 8080:&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;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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Chart.Name&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
    &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;- toYaml .Values.securityContext | nindent 12&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Values.image.repository&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}:{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Values.image.tag&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Chart.AppVersion&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
    &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.image.pullPolicy&lt;/span&gt; &lt;span class="pi"&gt;}}&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&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="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, let's look into the &lt;code&gt;values.yaml&lt;/code&gt; file. This stores the image name, replica count, service configuration data, etc. Update the image repository and tag value from:&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;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;pullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IfNotPresent&lt;/span&gt;
  &lt;span class="c1"&gt;# Overrides the image tag whose default is the chart appVersion.&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to&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;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$IMAGE_REGISTRY/recipe-app&lt;/span&gt;
  &lt;span class="na"&gt;pullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IfNotPresent&lt;/span&gt;
  &lt;span class="c1"&gt;# Overrides the image tag whose default is the chart appVersion.&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code block above, replace &lt;code&gt;$IMAGE_REGISTRY&lt;/code&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;okteto.dev/recipe-app&lt;/code&gt; if you used the Okteto registry&lt;/li&gt;
&lt;li&gt;Your docker hub username if you pushed your image to docker hub.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, under the &lt;code&gt;serviceAccount&lt;/code&gt; heading, set the &lt;code&gt;create&lt;/code&gt; variable to &lt;code&gt;false&lt;/code&gt; as we're not interested in creating a &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"&gt;service account&lt;/a&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;serviceAccount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Specifies whether a service account should be created&lt;/span&gt;
  &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
  &lt;span class="c1"&gt;# Annotations to add to the service account&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="c1"&gt;# The name of the service account to use.&lt;/span&gt;
  &lt;span class="c1"&gt;# If not set and create is true, a name is generated using the fullname template&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, change the service type and port to:&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;service&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="na"&gt;port&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;We have successfully configured our application's helm chart. The next step is to deploy it to Okteto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying to Okteto
&lt;/h3&gt;

&lt;p&gt;To deploy our application to Okteto, return to the base directory in your terminal and run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;recipe-app chart/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get a response from the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;NAME: recipe-app
LAST DEPLOYED: Mon Dec 13 19:09:29 2021
NAMESPACE: youngestdev
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
&lt;/span&gt;&lt;span class="gp"&gt;  export NODE_PORT=$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;kubectl get &lt;span class="nt"&gt;--namespace&lt;/span&gt; youngestdev &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.spec.ports[0].nodePort}"&lt;/span&gt; services recipe-app-chart&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;  export NODE_IP=$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;kubectl get nodes &lt;span class="nt"&gt;--namespace&lt;/span&gt; youngestdev &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.items[0].status.addresses[0].address}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;  echo http://$&lt;/span&gt;NODE_IP:&lt;span class="nv"&gt;$NODE_PORT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells us our application has been deployed. In our &lt;a href="https://cloud.okteto.com"&gt;Okteto dashboard&lt;/a&gt;, we can see the deployed application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SV4-bZAI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.okteto.com/static/8a2ffb0762cf67edb79f7ffa08645615/4b39a/deployed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SV4-bZAI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.okteto.com/static/8a2ffb0762cf67edb79f7ffa08645615/4b39a/deployed.png" alt="Deployed Helm Chart" width="880" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Development environments for Helm applications
&lt;/h2&gt;

&lt;p&gt;Helm chart powered applications can also be remotely developed in Okteto. Let's create a &lt;a href="https://okteto.com/docs/reference/development-environment/"&gt;development container&lt;/a&gt; to verify this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;okteto init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select the deployed application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt; i  Using youngestdev @ cloud.okteto.com as context
This command walks you through creating an okteto manifest.
It only covers the most common items, and tries to guess sensible defaults.
See https://okteto.com/docs/reference/manifest/ for the official documentation about the okteto manifest.
Use the arrow keys to navigate: ↓ ↑ → ←
Select the resource you want to develop:
  ▸ recipe-app-chart
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;okteto.yml&lt;/code&gt; manifest is created and we can start our development container by running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;okteto up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt; i  Using youngestdev @ cloud.okteto.com as context
 ✓  Persistent volume successfully attached
 ✓  Images successfully pulled
 ✓  Files synchronized
    Context:   cloud.okteto.com
    Namespace: youngestdev
    Name:      recipe-app-chart
&lt;/span&gt;&lt;span class="gp"&gt;    Forward:   8080 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;8080
&lt;span class="go"&gt;    Reverse:   9000 &amp;lt;- 9000

&lt;/span&gt;&lt;span class="gp"&gt;root@recipe-app-chart-okteto-c88fff58f-pt8c8:/app#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have verified that our application can indeed be developed locally. In our dashboard, the state of the application has changed to &lt;strong&gt;In Development&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h_LQ1Oif--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.okteto.com/static/aa0c09304cccda2d451168138e0a60aa/fa65c/development.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h_LQ1Oif--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.okteto.com/static/aa0c09304cccda2d451168138e0a60aa/fa65c/development.png" alt="Development mode" width="880" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start our application remotely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO:     Started reloader process [80] using statreload
INFO:     Started server process [82]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HyUZcI7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/original.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HyUZcI7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/original.png" alt="Development mode application" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The development environment updates the application on every file change. Let's change the welcome message in &lt;code&gt;app/api.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Root"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_root&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Welcome to your Okteto app powered by Helm charts live in development mode!"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okteto automatically synchronizes the changes, and the application is now updated:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DhgtSkT8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.okteto.com/static/51f1a4512bf5ec586524a6b28add0b11/4b39a/updated.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DhgtSkT8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.okteto.com/static/51f1a4512bf5ec586524a6b28add0b11/4b39a/updated.png" alt="Updated" width="880" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have successfully deployed a helm chart powered application as well as developed it using Okteto's remote development environment.&lt;/p&gt;

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

&lt;p&gt;In this article, you learned how to build an application's image and push it to Okteto's build registry and docker hub. You also learned how to create helm charts for your application for deployments to Kubernetes. The application deployed using helm charts was also developed remotely by creating a development environment in Okteto.&lt;/p&gt;

&lt;p&gt;Sign up on &lt;a href="https://okteto.com"&gt;Okteto&lt;/a&gt; today to improve your development process experience using development environments and preview environmemts!&lt;/p&gt;

&lt;p&gt;The code used for this article can be found on &lt;a href="https://github.com/okteto/recipe-app"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>cloud</category>
      <category>kubernetes</category>
      <category>helm</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>Developing a Rasa chatbot in Okteto</title>
      <dc:creator>Abdulazeez Abdulazeez</dc:creator>
      <pubDate>Mon, 07 Feb 2022 18:16:52 +0000</pubDate>
      <link>https://forem.com/okteto/developing-a-rasa-chatbot-in-okteto-5dma</link>
      <guid>https://forem.com/okteto/developing-a-rasa-chatbot-in-okteto-5dma</guid>
      <description>&lt;p&gt;&lt;a href="https://rasa.com/" rel="noopener noreferrer"&gt;Rasa&lt;/a&gt; is a Python framework for training and building an AI-powered chatbot integrated into various platforms.&lt;/p&gt;

&lt;p&gt;Training and building AI-powered applications such as chatbots can be expensive. It requires high computational power and supported firmware. Okteto provides you with a development environment where you can train, build and deploy your models &lt;strong&gt;remotely&lt;/strong&gt; on the Cloud.&lt;/p&gt;

&lt;p&gt;In this article, we’ll show you how you can build a simple rasa chatbot, Oktebot, remotely in Okteto.&lt;/p&gt;

&lt;p&gt;Want to see this built live? Watch the recorded live-stream on our &lt;a href=""&gt;Youtube channel!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An Okteto Cloud account (It’s free! )&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://okteto.com/docs/getting-started/installation/" rel="noopener noreferrer"&gt;Okteto CLI&lt;/a&gt; installed&lt;/li&gt;
&lt;li&gt;Basic knowledge of Python&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up
&lt;/h2&gt;

&lt;p&gt;We’ll start by creating a project directory to house our application:&lt;/p&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;oktebot
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;oktebot


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Building Oktebot in Okteto’s development environment
&lt;/h2&gt;

&lt;p&gt;Now that we have created the project directory, the next step is to sign in to our Okteto account via Okteto CLI from our local terminal:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;okteto context use https://cloud.okteto.com
&lt;span class="go"&gt;

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

&lt;/div&gt;

&lt;p&gt;In the project directory, we’ll create an Okteto manifest as the first step in creating our development container:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;okteto init
&lt;span class="go"&gt;

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

&lt;/div&gt;

&lt;p&gt;The first prompt asks us to select the language we'll be working with:&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%2Fwww.okteto.com%2Fstatic%2F43ba25f1fb85852ad2e8d0bbc2ad712d%2F1132d%2Flanguage.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%2Fwww.okteto.com%2Fstatic%2F43ba25f1fb85852ad2e8d0bbc2ad712d%2F1132d%2Flanguage.png" alt="Select a language"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is to enable Okteto provide the necessary toolings for our remote development session.&lt;/p&gt;

&lt;p&gt;In the prompt from the command above, select &lt;strong&gt;Use default values&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

Select the resource you want to develop:
  ▸ Use default values


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

&lt;/div&gt;

&lt;p&gt;In the newly created manifest file, &lt;code&gt;okteto.yml&lt;/code&gt;, modify the image name:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

image: rasa/rasa


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

&lt;/div&gt;

&lt;p&gt;We have successfully created the manifest file. The next step is to start our development container and select Python as the default language in the prompt:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;okteto up
&lt;span class="go"&gt;

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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;okteto up&lt;/code&gt; command creates a new development container in your dashboard from the parameters included in the &lt;code&gt;okteto.yml&lt;/code&gt; manifest file and then starts a remote development session:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;


i  Using youngestdev @ cloud.okteto.com as context
 ✓  Persistent volume successfully attached
 ✓  Images successfully pulled
 ✓  Files synchronized
    Context:   cloud.okteto.com
    Namespace: youngestdev
    Name:      oktebot
&lt;/span&gt;&lt;span class="gp"&gt;    Forward:   8080 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;8080
&lt;span class="go"&gt;    Reverse:   9000 &amp;lt;- 9000

&lt;/span&gt;&lt;span class="gp"&gt;root@oktebot-okteto-7bbddd5c59-d7bmx:~#&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="go"&gt;

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

&lt;/div&gt;

&lt;p&gt;In the remote development container, we’ll create a new rasa bot in the project directory:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

&lt;/span&gt;&lt;span class="gp"&gt;root@oktebot-okteto-7bbddd5c59-d7bmx:~#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rasa init
&lt;span class="go"&gt;

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

&lt;/div&gt;

&lt;p&gt;In the prompt in the remote terminal, select the current directory and train the initial model:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

? Please enter a path where the project will be created [default: current direct
ory] 
? Directory’/app’ is not empty. Continue? (Y/n) Y
? Do you want to train an initial model? Y


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

&lt;/div&gt;

&lt;p&gt;Once the training is complete, the rasa tool prompts us to ask if we’d like to speak to the trained assistant:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

Do you want to speak to the trained assistant on the command line? Y


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

&lt;/div&gt;

&lt;p&gt;Let’s speak with the trained assistant:&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%2Fwww.okteto.com%2Fstatic%2F13e47bac6036468aa781ebab6734db37%2F4352a%2Fdefault.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%2Fwww.okteto.com%2Fstatic%2F13e47bac6036468aa781ebab6734db37%2F4352a%2Fdefault.png" alt="Default assistant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Training Oktebot
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;data&lt;/code&gt; folder contains our bot's training data and responses in our project folder. There are three files currently present:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;nlu.yml&lt;/code&gt;: This file contains the sample data for Natural Language Understanding.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stories.yml&lt;/code&gt;: This file includes example conversations with the bot to train the assistant to respond correctly depending on the preceding text.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;domain.yml&lt;/code&gt;: This file defines the scenario in which the bot acts. This file defines intents from our NLU files and accompanying responses.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that we have successfully created our chatbot, let’s train the bot with our data. In the &lt;code&gt;data&lt;/code&gt; folder, create two new files from your remote development container terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

&lt;/span&gt;&lt;span class="gp"&gt;root@oktebot-okteto-7bbddd5c59-d7bmx:~#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;chat,faq&lt;span class="o"&gt;}&lt;/span&gt;.yml
&lt;span class="go"&gt;

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

&lt;/div&gt;

&lt;p&gt;The newly created files will contain the intent and examples for training our bot similar to &lt;code&gt;nlu.yml&lt;/code&gt;. The &lt;code&gt;chat.yml&lt;/code&gt; file will house the intent for when a user starts a conversation with the bot, and &lt;code&gt;faq.yml&lt;/code&gt; will contain the training data for when a user asks a question.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;chat.yml&lt;/code&gt; file, add the following:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.0"&lt;/span&gt;

&lt;span class="na"&gt;nlu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chat/hello&lt;/span&gt;
    &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;- How can we help&lt;/span&gt;
      &lt;span class="s"&gt;- we're glad we can help&lt;/span&gt;
      &lt;span class="s"&gt;- please hold on while I get you an engineer&lt;/span&gt;
      &lt;span class="s"&gt;- glad you love okteto&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chat/bye&lt;/span&gt;
    &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;- do come back next time&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chat/sales&lt;/span&gt;
    &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;- the sales rep will respond in a moment&lt;/span&gt;
      &lt;span class="s"&gt;- you can pay using your credit card too&lt;/span&gt;
      &lt;span class="s"&gt;- schedule a meeting with our sales team&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the code block above, we have defined three conversation intents in our chatbot. The examples listed are used to train the bot to respond appropriatelys to a similar message.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;faq.yml&lt;/code&gt;, add the following:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.0"&lt;/span&gt;

&lt;span class="na"&gt;nlu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq/more_resources&lt;/span&gt;
    &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;- how much does the developer pro plan cost&lt;/span&gt;
      &lt;span class="s"&gt;- I'll like to increase my bandwidth&lt;/span&gt;
      &lt;span class="s"&gt;- What plans can give more benefit than the free plan&lt;/span&gt;
      &lt;span class="s"&gt;- I'm hitting my limits easily. What can I do&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq/plan_expires&lt;/span&gt;
    &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;- what happens after my plan expires&lt;/span&gt;
      &lt;span class="s"&gt;- can i renew my subscription&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq/application_status&lt;/span&gt;
    &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;- what happens to my applications after 24 hours&lt;/span&gt;
      &lt;span class="s"&gt;- how can i check my deployment&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq/restart_application&lt;/span&gt;
    &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;- how can i restart my application&lt;/span&gt;
      &lt;span class="s"&gt;- my application is asleep&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the code block above, we have defined three frequently asked questions ( FAQ ) intents in our chatbot. The examples listed are used to train the bot to respond to a similar message properly.&lt;/p&gt;

&lt;p&gt;With the natural learning understanding files populated, let’s update the &lt;code&gt;rules.yml&lt;/code&gt; guiding the chatbot. In &lt;code&gt;rules.yml&lt;/code&gt;, add the following:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.0"&lt;/span&gt;

&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Say goodbye anytime the user says goodbye&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;goodbye&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_goodbye&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_faq&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chat&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chat&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_chat&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Lastly, let’s update the stories in &lt;code&gt;stories.yml&lt;/code&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.0"&lt;/span&gt;

&lt;span class="na"&gt;stories&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;story&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;greet&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_greet&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;faq&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_faq&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;story&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chat&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;greet&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_greet&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chat&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_chat&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;To wrap up the training data, let’s update the &lt;code&gt;domain.yml&lt;/code&gt; file in the project directory:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.0"&lt;/span&gt;

&lt;span class="na"&gt;intents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;greet&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chat&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;goodbye&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;affirm&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deny&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;faq&lt;/span&gt;

&lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;utter_greet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hi!&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;How&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;help&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;today?"&lt;/span&gt;

  &lt;span class="na"&gt;utter_chat/hello&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hi,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;welcome&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Oktebot.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;How&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;may&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;be&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;help?"&lt;/span&gt;

  &lt;span class="na"&gt;utter_chat/bye&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Thanks&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;stopping&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by!"&lt;/span&gt;

  &lt;span class="na"&gt;utter_chat/sales&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sales&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;rep&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;will&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;respond&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;moment"&lt;/span&gt;

  &lt;span class="na"&gt;utter_cheer_up&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;We&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;hope&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;enjoy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Okteto&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;platform!"&lt;/span&gt;

  &lt;span class="na"&gt;utter_did_that_help&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Did&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;help&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you?"&lt;/span&gt;

  &lt;span class="na"&gt;utter_happy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Great,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;carry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on!"&lt;/span&gt;

  &lt;span class="na"&gt;utter_goodbye&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bye.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;See&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;soon!"&lt;/span&gt;

  &lt;span class="na"&gt;utter_faq/more_resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;request&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;more&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;resources&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;either&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;changing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;contacting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;team&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;at&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;support@okteto.com"&lt;/span&gt;

  &lt;span class="na"&gt;utter_faq/plan_expires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;account&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;automatically&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;reverts&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;developer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;once&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;previous&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;expires.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;renew&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;avoid&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that"&lt;/span&gt;

  &lt;span class="na"&gt;utter_faq/application_status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;application&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;automatically&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;goes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sleep&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;24&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;hours&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;inactivity&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;only"&lt;/span&gt;

  &lt;span class="na"&gt;utter_faq/restart_application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;restart&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;application&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dashboard&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;wake&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;them&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;visiting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;endpoint"&lt;/span&gt;

&lt;span class="na"&gt;session_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;session_expiration_time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
  &lt;span class="na"&gt;carry_over_slots_to_new_session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;By updating the &lt;code&gt;domain.yml&lt;/code&gt;, we have updated the intent and responses our bot returns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retraining our bot
&lt;/h3&gt;

&lt;p&gt;After populating our sample training data, the next step is to train the bot. Run the command in your development environment shell:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

&lt;/span&gt;&lt;span class="gp"&gt;root@oktebot-okteto-7bbddd5c59-d7bmx:~#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rasa train
&lt;span class="go"&gt;Your Rasa model is trained and saved at 'models/20220113-053154-formal-sequence.tar.gz'.


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

&lt;/div&gt;

&lt;p&gt;Now that we have retrained our bot, we can test it from the shell:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

&lt;/span&gt;&lt;span class="gp"&gt;root@oktebot-okteto-7bbddd5c59-d7bmx:~#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rasa shell
&lt;span class="go"&gt;

&lt;/span&gt;&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%2Fwww.okteto.com%2Fstatic%2F12e9fffeea267ee5a8590963b5c96035%2F497e9%2Foktebot.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%2Fwww.okteto.com%2Fstatic%2F12e9fffeea267ee5a8590963b5c96035%2F497e9%2Foktebot.png" alt="Oktebot in action."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have interacted with the bot in the screenshot above, and it works according to the trained data. We can now exit the development container and start it whenever we introduce a model before deploying it.&lt;/p&gt;

&lt;p&gt;The chatbot files created in our development environment are now available locally. This is as a result of the &lt;a href="https://okteto.com/docs/reference/file-synchronization/" rel="noopener noreferrer"&gt;synchronization feature&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;This article taught you how to train, build, and test a Rasa chatbot remotely using Okteto’s development environment. You also learned how Okteto synchronizes from the development environment to your local environment and vice versa.&lt;/p&gt;

&lt;p&gt;Now that you have learned how to train and develop a rasa chatbot in Okteto, create a personal virtual assistant using rasa in Okteto and share it with us on our &lt;a href="https://kubernetes.slack.com/messages/CM1QMQGS0/" rel="noopener noreferrer"&gt;slack channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sign up on &lt;a href="https://okteto.com" rel="noopener noreferrer"&gt;Okteto&lt;/a&gt; today to improve your development process experience using development environments and preview environmemts!&lt;/p&gt;

&lt;p&gt;You can find the code used for this article on &lt;a href="https://github.com/okteto/oktebot/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rasa</category>
      <category>kubernetes</category>
      <category>chatbot</category>
      <category>ai</category>
    </item>
    <item>
      <title>Fundamental Kubernetes Concepts Everyone Needs To Know</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Wed, 02 Feb 2022 14:30:08 +0000</pubDate>
      <link>https://forem.com/okteto/fundamental-kubernetes-concepts-everyone-needs-to-know-mm7</link>
      <guid>https://forem.com/okteto/fundamental-kubernetes-concepts-everyone-needs-to-know-mm7</guid>
      <description>&lt;p&gt;Ready to get your hands dirty and start using Kubernetes? If you recall, in the &lt;a href="//okteto.com/blog/getting-started-with-kubernetes-as-a-developer/"&gt;last article&lt;/a&gt; we talked about what K8s is and how it works internally. Let’s see Kubernetes in action in this one!&lt;/p&gt;

&lt;p&gt;In the Kubernetes world everything is an object. To put simply, an object is something you create in Kubernetes to give it a configuration of sorts so that it knows how to run and serve your application. Once you create K8s objects describing your application, the &lt;a href="//okteto.com/blog/getting-started-with-kubernetes-as-a-developer/#kubernetes-under-the-hood"&gt;controllers&lt;/a&gt; work to ensure that the object's current state matches the described desired state.&lt;/p&gt;

&lt;p&gt;There are many Kubernetes objects, some of which you already would have come across if you tried the Okteto &lt;a href="//okteto.com/docs/getting-started/"&gt;Quick Start Guide&lt;/a&gt;. We’ll talk about three very important objects in this article: Pods, Deployments, and Namespaces. Trying out the things mentioned in this tutorial series yourself is highly recommended if you really want to be comfortable using K8s. In case you're looking to get that hands-on experience with these concepts without having to do the setup work - don't worry we've got you covered for free with &lt;a href="https://cloud.okteto.com/" rel="noopener noreferrer"&gt;Okteto Cloud&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Pods
&lt;/h2&gt;

&lt;p&gt;Pods are the smallest and most fundamental of objects in Kubernetes. Instead of running containers directly on &lt;a href="//okteto.com/blog/getting-started-with-kubernetes-as-a-developer/#kubernetes-under-the-hood"&gt;nodes&lt;/a&gt;, Kubernetes runs them inside pods. So think of a pod basically as a wrapper for your containers. A pod usually runs a single container but it can have multiple containers too. What's important to remember is that all the containers of a pod will run on the same node, sharing the same network and resources. Another important thing to remember about Pods is that they are immutable. While you can change the image being used to run the container in the Pod, you can not update fields like the Pod name or the &lt;a href="https://www.okteto.com/blog/fundamental-kubernetes-concepts-everyone-needs-to-know/#namespaces" rel="noopener noreferrer"&gt;namespace&lt;/a&gt; it’s in.&lt;/p&gt;

&lt;p&gt;You would usually containerize your application's front-end and back-end parts and have these containers run in separate pods. This is what we saw in the &lt;a href="//okteto.com/docs/getting-started/"&gt;Quick Start Guide&lt;/a&gt;. If you open a terminal and run&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;you would see these pods. Additionally, you’ll see another pod running a MongoDB container which is used as the database for our application.&lt;/p&gt;

&lt;p&gt;Each pod has a unique IP address assigned to it. While you can’t ping this IP address from outside the cluster, it can be pinged from within.&lt;/p&gt;

&lt;p&gt;Let’s do something exciting shall we? Let’s launch a pod and use that to ping our existing frontend pod. To create an object in Kubernetes, a Pod in this case, there are two ways: declarative and imperative. The declarative way involves writing a YAML file describing the object, whereas the imperative way involves using kubectl. &lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;kubectl&lt;/a&gt; is a command-line tool that allows you to talk to your Kubernetes cluster. Let’s use the imperative way here and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl run temp-pod --image=busybox -it -- /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command does a couple of things for us. &lt;code&gt;kubectl run&lt;/code&gt; creates a Pod named “temp-pod” and runs a container inside it using the “busybox” image. The &lt;code&gt;-it&lt;/code&gt; is used to give us access to a shell inside this Pod and we also specify that we want to run &lt;code&gt;/bin/sh&lt;/code&gt; as the first command in this shell. You should also be able to see this pod on your Okteto dashboard. Now let us get the IP address of the frontend pod so we can ping it. To do that, in another terminal, run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;kubectl get&lt;/code&gt; command can be used to get all kubernetes objects of a particular type. Here we use it to get all pods. The &lt;code&gt;-o wide&lt;/code&gt; flag tells it to provide us with even more details like the IP addresses of the Pods. Once you copy the IP address of the pod, go back to the shell inside the “temp-pod” and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget -O- &amp;lt;IP Address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see an output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connecting to 10.8.6.136 (10.8.6.136:80)
writing to stdout
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Movies&amp;lt;/title&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/&amp;gt;
  &amp;lt;link rel="icon" href="favicon.png"&amp;gt;&amp;lt;script defer src="app.770412f1098441c2c698.js"&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
-                    100% |************************************************************************************************************|   353  0:00:00 ETA
written to stdout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How cool, right? To destroy this pod you can simply select it in your Dashboard and click on “Destroy”. If you want to go the &lt;code&gt;kubectl&lt;/code&gt; route then you can run &lt;code&gt;kubectl delete pod temp-pod&lt;/code&gt; in your terminal. The &lt;code&gt;kubectl delete&lt;/code&gt; command works for all Kubernetes objects and takes in the object type and object name as arguments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fg9pqjg7jp3rnqsvdfvoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fg9pqjg7jp3rnqsvdfvoa.png" alt="destroy a pod using the button in the okteto dashboard" width="745" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployments
&lt;/h2&gt;

&lt;p&gt;So you might be wondering why Kubernetes doesn’t run containers directly instead of running Pods. This is because Pods are meant to be ephemeral and having containers in Pods enables easy replication - which is one of the most important features of K8s.&lt;/p&gt;

&lt;p&gt;A single pod is just meant to run a single instance of your application. You would never create individual pods to serve your application. Why? Because that would mean if the traffic suddenly increases, your Pod will run out of resources and you will face downtime. Instead you create a bunch of identical pods. If one of these pods goes down or the traffic increases and you need more pods, Kubernetes will itself bring up more pods. This management of multiple similar pods is done by the deployment controller when you create a Deployment object.&lt;/p&gt;

&lt;p&gt;I think you can now see now why it’s recommended to create a Deployment instead of Pods. The Deployment object will further create and manage the Pods for you. If you look closely at your dashboard you’ll see that &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;frontend&lt;/code&gt; are actually Deployments. This is why when you did &lt;code&gt;kubectl get pods&lt;/code&gt; the pods were not called &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;frontend&lt;/code&gt; and instead had some random string added to the end. This helps tell that the pods were created by the deployment and not us directly.&lt;/p&gt;

&lt;p&gt;Let’s not take my word for it and verify that Pods are indeed actually managed by their Deployments :)&lt;/p&gt;

&lt;p&gt;Go to your terminal and see the name of the pod created by the api deployment. After that delete the pod by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl delete pod &amp;lt;api pod name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;kubectl get pods&lt;/code&gt; again and you’ll see that another pod is coming up in its place with a different name. This is because Okteto told Kubernetes to create a deployment which ensures that one api pod runs at all times. You can also see this in the YAML used to create the deployment from your dashboard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fib0aab6vpuun10opxi0y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fib0aab6vpuun10opxi0y.png" alt="see the number of replicas in the okteto dashboard" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Namespaces
&lt;/h2&gt;

&lt;p&gt;If you took a closer look at your Okteto dashboard, you’d see that there is something called “Namespace” in the top right corner. If you click that, you’ll also see the option to create a new namespace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsk0knkfq78gcx28uhqnt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsk0knkfq78gcx28uhqnt.png" alt="create a new namespace directly okteto dashboard" width="594" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Namespaces in Kubernetes are a way to partition your cluster into multiple virtual clusters. You always deploy K8s objects (like Pods, Deployments, etc) in a particular namespace. Deploying different objects in different namespaces allows you to isolate different projects on the same cluster.&lt;/p&gt;

&lt;p&gt;Let’s see this in action. Click on “New Namespace” in the dropdown shown above and enter a name - I’m going to go with “golang-rinkiyakedad”. Now switch to this namespace from the same menu and deploy using the same steps you followed in the &lt;a href="//okteto.com/docs/getting-started/index.html#step-1-deploy-the-movies-app"&gt;Quick Start Guide&lt;/a&gt;, except that use &lt;a href="https://github.com/okteto/go-getting-started" rel="noopener noreferrer"&gt;https://github.com/okteto/go-getting-started&lt;/a&gt; as the repository URL this time.&lt;/p&gt;

&lt;p&gt;Once the deployment process is complete, head over to the URL shown under “Endpoints” in the dashboard and you should see a webpage showing “Hello world!”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F32e3ur3ajplf3dz821b3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F32e3ur3ajplf3dz821b3.png" alt="see the application's endpoints directly okteto dashboard" width="742" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means you can now work on two completely different projects and both are running on the same cluster. Pretty cool, right? When using Kubernetes directly, we specify the namespace under the &lt;code&gt;metadata&lt;/code&gt; section of an object’s YAML. You can see this by selecting the “hello-world” deployment and seeing its YAML:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fh2bepce84kh99c3soq5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fh2bepce84kh99c3soq5u.png" alt="see the application's yaml directly okteto dashboard" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read more about how to manage your namespaces in Okteto by heading over to the &lt;a href="//okteto.com/docs/cloud/namespaces/"&gt;Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So this was it for this article, we started by taking a look at the most fundamental Kubernetes object - Pods. From there we discussed how serving your application using a single pod is not ideal and how you should be leveraging the Deployment object for this instead. Finally, we took a look at Namespaces and saw how they allow you to divide up your Kubernetes cluster and enable deploying multiple different applications. I hope you now have a much better idea about these three very important Kubernetes objects!&lt;/p&gt;

&lt;p&gt;In the &lt;a href="//okteto.com/blog/configuration-and-storage-in-kubernetes/"&gt;next article&lt;/a&gt;, we’ll see how storage works in K8s clusters and take a look at some other important Kubernetes objects. Until then, feel free to &lt;a href="//okteto.com/docs/getting-started/#step-4-activate-your-development-container"&gt;experiment&lt;/a&gt; with the apps we deployed on Kubernetes in this article :)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The "Kubernetes for Developers" blog series has now concluded, and you can find all the posts in this series &lt;a href="//okteto.com/blog/kubernetes-for-developers-blog-series-by-okteto/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>kubernetes</category>
      <category>docker</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Getting Started with Kubernetes as a Developer</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Thu, 27 Jan 2022 15:45:00 +0000</pubDate>
      <link>https://forem.com/okteto/getting-started-with-kubernetes-as-a-developer-2jea</link>
      <guid>https://forem.com/okteto/getting-started-with-kubernetes-as-a-developer-2jea</guid>
      <description>&lt;p&gt;Are you tired of listening to everyone in DevOps talk about “Kubernetes” while you're still struggling with how to pronounce it? Unless you started programming today, I’m pretty sure you have heard the word but most likely as a developer you haven’t gotten the chance to learn about it - maybe because it seems intimidating or maybe because you aren’t sure how it’s useful for you. &lt;/p&gt;

&lt;p&gt;Let me take you on a journey from being a developer clueless about Kubernetes to one who can understand all the mumbo jumbo the infra team talks about. In the process, you’ll also start appreciating its beauty and usefulness in increasing developer productivity. We’ve got a lot to cover over the course of this series, so let’s jump right in!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Death Of “It Works On My Machine!”
&lt;/h2&gt;

&lt;p&gt;It's important to have an understanding of containers before talking about Kubernetes. Containers are executable packages of software that contain all the code and dependencies necessary to run an application anywhere. And by anywhere I literally mean anywhere - my laptop, your laptop or even on “the cloud”. &lt;/p&gt;

&lt;p&gt;Are containers starting to sound similar to virtual machines? Well they're not, and in fact they're even better! Why? Because unlike VMs, containers do not contain operating system images. This means they're much more lightweight! To create and run containers locally you would use a container engine like Docker.&lt;/p&gt;

&lt;p&gt;Containers grew in popularity because they truly embraced the ideology of write once, run anywhere. Because of how fast and easy it is to deploy containers, they increased developer productivity significantly. A fun fact is that &lt;a href="https://www.okteto.com/docs/getting-started/#step-4-activate-your-development-container" rel="noopener noreferrer"&gt;Okteto also utilizes these containers&lt;/a&gt; to give you a live preview of the changes you make while developing locally. &lt;/p&gt;

&lt;p&gt;But as more and more companies started using containers a new problem arose. How do you manage thousands of containers running on distributed systems? And that’s where Kubernetes saved the day!&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes To The Rescue!
&lt;/h2&gt;

&lt;p&gt;Kubernetes, often abbreviated as K8s, is a container orchestration platform. Let me explain this in very simple terms. &lt;/p&gt;

&lt;p&gt;Let’s say you have your app which you have containerized. So you run a bunch of containers to serve your app to users. But how do you manage these different containers? The situation is complicated even more by the fact that these containers needn’t necessarily be running on the same machine!&lt;/p&gt;

&lt;p&gt;This is where K8s comes to the rescue. It makes deploying, managing, and scaling containerized workloads a breeze! I want to explicitly call out here that K8s is NOT a &lt;strong&gt;container engine&lt;/strong&gt; like Docker. Rather it is a &lt;strong&gt;container orchestrator&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;As a developer you won’t need to worry about “how” K8s does all this orchestration. You probably also will not have to set up a K8s cluster for your application. But what you would mostly be doing is interacting with a cluster set up for you by the infrastructure team. So it becomes important to be familiar with the K8s objects you’ll be interacting with. That’s what we’ll be focusing on in the articles in this series. &lt;/p&gt;

&lt;p&gt;Before we do that, let’s have a high level idea about the architecture of Kubernetes so that you’re not totally clueless about what is happening under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes Under The Hood
&lt;/h2&gt;

&lt;p&gt;In the Kubernetes world a machine is called a node. A K8s “cluster” is nothing but a group of nodes that run your containerized application. These nodes may be bare metal servers in your home or instances you’re running on a cloud provider. These nodes are also of two types: worker and master. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fvv3le95opsouom96u55w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvv3le95opsouom96u55w.png" alt="The different types of nodes" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The worker nodes are the ones where your application’s containers would actually be running. Kubernetes actually uses an object called Pod to run these containers but more on that in the next article. Three essential things running on a worker node in a Kubernetes cluster are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Container runtime: This should be no surprise since a container runtime is what is actually responsible for running containers. Kubernetes supports multiple container runtimes including Docker and containerd.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kubelet: This is the agent which is responsible for communicating with the Kubernetes control plane running on the master node. It is responsible for executing any instructions it receives from the control plane. It also makes sure that containers are running in the pods properly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kube-proxy: This is a network proxy running on each node. Not going into much detail, you can think of it as being responsible for network communications within the cluster as well as outside the cluster. We’ll be exploring how all these communications happen between pods in a future article. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.okteto.com%2Fstatic%2F1a457960b6e8f4416990bbc6a17bbedd%2Fae694%2Fcomponents.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.okteto.com%2Fstatic%2F1a457960b6e8f4416990bbc6a17bbedd%2Fae694%2Fcomponents.png" alt="The basic componenets of a Kubernetes cluster" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The master node is the one which has all the components of the Kubernetes control plane running on it. You can also set up multiple master nodes for high availability. Following are some important control plane components you should be familiar with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;kube-apiserver: This exposes the Kubernetes API which we can use to talk to our K8s cluster. This can be thought of as the frontend for the Kubernetes control plane. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;etcd: This is the distributed key value store where all cluster related data is stored. For security reasons it is only accessible through the API server. This also helps ensure that the data stored in etcd is consistent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kube-scheduler: This is responsible for scheduling pods on available worker nodes. While scheduling it takes into consideration resource requirements of the pod and any other constraints that we specify.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kube-controller-manager: A controller in K8s is responsible for observing an object and making sure that the current state of that object matches the desired state that we specified. There are various controllers in K8s for different objects. All these are combined into a single binary which is the kube-controller-manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cloud-controller-manager: This is the component which lets you link your cluster to a cloud provider. This binary contains all the cloud provider specific controllers. So when something like a node termination happens in the cloud provider then this component will be responsible for handling that.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;And this covers all the basics of the Kubernetes architecture. The really cool thing is that while it's good to have this knowledge, as a Developer you probably won’t have to worry about any of this at all, especially if your team is using development environments like those provided by Okteto. &lt;/p&gt;

&lt;p&gt;When you use Okteto you're able to develop from the comfort of your favorite IDE while at the same time you’re able to see changes you make to your app live without having to commit, build, push, or deploy! You get to see a deployed preview of your changes exactly as users would see in production since Okteto deploys on an actual Kubernetes cluster. &lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://www.okteto.com/blog/fundamental-kubernetes-concepts-everyone-needs-to-know/" rel="noopener noreferrer"&gt;next article&lt;/a&gt;, we’ll start diving deeper into common Kubernetes objects. We will explore the Pods I mentioned briefly here and see how they can be managed using a Deployment - which is another important Kubernetes object. So while you wait for the next article in the series, why don’t you &lt;a href="//okteto.com/docs/samples/golang/"&gt;go give Okteto a try&lt;/a&gt; and see the magic for yourself? 🙂&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The "Kubernetes for Developers" blog series has now concluded, and you can find all the posts in this series &lt;a href="//okteto.com/blog/kubernetes-for-developers-blog-series-by-okteto/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>beginners</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Building Docker Images Faster for Webpack</title>
      <dc:creator>Pablo Chico de Guzman</dc:creator>
      <pubDate>Fri, 17 Dec 2021 07:58:33 +0000</pubDate>
      <link>https://forem.com/okteto/building-docker-images-faster-for-webpack-44jc</link>
      <guid>https://forem.com/okteto/building-docker-images-faster-for-webpack-44jc</guid>
      <description>&lt;p&gt;At Okteto we are very passionate about increasing developer productivity. We were looking for ways to improve our container build times when we came across an amazing project, &lt;a href="https://github.com/moby/buildkit" rel="noopener noreferrer"&gt;BuildKit&lt;/a&gt;. BuildKit helps us build Docker images faster than ever. &lt;/p&gt;

&lt;p&gt;But when getting started we found that there were very few practical examples on how one could optimize their Dockerfiles with Buildkit - so we thought why not change that? This article is going to be about how you too can optimize your Docker builds using &lt;a href="https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md#run---mounttypecache" rel="noopener noreferrer"&gt;Buildkit caches&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Why
&lt;/h2&gt;

&lt;p&gt;The first question which arises is, why even bother with optimizing your Dockerfiles? Well, the thing is that containers have revolutionized how we build, ship, and run our applications these days. So much so that containers are now heavily integrated into the development cycle and are built over and over - manually or in CI pipelines for testing and live previews.&lt;/p&gt;

&lt;p&gt;The biggest quality of life improvement that comes with better image build times is faster testing and review cycles. The quicker everyone can see and test the changes they make, the more the productivity of the team would increase! We have first-hand witnessed this for our website, but more on that later. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Standard Dockerfile for Webpack
&lt;/h2&gt;

&lt;p&gt;Before we look at how we can speed up build times using BuildKit, let's first see how a standard Dockerfile for Webpack should look like.&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="c1"&gt;# Dockerfile&lt;/span&gt;

&lt;span class="s"&gt;FROM node:16 as build&lt;/span&gt;

&lt;span class="s"&gt;WORKDIR /usr/src/app&lt;/span&gt;

&lt;span class="s"&gt;COPY package.json yarn.lock ./&lt;/span&gt;
&lt;span class="s"&gt;RUN yarn install&lt;/span&gt;

&lt;span class="s"&gt;COPY . .&lt;/span&gt;
&lt;span class="s"&gt;RUN yarn build&lt;/span&gt;

&lt;span class="s"&gt;FROM nginx:alpine&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=build /usr/src/app/dist /usr/share/nginx/html&lt;/span&gt;
&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Dockerfile uses a &lt;code&gt;build&lt;/code&gt; step to build the final artifacts, and then, it copies the artifacts to an &lt;code&gt;nginx&lt;/code&gt; image.&lt;/p&gt;

&lt;p&gt;In order to optimize the Dockerfile instructions cache, we are purposefully &lt;strong&gt;first&lt;/strong&gt; copying &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;yarn.lock&lt;/code&gt; to install the runtime dependencies. We don't copy over everything else in this same step since most of the commits don't change the yarn dependencies, allowing this step to be cached in those cases leading to better build times! But this is already a commonly known best practice and BuildKit would help us optimize the process even more.&lt;/p&gt;

&lt;p&gt;The next thing we do is to &lt;code&gt;COPY&lt;/code&gt; all our remaining files from our local folder to our &lt;code&gt;WORKDIR&lt;/code&gt;. Our changes would be made to one of these files so this means that &lt;code&gt;yarn build&lt;/code&gt; is always executed unlike the &lt;code&gt;yarn install&lt;/code&gt; instruction above.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember to configure your &lt;code&gt;.dockerignore&lt;/code&gt; file. In this case, adding &lt;code&gt;.git&lt;/code&gt; or &lt;code&gt;node_modules&lt;/code&gt; to your &lt;code&gt;.dockerignore&lt;/code&gt; file will dramatically reduce the time to send your build context to the docker daemon. This is even more relevant if your build is running on a remote server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Optimizing the Standard Dockerfile
&lt;/h2&gt;

&lt;p&gt;Now that we've looked at how a standard Dockerfile for Webpack looks like, let's see how we can leverage BuildKit caches to further reduce our build times. BuildKit enables us to configure cache folders for the &lt;code&gt;RUN&lt;/code&gt; instructions in our Dockerfile.&lt;/p&gt;

&lt;p&gt;Contents of the BuildKit cache directories persist between builder invocations without invalidating the instruction cache. BuildKit also takes care of compatibility - our builds would work with any contents of the cache directory. This is necessary since another build may overwrite the cache files or GC may clean it if more storage space is needed.&lt;/p&gt;

&lt;p&gt;In our case, we will use BuildKit caches to persist the &lt;a href="https://classic.yarnpkg.com/en/docs/cli/cache" rel="noopener noreferrer"&gt;yarn cache&lt;/a&gt; and the &lt;a href="https://webpack.js.org/configuration/cache/#cachecachedirectory" rel="noopener noreferrer"&gt;webpack cache&lt;/a&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="c1"&gt;# Dockerfile.buildkit&lt;/span&gt;

&lt;span class="s"&gt;FROM node:16 as build&lt;/span&gt;

&lt;span class="s"&gt;WORKDIR /usr/src/app&lt;/span&gt;

&lt;span class="s"&gt;COPY package.json yarn.lock ./&lt;/span&gt;
&lt;span class="s"&gt;RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install&lt;/span&gt;

&lt;span class="s"&gt;COPY . .&lt;/span&gt;
&lt;span class="s"&gt;RUN --mount=type=cache,target=./node_modules/.cache/webpack yarn build&lt;/span&gt;

&lt;span class="s"&gt;FROM nginx:alpine&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=build /usr/src/app/dist /usr/share/nginx/html&lt;/span&gt;
&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this means is that &lt;code&gt;yarn install&lt;/code&gt; and &lt;code&gt;yarn build&lt;/code&gt; will be much faster. This is because their contents will be cached now onwards instead of them being run from scratch every time like earlier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that we've not covered the installation process for BuildKit in this article since it's fairly simple and is documented well &lt;a href="https://github.com/moby/buildkit#quick-start" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Performance Evaluation
&lt;/h2&gt;

&lt;p&gt;The improvement in build times we saw for our website after using BuildKit was phenomenal! Have a look yourself.&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%2Fpem7j1ujloqqxpc9dfbq.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%2Fpem7j1ujloqqxpc9dfbq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first graph shows the performance improvement we saw whenever we changed a dependency of our website and the second one shows the boost we got from using BuildKit when making code changes.&lt;/p&gt;

&lt;p&gt;This means if you're building your images 100 times a day, you save more than 1 hr 23 mins of build time every day!&lt;/p&gt;

&lt;p&gt;We hope you too can now appreciate how powerful BuildKit is. A change of only two lines of code in your Dockerfile can dramatically decrease your image build times! We hope this article was useful and you too are now able to optimize your Docker builds. &lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webpack</category>
      <category>buildkit</category>
      <category>dockerfile</category>
    </item>
    <item>
      <title>Using Github Actions and Okteto Cloud to Preview your Changes</title>
      <dc:creator>Abdulazeez Abdulazeez</dc:creator>
      <pubDate>Tue, 20 Apr 2021 11:04:15 +0000</pubDate>
      <link>https://forem.com/okteto/using-github-actions-and-okteto-cloud-to-preview-your-changes-2g7h</link>
      <guid>https://forem.com/okteto/using-github-actions-and-okteto-cloud-to-preview-your-changes-2g7h</guid>
      <description>&lt;p&gt;Preview environments serve an important role when performing code reviews for an incoming change or addition to an application's codebase. It is a fantastic way for technical and non-technical members of your team to assess and give feedback on the changes made to your application.&lt;/p&gt;

&lt;p&gt;In previous posts of our series on FastAPI you have learned &lt;a href="https://dev.to/okteto/building-and-deploying-a-fastapi-application-in-okteto-cloud-15d5"&gt;how to build a FastAPI application&lt;/a&gt;, &lt;a href="https://dev.to/okteto/deploying-an-existing-application-using-okteto-cloud-2b5n"&gt;deploy the application to Okteto&lt;/a&gt; and &lt;a href="https://dev.to/okteto/adding-a-database-to-your-application-using-okteto-stacks-5b79"&gt;add a database to it using Okteto stacks&lt;/a&gt;. In this article, you will learn how to automatically create a preview environment for your pull requests, using Github Actions and Okteto.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Github Actions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/actions/learn-github-actions/introduction-to-github-actions"&gt;GitHub Actions&lt;/a&gt; are event-driven task automation tools that runs a series of command after an event has occurred. These events and commands are contained in a workflow file. The workflow file is responsible for the orderly execution by GitHub Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating A GitHub Action Workflow
&lt;/h2&gt;

&lt;p&gt;GitHub Actions are created and managed from the &lt;strong&gt;Actions&lt;/strong&gt; tab in a repository. Create a new workflow from the Actions tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sv61PELH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/new-workflow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sv61PELH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/new-workflow.png" alt="Create A New Workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a number of available templates on the GitHub Actions page. However, click on the &lt;strong&gt;set up a workflow yourself&lt;/strong&gt; link. This opens a new page with a default workflow, let's rewrite the workflow file:&lt;/p&gt;

&lt;p&gt;Start by defining the name of the workflow, and the event which should trigger the execution of the workflow file:&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;CRUD App Preview Deployment&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the code block above, we have set the name of the workflow, and the event to trigger the workflow. The workflow file is executed when a pull request is made to the &lt;code&gt;main&lt;/code&gt; branch. Next, let's define the series of tasks to be executed. These tasks are called &lt;strong&gt;jobs&lt;/strong&gt; in GitHub Actions.&lt;/p&gt;

&lt;p&gt;Add the instructions below to the existing code in the workflow file:&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;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;preview&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&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;checkout&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@master&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;Login&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;okteto/login@master&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.OKTETO_TOKEN }}&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;Create namespace&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;okteto/create-namespace@master&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&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;pr-${{ github.event.number }}-namespace&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;Deploy application&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;okteto/deploy-stack@master&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&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;pr-${{ github.event.number }}-namespace&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;add comment to PR&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;okteto/notify-pr@master&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Preview&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;environment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;available&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;at&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;https://fastapi-pr-${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;github.event.number&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}-namespace.cloud.okteto.net"&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code block above, we defined the job &lt;code&gt;preview&lt;/code&gt; which runs on the &lt;code&gt;ubuntu-latest&lt;/code&gt; environment. The steps to be executed under this job is defined under the &lt;code&gt;steps&lt;/code&gt; heading. Let's go over these steps.&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;namespace&lt;/code&gt; in the code block above with your Okteto default namespace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps
&lt;/h3&gt;

&lt;p&gt;In our &lt;code&gt;preview&lt;/code&gt; job, we have five tasks to be executed. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;checkout&lt;/code&gt;: This step checks out the repository using the &lt;code&gt;actions/checkout@master&lt;/code&gt; actions, so that the repository is accessible by the entire workflow. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Login&lt;/code&gt;: This step logs into your Okteto account. This task makes use of&lt;code&gt;secrets.OKTETO_TOKEN&lt;/code&gt;,  which holds the value of your Okteto token. You'll learn how to create the secret in the next section.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Create Namespace&lt;/code&gt;: This step creates a new namespace using the &lt;code&gt;okteto/create-namespace@master&lt;/code&gt; action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Deploy Application&lt;/code&gt;: This step uses the action &lt;code&gt;okteto/deploy-stack@master&lt;/code&gt; to deploy the application using the okteto stack file defined in the repository. Once again, &lt;em&gt;we have witnessed the adaptability of Okteto stacks&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;add comment to PR&lt;/code&gt;: This step adds a comment on the pull request discussion indicating a link to the deployed application. It makes use of the &lt;code&gt;okteto/notify-pr@master&lt;/code&gt; action.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Adding Your Okteto Token To GitHub
&lt;/h3&gt;

&lt;p&gt;Before adding your Okteto token to GitHub, retrieve your Okteto token from your dashboard settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S_ozVNu6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/dashboard-settings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S_ozVNu6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/dashboard-settings.png" alt="Okteto dashboard - Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The workflow file needs your &lt;a href="https://cloud.okteto.com"&gt;Okteto account&lt;/a&gt; token to function properly. Follow the steps below to add your okteto token to your GitHub repository:&lt;/p&gt;

&lt;p&gt;i. In your repository, navigate to the &lt;strong&gt;Settings&lt;/strong&gt; tab and click on the &lt;strong&gt;Secrets&lt;/strong&gt; link on the menu by the left:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X7h9LN1A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/okteto-secrets.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X7h9LN1A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/okteto-secrets.png" alt="Secrets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ii. Click on &lt;strong&gt;New Repository Secret&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X8ZnWVTQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/new-secret.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X8ZnWVTQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/new-secret.png" alt="Add A New Secret"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;iii. Create a new secret &lt;code&gt;OKTETO_TOKEN&lt;/code&gt; and set the value to the token you copied from your dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Ylv4ZE6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/create-new-secret.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Ylv4ZE6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/create-new-secret.png" alt="Create New Secret"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can learn more on how to store and manage GitHub secrets on their official &lt;a href="https://docs.github.com/en/actions/reference/encrypted-secrets"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building The Preview Environment
&lt;/h2&gt;

&lt;p&gt;With the secret in place, let's go on to create a pull request from the &lt;code&gt;mongodb-crud&lt;/code&gt; branch into the &lt;code&gt;main&lt;/code&gt; branch to see the workflow in action:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jgNgItvY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/new-pull-request.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jgNgItvY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/new-pull-request.png" alt="New Pull Request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Immediately the pull request is created, the workflow kicks into action:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KCCGripa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/workflow-in-action.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KCCGripa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/workflow-in-action.png" alt="Workflow In Action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To monitor the progress of the workflow in action, navigate to the &lt;strong&gt;Actions&lt;/strong&gt; tab. The current workflow is listed like in the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ej9MWSmw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/actions.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ej9MWSmw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/actions.png" alt="Actions Tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the workflow currently under execution. In the workflow page, click on the &lt;code&gt;preview&lt;/code&gt; job to view the execution and logs of each step:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O2F5P5P0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/preview-job.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O2F5P5P0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/preview-job.png" alt="Preview Job"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tasks undergoing execution are listed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1GbIro0S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/task-execution.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1GbIro0S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/task-execution.png" alt="Tasks undergoing execution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With all the necessary details put in place, the execution completes successfully:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Er6Riz8h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/workflow-complete.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Er6Riz8h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/workflow-complete.png" alt="Workflow complete"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Return to the pull request thread to view the comment made by &lt;code&gt;github-actions&lt;/code&gt; bot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BiYo7_M3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/comment.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BiYo7_M3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/comment.png" alt="Comment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deleting Preview Environment Namespace
&lt;/h3&gt;

&lt;p&gt;The preview environment ceases to be of use after the pull request has been merged. As such, there is no point in keeping the namespace created by the workflow earlier as newer pull requests will create new namespaces. Okteto provides an action to automatically delete a namespace.&lt;/p&gt;

&lt;p&gt;Repeating the steps followed in creating a workflow above, create a new workflow &lt;code&gt;preview-close&lt;/code&gt; to automatically destroy the namespace after the pull request has either been merged or close:&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;Delete Preview Namespace&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;closed&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&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;checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@master&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;Login&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;okteto/login@master&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.OKTETO_TOKEN }}&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;Delete namespace&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;okteto/delete-namespace@master&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&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;pr-${{ github.event.number }}-namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to change &lt;code&gt;namespace&lt;/code&gt; to your Okteto namespace.&lt;/p&gt;

&lt;p&gt;With the workflow in place, let's merge the pull request and verify that the &lt;code&gt;Delete Preview Namespace&lt;/code&gt; workflow was executed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1a3Y3J9B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/merge-pull-request.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1a3Y3J9B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/merge-pull-request.png" alt="Merge Pull Request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the &lt;strong&gt;Actions&lt;/strong&gt; tab and click on the workflow undergoing execution:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7d331wUf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/actions-tab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7d331wUf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/actions-tab.png" alt="Actions Tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The namespace has been deleted successfully:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Er6Riz8h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/workflow-complete.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Er6Riz8h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://okteto.com/blog/using-github-actions-and-okteto-cloud-to-preview-changes/workflow-complete.png" alt="Workflow Execution Complete"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In this article, you built a workflow for creating a preview environment when a pull request is made to the main branch and another workflow to delete the namespace containing the preview environment after the pull request has either been closed or merged.&lt;/p&gt;

&lt;p&gt;Once again, the deployment of the preview environment was made possible by the stack manifest we have been using from the &lt;a href="https://dev.to/okteto/building-and-deploying-a-fastapi-application-in-okteto-cloud-15d5"&gt;first post&lt;/a&gt; in the series. This way, you are reusing the same manifest for development, deployment, and preview environments. &lt;/p&gt;

&lt;p&gt;The complete code used in this article can be found in our &lt;a href="https://github.com/okteto/fastapi-crud"&gt;GitHub repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>okteto</category>
      <category>fastapi</category>
      <category>github</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
