<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ninii</title>
    <description>The latest articles on DEV Community by Ninii (@ninii72387534).</description>
    <link>https://dev.to/ninii72387534</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F580897%2F61b3bb8a-a4c3-4cf2-9b81-59eecc53bdc8.png</url>
      <title>DEV Community: Ninii</title>
      <link>https://dev.to/ninii72387534</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ninii72387534"/>
    <language>en</language>
    <item>
      <title>REST vs gRPC in Python: A Practical Benchmark!</title>
      <dc:creator>Ninii</dc:creator>
      <pubDate>Mon, 28 Apr 2025 13:28:58 +0000</pubDate>
      <link>https://dev.to/ninii72387534/rest-vs-grpc-in-python-a-practical-benchmark-3o35</link>
      <guid>https://dev.to/ninii72387534/rest-vs-grpc-in-python-a-practical-benchmark-3o35</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Ever wondered: &lt;em&gt;"Is gRPC really faster than REST?"&lt;/em&gt; Let's not just believe the hype. Let's &lt;strong&gt;measure it ourselves&lt;/strong&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this blog, we'll build small REST and gRPC services in Python, benchmark them, and compare their real-world performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  REST vs gRPC: Quick Intro
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;REST (Flask)&lt;/th&gt;
&lt;th&gt;gRPC (Protobuf)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Protocol&lt;/td&gt;
&lt;td&gt;HTTP/1.1&lt;/td&gt;
&lt;td&gt;HTTP/2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Format&lt;/td&gt;
&lt;td&gt;JSON (text)&lt;/td&gt;
&lt;td&gt;Protobuf (binary)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human-readable?&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed&lt;/td&gt;
&lt;td&gt;Slower&lt;/td&gt;
&lt;td&gt;Faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Streaming support&lt;/td&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Setup: Build Two Simple Services
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. REST API Server (Flask)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# rest_server.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/hello&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&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;say_hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. gRPC Server (Python)
&lt;/h2&gt;

&lt;p&gt;First, define your service using Protocol Buffers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;hello.proto&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;HelloService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;SayHello&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate Python files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; grpc_tools.protoc &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--python_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--grpc_python_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; hello.proto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;gRPC server:&lt;/strong&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="c1"&gt;# grpc_server.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;concurrent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;futures&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hello_pb2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloServiceServicer&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;SayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hello_pb2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HelloResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_HelloServiceServicer_to_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HelloService&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_insecure_port&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[::]:50051&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_termination&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Benchmark: How to Measure?
&lt;/h2&gt;

&lt;p&gt;We will send &lt;strong&gt;1000 requests&lt;/strong&gt; to each server and measure total time taken.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST Benchmark Client
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;benchmark_rest&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:5000/hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ninad&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;REST Total Time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;benchmark_rest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  gRPC Benchmark Client
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hello_pb2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;benchmark_grpc&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insecure_channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost:50051&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;stub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HelloServiceStub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hello_pb2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ninad&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRPC Total Time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;benchmark_grpc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Results: What I Observed
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;REST&lt;/th&gt;
&lt;th&gt;gRPC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total Time (1000 req)&lt;/td&gt;
&lt;td&gt;~15-20 seconds&lt;/td&gt;
&lt;td&gt;~3-5 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avg Latency/request&lt;/td&gt;
&lt;td&gt;~15-20 ms&lt;/td&gt;
&lt;td&gt;~3-5 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payload Size&lt;/td&gt;
&lt;td&gt;Larger (text)&lt;/td&gt;
&lt;td&gt;Smaller (binary)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;gRPC was about 4-5x faster than REST&lt;/strong&gt; in this small test!&lt;/p&gt;




&lt;h2&gt;
  
  
  Why is gRPC Faster?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;strong&gt;HTTP/2&lt;/strong&gt;: multiplexing multiple streams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary Protobufs&lt;/strong&gt;: smaller, faster to serialize/deserialize.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent connection&lt;/strong&gt;: no 3-way TCP handshake every call.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;If you're building &lt;strong&gt;frontend APIs&lt;/strong&gt; (browsers/mobile apps) -&amp;gt; &lt;strong&gt;REST&lt;/strong&gt; is still great.&lt;/li&gt;
&lt;li&gt;If you're building &lt;strong&gt;internal microservices&lt;/strong&gt; at scale -&amp;gt; &lt;strong&gt;gRPC&lt;/strong&gt; shines!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bonus: Advanced Benchmarking Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For REST: &lt;a href="https://github.com/wg/wrk" rel="noopener noreferrer"&gt;wrk&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For gRPC: &lt;a href="https://github.com/bojand/ghz" rel="noopener noreferrer"&gt;ghz&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thought:
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Real engineers don't guess performance — they measure it!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Happy benchmarking! 💪&lt;/p&gt;




&lt;p&gt;Would love to hear your thoughts — have you tried gRPC before? How did it go for you? Feel free to share in the comments! 🚀&lt;/p&gt;

</description>
      <category>python</category>
      <category>grpc</category>
      <category>restapi</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Progressive Delivery with Argo Rollouts: Canary Deployment</title>
      <dc:creator>Ninii</dc:creator>
      <pubDate>Sat, 25 Jun 2022 13:51:50 +0000</pubDate>
      <link>https://dev.to/infracloud/progressive-delivery-with-argo-rollouts-canary-deployment-4eoj</link>
      <guid>https://dev.to/infracloud/progressive-delivery-with-argo-rollouts-canary-deployment-4eoj</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/blogs/progressive-delivery-argo-rollouts-blue-green-deployment/"&gt;Part 1 of Argo Rollouts&lt;/a&gt;, we have seen what Progressive Delivery is and how you can achieve the Blue-Green deployment type using Argo Rollouts. We also deployed a sample app in a Kubernetes cluster using it. Do read the &lt;a href="https://dev.to/blogs/progressive-delivery-argo-rollouts-blue-green-deployment/"&gt;first part of this Progressive Delivery blog series&lt;/a&gt;, if you haven't yet.&lt;/p&gt;

&lt;p&gt;In this hands-on article, we will explore what is the &lt;a href="https://argoproj.github.io/argo-rollouts/features/canary/"&gt;canary deployment strategy&lt;/a&gt; and how you can achieve the same using Argo Rollouts. But before that, let's first understand what is canary deployment and the need behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Canary Deployment?
&lt;/h2&gt;

&lt;p&gt;As stated rightly by Danilo Sato in this &lt;a href="https://martinfowler.com/bliki/CanaryRelease.html"&gt;CanaryRelease&lt;/a&gt; article,&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“&lt;/em&gt;&lt;em&gt;Canary release&lt;/em&gt;* is a technique to reduce the risk of introducing a new software version in production by slowly rolling out the change to a small subset of users before rolling it out to the entire infrastructure and making it available to everybody.”*&lt;/p&gt;

&lt;p&gt;Canary is one of the most popular and widely adopted techniques of progressive delivery. Do you know why we call it canary and not anything else? The term “canary deployment” comes from an &lt;strong&gt;old coal mining technique&lt;/strong&gt;. These mines often contained carbon monoxide and other dangerous gases that could kill the miners. Canary birds were more sensitive to airborne toxins than humans, so miners would use them as early detectors, So Similar approach is used in canary deployment, where instead of putting entire end-users in danger like in old big-bang deployment, we instead start releasing our new version of the application to a very small percentage of users and then try to do analysis and see if all working as expected and then gradually release it to a larger audience in an incremental way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N40MUh1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4v59mp71c7hpdlwn40r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N40MUh1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4v59mp71c7hpdlwn40r.png" alt="Canary deployement" width="600" height="948"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;center&gt;
&lt;br&gt;
 &lt;a href="https://argoproj.github.io/argo-rollouts/concepts"&gt;Image Source&lt;/a&gt; &lt;br&gt;
&lt;/center&gt;
&lt;h2&gt;
  
  
  Need for Canary Deployment
&lt;/h2&gt;

&lt;p&gt;Some of us have already seen that sometimes new updates of apps (like WhatsApp or Facebook) is visible to one of our friends but not to everyone, and that's the power of canary deployment strategy handling new version rollout in the background. The problems that canary deployment tries to solve are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canary deployments help to do testing in production with real users and real traffic which unfortunately Blue-Green deployment can not help with&lt;/li&gt;
&lt;li&gt;One gets the ability to analyze the response of a new version of your application in more controlled manner and then rollout efficiently to all the end-users incrementally.&lt;/li&gt;
&lt;li&gt;Infrastructure cost involved compared to the Blue-Green deployment technique is less.&lt;/li&gt;
&lt;li&gt;Lowest risk-prone compared to all other deployment strategies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  How does Argo Rollouts handle the Canary Deployment?
&lt;/h2&gt;

&lt;p&gt;Let's say, once you start using the Argo Rollouts controller for canary style deployment, it basically creates a new ReplicaSet of the new version of the application (which creates a new set of pod) and divides the traffic between the old stable and this new canary version by using the single service object that it was using to route traffic to the older stable version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vg794sx8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cuyppm5fw5v7smgtx20r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vg794sx8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cuyppm5fw5v7smgtx20r.png" alt="Argo Rollouts Canary Deployement" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;center&gt;
&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=VSFfqMsVcTw"&gt;Image Source&lt;/a&gt;&lt;br&gt;
&lt;/center&gt;

&lt;p&gt;Now, let's try on our own with some hands-on to see how it works in real.&lt;/p&gt;
&lt;h3&gt;
  
  
  Lab/Hands-on of Argo Rollouts with Canary Deployment
&lt;/h3&gt;

&lt;p&gt;If you do not have K8s cluster readily available to do further lab then we recommend going for &lt;a href="https://prod.cloudyuga.guru/hands_on_lab/canary-deploy"&gt;CloudYuga platform-based version&lt;/a&gt; of this blogpost. Else, you can &lt;a href="https://kind.sigs.k8s.io/docs/user/ingress/#setting-up-an-ingress-controller"&gt;set up your own kind local cluster with Nginx controller&lt;/a&gt; also deployed, and follow along to execute the below commands against your kind cluster.&lt;/p&gt;

&lt;p&gt;Clone the Argo Rollouts example GitHub repo or preferably, please fork this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/NiniiGit/argo-rollouts-example.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installation of Argo Rollouts controller
&lt;/h3&gt;

&lt;p&gt;Create the namespace for installation of the Argo Rollouts controller and Install the Argo Rollouts through the below command, more about the installation can be found in the &lt;a href="https://www.infracloud.io/blogs/progressive-delivery-argo-rollouts-blue-green-deployment/"&gt;first part of the progressive delivery blog series&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create namespace argo-rollouts
kubectl apply &lt;span class="nt"&gt;-n&lt;/span&gt; argo-rollouts &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see that the &lt;strong&gt;controller and other components&lt;/strong&gt; have been deployed. Wait for the pods to be in the Running state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get all &lt;span class="nt"&gt;-n&lt;/span&gt; argo-rollouts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;strong&gt;Argo Rollouts Kubectl plugin&lt;/strong&gt; with curl for easy interaction with Rollout controller and resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./kubectl-argo-rollouts-linux-amd64
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
kubectl argo rollouts version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Argo Rollouts comes with its own &lt;strong&gt;GUI&lt;/strong&gt; as well that you can access with the below command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you can access Argo Rollouts console, by accessing &lt;code&gt;http://localhost:3100&lt;/code&gt; on your browser.&lt;br&gt;
You would be presented with UI as shown below (currently it won't show you anything since we are yet to deploy any Argo Rollouts based).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SueqtKS4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hfdv19x84byyue0cti90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SueqtKS4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hfdv19x84byyue0cti90.png" alt="Argo Rollouts Dashboard" width="880" height="304"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: Argo Rollouts Dashboard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, let's go ahead and deploy the sample app using the canary deployment strategy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Canary Deployment with Argo Rollouts
&lt;/h3&gt;

&lt;p&gt;To experience how the &lt;a href="https://argoproj.github.io/argo-rollouts/features/canary/"&gt;canary deployment works with Argo Rollouts&lt;/a&gt;, we will deploy the sample app which contains Rollouts with canary strategy, Service, and Ingress as Kubernetes objects.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rollout.yaml&lt;/code&gt; content:&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;argoproj.io/v1alpha1&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;Rollout&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;rollouts-demo&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;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;canary&lt;/span&gt;&lt;span class="pi"&gt;:&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;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;revisionHistoryLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&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;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollouts-demo&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&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;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollouts-demo&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollouts-demo&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj/rollouts-demo:blue&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;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;32Mi&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;setWeight&lt;/code&gt; field dictates the percentage of traffic that should be sent to the canary, and the &lt;code&gt;pause&lt;/code&gt; struct instructs the rollout to pause. When the controller reaches a pause step for a rollout, it will set adds a PauseCondition struct to the &lt;code&gt;.status.PauseConditions&lt;/code&gt; field. If the duration field within the pause struct is set, the rollout will not progress to the next step until it has waited for the value of the duration field. Otherwise, the rollout will wait indefinitely until that &lt;code&gt;pause&lt;/code&gt; condition is removed. By using the &lt;code&gt;setWeight&lt;/code&gt; and the &lt;code&gt;pause&lt;/code&gt; fields, a user can declarative describe how they want to progress to the new version. You can find more details about &lt;a href="https://argoproj.github.io/argo-rollouts/features/specification/"&gt;all the different parameters available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we will create the service object for this rollout object.&lt;br&gt;
&lt;code&gt;service.yaml&lt;/code&gt; content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollouts-demo&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;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&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;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;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;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollouts-demo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now create an ingress object.&lt;br&gt;
&lt;code&gt;ingress.yaml&lt;/code&gt; content:&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;Ingress&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;rollouts-ingress&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubernetes.io/ingress.class&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;spec&lt;/span&gt;&lt;span class="pi"&gt;:&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;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&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;rollouts-demo&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep things simple, let's create all these objects for now in the &lt;code&gt;default&lt;/code&gt; namespace by executing the below commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; argo-rollouts-example/canary-deployment-example/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would be able to see all the objects created in the default namespace by running the below command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, you can access your sample app, by accessing this &lt;code&gt;http://localhost:80&lt;/code&gt; on your browser.&lt;br&gt;
You would be able to see the app as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zBT_coVg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5i14pzn879h411fdve1m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zBT_coVg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5i14pzn879h411fdve1m.png" alt="Sample app Blue Version" width="880" height="401"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2: Sample app with blue-version&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you visit the &lt;strong&gt;Argo Rollouts console&lt;/strong&gt; by again accessing &lt;a href="http://localhost:3100"&gt;http://localhost:3100&lt;/a&gt; on your browser then this time, you could see the &lt;strong&gt;sample deployed&lt;/strong&gt; on the Argo Rollouts console as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uf9Z9K_S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ugbpjgxykxnhvvfzj6s1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uf9Z9K_S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ugbpjgxykxnhvvfzj6s1.png" alt="Canary Deployement Argo Rollouts" width="880" height="387"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3: Canary Deployment on Argo Rollouts Dashboard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Click on this rollout-demo in the console and it will present you with its current status of it as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Cqqj-K9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b76zsvwyfpz4xbtruwdl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Cqqj-K9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b76zsvwyfpz4xbtruwdl.png" alt="Details Canary Depoyement Argo Rollouts" width="880" height="438"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4: Details of Canary Deployment on Argo Rollouts Dashboard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Again, either you can use this &lt;strong&gt;GUI&lt;/strong&gt; or else use the &lt;strong&gt;command&lt;/strong&gt; shown below to continue with this demo.&lt;br&gt;
You can see the current status of this rollout by running the below command as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts get rollout rollouts-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's deploy the &lt;strong&gt;Yellow version&lt;/strong&gt; of the app using canary strategy via command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts &lt;span class="nb"&gt;set &lt;/span&gt;image rollouts-demo rollouts-demo&lt;span class="o"&gt;=&lt;/span&gt;argoproj/rollouts-demo:yellow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would be able to see a new, i.e &lt;strong&gt;yellow version-based pod&lt;/strong&gt; of our sample app, coming up.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Currently, &lt;strong&gt;only 20% i.e 1 out of 5 pods&lt;/strong&gt; with a yellow version will come online, and then it will be paused as we have mentioned in the steps above. See &lt;strong&gt;line number 9&lt;/strong&gt; in the &lt;strong&gt;&lt;code&gt;rollout.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
On the Argo console, you would be able to see the new revision of the app with the changed image version running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zJcK_tmf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jyne8nmcdhwuz9zzae01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zJcK_tmf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jyne8nmcdhwuz9zzae01.png" alt="Sample App Canary Deployement Argo Rollouts" width="880" height="415"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5: Another version of the sample app in Canary Deployment on Argo Rollouts Dashboard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you visit the &lt;code&gt;http://localhost:80&lt;/code&gt; on your browser, you would still see only the majority of blue versions, and a very less number of yellow is visible as we have not yet fully promoted the yellow version of our app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cQdlkHNC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n780dl3dum5hwhio2hhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cQdlkHNC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n780dl3dum5hwhio2hhb.png" alt="Blue Yellow sample versions" width="880" height="414"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 6: blue-yellow versions of the sample app&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can confirm the same now, by running the command below, which shows, the new version is in paused state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts get rollout rollouts-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's promote the &lt;strong&gt;yellow version&lt;/strong&gt; of our app, by executing the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts promote rollouts-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command and you would see it's scaling the new, i.e &lt;strong&gt;yellow version&lt;/strong&gt; of our app completely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts get rollout rollouts-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same can be confirmed by running the below command, which shows the old set of pods i.e old &lt;strong&gt;blue version&lt;/strong&gt; of our app, terminating or already terminated.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Eventually, if you visit the app URL on &lt;code&gt;http://localhost:80&lt;/code&gt; on your browser, you would see only the &lt;strong&gt;Yellow version&lt;/strong&gt; is visible right now because we have fully promoted the yellow version of our app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FIzwRvsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5myteqlppzina1y88l80.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FIzwRvsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5myteqlppzina1y88l80.png" alt="Sample Yellow version" width="880" height="387"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 7: Sample app with yellow-version&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Kudos!! you have successfully completed the canary deployment using Argo Rollouts.&lt;br&gt;
You can also delete this entire setup i.e our sample deployed app using the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete &lt;span class="nt"&gt;-f&lt;/span&gt; argo-rollouts-example/canary-deployment-example/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;In this post, we experienced how we can achieve canary deployment style of progressive delivery using Argo Rollouts quite easily. Achieving canary deployment in this way with Argo Rollouts is simple and does not require any service mesh and provides much better control on rolling out a new version of your application than using the default rolling update strategy of Kubernetes.&lt;/p&gt;

&lt;p&gt;I hope you found this post informative and engaging. I’d love to hear your thoughts on this post, so start a conversation on &lt;a href="https://twitter.com/NinadDesai73"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/ninad-desai/"&gt;LinkedIn&lt;/a&gt; :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Next?&lt;/strong&gt; Now we have developed some more understanding of progressive delivery and created a canary deployment out of it. Next would be diving deeper to try the canary deployment with &lt;a href="https://argoproj.github.io/argo-rollouts/features/analysis/"&gt;Analysis&lt;/a&gt; using Argo Rollouts, stay tuned for this post.&lt;/p&gt;

&lt;p&gt;You can find all the parts of this Argo Rollouts Series below:&lt;br&gt;
Part 1: &lt;a href="https://www.infracloud.io/blogs/progressive-delivery-argo-rollouts-blue-green-deployment/"&gt;Progressive Delivery with Argo Rollouts: Blue Green Deployment&lt;/a&gt;&lt;br&gt;
Part 2: &lt;a href="https://www.infracloud.io/blogs/progressive-delivery-argo-rollouts-canary-deployment/"&gt;Progressive Delivery with Argo Rollouts: Canary  Deployment&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  References and further reading:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://argoproj.github.io/rollouts/"&gt;Argo Rollouts&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=791q82vg5M8&amp;amp;t=3210s"&gt;Kubernets Banglore workshop on Argo Rollouts&lt;/a&gt;&lt;br&gt;
&lt;a href="https://argoproj.github.io/argo-rollouts/"&gt;Argo Rollouts - Kubernetes Progressive Delivery Controller&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=VSFfqMsVcTw&amp;amp;t=9274s"&gt;CICD with Argo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking for help with building your DevOps strategy or want to outsource DevOps to the experts? learn why so many startups &amp;amp; enterprises consider us as one of the &lt;a href="https://dev.to/devops-consulting-services/"&gt;best DevOps consulting &amp;amp; services companies&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>argo</category>
      <category>argorollouts</category>
      <category>progressivedelivery</category>
      <category>deployment</category>
    </item>
    <item>
      <title>Progressive Delivery with Argo Rollouts : Blue-Green Deployment</title>
      <dc:creator>Ninii</dc:creator>
      <pubDate>Sat, 25 Jun 2022 13:46:10 +0000</pubDate>
      <link>https://dev.to/infracloud/progressive-delivery-with-argo-rollouts-blue-green-deployment-4ocb</link>
      <guid>https://dev.to/infracloud/progressive-delivery-with-argo-rollouts-blue-green-deployment-4ocb</guid>
      <description>&lt;p&gt;&lt;strong&gt;To understand about blue-green deployment with Argo Rollouts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Continuous Integration (CI) and Continuous Delivery (CD) have been widely adopted in modern software development enabling organizations to quickly deploy these software to customers. But doing it in the right way is equally important as in some cases unfinished code can lead to failures and customers have to face downtime.&lt;br&gt;
So to solve this, progressive delivery was introduced which enables the delivery of software with the right changes to the right amount of customers at the right time. More precisely, it controls the speed at which changes are deployed for a software.&lt;/p&gt;
&lt;h2&gt;
  
  
  Traditional CI/CD and Progressive Delivery
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/devops/continuous-integration/"&gt;Continuous Integration (CI)&lt;/a&gt; is an automation process that helps in continuously integrating software development changes. It automates the building, testing, and validation of the source code. Its goal is to ultimately produce a packaged artifact that is ready to deploy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/devops/continuous-delivery/"&gt;Continuous Delivery (CD)&lt;/a&gt; helps in deploying software changes to users. It needs CI which produces an artifact that can be deployed to users. Hence, &lt;a href="https://dev.to/ci-cd-consulting/"&gt;CI and CD&lt;/a&gt; are often used together.&lt;/p&gt;

&lt;p&gt;But Continuous Delivery poses many challenges, such as handling fast delivery of changes, handling high-risk failures, to ensure uptime and efficient performance of the software.&lt;br&gt;
To solve the above problems of continuous delivery, progressive delivery comes into action along with different deployment strategies like blue-green deployment, canary deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://argoproj.github.io/argo-rollouts/concepts/#progressive-delivery"&gt;Progressive Delivery&lt;/a&gt; is one step ahead of Continuous Delivery. It enables delivering the software updates in a controlled manner by reducing the risks of failures. It is done by exposing the new changes of software to a smaller set of users, and then by observing and analyzing the correct behavior, it is then exposed to more users progressively. It is known to move fast but with control.&lt;/p&gt;
&lt;h2&gt;
  
  
  Challenges with default “RollingUpdate” Kubernetes deployment strategy
&lt;/h2&gt;

&lt;p&gt;Kubernetes comes up with default &lt;code&gt;RollingUpdate&lt;/code&gt; deployment strategy which at present, have below set of limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fewer controls over speed of the rollout&lt;/li&gt;
&lt;li&gt;Inability to control traffic flow to the new version&lt;/li&gt;
&lt;li&gt;Readiness probes are unsuitable for deeper, stress, or one-time checks&lt;/li&gt;
&lt;li&gt;No ability to query external metrics to verify an update&lt;/li&gt;
&lt;li&gt;Can halt the progression, but unable to automatically abort and rollback the update&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Argo Projects
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://argoproj.github.io/"&gt;Argo&lt;/a&gt; is a group of many open source projects which help in the fast and safe delivery of software by extending the capabilities of Kubernetes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/argoproj/argo-workflows"&gt;Argo Workflows&lt;/a&gt; - Container-native Workflow Engine&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/argoproj/argo-cd"&gt;Argo CD&lt;/a&gt; - Declarative GitOps Continuous Delivery&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/argoproj/argo-events"&gt;Argo Events&lt;/a&gt; - Event-based Dependency Manager&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/argoproj/argo-rollouts"&gt;Argo Rollouts&lt;/a&gt; - Progressive Delivery with support for Canary and Blue Green deployment strategies&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/argoproj-labs"&gt;Argoproj-labs&lt;/a&gt; - separate GitHub org that is setup for community contributions related to the Argoproj ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To overcome the limitations of native Kubernetes deployment strategies, &lt;a href="https://argoproj.github.io/rollouts"&gt;Argo Rollouts&lt;/a&gt; has been introduced and it contains below a different set of projects.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Argo Rollouts?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://argoproj.github.io/argo-rollouts/"&gt;Argo Rollouts&lt;/a&gt; is a Kubernetes controller and a set of  CRDs which provides progressive delivery features along with advanced deployments such as blue-green, canary, canary analysis. It has the potential to control and shift traffic to a newer version of software through ingress controllers and service meshes.&lt;/p&gt;

&lt;p&gt;The below table shows comparative analysis of capabilities of the  default Kubernetes deployment strategy vs ArgoRollouts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v2W50T5W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a60wgjsn008fn4rjmylg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v2W50T5W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a60wgjsn008fn4rjmylg.png" alt="Argo Rollouts" width="649" height="366"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Working of Argo Rollouts
&lt;/h3&gt;

&lt;p&gt;Argo Rollout controller helps in finding and detecting the resource of a kind: Rollout in the cluster which manages the replicasets just like Kubernetes Deployment does. It creates a stable replicaset for the older version of the software and a canary replicaset for the newer version of the software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vJkVkq8J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/paojvpdvd58rqyyvrhdi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJkVkq8J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/paojvpdvd58rqyyvrhdi.png" alt="Working of Argo Rollouts" width="786" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;source: &lt;a href="https://argoproj.github.io/argo-rollouts/architecture/"&gt;Argo-Rollout-Architecture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;AnalysisTemplate&lt;/code&gt; helps in doing the analysis of the replicasets through the &lt;code&gt;AnalysisRun&lt;/code&gt; component. Together, they help to observe the working of the newly deployed version. Accordingly, it can automatically roll out to a newer version or roll back it. For this one can use any metrics tool like &lt;strong&gt;&lt;em&gt;Prometheus&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;Kubernetes jobs&lt;/em&gt;&lt;/strong&gt;, and so on.&lt;/p&gt;
&lt;h3&gt;
  
  
  Lab/Hands-on of Argo Rollouts with Blue-Green Deployments
&lt;/h3&gt;

&lt;p&gt;If you do not have k8s cluster readily available to do further lab then we recommend to go for &lt;a href="https://cloudyuga.guru/hands_on_lab/blue-green-deploy-argorollout"&gt;CloudYuga platform based version&lt;/a&gt; of this blogpost. Else, you can &lt;a href="https://kind.sigs.k8s.io/docs/user/ingress/#setting-up-an-ingress-controller"&gt;set up your own kind local cluster with nginx controller&lt;/a&gt; also deployed,and follow along to execute below commands against your kind cluster.&lt;/p&gt;

&lt;p&gt;Clone the Argo Rollouts example GitHub repo or preferably, please fork this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/NiniiGit/argo-rollouts-example.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installation of Argo Rollouts controller
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create the namespace for installation of the Argo Rollouts controller
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create namespace argo-rollouts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see the namespace has been created&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We will use the latest version to install the Argo Rollouts controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-n&lt;/span&gt; argo-rollouts &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see the &lt;strong&gt;controller and other components&lt;/strong&gt; have been deployed. Wait for the pods to be in the &lt;code&gt;Running&lt;/code&gt; state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get all &lt;span class="nt"&gt;-n&lt;/span&gt; argo-rollouts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Argo Rollouts Kubectl plugin with &lt;code&gt;curl&lt;/code&gt; for easy interaction with Rollout controller and resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./kubectl-argo-rollouts-linux-amd64
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
kubectl argo rollouts version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Argo Rollouts comes with its own GUI as well that you can access with the below command&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;and now you can access Argo Rollout console, by accessing &lt;a href="http://localhost:3100"&gt;http://localhost:3100&lt;/a&gt; on your browser.&lt;br&gt;
You would be presented with UI as shown below (currently it won't show you anything since we are yet to deploy any Argo Rollouts based app)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mr_xHHnz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5ncrnucz1hsg4xnqxed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mr_xHHnz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5ncrnucz1hsg4xnqxed.png" alt="Argo Rollouts Dashboard" width="880" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Now, let's go ahead and deploy our first sample app using the Blue-Green Deployment strategy.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Blue-Green Deployment with Argo Rollouts
&lt;/h3&gt;

&lt;p&gt;To experience how the &lt;a href="https://argoproj.github.io/argo-rollouts/features/bluegreen/"&gt;blue-green deployment&lt;/a&gt; works with Argo Rollouts, we will deploy the sample app which contains Rollouts, Service, and Ingress as Kubernetes objects.\&lt;br&gt;
&lt;code&gt;rollout.yaml&lt;/code&gt; content:&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;# This example demonstrates a Rollout using the blue-green update strategy, which contains a manual&lt;/span&gt;
&lt;span class="c1"&gt;# gate before promoting the new stack.&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&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;Rollout&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;rollout-bluegreen&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;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;revisionHistoryLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&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;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollout-bluegreen&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&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;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollout-bluegreen&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollouts-demo&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj/rollouts-demo:blue&lt;/span&gt;
        &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Always&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;blueGreen&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="c1"&gt;# activeService specifies the service to update with the new template hash at time of promotion.&lt;/span&gt;
      &lt;span class="c1"&gt;# This field is mandatory for the blueGreen update strategy.&lt;/span&gt;
      &lt;span class="na"&gt;activeService&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollout-bluegreen-active&lt;/span&gt;
      &lt;span class="c1"&gt;# previewService specifies the service to update with the new template hash before promotion.&lt;/span&gt;
      &lt;span class="c1"&gt;# This allows the preview stack to be reachable without serving production traffic.&lt;/span&gt;
      &lt;span class="c1"&gt;# This field is optional.&lt;/span&gt;
      &lt;span class="na"&gt;previewService&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollout-bluegreen-preview&lt;/span&gt;
      &lt;span class="c1"&gt;# autoPromotionEnabled disables automated promotion of the new stack by pausing the rollout&lt;/span&gt;
      &lt;span class="c1"&gt;# immediately before the promotion. If omitted, the default behavior is to promote the new&lt;/span&gt;
      &lt;span class="c1"&gt;# stack as soon as the ReplicaSet are completely ready/available.&lt;/span&gt;
      &lt;span class="c1"&gt;# Rollouts can be resumed using: `kubectl argo rollouts promote ROLLOUT`&lt;/span&gt;
      &lt;span class="na"&gt;autoPromotionEnabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;service.yaml&lt;/code&gt; content:&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;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;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;rollout-bluegreen-active&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;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollout-bluegreen&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;80&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;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;rollout-bluegreen-preview&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;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rollout-bluegreen&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;80&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ingress.yaml&lt;/code&gt; content:&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;Ingress&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;rollout-bluegreen&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubernetes.io/ingress.class&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;spec&lt;/span&gt;&lt;span class="pi"&gt;:&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;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&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;rollout-bluegreen-active&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's create all these objects for now in the default namespace. Please execute the below commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; argo-rollouts-example/blue-green-deployment-example/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would be able to see all the objects been created in the &lt;code&gt;default&lt;/code&gt; namespace by running the below commands:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, you can access your sample app, by accessing &lt;a href="http://localhost:80"&gt;http://localhost:80&lt;/a&gt; on your browser.\&lt;br&gt;
You would be able to see the app as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tnSlRQSe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0odt2wxyvs71zfvt52x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tnSlRQSe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0odt2wxyvs71zfvt52x3.png" alt="Argo Rollouts sample app with blue-version" width="880" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, again visit the Argo-Rollouts console. And this time, you could see the sample deployed on the Argo Rollouts console as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9WOQvcQV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqzw3d2k0ilb6bbrgmub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9WOQvcQV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqzw3d2k0ilb6bbrgmub.png" alt="Blue-Green deployment on argo rollouts dashboard" width="880" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can click on this &lt;code&gt;rollout-bluegreen&lt;/code&gt; in the console and it will present you with its current status as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fZvYfCZq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9e2j12lk4rn10gwsrcqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fZvYfCZq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9e2j12lk4rn10gwsrcqb.png" alt="Details of blue-green deployment" width="880" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going forward, either you can use this GUI or else (Preferably) use the commands shown below to continue with this demo. &lt;/p&gt;

&lt;p&gt;You can see the current status of this rollout by running the below command as well&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts get rollout rollout-bluegreen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's deploy the Green version of the app via command line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts &lt;span class="nb"&gt;set &lt;/span&gt;image rollout-bluegreen rollouts-demo&lt;span class="o"&gt;=&lt;/span&gt;argoproj/rollouts-demo:green
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;​​You would be able to see new i.e &lt;code&gt;green&lt;/code&gt; version based set of pods of our sample app, coming up&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, after a few seconds, you would be able to see both your old set of pods (with version blue) as well as the new set of pods(with version green) available. Also on the Argo console, you would be able to see below the kind of new revision of the app with the changed image version running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gl0We8pT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmoy2ch5tb9a9a4iiik5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gl0We8pT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmoy2ch5tb9a9a4iiik5.png" alt="New Version of blue-green deployement" width="880" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you visit the &lt;a href="http://localhost:80"&gt;http://localhost:80&lt;/a&gt; on your browser, you would still see only the blue version is visible rightly because we have not yet fully promoted the green version of our app&lt;br&gt;
You can confirm the same now, by running the command below, which shows the new version is in paused state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts get rollout rollout-bluegreen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now, let us promote the green version of our app, by executing below command
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts promote rollout-bluegreen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command and you would see it's scaling the new i.e green version of our app completely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl argo rollouts get rollout rollout-bluegreen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same can be confirmed by running the below command, which shows the old set of pods i.e old blue version of our app, terminating or already terminated.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you visit the app URL on &lt;a href="http://localhost:80"&gt;http://localhost:80&lt;/a&gt; on your browser, you would see only the Green version is visible right now because we have fully promoted the green version of our app&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lJVutByF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzups8qz65urwpowfpqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lJVutByF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzups8qz65urwpowfpqx.png" alt="Argo Rollouts sample app with green-version" width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations!! you have successfully completed the blue-green deployment using Argo Rollouts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can delete this entire setup i.e our sample deployed app using the below command.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete &lt;span class="nt"&gt;-f&lt;/span&gt; argo-rollouts-example/blue-green-deployment-example/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this post, we discussed what progressive delivery is all about and its characteristics. We also learned about ArgoRollouts custom controller and how it can help to achieve the blue-green deployment, which is ultimately a form of progressive delivery.&lt;/p&gt;

&lt;p&gt;I hope you found this post informative and engaging. For more posts like this one, do subscribe to our weekly newsletter. I’d love to hear your thoughts on this post, so start a conversation on &lt;a href="https://twitter.com/NinadDesai73"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/ninad-desai/"&gt;LinkedIn&lt;/a&gt; :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Next?&lt;/strong&gt;&lt;br&gt;
Now we have developed an understanding of progressive delivery and created a blue-green deployment. Next would be to try the &lt;a href="https://www.infracloud.io/blogs/progressive-delivery-argo-rollouts-canary-deployment/"&gt;canary deployment using Argo Rollouts&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  References and further reading:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://argoproj.github.io/rollouts/"&gt;Argo Rollouts&lt;/a&gt;\&lt;br&gt;
&lt;a href="https://argoproj.github.io/argo-rollouts/"&gt;Argo Rollouts - Kubernetes Progressive Delivery Controller&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking for help with building your DevOps strategy or want to outsource DevOps to the experts? learn why so many startups &amp;amp; enterprises consider us as one of the &lt;a href="https://dev.to/devops-consulting-services/"&gt;best DevOps consulting &amp;amp; services companies&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>argo</category>
      <category>argorollouts</category>
      <category>progressivedelivery</category>
      <category>deployment</category>
    </item>
    <item>
      <title>Prometheus Definitive Guide Part III - Prometheus Operator</title>
      <dc:creator>Ninii</dc:creator>
      <pubDate>Tue, 21 Sep 2021 13:14:00 +0000</pubDate>
      <link>https://dev.to/ninii72387534/prometheus-definitive-guide-part-iii-prometheus-operator-5338</link>
      <guid>https://dev.to/ninii72387534/prometheus-definitive-guide-part-iii-prometheus-operator-5338</guid>
      <description>&lt;p&gt;In the previous post, we covered monitoring basics, including &lt;a href="https://www.infracloud.io/blogs/prometheus-architecture-metrics-use-cases/" rel="noopener noreferrer"&gt;Prometheus, metrics, its most common use cases&lt;/a&gt;, and &lt;a href="https://www.infracloud.io/blogs/promql-prometheus-guide/" rel="noopener noreferrer"&gt;how to query Prometheus data using PromQL&lt;/a&gt;. If you’re just starting with Prometheus, I’d highly recommend reading the first two parts of the ‘Prometheus Definitive Guide’ series. In this blog post, we will focus on how we can install and manage Prometheus on the Kubernetes cluster using the Prometheus Operator and Helm in an easy way. Let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an operator?
&lt;/h2&gt;

&lt;p&gt;Before moving directly to the installation of the Prometheus using the Prometheus Operator, let's first understand some of the key concepts needed to understand the Prometheus Operator. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Resource Definition (CRD)&lt;/strong&gt; resource is a way to define your own resource kind like Deployment, StatefulSet etc. CRDs define the structure and validation of the custom kind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Resource (CR)&lt;/strong&gt; are the resources that are created by following the structure from a Custom Resource Definition (CRD).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Controller&lt;/strong&gt; makes sure that our Kubernetes cluster or application always matches its current state with the desired state that we expect it to.&lt;/p&gt;

&lt;p&gt;So, &lt;strong&gt;Operator&lt;/strong&gt; is a set of Kubernetes custom controllers that we deploy in the cluster. These listen for changes in the custom resources owned by them (those which we have created using CRDs), and perform certain actions like creating, modifying, deleting Kubernetes resources.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can read more about this in the &lt;a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/" rel="noopener noreferrer"&gt;Custom Resources&lt;/a&gt; documentation page.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What are some use cases of Kubernetes operators?
&lt;/h2&gt;

&lt;p&gt;A Kubernetes operator can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide a great way to deploy stateful services like any database on Kubernetes&lt;/li&gt;
&lt;li&gt;Handling upgrades of your application code &lt;/li&gt;
&lt;li&gt;Horizontal scaling of resources according to performance metrics&lt;/li&gt;
&lt;li&gt;Backup and restoration of your application state or databases on demand&lt;/li&gt;
&lt;li&gt;Deploy any monitoring, storage, vault solutions to Kubernetes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Prometheus Operator?
&lt;/h2&gt;

&lt;p&gt;In simple words, &lt;a href="https://prometheus-operator.dev/" rel="noopener noreferrer"&gt;Prometheus Operator&lt;/a&gt; is a fully automated way of deploying (like any other standard Kubernetes Deployment object) Prometheus server, Alertmanager and all the related secrets, configmap etc; that will help to set up Prometheus monitoring ecosystem and instantiate Kubernetes cluster monitoring in just a few minutes.&lt;/p&gt;

&lt;p&gt;Once deployed, Prometheus Operator provides the following features:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Easily launch a Prometheus instance for your Kubernetes namespace, a specific application, or a team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service discovery:&lt;/strong&gt; Automatically discover the targets to be monitored using familiar Kubernetes label queries; without a need to learn a Prometheus specific configuration language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy Configuration:&lt;/strong&gt; Manage the configuration of the essential resources of Prometheus like versions, persistence, retention policies, and replicas from a Kubernetes resource.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ways to install Prometheus stack
&lt;/h2&gt;

&lt;p&gt;There are three different ways to setup the Prometheus monitoring stack in Kubernetes.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.Creating everything on your own
&lt;/h3&gt;

&lt;p&gt;If you’re completely comfortable with Prometheus components and its every prerequisites, you can then manually deploy YAML spec file for every component like Prometheus, Alertmanager and Grafana, all the Secrets and ConfigMaps used by Prometheus stack in right sequence by considering its inter dependency. &lt;/p&gt;

&lt;p&gt;This approach can be quite time consuming and take a lot of effort to deploy and manage the Prometheus ecosystem. Also it would need a strong documentation to be built to replicate it for any other environments &lt;/p&gt;

&lt;h3&gt;
  
  
  2.Using Prometheus Operator
&lt;/h3&gt;

&lt;p&gt;We have conceptually already seen the way the Prometheus Operator can ease our life by managing the life cycle of all the Prometheus components single-handedly.&lt;/p&gt;

&lt;p&gt;We can &lt;a href="https://github.com/prometheus-operator/prometheus-operator" rel="noopener noreferrer"&gt;find the Prometheus Operator here&lt;/a&gt;, that we can use to deploy Prometheus inside your Kubernetes cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.Using Helm chart to deploy operator
&lt;/h3&gt;

&lt;p&gt;This approach is the most efficient and better option where we can use the Helm chart maintained by the Prometheus community to deploy Prometheus Operator. So, in a nutshell, Helm will do initial Prometheus Operator installation along with creation of &lt;code&gt;Prometheus&lt;/code&gt;, &lt;code&gt;Alertmanager&lt;/code&gt;, and other custom resources. And then the Prometheus Operator will manage the entire life-cycle of those custom resources. It's very easy and straightforward to install by just executing the following steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

helm repo update

helm &lt;span class="nb"&gt;install &lt;/span&gt;prometheus prometheus-community/kube-prometheus-stack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kube-prometheus-stack chart installs the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus Operator&lt;/li&gt;
&lt;li&gt;Prometheus and Alertmanager (creates the &lt;code&gt;Prometheus&lt;/code&gt;, &lt;code&gt;Alertmanager&lt;/code&gt; and related CRs)&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;node-exporter, and a couple of other exporters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are also pre-configured to work together and set up basic cluster monitoring for you while also making it easy to tweak and add your own customization.&lt;/p&gt;

&lt;p&gt;The execution of the above commands will be quite quick and it will take a few more minutes to bring all the components up and running.&lt;/p&gt;

&lt;p&gt;You can run &lt;code&gt;helm get manifest prometheus | kubectl get -f -&lt;/code&gt; command to see all the objects created as below: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwt072x12tjhhegzcb7dx.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%2Fwt072x12tjhhegzcb7dx.png" alt="image"&gt;&lt;/a&gt;        &lt;/p&gt;

&lt;p&gt;You would be able to see all the different resources like the Deployments, StatefulSets of the Prometheus stack being created as shown above.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Prometheus find all the targets to monitor and scrape?
&lt;/h2&gt;

&lt;p&gt;For Prometheus to figure out what all it needs to monitor, we need to pass a &lt;a href="https://yaml.org/start.html" rel="noopener noreferrer"&gt;YAML&lt;/a&gt; configuration file, usually called &lt;code&gt;prometheus.yaml&lt;/code&gt;; that Prometheus can refer to and start monitoring accordingly. Each target endpoint to be monitored is defined under the &lt;code&gt;scrape_configs&lt;/code&gt; section in the prometheus.yaml. A typical sample configuration file that comes with Prometheus release tar has the following content:&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;# my global config&lt;/span&gt;
&lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;15s&lt;/span&gt; &lt;span class="c1"&gt;# Set the scrape interval to every 15 seconds. Default is every 1 minute.&lt;/span&gt;
  &lt;span class="na"&gt;evaluation_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15s&lt;/span&gt; &lt;span class="c1"&gt;# Evaluate rules every 15 seconds. The default is every 1 minute.&lt;/span&gt;
  &lt;span class="c1"&gt;# scrape_timeout is set to the global default (10s).&lt;/span&gt;

&lt;span class="c1"&gt;# Alertmanager configuration&lt;/span&gt;
&lt;span class="na"&gt;alerting&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;alertmanagers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;localhost:9093&lt;/span&gt;

&lt;span class="c1"&gt;# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.&lt;/span&gt;
&lt;span class="na"&gt;rule_files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/etc/prometheus/alert.rules'&lt;/span&gt;

  &lt;span class="c1"&gt;# - "first_rules.yml"&lt;/span&gt;
  &lt;span class="c1"&gt;# - "second_rules.yml"&lt;/span&gt;

&lt;span class="c1"&gt;# A scrape configuration containing exactly one endpoint to scrape:&lt;/span&gt;
&lt;span class="c1"&gt;# Here it's Prometheus itself.&lt;/span&gt;
&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# The job name is added as a label `job=&amp;lt;job_name&amp;gt;` to any timeseries scraped from this config.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prometheus'&lt;/span&gt;

    &lt;span class="c1"&gt;# metrics_path defaults to '/metrics'&lt;/span&gt;
    &lt;span class="c1"&gt;# scheme defaults to 'http'.&lt;/span&gt;

    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost:9090'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;node_exporter'&lt;/span&gt;
    &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost:9100'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, let’s dive deep into some of the major key terms from the prometheus.yaml file.&lt;/p&gt;

&lt;p&gt;There are two ways to specify a set of target endpoints &lt;strong&gt;to be scraped&lt;/strong&gt; by Prometheus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using &lt;code&gt;scrape_config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Using ServiceMonitors (Prometheus Operator specific)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  scrape_config vs ServiceMonitor: When to use one over the other?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;scrape_config&lt;/strong&gt; specifies a set of targets and configuration parameters describing how to scrape them. In this case, for each target; one scrape configuration block needs to be defined as you see in the above sample prometheus.yaml file.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;ServiceMonitor&lt;/strong&gt; lets us create a job entry in &lt;code&gt;scrape_config&lt;/code&gt; in an easier Kubernetes-native way. Internally Prometheus Operator translates the configuration from each ServiceMonitor resource to prometheus.yaml's &lt;code&gt;scrape_config&lt;/code&gt; section. The &lt;code&gt;Prometheus&lt;/code&gt; resource created by the kube-prometheus-stack has a selector which says, act on all the ServiceMonitors with label &lt;code&gt;release: prometheus&lt;/code&gt; (&lt;a href="https://github.com/prometheus-community/helm-charts/blob/2a0d552bab9f9686008fbcdb9ad63c6382485f98/charts/kube-prometheus-stack/values.yaml#L2078-L2099" rel="noopener noreferrer"&gt;configuration&lt;/a&gt;). Take a look at the diagram below of how it works:&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%2Fbka6dul8rxxzn8bxpv9i.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%2Fbka6dul8rxxzn8bxpv9i.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image Credits: &lt;a href="https://www.openshift.com/blog" rel="noopener noreferrer"&gt;CoreOS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's check if a ServiceMonitor automatically creates a scrape_config entry in the Prometheus config file or not by taking Prometheus service itself as an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get services prometheus-prometheus-oper-prometheus &lt;span class="nt"&gt;-o&lt;/span&gt; wide &lt;span class="nt"&gt;--show-labels&lt;/span&gt; 
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   SELECTOR                                                          LABELS
prometheus-prometheus-oper-prometheus   ClusterIP   10.105.67.172   &amp;lt;none&amp;gt;        9090/TCP   12d   &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prometheus,prometheus&lt;span class="o"&gt;=&lt;/span&gt;prometheus-prometheus-oper-prometheus   &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prometheus-operator-prometheus,release&lt;span class="o"&gt;=&lt;/span&gt;prometheus,self-monitor&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look if the respective ServiceMonitor is in place for Prometheus' service or not.&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 servicemonitors.monitoring.coreos.com -l app=prometheus-operator-prometheus
NAME                                    AGE
prometheus-prometheus-oper-prometheus   12d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that the ServiceMonitor for the Prometheus service itself is present. Let’s now try to see if this ServiceMonitor “prometheus-prometheus-oper-prometheus” has added a job inside the Prometheus config YAML file.&lt;/p&gt;

&lt;p&gt;To check this, we first need to access the Prometheus pod created by the Prometheus Operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; prometheus-prometheus-prometheus-oper-prometheus-0 &lt;span class="nt"&gt;--&lt;/span&gt; /bin/sh
/prometheus &lt;span class="nv"&gt;$ &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we are inside the pod, let's find out the configuration file name used by Prometheus inside the pod now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/prometheus &lt;span class="nv"&gt;$ &lt;/span&gt;ps

PID   USER     TIME  COMMAND
1     1000      4h58 /bin/prometheus … &lt;span class="nt"&gt;--config&lt;/span&gt;.file&lt;span class="o"&gt;=&lt;/span&gt;/etc/prometheus/config_out/prometheus.env.yaml
59    1000      0:00 /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could see above, the config file with name prometheus.env.yaml is created by the operator and used by the Prometheus server to find out target endpoints to be monitored and scraped. Finally, let’s try to find out if the job for the Prometheus service itself is added by ServiceMonitor or not inside this configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/prometheus &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/prometheus/config_out/prometheus.env.yaml | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; 10 &lt;span class="s2"&gt;"job_name: default/prometheus-prometheus-oper-prometheus/0"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default/prometheus-prometheus-oper-prometheus/0&lt;/span&gt;
  &lt;span class="na"&gt;honor_labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;kubernetes_sd_configs&lt;/span&gt;&lt;span class="pi"&gt;:&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;endpoints&lt;/span&gt;
    &lt;span class="na"&gt;namespaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;metrics_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/metrics&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could see the job for Prometheus service. So, this shows that a ServiceMonitor automatically creates job for the Kubernetes-based service to be monitored and scraped.&lt;/p&gt;

&lt;p&gt;There is also another way to view the scrape_config directly inside the Prometheus web UI at &lt;strong&gt;Status&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Configuration&lt;/strong&gt; as you can see below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvauhm1dt3y355yfavu9.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%2Fxvauhm1dt3y355yfavu9.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apart from ServiceMonitor, there is another way called PodMonitor to scrape your Kubernetes pods. This is also a custom resource handled by Prometheus Operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a PodMonitor, when is it needed?
&lt;/h2&gt;

&lt;p&gt;PodMonitor declaratively specifies how to directly monitor a group of pods.&lt;/p&gt;

&lt;h4&gt;
  
  
  PodMonitor vs ServiceMonitor
&lt;/h4&gt;

&lt;p&gt;One must be wondering that when we have ServiceMonitor in place, then what is the need to have PodMonitor which ultimately do the same job as ServiceMonitor.&lt;/p&gt;

&lt;p&gt;The way I see it, ServiceMonitor is suitable if you already have a Service for your pods. However, if in a certain scenario, you don't have it, then PodMonitor is the right choice. &lt;/p&gt;

&lt;h3&gt;
  
  
  Discovering targets to scrape
&lt;/h3&gt;

&lt;p&gt;To scrape target endpoints, first Prometheus should know what those are and how to monitor those targets. So, there are mainly two ways in Prometheus configuration to define the target endpoints &lt;strong&gt;to be monitored.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Using static_config mechanism
&lt;/h4&gt;

&lt;p&gt;If you have a very small and fixed set of Kubernetes services/endpoints to be monitored, then you can define those static endpoints using static_config in the prometheus.yml file.&lt;/p&gt;

&lt;p&gt;Take a look at &lt;a href="https://github.com/prometheus/prometheus/blob/release-2.29/documentation/examples/prometheus.yml" rel="noopener noreferrer"&gt;this example&lt;/a&gt; that shows how we can configure Prometheus to use static_configs to monitor Prometheus itself by default.&lt;/p&gt;

&lt;p&gt;This is fine for simple use cases, but practically having to manually keep your prometheus.yml up to date as machines are added and removed would get annoying, particularly if you were in a dynamic environment like Kubernetes where new instances of application services might be brought up every minute.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using service_discovery mechanism
&lt;/h4&gt;

&lt;p&gt;There are different Prometheus supported service-discovery mechanisms like DNS, Kubernetes, AWS, Consul, custom one, etc. These mechanisms dynamically discover target endpoints to be monitored and scraped. In the case of Kubernetes, it uses the Kubernetes API to discover a list of target endpoints to monitor and scrape.&lt;/p&gt;

&lt;p&gt;Take a look at &lt;a href="https://github.com/prometheus/prometheus/blob/release-2.29/documentation/examples/prometheus-kubernetes.yml" rel="noopener noreferrer"&gt;this example&lt;/a&gt; that shows how we can configure Prometheus for Kubernetes.&lt;/p&gt;

&lt;p&gt;Prometheus Operator takes care of configuring above based on the &lt;a href="https://prometheus-operator.dev/docs/operator/api/#servicemonitor" rel="noopener noreferrer"&gt;ServiceMonitor&lt;/a&gt; and &lt;a href="https://prometheus-operator.dev/docs/operator/api/#podmonitor" rel="noopener noreferrer"&gt;PodMonitor&lt;/a&gt; resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules in Prometheus
&lt;/h3&gt;

&lt;p&gt;Prometheus supports two types of rules which can be configured and evaluated at regular intervals. These are mainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recording rules&lt;/li&gt;
&lt;li&gt;Alerting rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can create a YAML file containing your rule statements and load them into Prometheus using the rule_files field in &lt;a href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/" rel="noopener noreferrer"&gt;Prometheus configuration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When using Prometheus Operator, these rules can be created with the helm of &lt;a href="https://prometheus-operator.dev/docs/operator/api/#prometheusrule" rel="noopener noreferrer"&gt;PrometheusRule&lt;/a&gt; resource.&lt;/p&gt;

&lt;h4&gt;
  
  
  Recording rules
&lt;/h4&gt;

&lt;p&gt;Recording rules allow you to pre-compute PromQL expressions which are frequently used and internally require a relatively large number of steps to complete the result of that expression. Next time, when you run the same PromQL query, results will be fetched from pre-computed PromQL results. These are faster than originally executing the same query again and again. &lt;/p&gt;

&lt;p&gt;For example:&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;groups&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;example&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;record&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;job:http_inprogress_requests:sum&lt;/span&gt;
      &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sum by (job) (http_inprogress_requests)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Alerting rules
&lt;/h4&gt;

&lt;p&gt;Alerting rules allow you to define alert conditions based on PromQL and to send notifications about firing alerts to an external receiver. Whenever the alert expression results in True at any point of time, it sends alerts. &lt;/p&gt;

&lt;p&gt;For example:&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;groups&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;example&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;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HighRequestLatency&lt;/span&gt;
    &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;job:request_latency_seconds:mean5m{job="myjob"} &amp;gt; &lt;/span&gt;&lt;span class="m"&gt;0.5&lt;/span&gt;
    &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10m&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;page&lt;/span&gt;
    &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;High request latency&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Alerts and visualization
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpme4enxhzun5c90a682.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%2Fdpme4enxhzun5c90a682.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Credit: &lt;a href="https://www.youtube.com/watch?v=9GMWvFcQjYI&amp;amp;t=314s" rel="noopener noreferrer"&gt;Prometheus introduction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the Alerting rules are configured, we would like to send alerts to external receivers. We would need someone who can add alert summary, control, and sometimes silence the number of notifications that the receiver will receive. This is where Alertmanager comes into the picture. &lt;/p&gt;

&lt;h3&gt;
  
  
  Alertmanager Insights
&lt;/h3&gt;

&lt;p&gt;As you can see in the above diagram, Alertmanager periodically receives information about alert state from Prometheus server and then it makes sure to group, deduplicate and send notifications to the defined receiver like email, PagerDuty, etc.&lt;/p&gt;

&lt;p&gt;But where and how to define or set up Alertmanager in the Kubernetes cluster? Well, we don't need to worry about it as the Prometheus Operator we had deployed with help of Helm chart earlier, creates an Alertmanager as a StatefulSet as you could see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get statefulsets.apps 

NAME                                                    READY      AGE
alertmanager-prometheus-prometheus-oper-alertmanager    1/1         8d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Alertmanager StatefulSet internally uses a configuration file called alertmanager.yaml as you could see below (inside alertmanager pod) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/bin/alertmanager &lt;span class="nt"&gt;--config&lt;/span&gt;.file&lt;span class="o"&gt;=&lt;/span&gt;/etc/alertmanager/config/alertmanager.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this alertmanager.yaml file (as you could see below), some of the key things like route and receiver are defined.&lt;/p&gt;

&lt;p&gt;Here,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;route:&lt;/strong&gt;&lt;br&gt;
It's a code block that defines where the alerts will be further routed to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;receiver:&lt;/strong&gt; &lt;br&gt;
Receiver is the one to whom alerts will be sent or notified finally. It can be a webhook or an email address or a tool like PagerDuty. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;inhibit_rules:&lt;/strong&gt;&lt;br&gt;
The inhibit rules section allows to silence a set of alerts given that another alert is firing for the same cause. For example, normally if any application service goes down then warning-level notification will be silenced as that service has gone into critical mode already.&lt;/p&gt;

&lt;p&gt;You can take a look at the sample Alertmanager configuration 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;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;resolve_timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5m&lt;/span&gt;

&lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;group_by&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alertname'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;group_wait&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
  &lt;span class="na"&gt;group_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
  &lt;span class="na"&gt;repeat_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1h&lt;/span&gt;
  &lt;span class="na"&gt;receiver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;web.hook'&lt;/span&gt;
&lt;span class="na"&gt;receivers&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="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;web.hook'&lt;/span&gt;
  &lt;span class="na"&gt;webhook_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://127.0.0.1:5001/'&lt;/span&gt;
&lt;span class="na"&gt;inhibit_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;source_match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;critical'&lt;/span&gt;
    &lt;span class="na"&gt;target_match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;warning'&lt;/span&gt;
    &lt;span class="na"&gt;equal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alertname'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dev'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;instance'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Metrics visualization with Grafana
&lt;/h3&gt;

&lt;p&gt;Okay, now enough of all the insights and let’s access Grafana straight away, which is a standard tool that helps you to visualize all the metrics you have gathered with help of Prometheus.&lt;/p&gt;

&lt;p&gt;Our kube-prometheus-stack Helm chart has already deployed Grafana for us. Now, to access Grafana dashboard, we first need to find the Grafana service.&lt;br&gt;
&lt;/p&gt;

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


NAME                               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;                      

prometheus-grafana                ClusterIP    10.104.143.147    &amp;lt;none&amp;gt;       80/TCP                 

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

&lt;/div&gt;



&lt;p&gt;Let's port-forward to this service so that we can access the Grafana web interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl port-forward svc/prometheus-grafana 3000:80

Forwarding from 127.0.0.1:3000 -&amp;gt; 3000
Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1]:3000 -&amp;gt; 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then in the browser visit &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re able to see the Grafana dashboard below, Congratulations!!! &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%2Fx8hhkn2k8uascbjuwrpm.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%2Fx8hhkn2k8uascbjuwrpm.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the default &lt;em&gt;username: admin&lt;/em&gt; and &lt;em&gt;password: prom-operator&lt;/em&gt; which you can find from &lt;a href="https://github.com/helm/charts/tree/master/stable/prometheus-operator" rel="noopener noreferrer"&gt;here&lt;/a&gt; to access Grafana.&lt;/p&gt;

&lt;p&gt;After adding these credentials, you would be able to logged-in to Grafana as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowtjpzzttms53pc1wtzo.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%2Fowtjpzzttms53pc1wtzo.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;Dashboard&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Manage&lt;/strong&gt;, and you would be able to see all the dashboards provided by kube-prometheus-stack about our Kubernetes cluster:&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%2Fjdy7eop20mmwdxr2g4iu.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%2Fjdy7eop20mmwdxr2g4iu.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you can browse through any of those dashboards. For example, 'Kubernetes/Compute Resources/Pod' dashboard as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6i56kx4l0xlgyv4a9mg.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%2Fh6i56kx4l0xlgyv4a9mg.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These all standard dashboards are basically generated from the &lt;a href="https://github.com/kubernetes-monitoring/kubernetes-mixin" rel="noopener noreferrer"&gt;kubernetes-mixin&lt;/a&gt; project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Let’s do a quick recap before concluding this post. We discussed what the Prometheus Operator is and how we can configure Prometheus easily with help of the Prometheus Operator and Helm charts. We also explored how Prometheus discovers the resources to monitor and what all components of Prometheus one needs to configure and how they work. Plus, we  also looked at how we can set up alerts as well as how to visualize them.&lt;/p&gt;

&lt;p&gt;I hope you found this post informative and engaging. For more posts like this one, do subscribe to our weekly newsletter. I’d love to hear your thoughts on this post, so do start a conversation on &lt;a href="https://www.twitter.com/infracloudio" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/company/infracloudio" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; :).&lt;/p&gt;

&lt;h3&gt;
  
  
  References and further reading:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;Official Prometheus documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=QoDqxm7ybLc&amp;amp;t=284s&amp;amp;ab_channel=TechWorldwithNana" rel="noopener noreferrer"&gt;Setup Prometheus Monitoring on Kubernetes using Helm and Prometheus Operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prometheus-operator/prometheus-operator" rel="noopener noreferrer"&gt;https://github.com/prometheus-operator/prometheus-operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>monitoring</category>
      <category>prometheus</category>
      <category>operator</category>
      <category>observability</category>
    </item>
    <item>
      <title>Achieving Cloud Native Security and Compliance with Teleport</title>
      <dc:creator>Ninii</dc:creator>
      <pubDate>Wed, 17 Feb 2021 13:34:42 +0000</pubDate>
      <link>https://dev.to/ninii72387534/achieving-cloud-native-security-and-compliance-with-teleport-554b</link>
      <guid>https://dev.to/ninii72387534/achieving-cloud-native-security-and-compliance-with-teleport-554b</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S_wdCjoZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v8s4byx3i1s0g5osfipw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S_wdCjoZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v8s4byx3i1s0g5osfipw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Security is the most critical aspect for any IT solutions and with the ever-increasing adoption of cloud-native technologies, the need for &lt;a href="https://www.nccoe.nist.gov/projects/building-blocks/zero-trust-architecture"&gt;Zero Trust Architecture&lt;/a&gt; is irrefutable as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The traditional networking approach is not effective enough to provide full security to cloud-native applications.&lt;/li&gt;
&lt;li&gt;With cloud offerings being heavily getting used going forward, security policies around the application need to be scalable as well.&lt;/li&gt;
&lt;li&gt;With more emphasis on loosely coupled microservice-based applications, chances of vulnerabilities getting introduced also increases.&lt;/li&gt;
&lt;li&gt;People are using multiple clouds to take advantage of the offerings.&lt;/li&gt;
&lt;li&gt;On-premise to the cloud and another way around connectivity is a reality.&lt;/li&gt;
&lt;li&gt;Devices that span beyond traditional data centres &amp;amp; cloud are increasingly being used to provide connectivity to remote sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To sum up, it means there is no "real network boundary" anymore, and hence we need to have a way in which we don't trust anyone. Traditionally it was assumed that communication between entities inside the same data centre is secure; whereas with zero trusts, we don't even assume that. So, it has become a mandate to have a zero-trust security framework around your cloud-native applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teleport? What is it? Why is it needed?
&lt;/h2&gt;

&lt;p&gt;Gravitational &lt;a href="https://goteleport.com/"&gt;Teleport&lt;/a&gt; is one such fine product which fits in the space of &lt;a href="https://en.wikipedia.org/wiki/Zero_Trust_Networks"&gt;“Zero Trust Networks”&lt;/a&gt; for cloud-native applications. It acts as a gateway machine for identity and access management of clusters of Linux servers via SSH or the Kubernetes API. It can replace the use of traditional OpenSSH going forward for organizations who are looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better security and compliance practices.&lt;/li&gt;
&lt;li&gt;End to end visibility of activities happening in their infrastructure.&lt;/li&gt;
&lt;li&gt;Achieving compliance for their software products like SOC 2.&lt;/li&gt;
&lt;li&gt;Reduction in the operational burden of access management across both on-premise and cloud-native infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Benefits of using Teleport for cloud-native applications
&lt;/h2&gt;

&lt;p&gt;Teleport is a cloud-native SSH solution. Below is a list of the key features that Teleport offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can act as a single SSH/Kubernetes gateway machine for your organizations.&lt;/li&gt;
&lt;li&gt;It can provide an audit log and recording of all kubectl commands executed in your Kubernetes cluster.&lt;/li&gt;
&lt;li&gt;It can also run in “agentless” mode also where session details can be MITM-ed and taped on the proxy server; instead of keeping them on the nodes.&lt;/li&gt;
&lt;li&gt;It does not rely on static keys and provides authentication based on SSH certificate.&lt;/li&gt;
&lt;li&gt;It uses auto-expiring keys signed by a cluster certificate authority (CA).&lt;/li&gt;
&lt;li&gt;It enforces 2nd-factor authentication.&lt;/li&gt;
&lt;li&gt;You can connect to your clusters (protected by a firewall) without internet access via SSH bastion host.&lt;/li&gt;
&lt;li&gt;You can share sessions with your colleagues for troubleshooting any issues collectively.&lt;/li&gt;
&lt;li&gt;It’s a single tool that can manage RBAC for both SSH and Kubernetes.&lt;/li&gt;
&lt;li&gt;You can replay audit logs from recorded sessions to detect any safety issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s find out how this tool works in the following sections along with the inner workings of Teleport.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Let's walk through a scenario of a user connecting to a node and how Teleport works in that case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zVxJ3JUz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yawwlrbacqa7qbum35z6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zVxJ3JUz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yawwlrbacqa7qbum35z6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
source: &lt;a href="https://goteleport.com/teleport/docs/architecture/overview/"&gt;https://goteleport.com/teleport/docs/architecture/overview/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1: Establishing client connection
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Lkxfzv9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aimxseiceh0bfzubqq7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Lkxfzv9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aimxseiceh0bfzubqq7t.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
source: &lt;a href="https://goteleport.com/teleport/docs/architecture/overview/"&gt;https://goteleport.com/teleport/docs/architecture/overview/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To initiate the client connection; when the client tries to SSH to the required target, it first establishes a connection to the Teleport proxy and offers the client’s certificate. Teleport proxy makes sure to record SSH sessions and keep an eye on live and active sessions of users. With records of all users logged in to the target server, Teleport proxy also helps SSH users to see if anyone else is also connected to the same target that the client is intending. Once client ssh to server, it can run command &lt;code&gt;tsh status&lt;/code&gt; which provides session id as well user id of the users who are logged in.&lt;/p&gt;
&lt;h3&gt;
  
  
  2: Authenticate client provided certificate
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8NlWeGZh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wz800tpxjdpiozf9a4ew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8NlWeGZh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wz800tpxjdpiozf9a4ew.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
source: &lt;a href="https://goteleport.com/teleport/docs/architecture/overview/"&gt;https://goteleport.com/teleport/docs/architecture/overview/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the user or client is logging in for the 1st time or if the previously provided client certificate is expired, the proxy server will deny the further connection. In this case, it requests the user or client to again login using a new password and two-factor authentication code if it is enabled already. Since this connection request is HTTPS, Teleport must have the right HTTPS certificate installed on the proxy server.&lt;/p&gt;

&lt;p&gt;For 2FA currently, Teleport supports Google Authenticator, Authy, and any time-based one-time password generators.&lt;/p&gt;
&lt;h3&gt;
  
  
  3: Lookup node
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SOaQZN31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqwi3hmap1cpn5rdhz6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SOaQZN31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqwi3hmap1cpn5rdhz6m.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
source: &lt;a href="https://goteleport.com/teleport/docs/architecture/overview/"&gt;https://goteleport.com/teleport/docs/architecture/overview/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this stage, the proxy server tries to find out the requested target server in the cluster. It uses three lookup mechanisms to find out the requested target/node server’s IP address.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lookup mechanism 1&lt;/strong&gt;: Using DNS resolver to resolve the target name requested by the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lookup mechanism 2&lt;/strong&gt;: The next step is to check with the Teleport Auth Server if the requested target/node server is present in its list of target/nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lookup mechanism 3&lt;/strong&gt;: Finally the Teleport Auth Server is used to find the target server/node with the label name suggested by the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the requested target/node server is located, the proxy server further forwards the connection request from the client to that target/node server. Then that target server starts creating an event log file using the dir backend. The entire session recording log is stored in &lt;code&gt;data_dir&lt;/code&gt; under log directory (usually in &lt;code&gt;/var/lib/teleport/log/sessions/default&lt;/code&gt;) .This session log contains events like &lt;code&gt;session.start&lt;/code&gt; and &lt;code&gt;session.end&lt;/code&gt;. It also records the complete stream of bytes which goes as the standard input to an SSH session as well as the standard output from an SSH session. These target session's event logs are stored in a raw format which is either &lt;code&gt;.bytes&lt;/code&gt; or &lt;code&gt;.chunks.gz&lt;/code&gt;. From these raw logs, a video recording of the SSH session is generated.&lt;/p&gt;

&lt;p&gt;For example, we can see the session files from one target node by running following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ls /var/lib/teleport/log/sessions/default

-rw-r----- 1 root root 506192 Feb 4 00:46 1c301ec7-aec5-22e4-c1c3-40167a86o821.session.bytes

-rw-r----- 1 root root  44943 Feb 4 00:46 1c301ec7-aec5-22e4-c1c3-40167a86o821.session.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If needed, we can run commands like &lt;code&gt;tsh --proxy=proxy play 1c301ec7-aec5-22e4-c1c3-40167a86o821&lt;/code&gt; to replay a session.&lt;/p&gt;

&lt;p&gt;This is how the target server records the session and keep sharing it to Auth Server for storage purpose.&lt;/p&gt;
&lt;h3&gt;
  
  
  4: Authenticate node certificate
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6whdsvx8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mn9r1z04vdz1onqz3y2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6whdsvx8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mn9r1z04vdz1onqz3y2i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
source:&lt;a href="https://goteleport.com/teleport/docs/architecture/overview/"&gt;https://goteleport.com/teleport/docs/architecture/overview/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For future connection requests, when the target/node server receives a client connection request, it again goes back and checks with the Teleport Auth Server if the target/node’s certificate is valid or not. If the certificate is valid, then the target/node server starts the SSH session.&lt;/p&gt;
&lt;h3&gt;
  
  
  5: Grant user node access
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MIMFTzgl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nhpagpjbunu85b684yc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MIMFTzgl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nhpagpjbunu85b684yc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
source:&lt;a href="https://goteleport.com/teleport/docs/architecture/overview/"&gt;https://goteleport.com/teleport/docs/architecture/overview/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the last step, target/node server requests to the Teleport Auth Server to provide a list of OS users and cross-verify that the client is really authorized to use the requested OS login and thus the client is authorized to SSH to requested target/node server.&lt;/p&gt;

&lt;p&gt;To sum up, if a user Joe wants to connect the server/node called &lt;code&gt;grav-00&lt;/code&gt;; then below is the sequence of actions that takes place inside Teleport to allow Joe access to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---pwUNa6_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8mihp0si3qzhsifle231.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---pwUNa6_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8mihp0si3qzhsifle231.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;source:&lt;a href="https://goteleport.com/teleport/docs/architecture/overview/"&gt;https://goteleport.com/teleport/docs/architecture/overview/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation/demo
&lt;/h2&gt;

&lt;p&gt;Just for demo purpose, we will have one Teleport master, which will run Teleport and secure only one node/target server. In production, you might have more than one Teleport master for high availability and potentially hundreds of nodes secured by Teleport. For now, we will do these steps manually but you can easily automate them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y9K5iPXi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p7pdobzdfp0x0x6wuiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y9K5iPXi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p7pdobzdfp0x0x6wuiw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;For installation of Teleport, we would need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Linux machine with ports 3023, 3024, 3025 and 3080 open.&lt;/li&gt;
&lt;li&gt;A domain name, DNS and TLS certificates for a production system.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Installation steps
&lt;/h2&gt;

&lt;p&gt;Note that the following installation is completed and tested with help of localhost and self-signed certificate, by referring to the &lt;a href="https://goteleport.com/teleport/docs/quickstart/"&gt;Teleport Quick Start guide&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Install Teleport on a Linux host
&lt;/h3&gt;

&lt;p&gt;There are multiple ways to install Teleport which you can find &lt;a href="https://goteleport.com/teleport/docs/installation/"&gt;here&lt;/a&gt;. I will be following the one for Amazon Linux.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum-config-manager --add-repo https://rpm.releases.teleport.dev/teleport.repo
sudo yum install teleport
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 2: Configure Teleport
&lt;/h3&gt;

&lt;p&gt;It’s recommended by Teleport to use a YAML configuration file for setting it up. Create a YAML file called &lt;code&gt;teleport.yaml&lt;/code&gt;, and add the below configurations to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Make sure to validate your &lt;code&gt;teleport.yaml&lt;/code&gt; file, with the help of local tools like &lt;a href="https://yamllint.readthedocs.io/en/stable/quickstart.html"&gt;yamllint&lt;/a&gt; (which can be launched easily from the local console) to avoid any syntax errors.&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;# teleport.yaml&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;app_service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;debug_app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;auth_service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cluster_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;teleport-quickstart&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;listen_addr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;internal_ip_of_server&amp;gt;:3025"&lt;/span&gt;
  &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proxy,node,app:f7adb7ccdf04037bcd2b52ec6010fd6f0caec94ba190b765"&lt;/span&gt;
&lt;span class="na"&gt;proxy_service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;listen_addr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:3023"&lt;/span&gt;
  &lt;span class="na"&gt;tunnel_listen_addr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:3024"&lt;/span&gt;
  &lt;span class="na"&gt;web_listen_addr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:3080"&lt;/span&gt;
&lt;span class="na"&gt;ssh_service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;staging&lt;/span&gt;
&lt;span class="na"&gt;teleport&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/lib/teleport&lt;/span&gt;  &lt;span class="c1"&gt;# This is the default directory, where Teleport stores its log and all the configuration files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Below are some of the configuration details present in this above yaml file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;teleport.data_dir: /var/lib/teleport&lt;/code&gt;:&lt;br&gt;This is the default data directory, where Teleport stores its log and all the configuration files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;auth_service&lt;/code&gt; section:&lt;br&gt;Auth service listens on SSH port 3025 to provide its API to communicate with other nodes in a cluster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;auth_service.tokens&lt;/code&gt;:&lt;br&gt;To make each node/server participate in the Teleport cluster, we need to establish a secure tunnel between the master and the other participating nodes. For this connection, there should be a shared secret among them. This secret is nothing but what we call a token. We can generate a static token or a dynamic one. For the demo purpose, we are going to use a static one &lt;code&gt;f7adb7ccdf04037bcd2b52ec6010fd6f0caec94ba190b765&lt;/code&gt;. (Teleport recommends using tools like &lt;code&gt;pwgen -s 32&lt;/code&gt; to generate sufficiently random static tokens of 32+ byte length).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy_service&lt;/code&gt; section:&lt;br&gt;Proxy service listens on port 3023 (i.e &lt;code&gt;listen_addr&lt;/code&gt;) and acts as a forwarder to direct incoming connection request to desired target node on port 3022 (which is Teleport equivalent of port 22 for SSH).&lt;br&gt;Also this proxy service uses SSH port 3024 to do a reverse SSH tunnelling behind a firewall, into a proxy server.&lt;br&gt;Web UI of teleport listen on this port and all HTTPS connection are from tsh users are authenticated on this port.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;app_service&lt;/code&gt; section:&lt;br&gt;For testing and debugging, Teleport provides an in-bulit app, which can be enabled by setting &lt;code&gt;debug_app&lt;/code&gt; as &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, you can move this file to Teleport's default configuration location by running &lt;code&gt;sudo mv teleport.yaml /etc&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Configure domain name and obtain TLS certificates
&lt;/h3&gt;

&lt;p&gt;Teleport normally requires a secured publicly accessible endpoint, and so a domain name and TLS certificates are needed too. But since we are doing just a test here; we can locally set up them using the self-signed TLS certificate without a domain name.&lt;/p&gt;
&lt;h4&gt;
  
  
  Self-signed TLS certificate creation
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openssl req -x509 -out localhost.crt -keyout localhost.key \
    -newkey rsa:2048 -nodes -sha256 \
    -subj '/CN=localhost' -extensions EXT -config &amp;lt;( \printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This will create a certificate &lt;code&gt;localhost.crt&lt;/code&gt; and a key &lt;code&gt;localhost.key&lt;/code&gt; in your current directory.&lt;/p&gt;
&lt;h4&gt;
  
  
  Update teleport.yaml with certificate details
&lt;/h4&gt;

&lt;p&gt;We can now amend the previously created &lt;code&gt;teleport.yaml&lt;/code&gt; configuration with above locally created TLS certificate. Add the below code at the end of previous YAML configurations with a new section &lt;code&gt;https_keypairs&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;https_keypairs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/local/bin/localhost.key&lt;/span&gt;
  &lt;span class="na"&gt;cert_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/local/bin/localhost.crt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now, you can start Teleport directly using &lt;code&gt;sudo teleport start&lt;/code&gt; or else in case, if you are already in /usr/local/bin directory, you can also use &lt;code&gt;nohup sudo ./teleport start &amp;amp;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also setup a systemd service by following &lt;a href="https://github.com/gravitational/teleport/tree/master/examples/systemd"&gt;these instructions&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4: Create a Teleport user and set up 2-factor authentication
&lt;/h3&gt;

&lt;p&gt;Next step is to create teleport-admin which will help us to SSH into any node which is part of the Teleport cluster. For that, we need to assign an OS user to the teleport-admin account. This can be achieved using the below command which will assign OS users &lt;code&gt;root&lt;/code&gt;, &lt;code&gt;ubuntu&lt;/code&gt; and &lt;code&gt;ec2-user&lt;/code&gt; to the &lt;code&gt;teleport-admin&lt;/code&gt; user.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo tctl users add teleport-admin root,ubuntu,ec2-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Once you run this command, Teleport will give you output similar to below.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User teleport-admin has been created but requires a password. Share this URL with the user to complete user setup, link is valid for 1h0m0s:

https://&amp;lt;internal_ip_address&amp;gt;:3080/web/invite/7e3bd3d504c10b2637db6b06f29529

NOTE: Make sure &amp;lt;internal_ip_address&amp;gt;:3080 points at a Teleport proxy that users can access.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You can now go to your any favourite browser, and put the URL:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;public_ip_address_of_server_where_teleport_installed&amp;gt;:3080/web/invite/7e3bd3d504c10b2637db6b06f29529
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Which will open a page like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ON0p4UO0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bhtnzf9604giyanqwqqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ON0p4UO0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bhtnzf9604giyanqwqqz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set any desired password with a minimum length of six characters and use any authenticator (like Google Authenticator, Authy etc) to scan and obtain 6 digit code and put that into TWO FACTOR TOKEN dialogue box.&lt;/p&gt;

&lt;p&gt;Once completed above, below home-page will appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cu2dSeex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/02mjfun69f8e6f6w1eds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cu2dSeex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/02mjfun69f8e6f6w1eds.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congratulations!! You have successfully installed a single node cluster of Teleport.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5: Log in using tsh to your Teleport cluster
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsh login --proxy=localhost:3080 --user=teleport-admin --insecure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You will see the below kind of prompt for password and OTP that you will receive over your authenticator.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING: You are using insecure connection to SSH proxy https://localhost:3080
Enter password for Teleport user teleport-admin:
Enter your OTP token:
511510
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;On successful login, you will see the below message displayed.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING: You are using insecure connection to SSH proxy https://localhost:3080
Profile URL:   https://localhost:3080
Logged in as:       teleport-admin
Cluster:            teleport-quickstart
Roles:              admin*
Logins:             ec2-user, root, ubuntu
Kubernetes:         disabled
Valid until:        2021-01-07 05:20:50 +0000 UTC [valid for 12h0m0s]
Extensions:         permit-agent-forwarding, permit-port-forwarding, permit-pty
RBAC is only available in Teleport Enterprise
https://gravitational.com/teleport/docs/enterprise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 6: Check Teleport cluster
&lt;/h3&gt;

&lt;p&gt;You can check the status of your cluster using command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user@ip-172-31-34-133 bin]$ tsh ls
Node Name                                    Address            Labels
-------------------------------------------- ------------------ -----------
ip-172-31-34-133.ap-south-1.compute.internal 172.31.34.133:3022 env=staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 7: Add new node or target server in Teleport cluster
&lt;/h3&gt;

&lt;p&gt;You can now secure more servers with Teleport by adding them to the Teleport cluster we just created. For that, we need to install Teleport on all those servers/nodes by doing &lt;strong&gt;Step 1 and Step 2&lt;/strong&gt; that we did earlier on those new target servers, followed by a simple below command to be executed on those target servers (to add those servers in a cluster).&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo teleport start --roles=node --token=f7adb7ccdf04037bcd2b52ec6010fd6f0caec94ba190b765 --labels=env=quickstart --insecure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;After this command, you will see the output as:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[NODE]         Service 5.1.0:v5.1.0-0-g46679fb34 is starting on 0.0.0.0:3022.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Which confirms that the node has been added in the Teleport cluster. We can be sure of that by running &lt;code&gt;tsh ls&lt;/code&gt; command on Teleport master server (where we installed Teleport cluster first).&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user@ip-172-31-34-133 bin]$ tsh ls
Node Name                                    Address            Labels
------------------------------------------------- ------------------ --------------
ip-172-31-34-133.ap-south-1.compute.internal 172.31.34.133:3022 env=staging
ip-172-31-41-130.ap-south-1.compute.internal 172.31.41.130:3022 env=quickstart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We can now login into any node by doing, &lt;code&gt;tsh ssh user-name@Node Name&lt;/code&gt;. The target &lt;code&gt;Node Name&lt;/code&gt; in this command, is the one you will find in 'Node Name' column of &lt;code&gt;tsh ls&lt;/code&gt; command's output.&lt;/p&gt;

&lt;p&gt;And now, once the user is connected to the required target server/node, then on the Teleport web UI, you would be able to see video recordings of all the user activities during a particular session on the Teleport web UI once the user is connected to the required target server/node. A quick video demonstration of the same is shown below.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Demo
&lt;/h2&gt;

&lt;p&gt;The demo video will show you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How to check Teleport cluster status by running the &lt;code&gt;tsh status&lt;/code&gt; command and list the nodes participating in the cluster with the help of the &lt;code&gt;tsh ls&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;How the web interface of Teleport looks like, with different sections.&lt;/li&gt;
&lt;li&gt;How to access the &lt;strong&gt;Session Recordings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;How you can &lt;strong&gt;Join session&lt;/strong&gt; for troubleshooting collectively with other users.&lt;/li&gt;
&lt;li&gt;How you can access the &lt;strong&gt;Audit logs&lt;/strong&gt; in JSON format.&lt;/li&gt;
&lt;/ol&gt;

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

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

&lt;p&gt;Implementing security and achieving compliance particularly in the cloud-native infrastructure has been challenging for most organisations. In many cases, doing-it-yourself with a variety of capabilities and tools turns out to be a complex solution.&lt;/p&gt;

&lt;p&gt;Teleport is a mature product with a focus on developer productivity and its alignment to help with compliance makes them a leader. Some features like ChatOps integration, focus on edge/IoT connectivity, a variety of SSO integrations, are attractive. Just to keep in mind that a lot of things can be done using their open-source offering but I find that implementing RBAC would become a bare minimum requirement in an enterprise environment, where you would need the enterprise version.&lt;/p&gt;

&lt;p&gt;Hope this post was helpful to you. Do try Teleport for cloud-native security and compliance, and share your experience in the comments section below. Happy Coding :)&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://goteleport.com/teleport/docs/"&gt;https://goteleport.com/teleport/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href="https://www.nccoe.nist.gov/projects/building-blocks/zero-trust-architecture"&gt;https://www.nccoe.nist.gov/projects/building-blocks/zero-trust-architecture&lt;/a&gt;]&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cloudnative</category>
      <category>cybersecurity</category>
      <category>security</category>
      <category>compliance</category>
    </item>
  </channel>
</rss>
