<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Tunde Oladipupo</title>
    <description>The latest articles on Forem by Tunde Oladipupo (@simplytunde).</description>
    <link>https://forem.com/simplytunde</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%2F99364%2F7cd4a4ed-af20-4974-98d7-7362033a3ed7.jpeg</url>
      <title>Forem: Tunde Oladipupo</title>
      <link>https://forem.com/simplytunde</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/simplytunde"/>
    <language>en</language>
    <item>
      <title>Terraform and AWS</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Sat, 31 Dec 2022 15:28:39 +0000</pubDate>
      <link>https://forem.com/simplytunde/terraform-and-aws-4l0n</link>
      <guid>https://forem.com/simplytunde/terraform-and-aws-4l0n</guid>
      <description>&lt;p&gt;This is tunde&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>Randomness in Go</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Sat, 29 Aug 2020 04:08:46 +0000</pubDate>
      <link>https://forem.com/simplytunde/randomness-in-go-1ang</link>
      <guid>https://forem.com/simplytunde/randomness-in-go-1ang</guid>
      <description>&lt;p&gt;This is to discuss ways to generate random values in go using the rand package or the crypto rand. They both achieve the same end depending on your need regarding true randomness and performance.  Lets start with the common &lt;code&gt;math/rand&lt;/code&gt; package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"math/rand"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;))&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;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;gotest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; 
&lt;span class="m"&gt;31&lt;/span&gt;
&lt;span class="m"&gt;37&lt;/span&gt;
&lt;span class="m"&gt;47&lt;/span&gt;
&lt;span class="m"&gt;9&lt;/span&gt;
&lt;span class="m"&gt;31&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;gotest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; 
&lt;span class="m"&gt;31&lt;/span&gt;
&lt;span class="m"&gt;37&lt;/span&gt;
&lt;span class="m"&gt;47&lt;/span&gt;
&lt;span class="m"&gt;9&lt;/span&gt;
&lt;span class="m"&gt;31&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see from above, the run produces the same sequence because the default seeding source.Now, lets try to use a different seeding for our random sequence generation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"math/rand"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnixNano&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;))&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;blockquote&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Random numbers are generated by a Source. Top-level functions, such as
// Float64 and Int, use a default shared Source that produces a deterministic
// sequence of values each time a program is run. Use the Seed function to
// initialize the default Source if different behavior is required for each run.
// The default Source is safe for concurrent use by multiple goroutines, but
// Sources created by NewSource are not.
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;What we simply did was provide new seeding via new  source. Please note this source is not safe for concurrent use unlike the shared source used globally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;gotest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; 
&lt;span class="m"&gt;44&lt;/span&gt;
&lt;span class="m"&gt;17&lt;/span&gt;
&lt;span class="m"&gt;41&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;
&lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;gotest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; 
&lt;span class="m"&gt;18&lt;/span&gt;
&lt;span class="m"&gt;7&lt;/span&gt;
&lt;span class="m"&gt;37&lt;/span&gt;
&lt;span class="m"&gt;17&lt;/span&gt;
&lt;span class="m"&gt;13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now to be truly random, you can use the better &lt;code&gt;crypto/rand&lt;/code&gt; but with less performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crypto Rand
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;crypto_rand&lt;/span&gt; &lt;span class="s"&gt;"crypto/rand"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/base64"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GenerateRandomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;crypto_rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GenerateRandomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GenerateRandomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URLEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&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;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GenerateRandomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&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;What we doing here is very simple, we are not using clock to generate our seedling.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>What on earth is Go Mod?</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Wed, 19 Feb 2020 16:04:57 +0000</pubDate>
      <link>https://forem.com/simplytunde/what-on-earth-is-go-mod-2fla</link>
      <guid>https://forem.com/simplytunde/what-on-earth-is-go-mod-2fla</guid>
      <description>&lt;p&gt;Go mod is the recommended way to manage packages and their dependencies in go. Go can look at your imported packages and add them to its &lt;strong&gt;go.mod&lt;/strong&gt; for management. For example, in this &lt;a href="https://github.com/knative/client/blob/master/go.mod"&gt;project&lt;/a&gt;;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;knative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;

&lt;span class="n"&gt;require&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;contrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opencensus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;exporter&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ocagent&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.6.0&lt;/span&gt; &lt;span class="c"&gt;// indirect&lt;/span&gt;
    &lt;span class="n"&gt;contrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opencensus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;exporter&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;prometheus&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.1.0&lt;/span&gt; &lt;span class="c"&gt;// indirect&lt;/span&gt;
    &lt;span class="n"&gt;contrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opencensus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;exporter&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;stackdriver&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.12.9&lt;/span&gt; &lt;span class="c"&gt;// indirect&lt;/span&gt;
    &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;containerregistry&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.0.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;20200131185320&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;aec8da010de2&lt;/span&gt; &lt;span class="c"&gt;// indirect&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openzipkin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;zipkin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.2.2&lt;/span&gt; &lt;span class="c"&gt;// indirect&lt;/span&gt;
    &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.8.1&lt;/span&gt;
    &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;robfig&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.2.0&lt;/span&gt; &lt;span class="c"&gt;// indirect&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;golang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;crypto&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.0.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;20191206172530&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e9b2fee46413&lt;/span&gt;
    &lt;span class="n"&gt;gotest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="m"&gt;.2.0&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;incompatible&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;sigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;yaml&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.1.0&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Temporary pinning certain libraries. Please check periodically, whether these are still needed&lt;/span&gt;
&lt;span class="c"&gt;// ----------------------------------------------------------------------------------------------&lt;/span&gt;

&lt;span class="c"&gt;// Fix for `[` in help messages and shell completion code&lt;/span&gt;
&lt;span class="c"&gt;// See https://github.com/spf13/cobra/pull/899&lt;/span&gt;
&lt;span class="n"&gt;replace&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;spf13&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cobra&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;chmouel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cobra&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.0.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;20191021105835&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a78788917390&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="m"&gt;1.13&lt;/span&gt;

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



&lt;p&gt;The go.mod has the required modules for this module as well as their specific version.  Talking about version, you can see we have different version as well as comment. Lets take a look;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Semvars&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;github.com/pkg/errors v0.8.1
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This package is required but version &lt;code&gt;v0.8.1&lt;/code&gt; of it. If this module is updated in its remote git repo with the new version, go will not used it but &lt;code&gt;v0.8.1&lt;/code&gt; instead&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pseudo-versions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;knative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;eventing&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.12.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;0.20200206203632&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b0a7d8a77cc7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This is the same as semvar but with weird version generated by go in form of &lt;code&gt;last_tag-date-commit_hash&lt;/code&gt;. This is done when you import a package without specifying the version to use. Go simply update with the last tagged version(v0.12.1 in the case of knative.dev/eventing), then calculate the time of last commit as well as hash of last commit in the git repo to generate its version tag to give us &lt;code&gt;v0.12.1-0.20200206203632-b0a7d8a77cc7&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  replace
&lt;/h4&gt;

&lt;p&gt;So you have an external dependency in your project that you want to make some local changes to or replace temporarily with another source for testing or specific purpose. How do you do that? You can use &lt;code&gt;replace&lt;/code&gt;. This means instead of using the external dependency source, it will use the replacement instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;replace github.com/spf13/cobra =&amp;gt; github.com/chmouel/cobra v0.0.0-20191021105835-a78788917390&lt;/span&gt;

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



&lt;p&gt;This will make go mod use &lt;code&gt;github.com/chmouel/cobra&lt;/code&gt;  anywhere &lt;code&gt;github.com/spf13/cobra&lt;/code&gt; is used. You can do the same locally by pointing the replacement to local path.&lt;/p&gt;

&lt;h4&gt;
  
  
  incompatible
&lt;/h4&gt;

&lt;p&gt;Let's talk incompatible. If a repo does not have &lt;code&gt;go.mod&lt;/code&gt; and it has semver  that is &lt;code&gt;&amp;gt;= 2&lt;/code&gt;,it will tagged with the semver as well as incompatible to indicate this is not a go mod repo. For our case,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;gotest.tools v2.2.0+incompatible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you look at the tagged &lt;a href="https://github.com/gotestyourself/gotest.tools/tree/v2.2.0"&gt;repo&lt;/a&gt;, you can see the repo is missing go.mod and its on &lt;code&gt;&amp;gt;=2&lt;/code&gt; tag.&lt;/p&gt;

&lt;h4&gt;
  
  
  go version directive
&lt;/h4&gt;

&lt;p&gt;This simply answers the question of which golang version and features should I use? I will quote one of the &lt;a href="https://github.com/golang/go/issues/30791#issuecomment-472217112"&gt;authority&lt;/a&gt; on this for better explanation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The basic guideline is fairly simple: a "go" directive 1.N means that the code in that module is permitted to use language features that  existed in 1.N even if those features were removed in later releases of  the language. &lt;/p&gt;

&lt;p&gt;In other words, if the code compiles successfully at version 1.N,  then it will continue to compile for all later versions of the language, even if it happens to use language features that were later removed. &lt;/p&gt;

&lt;p&gt;To a first approximation, nobody should ever have to worry about the  "go" directive.  The only likely time you might need to set it manually  is if you are copying some existing code to a new module, that code uses some obsolete language feature, and you don't have time to rewrite it.  In that case you might want to set the "go" directive (using &lt;code&gt;go mod edit -go&lt;/code&gt;) to the version used by the original module, thus permitting your new  module to use the obsolete features.  When writing new code you will  presumably simply avoid the obsolete language features.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  go sum
&lt;/h4&gt;

&lt;p&gt;This &lt;code&gt;go.sum&lt;/code&gt; is way for go to keep cryptographic hash of the  modules version in &lt;code&gt;go.mod&lt;/code&gt;. It keeps a cache copy of this  hashes and verifies them during run. Make sure to check in the &lt;code&gt;go.sum&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;golang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.0.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;20170915032832&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="n"&gt;c0d48ead0c&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="n"&gt;golang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.0.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;20170915032832&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="n"&gt;c0d48ead0c&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;NqM8EUOU14njkJ3fqMW&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;pc6Ldnwhi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;IjpwHt7yyuwOQ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="n"&gt;rsc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;quote&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.5.2&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;w5fcysjrx7yqtD&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;aO&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;QwRjYZOKnaM9Uh2b40tElTs3Y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="n"&gt;rsc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;quote&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.5.2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;TKr0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="n"&gt;rsc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sampler&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.3.0&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="n"&gt;uVkIFmeBqHfdjD&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gZwtXXI&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;RODJ2Wc4O7MPEh&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;QiW4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="n"&gt;rsc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sampler&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="m"&gt;.3.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>go</category>
    </item>
    <item>
      <title>Go dependency management and dep</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Thu, 13 Feb 2020 20:25:38 +0000</pubDate>
      <link>https://forem.com/simplytunde/go-dependency-management-and-dep-46g0</link>
      <guid>https://forem.com/simplytunde/go-dependency-management-and-dep-46g0</guid>
      <description>&lt;p&gt;You may be aware of the "official experiment" for go dependency management tool called &lt;strong&gt;dep&lt;/strong&gt; but this has since be replaced by &lt;strong&gt;go mod&lt;/strong&gt;. Let's explore the tool via this opensource &lt;a href="https://github.com/knative/serving/blob/master/Gopkg.toml"&gt;project&lt;/a&gt; usage.  &lt;code&gt;Gopkg.toml&lt;/code&gt; is where you define your package dependencies while &lt;code&gt;Gopkg.lock&lt;/code&gt; contains snapshot of your project dependencies after evaluating &lt;code&gt;Gopkg.toml&lt;/code&gt; as well as some metadata. Here is;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Refer&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="c"&gt;//github.com/golang/dep/blob/master/docs/Gopkg.toml.md&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;detailed&lt;/span&gt; &lt;span class="n"&gt;Gopkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toml&lt;/span&gt; &lt;span class="n"&gt;documentation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;"knative.dev/pkg/codegen/cmd/injection-gen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="m"&gt;4549&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Drop&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;our&lt;/span&gt; &lt;span class="n"&gt;patches&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="s"&gt;"k8s.io/kubernetes/pkg/version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;"knative.dev/caching/pkg/apis/caching"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;cluster&lt;/span&gt; &lt;span class="n"&gt;management&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;performance&lt;/span&gt; &lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="s"&gt;"knative.dev/pkg/testutils/clustermanager/perf-tests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;"knative.dev/test-infra/scripts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;"knative.dev/test-infra/tools/dep-collector"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;load&lt;/span&gt; &lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="s"&gt;"github.com/tsenart/vegeta"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;constraint&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="s"&gt;"github.com/tsenart/vegeta"&lt;/span&gt;
  &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"master"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"gopkg.in/yaml.v2"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"v2.2.4"&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"github.com/google/mako"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"v0.1.0"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"go.uber.org/zap"&lt;/span&gt;
  &lt;span class="n"&gt;revision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"67bc79d13d155c02fd008f721863ff8cc5f30659"&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;constraint&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="s"&gt;"github.com/jetstack/cert-manager"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"v0.12.0"&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"k8s.io/api"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"kubernetes-1.16.4"&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"k8s.io/kube-openapi"&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;apiserver&lt;/span&gt; &lt;span class="n"&gt;depends&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;its&lt;/span&gt; &lt;span class="m"&gt;1.16.4&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;revision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"743ec37842bffe49dd4221d9026f30fb1d5adbc4"&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Added&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;apiserver&lt;/span&gt; &lt;span class="n"&gt;specifically&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"github.com/kubernetes-incubator/custom-metrics-apiserver"&lt;/span&gt;
  &lt;span class="n"&gt;revision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"3d9be26a50eb64531fc40eb31a5f3e6720956dc6"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"bitbucket.org/ww/goautoneg"&lt;/span&gt;
  &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github.com/munnerz/goautoneg"&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;prune&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;unused&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;prune&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;project&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="s"&gt;"k8s.io/code-generator"&lt;/span&gt;
  &lt;span class="n"&gt;unused&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;prune&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;project&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="s"&gt;"knative.dev/test-infra"&lt;/span&gt;
  &lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="n"&gt;below&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;opencensus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"google.golang.org/genproto"&lt;/span&gt;
  &lt;span class="n"&gt;revision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"357c62f0e4bbba7e6cc403ae09edcf3e2b9028fe"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"contrib.go.opencensus.io/exporter/prometheus"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"contrib.go.opencensus.io/exporter/zipkin"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.1"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;constraint&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="s"&gt;"go.opencensus.io"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.22.0"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"github.com/census-instrumentation/opencensus-proto"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.0"&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;override&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="s"&gt;"github.com/golang/protobuf"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.3.2"&lt;/span&gt;

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



&lt;h4&gt;
  
  
  required
&lt;/h4&gt;

&lt;p&gt;Lets talk about this required section; this is where you define what dependencies are required and must be included in the vendor folder;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;required &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
  ...
  &lt;span class="s2"&gt;"knative.dev/pkg/codegen/cmd/injection-gen"&lt;/span&gt;,
  &lt;span class="c"&gt;# TODO(#4549): Drop this when we drop our patches.&lt;/span&gt;
  &lt;span class="s2"&gt;"k8s.io/kubernetes/pkg/version"&lt;/span&gt;,
  &lt;span class="s2"&gt;"knative.dev/caching/pkg/apis/caching"&lt;/span&gt;,
  &lt;span class="c"&gt;# For cluster management in performance testing.&lt;/span&gt;
  &lt;span class="s2"&gt;"knative.dev/pkg/testutils/clustermanager/perf-tests"&lt;/span&gt;,
  &lt;span class="s2"&gt;"knative.dev/test-infra/scripts"&lt;/span&gt;,
  &lt;span class="s2"&gt;"knative.dev/test-infra/tools/dep-collector"&lt;/span&gt;,
  &lt;span class="c"&gt;# For load testing.&lt;/span&gt;
  &lt;span class="s2"&gt;"github.com/tsenart/vegeta"&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you look at the folder, you will see these dependencies in the &lt;a href="https://github.com/knative/serving/tree/master/vendor"&gt;folder&lt;/a&gt; as these are required. &lt;/p&gt;

&lt;h4&gt;
  
  
  direct and transitive dependency
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;A -&amp;gt; B -&amp;gt; C -&amp;gt; D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These are packages that your project imports or includes the required sections. For example above, A directly import B while B imports C and D. In this case, B is the direct dependent of A while C and D are transitive dependency.&lt;/p&gt;

&lt;h4&gt;
  
  
  constraint
&lt;/h4&gt;

&lt;p&gt;This is how you specify the version of your dependency to use for this project. In our case, we want  our project to use version&lt;code&gt;v2.2.4&lt;/code&gt; of the &lt;code&gt;gopkg.in/yaml.v2&lt;/code&gt;. To do this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[override]]
  name = "gopkg.in/yaml.v2"
  version = "v2.2.4"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can also use &lt;code&gt;branch&lt;/code&gt; or &lt;code&gt;revision&lt;/code&gt; to pin your dependency.&lt;/p&gt;

&lt;h4&gt;
  
  
  override
&lt;/h4&gt;

&lt;p&gt;These are like global constraint but supersedes constraints and should be used as last resort. They apply to direct dependencies and transitive dependencies unlike constraint and advisably should be used sparingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[override]]
  name="github.com/golang/protobuf"
  version = "1.3.2"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  prune
&lt;/h4&gt;

&lt;p&gt;When your project has a dependency, it extracts the package along with other files like README.md, LEGAL etc. If you dont want any or all of these files, you can use prune to inform dep.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[prune]
  go-tests = true
  unused-packages = true
  non-go = true

[[prune.project]]
  name = "k8s.io/code-generator"
  unused-packages = false
  non-go = false

[[prune.project]]
  name = "knative.dev/test-infra"
  non-go = false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The setting above simply tells dep to remove test files, unused-packages as well as non-go files like LEGAL from all dependencies. This is the overriden with a different setting for &lt;code&gt;k8s.io/code-generator&lt;/code&gt;   that unused-packages and no-go should not be pruned.&lt;/p&gt;

&lt;h4&gt;
  
  
  dep ensure
&lt;/h4&gt;

&lt;p&gt;Once you have configured your Gopkg.toml with your settings, you need to apply these changes, update vendor folder as well as Gopkg.lock. &lt;code&gt;dep ensure&lt;/code&gt; will do that for you and you have option to tell dep not to update  vendor, just Gopkg.lock.&lt;/p&gt;

</description>
      <category>go</category>
      <category>dep</category>
    </item>
    <item>
      <title>Reliability: ETCD Cluster</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Tue, 11 Feb 2020 22:18:38 +0000</pubDate>
      <link>https://forem.com/simplytunde/reliability-etcd-cluster-4hlp</link>
      <guid>https://forem.com/simplytunde/reliability-etcd-cluster-4hlp</guid>
      <description>&lt;h1&gt;
  
  
  ETCD
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Always benchmark your external etcd cluster using this &lt;a href="https://github.com/etcd-io/etcd/tree/master/tools/benchmark"&gt;tool&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Give etcd a higher disk &lt;a href="https://github.com/etcd-io/etcd/blob/master/Documentation/tuning.md#disk"&gt;priority&lt;/a&gt; if running along other processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Take advantage of learners for re-assignement and during upgrade. Checkout upcoming features in &lt;a href="https://github.com/etcd-io/etcd/blob/master/Documentation/learning/design-learner.md#features-in-v35"&gt;3.5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Election timeout should be 10x heart beat interval to makeup for network latency issues.&lt;/li&gt;
&lt;li&gt;You can only do minor upgrade for now.&lt;/li&gt;
&lt;li&gt;Use SSD for disk as this is the most critical resource in etcd cluster.&lt;/li&gt;
&lt;li&gt;You can change the default storage limit from 2GB to max of 8GB if using large cluster. &lt;a href="https://github.com/etcd-io/etcd/blob/master/Documentation/dev-guide/limit.md"&gt;checkout&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dont Do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Be careful when adding new node to etcd cluster that cannot tolerate any node failure. This is because if the new node fails, quorum is not achieved and etcd goes into read-mode. You can remove failing node before adding the new one.&lt;/li&gt;
&lt;li&gt;Do not route request to &lt;a href="https://github.com/etcd-io/etcd/blob/master/Documentation/learning/design-learner.md"&gt;learner&lt;/a&gt; especially when using load balancer.&lt;/li&gt;
&lt;li&gt;You risk cluster stability if you set different heartbeat and election timeout for the members.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Backup and Recovery
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Backup
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;etcdctl snapshot save backup.db &lt;span class="nt"&gt;--cacert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/lib/minikube/certs/etcd/ca.crt"&lt;/span&gt; &lt;span class="nt"&gt;--cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/lib/minikube/certs/etcd/server.crt"&lt;/span&gt; &lt;span class="nt"&gt;--key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/lib/minikube/certs/etcd/server.key"&lt;/span&gt; 
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"level"&lt;/span&gt;:&lt;span class="s2"&gt;"warn"&lt;/span&gt;,&lt;span class="s2"&gt;"ts"&lt;/span&gt;:&lt;span class="s2"&gt;"2020-02-10T19:00:17.325Z"&lt;/span&gt;,&lt;span class="s2"&gt;"caller"&lt;/span&gt;:&lt;span class="s2"&gt;"clientv3/retry_interceptor.go:116"&lt;/span&gt;,&lt;span class="s2"&gt;"msg"&lt;/span&gt;:&lt;span class="s2"&gt;"retry stream intercept"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
Snapshot saved at backup.db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Make sure you do this periodically probably using an automated method thats saves the backup in remote storage like s3.&lt;/p&gt;

&lt;h4&gt;
  
  
  Restore
&lt;/h4&gt;

&lt;p&gt;Remember that a snapshot restore creates a new logical member, making the node forgets its former identity. Hence you need to restore on other nodes and &lt;a href="https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/recovery.md#restoring-a-cluster"&gt;restart the cluster&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrade and Downgrade
&lt;/h2&gt;

&lt;p&gt;Before you do upgrade or downgrade, master the act of etcd backup and automated recovery unless though wishes to see what Dante was talking about.&lt;/p&gt;

&lt;h4&gt;
  
  
  Upgrade
&lt;/h4&gt;

&lt;p&gt;Replace the cluster members one by one to avoid potential issues with upgrade. If you have any member that is unhealthy, you can remove(provided you are not violating quorum) and add the member back to the cluster.&lt;/p&gt;

&lt;h4&gt;
  
  
  Downgrade
&lt;/h4&gt;

&lt;p&gt;You should probably read this &lt;a href="https://gravitational.com/blog/kubernetes-and-offline-etcd-upgrades/"&gt;post&lt;/a&gt; and &lt;a href="https://medium.com/@mrawesomenix/tale-of-etcd-upgrade-48c580e26d60"&gt;this&lt;/a&gt; before doing a downgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring
&lt;/h2&gt;

&lt;p&gt;Etcd exports metrics at &lt;em&gt;/metrics&lt;/em&gt; endpoint, so you can configure prometheus to ingest data from that endpoint for display in grafana.&lt;/p&gt;

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

</description>
      <category>reliability</category>
      <category>etcd</category>
    </item>
    <item>
      <title>ETCD Cluster and Non-voting Learners</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Tue, 11 Feb 2020 22:15:19 +0000</pubDate>
      <link>https://forem.com/simplytunde/etcd-cluster-and-non-voting-learners-4l0b</link>
      <guid>https://forem.com/simplytunde/etcd-cluster-and-non-voting-learners-4l0b</guid>
      <description>&lt;p&gt;In 3.4, etcd introduced raft learner for those looking to add new members to the cluster without giving them voting right. These are particularly useful because we can add members to the cluster without causing disruption then promote them to voting members once everything is good to go. Check this &lt;a href="https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/runtime-configuration.md#add-a-new-member-as-learner"&gt;out&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps to add a learner to the cluster;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the learner to existing cluster as below;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;etcdctl member add etcd-node-3 &lt;span class="nt"&gt;--peer-urls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://192.168.13.10:2380"&lt;/span&gt; &lt;span class="nt"&gt;--learner&lt;/span&gt;
Member 14d2e95e16c995c7 added to cluster 7ef1685daf3d8f18

&lt;span class="nv"&gt;ETCD_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"etcd-node-3"&lt;/span&gt;
&lt;span class="nv"&gt;ETCD_INITIAL_CLUSTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"etcd-node-3=http://192.168.13.10:2380,etcd-node-1=http://192.168.11.10:2380,etcd-node-0=http://192.168.10.10:2380,etcd-node-2=http://192.168.12.10:2380"&lt;/span&gt;
&lt;span class="nv"&gt;ETCD_INITIAL_ADVERTISE_PEER_URLS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://192.168.13.10:2380"&lt;/span&gt;
&lt;span class="nv"&gt;ETCD_INITIAL_CLUSTER_STATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"existing"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once add, you can check this status;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# etcdctl member list -w table &lt;/span&gt;
+------------------+---------+-------------+---------------------------+---------------------------+------------+
|        ID        | STATUS  |    NAME     |        PEER ADDRS         |       CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-------------+---------------------------+---------------------------+------------+
| 14d2e95e16c995c7 | started | etcd-node-3 | http://192.168.13.10:2380 | http://192.168.13.10:2379 |       &lt;span class="nb"&gt;true&lt;/span&gt; |
| 4c3c38d6652b5d75 | started | etcd-node-1 | http://192.168.11.10:2380 | http://192.168.11.10:2379 |      &lt;span class="nb"&gt;false&lt;/span&gt; |
| a00eaaf5194c573d | started | etcd-node-0 | http://192.168.10.10:2380 | http://192.168.10.10:2379 |      &lt;span class="nb"&gt;false&lt;/span&gt; |
| fdd13ca43538c5a2 | started | etcd-node-2 | http://192.168.12.10:2380 | http://192.168.12.10:2379 |      &lt;span class="nb"&gt;false&lt;/span&gt; |
+------------------+---------+-------------+---------------------------+---------------------------+------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can see our new member is a learner, meaning it syncs with the cluster but does not have voting right or accept read or write request but it is not started yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;etcdctl member list
16f23207f1b6cfc0, unstarted, , http://192.168.13.10:2379, , &lt;span class="nb"&gt;true
&lt;/span&gt;4c3c38d6652b5d75, started, etcd-node-1, http://192.168.11.10:2380, http://192.168.11.10:2379, &lt;span class="nb"&gt;false
&lt;/span&gt;a00eaaf5194c573d, started, etcd-node-0, http://192.168.10.10:2380, http://192.168.10.10:2379, &lt;span class="nb"&gt;false
&lt;/span&gt;fdd13ca43538c5a2, started, etcd-node-2, http://192.168.12.10:2380, http://192.168.12.10:2379, &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can now start the learner with the outputted configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt; /usr/local/bin/etcd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etcd-data &lt;span class="nt"&gt;--name&lt;/span&gt; etcd-node-3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-advertise-peer-urls&lt;/span&gt; http://192.168.13.10&lt;span class="o"&gt;}&lt;/span&gt;:2380 &lt;span class="nt"&gt;--listen-peer-urls&lt;/span&gt; http://0.0.0.0:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--advertise-client-urls&lt;/span&gt; http://192.168.13.10:2379 &lt;span class="nt"&gt;--listen-client-urls&lt;/span&gt; http://0.0.0.0:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster&lt;/span&gt; &lt;span class="s2"&gt;"etcd-node-3=http://192.168.13.10:2380,etcd-node-1=http://192.168.11.10:2380,etcd-node-0=http://192.168.10.10:2380,etcd-node-2=http://192.168.12.10:2380"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-state&lt;/span&gt; existing &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-token&lt;/span&gt; my-etcd-token
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, it should show the learner as started;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# etcdctl member list -w table&lt;/span&gt;
+------------------+---------+-------------+---------------------------+---------------------------+------------+
|        ID        | STATUS  |    NAME     |        PEER ADDRS         |       CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-------------+---------------------------+---------------------------+------------+
| 14d2e95e16c995c7 | started | etcd-node-3 | http://192.168.13.10:2380 | http://192.168.13.10:2379 |       &lt;span class="nb"&gt;true&lt;/span&gt; |
| 4c3c38d6652b5d75 | started | etcd-node-1 | http://192.168.11.10:2380 | http://192.168.11.10:2379 |      &lt;span class="nb"&gt;false&lt;/span&gt; |
| a00eaaf5194c573d | started | etcd-node-0 | http://192.168.10.10:2380 | http://192.168.10.10:2379 |      &lt;span class="nb"&gt;false&lt;/span&gt; |
| fdd13ca43538c5a2 | started | etcd-node-2 | http://192.168.12.10:2380 | http://192.168.12.10:2379 |      &lt;span class="nb"&gt;false&lt;/span&gt; |
+------------------+---------+-------------+---------------------------+---------------------------+------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is where learner is of importance; if any of our voting members goes down and our cluster is in inconsistent quorum state. You can promote the learner to replace the unstable voting member.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;etcdctl member promote 14d2e95e16c995c7
Member 14d2e95e16c995c7 promoted &lt;span class="k"&gt;in &lt;/span&gt;cluster 7ef1685daf3d8f18
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>etcd</category>
      <category>docker</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Downgrading ETCD Cluster</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Tue, 11 Feb 2020 08:56:11 +0000</pubDate>
      <link>https://forem.com/simplytunde/downgrading-etcd-cluster-4875</link>
      <guid>https://forem.com/simplytunde/downgrading-etcd-cluster-4875</guid>
      <description>&lt;p&gt;This process describes how you can downgrade etcd cluster. If you follow my &lt;a href="https://dev.to/simplytunde/etcd-multinode-cluster-using-docker-d36"&gt;post&lt;/a&gt; earlier, I was able to setup a 3-node cluster using script. In this post, I will be using script to initiate the snapshot, downgrade and restart. If you try to downgrade the cluster without doing restore, you will get something along&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;...
2020-02-11 08:40:47.532292 I | rafthttp: added peer a00eaaf5194c573d
2020-02-11 08:40:47.532577 I | etcdserver/membership: added member fdd13ca43538c5a2 &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.12.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:40:47.533041 N | etcdserver/membership: &lt;span class="nb"&gt;set &lt;/span&gt;the initial cluster version to 3.0
2020-02-11 08:40:47.533121 I | etcdserver/api: enabled capabilities &lt;span class="k"&gt;for &lt;/span&gt;version 3.0
2020-02-11 08:40:47.533524 N | etcdserver/membership: updated the cluster version from 3.0 to 3.2
2020-02-11 08:40:47.533747 I | etcdserver/api: enabled capabilities &lt;span class="k"&gt;for &lt;/span&gt;version 3.2
2020-02-11 08:40:47.534324 N | etcdserver/membership: updated the cluster version from 3.2 to 3.3
2020-02-11 08:40:47.534417 C | etcdserver/membership: cluster cannot be downgraded &lt;span class="o"&gt;(&lt;/span&gt;current version: 3.2.28 is lower than determined cluster version: 3.3&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

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



&lt;p&gt;First, take a snapshot of the cluster;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# etcdctl snapshot save /etcd-data/snapshot.db&lt;/span&gt;
Snapshot saved at /etcd-data/snapshot.db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Copy this snapshot to similar location on other nodes. Once this is done, let us tell etcd to do a restore from this snapshot into a different directory(in case of failure). I changed my data-dir to /etcd-data/new for demo purpose. Use the script below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;quay.io/coreos/etcd
&lt;span class="c"&gt;# available from v3.2.5&lt;/span&gt;
&lt;span class="c"&gt;# REGISTRY=gcr.io/etcd-development/etcd&lt;/span&gt;

&lt;span class="c"&gt;# For each machine&lt;/span&gt;
&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v3.2.28
&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-etcd-token
&lt;span class="nv"&gt;CLUSTER_STATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;new
&lt;span class="nv"&gt;NAME_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etcd-node-0
&lt;span class="nv"&gt;NAME_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etcd-node-1
&lt;span class="nv"&gt;NAME_3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etcd-node-2
&lt;span class="nv"&gt;HOST_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.10.10
&lt;span class="nv"&gt;HOST_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.11.10
&lt;span class="nv"&gt;HOST_3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.12.10
&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380,&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380,&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380
&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mydatadir/etcd &lt;span class="c"&gt;#make sure to change this&lt;/span&gt;

&lt;span class="c"&gt;# For node 1&lt;/span&gt;
&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ETCDCTL_API&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:/etcd-data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /usr/local/bin/etcdctl snapshot restore /etcd-data/snapshot.db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-token&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-advertise-peer-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt; /etcd-data/new 




&lt;span class="c"&gt;# For node 2&lt;/span&gt;
&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ETCDCTL_API&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:/etcd-data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /usr/local/bin/etcdctl snapshot restore /etcd-data/snapshot.db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-token&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-advertise-peer-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt; /etcd-data/new 

&lt;span class="c"&gt;# # For node 3&lt;/span&gt;
&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ETCDCTL_API&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:/etcd-data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /usr/local/bin/etcdctl snapshot restore /etcd-data/snapshot.db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-token&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-advertise-peer-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt; /etcd-data/new 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once your run the script, you should get something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./etcd-restore.sh 
2020-02-11 08:39:28.391951 I | etcdserver/membership: added member 4c3c38d6652b5d75 &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.11.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:28.392657 I | etcdserver/membership: added member a00eaaf5194c573d &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.10.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:28.392672 I | etcdserver/membership: added member fdd13ca43538c5a2 &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.12.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:29.407616 I | etcdserver/membership: added member 4c3c38d6652b5d75 &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.11.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:29.407817 I | etcdserver/membership: added member a00eaaf5194c573d &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.10.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:29.407847 I | etcdserver/membership: added member fdd13ca43538c5a2 &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.12.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:30.365027 I | etcdserver/membership: added member 4c3c38d6652b5d75 &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.11.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:30.365130 I | etcdserver/membership: added member a00eaaf5194c573d &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.10.10:2380] to cluster 7ef1685daf3d8f18
2020-02-11 08:39:30.365213 I | etcdserver/membership: added member fdd13ca43538c5a2 &lt;span class="o"&gt;[&lt;/span&gt;http://192.168.12.10:2380] to cluster 7ef1685daf3d8f18
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once the restore is complete, you simply start the cluster up and make sure the data-dir is pointing to the new restore location. You can use the same script as in this &lt;a href="https://dev.to/simplytunde/etcd-multinode-cluster-using-docker-d36"&gt;post&lt;/a&gt; but make sure to update the data dir.&lt;br&gt;
Once our cluster is up, you should check the health of the cluster&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; etcd-node-0 /bin/sh
/ &lt;span class="c"&gt;# export ETCDCTL_API=3&lt;/span&gt;
/ &lt;span class="c"&gt;# etcdctl -w table --endpoints=[192.168.11.10:2379,192.168.10.10:2379,192.168.12.10:2379] endpoint status&lt;/span&gt;
+--------------------+------------------+---------+---------+-----------+-----------+------------+
|      ENDPOINT      |        ID        | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+--------------------+------------------+---------+---------+-----------+-----------+------------+
| 192.168.11.10:2379 | 4c3c38d6652b5d75 |  3.2.28 |   25 kB |     &lt;span class="nb"&gt;false&lt;/span&gt; |         2 |          8 |
| 192.168.10.10:2379 | a00eaaf5194c573d |  3.2.28 |   25 kB |      &lt;span class="nb"&gt;true&lt;/span&gt; |         2 |          8 |
| 192.168.12.10:2379 | fdd13ca43538c5a2 |  3.2.28 |   25 kB |     &lt;span class="nb"&gt;false&lt;/span&gt; |         2 |          8 |
+--------------------+------------------+---------+---------+-----------+-----------+------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>etcd</category>
      <category>docker</category>
    </item>
    <item>
      <title>ETCD Multinode cluster using Docker</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Tue, 11 Feb 2020 06:48:16 +0000</pubDate>
      <link>https://forem.com/simplytunde/etcd-multinode-cluster-using-docker-d36</link>
      <guid>https://forem.com/simplytunde/etcd-multinode-cluster-using-docker-d36</guid>
      <description>&lt;p&gt;In this post, I will be showing how to create a 3-node cluster with each node represented by a docker container. First, lets create our nodes IP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ifconfig en0 &lt;span class="nb"&gt;alias &lt;/span&gt;192.168.10.10/24 up
&lt;span class="nb"&gt;sudo &lt;/span&gt;ifconfig en0 &lt;span class="nb"&gt;alias &lt;/span&gt;192.168.11.10/24 up
&lt;span class="nb"&gt;sudo &lt;/span&gt;ifconfig en0 &lt;span class="nb"&gt;alias &lt;/span&gt;192.168.12.10/24 up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once they are created, you can use script below which is a modified version of &lt;a href="https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/container.md#running-a-3-node-etcd-cluster-1"&gt;this&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;quay.io/coreos/etcd
&lt;span class="c"&gt;# available from v3.2.5&lt;/span&gt;
&lt;span class="c"&gt;# REGISTRY=gcr.io/etcd-development/etcd&lt;/span&gt;

&lt;span class="c"&gt;# For each machine&lt;/span&gt;
&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;latest
&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-etcd-token
&lt;span class="nv"&gt;CLUSTER_STATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;new
&lt;span class="nv"&gt;NAME_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etcd-node-0
&lt;span class="nv"&gt;NAME_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etcd-node-1
&lt;span class="nv"&gt;NAME_3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etcd-node-2
&lt;span class="nv"&gt;HOST_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.10.10
&lt;span class="nv"&gt;HOST_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.11.10
&lt;span class="nv"&gt;HOST_3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.12.10
&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380,&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380,&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380
&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mydir/etcd &lt;span class="c"&gt;#make sure to change this&lt;/span&gt;

&lt;span class="c"&gt;# For node 1&lt;/span&gt;
&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:/etcd-data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /usr/local/bin/etcd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etcd-data &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-advertise-peer-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380 &lt;span class="nt"&gt;--listen-peer-urls&lt;/span&gt; http://0.0.0.0:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--advertise-client-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379 &lt;span class="nt"&gt;--listen-client-urls&lt;/span&gt; http://0.0.0.0:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-state&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_STATE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--initial-cluster-token&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# For node 2&lt;/span&gt;
&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:/etcd-data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /usr/local/bin/etcd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etcd-data &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-advertise-peer-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380 &lt;span class="nt"&gt;--listen-peer-urls&lt;/span&gt; http://0.0.0.0:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--advertise-client-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379 &lt;span class="nt"&gt;--listen-client-urls&lt;/span&gt; http://0.0.0.0:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-state&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_STATE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--initial-cluster-token&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# # For node 3&lt;/span&gt;
&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST_3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATA_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:/etcd-data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGISTRY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ETCD_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /usr/local/bin/etcd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etcd-data &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-advertise-peer-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2380 &lt;span class="nt"&gt;--listen-peer-urls&lt;/span&gt; http://0.0.0.0:2380 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--advertise-client-urls&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THIS_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:2379 &lt;span class="nt"&gt;--listen-client-urls&lt;/span&gt; http://0.0.0.0:2379 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--initial-cluster-state&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_STATE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--initial-cluster-token&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

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



&lt;p&gt;Once the cluster is created, you can use the command below to check this cluster status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker exec -it etcd-node-0 /bin/sh
/ # etcdctl -w table --endpoints=192.168.11.10:2379,192.168.10.10:2379,192.168.12.10:2379 endpoint status
+--------------------+------------------+---------+---------+-----------+-----------+------------+
|      ENDPOINT      |        ID        | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+--------------------+------------------+---------+---------+-----------+-----------+------------+
| 192.168.11.10:2379 | 4c3c38d6652b5d75 |  3.2.28 |   25 kB |     false |         5 |         17 |
| 192.168.10.10:2379 | a00eaaf5194c573d |  3.2.28 |   25 kB |      true |         5 |         17 |
| 192.168.12.10:2379 | fdd13ca43538c5a2 |  3.2.28 |   25 kB |     false |         5 |         17 |
+--------------------+------------------+---------+---------+-----------+-----------+------------+

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



</description>
      <category>etcd</category>
      <category>docker</category>
    </item>
    <item>
      <title>Install Istio with kubectl</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Mon, 28 Oct 2019 01:37:13 +0000</pubDate>
      <link>https://forem.com/simplytunde/install-istio-with-kubectl-453l</link>
      <guid>https://forem.com/simplytunde/install-istio-with-kubectl-453l</guid>
      <description>&lt;p&gt;To install Istio on EKS with &lt;code&gt;kubectl&lt;/code&gt;, we will need to use helm to generate the manifest and use &lt;code&gt;kubectl&lt;/code&gt;to apply.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Istio Init
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.3.3 sh -&lt;/span&gt;
&lt;span class="s"&gt;cd istio-1.3.3&lt;/span&gt;
&lt;span class="s"&gt;helm template install/kubernetes/helm/istio-init --namespace istio-system | kubectl apply -f -&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Istio Demo
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;kubectl apply -f install/kubernetes/istio-demo.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;$ kubectl get pods -n istio-system&lt;/span&gt;
&lt;span class="s"&gt;NAME                                      READY   STATUS      RESTARTS   AGE&lt;/span&gt;
&lt;span class="s"&gt;grafana-9bdbcc98d-gzntp                   1/1     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-citadel-6759c5c4d4-7wlnw            1/1     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-egressgateway-c7776cf56-zjnx8       1/1     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-galley-8544f4ff94-9qj4m             1/1     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-grafana-post-install-1.3.3-l989d    0/1     Completed   0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-ingressgateway-8469cb69c5-kjvkc     1/1     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-pilot-748dd866dc-rh25k              2/2     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-policy-5c564f5bfb-8hvgc             2/2     Running     1          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-security-post-install-1.3.3-7pp5z   0/1     Completed   0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-sidecar-injector-59c8999585-lqlj7   1/1     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-telemetry-5fc579cb56-sjd9d          2/2     Running     1          23m&lt;/span&gt;
&lt;span class="s"&gt;istio-tracing-6f585d8877-24974            0/1     Running     10         23m&lt;/span&gt;
&lt;span class="s"&gt;kiali-5764f9c44d-c7ftg                    1/1     Running     0          23m&lt;/span&gt;
&lt;span class="s"&gt;prometheus-85d75b5f6b-fn7f2               1/1     Running     0          23m&lt;/span&gt;

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



&lt;h3&gt;
  
  
  Bookinfo application
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;kubectl label ns istio-system  istio-injection=disabled&lt;/span&gt;
&lt;span class="s"&gt;kubectl label ns istio-demo  istio-injection=enabled&lt;/span&gt;
&lt;span class="s"&gt;kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;$ kubectl get pods&lt;/span&gt;
&lt;span class="s"&gt;NAME                             READY   STATUS    RESTARTS   AGE&lt;/span&gt;
&lt;span class="s"&gt;details-v1-c5b5f496d-p5lr7       1/2     Running   0          98m&lt;/span&gt;
&lt;span class="s"&gt;helloworld-v1-7bb88866c4-hj8m2   2/2     Running   0          108m&lt;/span&gt;
&lt;span class="s"&gt;helloworld-v2-6cd449dff4-mxjwn   1/2     Running   0          108m&lt;/span&gt;
&lt;span class="s"&gt;productpage-v1-c7765c886-tbd2c   2/2     Running   0          98m&lt;/span&gt;
&lt;span class="s"&gt;ratings-v1-f745cf57b-qpthv       2/2     Running   0          98m&lt;/span&gt;
&lt;span class="s"&gt;reviews-v1-75b979578c-6hslt      2/2     Running   0          98m&lt;/span&gt;
&lt;span class="s"&gt;reviews-v2-597bf96c8f-q92v7      2/2     Running   0          98m&lt;/span&gt;
&lt;span class="s"&gt;reviews-v3-54c6c64795-9gc9q      2/2     Running   0          98m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>eks</category>
      <category>istio</category>
    </item>
    <item>
      <title>Kubernetes, PodSecurityPolicy and Kubeadm</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Sat, 01 Jun 2019 00:41:56 +0000</pubDate>
      <link>https://forem.com/simplytunde/kubernetes-podsecuritypolicy-and-kubeadm-26i3</link>
      <guid>https://forem.com/simplytunde/kubernetes-podsecuritypolicy-and-kubeadm-26i3</guid>
      <description>&lt;p&gt;I will assume you have a little background about PodSecurityPolicy and now its time to setup your cluster with PodSecurityPolicy admission controller enabled. For our setup, here is the kubeadm config;&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;InitConfiguration&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;kubeadm.k8s.io/v1beta1&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;InitConfiguration&lt;/span&gt;
&lt;span class="nn"&gt;---&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;kubelet.config.k8s.io/v1beta1&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;KubeletConfiguration&lt;/span&gt;
&lt;span class="na"&gt;featureGates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;AppArmor&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;cpuManagerPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;static&lt;/span&gt;
&lt;span class="na"&gt;systemReserved&lt;/span&gt;&lt;span class="pi"&gt;:&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;500m&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;256M&lt;/span&gt;
&lt;span class="na"&gt;kubeReserved&lt;/span&gt;&lt;span class="pi"&gt;:&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;500m&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;256M&lt;/span&gt;
&lt;span class="nn"&gt;---&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;kubeadm.k8s.io/v1beta1&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;ClusterConfiguration&lt;/span&gt;
&lt;span class="na"&gt;apiServer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;extraArgs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enable-admission-plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;PodSecurityPolicy,LimitRanger,ResourceQuota,AlwaysPullImages,DefaultStorageClass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's start the cluster,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;$ sudo kubeadm init --config kubeadm.json&lt;/span&gt; 
&lt;span class="s"&gt;$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config&lt;/span&gt;
&lt;span class="c1"&gt;#join a worker node to the master&lt;/span&gt;
&lt;span class="s"&gt;$ sudo kubeadm join 10.100.11.231:6443 --token 6yel1a.ce3le6eel3kfnxsz --discovery-token-ca-cert-hash sha256:99ee2e4ea&lt;/span&gt;
&lt;span class="s"&gt;302c5270f2047c7a0093533b69105a8c91bf20f48b230dce9fd3f3a&lt;/span&gt;
&lt;span class="s"&gt;$ kubectl get no&lt;/span&gt;
&lt;span class="s"&gt;NAME               STATUS     ROLES    AGE    VERSION&lt;/span&gt;
&lt;span class="s"&gt;ip-10-100-11-199   NotReady   &amp;lt;none&amp;gt;   109s   v1.13.1&lt;/span&gt;
&lt;span class="s"&gt;ip-10-100-11-231   NotReady   master   3m3s   v1.13.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, our cluster is not ready because we need to install a network plugin which you can see if you describe the node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl describe no ip-10-100-11-231
...
Conditions:
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  &lt;span class="nt"&gt;----&lt;/span&gt;             &lt;span class="nt"&gt;------&lt;/span&gt;  &lt;span class="nt"&gt;-----------------&lt;/span&gt;                 &lt;span class="nt"&gt;------------------&lt;/span&gt;                &lt;span class="nt"&gt;------&lt;/span&gt;                       &lt;span class="nt"&gt;-------&lt;/span&gt;
  MemoryPressure   False   Fri, 31 May 2019 22:50:36 +0000   Fri, 31 May 2019 22:46:39 +0000   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False   Fri, 31 May 2019 22:50:36 +0000   Fri, 31 May 2019 22:46:39 +0000   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure      False   Fri, 31 May 2019 22:50:36 +0000   Fri, 31 May 2019 22:46:39 +0000   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready            False   Fri, 31 May 2019 22:50:36 +0000   Fri, 31 May 2019 22:46:39 +0000   KubeletNotReady              runtime network not ready: &lt;span class="nv"&gt;NetworkReady&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false &lt;/span&gt;reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
Addresses:
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We will be using calico as our network plugin and you can follow the install instruction right &lt;a href="https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; https://docs.projectcalico.org/v3.7/manifests/calico.yaml
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.extensions/calico-node created
serviceaccount/calico-node created
deployment.extensions/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To our surprise, there is no pod running in kube-system as we would expect. Let look at calico-node daemonset;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;$ kubectl describe daemonset calico-node  -n kube-system&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;calico-node&lt;/span&gt;
&lt;span class="na"&gt;Selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;k8s-app=calico-node&lt;/span&gt;
&lt;span class="na"&gt;Node-Selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;beta.kubernetes.io/os=linux&lt;/span&gt;
&lt;span class="na"&gt;Labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;k8s-app=calico-node&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;Type     Reason        Age                  From                  Message&lt;/span&gt;
  &lt;span class="s"&gt;----     ------        ----                 ----                  -------&lt;/span&gt;
  &lt;span class="s"&gt;Warning  FailedCreate  20s (x15 over 102s)  daemonset-controller  Error creating&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods "calico-node-" is forbidden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no providers available to validate pod request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok, it says no provider and that means you do not have any PSP defined that will validate the daemonset pods. It is a very confusing error message.&lt;br&gt;
Now, we will apply this PSP below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;policy/v1beta1&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;PodSecurityPolicy&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;calico-psp&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;seccomp.security.alpha.kubernetes.io/allowedProfileNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*'&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;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;allowPrivilegeEscalation&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;allowedCapabilities&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;*'&lt;/span&gt;
  &lt;span class="na"&gt;volumes&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;*'&lt;/span&gt;
  &lt;span class="na"&gt;hostNetwork&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;hostPorts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65535&lt;/span&gt;
  &lt;span class="na"&gt;hostIPC&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;hostPID&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;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RunAsAny'&lt;/span&gt;
  &lt;span class="na"&gt;seLinux&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RunAsAny'&lt;/span&gt;
  &lt;span class="na"&gt;supplementalGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RunAsAny'&lt;/span&gt;
  &lt;span class="na"&gt;fsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RunAsAny'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; calico-psp.yaml 
podsecuritypolicy.policy/calico-psp created
&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get psp
NAME             PRIV    CAPS   SELINUX    RUNASUSER   FSGROUP    SUPGROUP   READONLYROOTFS   VOLUMES
calico-psp   &lt;span class="nb"&gt;false          &lt;/span&gt;RunAsAny   RunAsAny    RunAsAny   RunAsAny   &lt;span class="nb"&gt;false&lt;/span&gt;            &lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok everything should be good now? Well, if you describe the daemonset, you will still see the same message as above. You need to delete and re-apply the calico plugin manifest. After this, let's go ahead and describe our daemonset again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;$ kubectl describe daemonset calico-node  -n kube-system&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;calico-node&lt;/span&gt;
&lt;span class="na"&gt;Selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;k8s-app=calico-node&lt;/span&gt;
&lt;span class="na"&gt;Node-Selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;beta.kubernetes.io/os=linux&lt;/span&gt;
&lt;span class="na"&gt;Labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;k8s-app=calico-node&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;HostPath (bare host directory volume)&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;/var/lib/cni/networks&lt;/span&gt;
    &lt;span class="na"&gt;HostPathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;Type     Reason        Age                From                  Message&lt;/span&gt;
  &lt;span class="s"&gt;----     ------        ----               ----                  -------&lt;/span&gt;
  &lt;span class="s"&gt;Warning  FailedCreate  4s (x12 over 14s)  daemonset-controller  Error creating&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods "calico-node-" is forbidden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;unable to validate against any pod security policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The error means we have a psp but not something we can use to validate our daemonset. This is because our daemonset pod container cannot use our PSP and we need to modify the daemonset clusterrole to be able to use this specific PSP and add this rule. Yep, you need to recreate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Include a clusterrole for the calico-node DaemonSet,&lt;/span&gt;
&lt;span class="c1"&gt;# and bind it to the calico-node serviceaccount.&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;ClusterRole&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;rbac.authorization.k8s.io/v1beta1&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;calico-node&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;apiGroups&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;extensions"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;podsecuritypolicies&lt;/span&gt;
    &lt;span class="na"&gt;resourceNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;calico-psp&lt;/span&gt;
    &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;use&lt;/span&gt;
  &lt;span class="c1"&gt;# The CNI plugin needs to get pods, nodes, and namespaces.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&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;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pods&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;nodes&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;namespaces&lt;/span&gt;
    &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;get&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After the clusterrole has been modified, we will run into another error;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;...&lt;/span&gt;
   &lt;span class="na"&gt;host-local-net-dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;HostPath (bare host directory volume)&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;/var/lib/cni/networks&lt;/span&gt;
    &lt;span class="na"&gt;HostPathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;Type     Reason        Age               From                  Message&lt;/span&gt;
  &lt;span class="s"&gt;----     ------        ----              ----                  -------&lt;/span&gt;
  &lt;span class="s"&gt;Warning  FailedCreate  3s (x11 over 9s)  daemonset-controller  Error creating&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods "calico-node-" is forbidden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;unable to validate against any pod security policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;spec.containers&lt;/span&gt;&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;.securityContext.privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Invalid value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Privileged containers are not allowed&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our calico pods are forbidden because the PSP it is using forbids privileged container and Calico needs one to handle network policy. Now, lets go ahead and fix that in our PSP by updating;&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;policy/v1beta1&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;PodSecurityPolicy&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;calico-psp&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;seccomp.security.alpha.kubernetes.io/allowedProfileNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*'&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;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;#update this to true&lt;/span&gt;
  &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once the update has been applied, calico will create the pods and our node will become healthy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;Type     Reason            Age                     From                  Message&lt;/span&gt;
  &lt;span class="s"&gt;----     ------            ----                    ----                  -------&lt;/span&gt;
  &lt;span class="s"&gt;Warning  FailedCreate      3m10s (x16 over 5m54s)  daemonset-controller  Error creating&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pods "calico-node-" is forbidden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;unable to validate against any pod security policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;spec.containers&lt;/span&gt;&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;.securityContext.privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Invalid value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Privileged containers are not allowed&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;Normal   SuccessfulCreate  26s                     daemonset-controller  Created pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;calico-node-hwb2b&lt;/span&gt;
  &lt;span class="na"&gt;Normal   SuccessfulCreate  26s                     daemonset-controller  Created pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;calico-node-gtrm2&lt;/span&gt;

&lt;span class="s"&gt;$ kubectl get no&lt;/span&gt;
&lt;span class="s"&gt;NAME               STATUS   ROLES    AGE     VERSION&lt;/span&gt;
&lt;span class="s"&gt;ip-10-100-11-199   Ready    &amp;lt;none&amp;gt;   7m2s    v1.13.1&lt;/span&gt;
&lt;span class="s"&gt;ip-10-100-11-231   Ready    master   7m33s   v1.13.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Yayy!!! Our nodes are ready.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>kubeadm</category>
      <category>psp</category>
    </item>
    <item>
      <title>Lets Talk About Terraform 0.12</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Mon, 27 May 2019 16:28:39 +0000</pubDate>
      <link>https://forem.com/simplytunde/lets-talk-about-terraform-0-12-32j0</link>
      <guid>https://forem.com/simplytunde/lets-talk-about-terraform-0-12-32j0</guid>
      <description>&lt;p&gt;Terraform 0.12 was recently released and you can check out the details more in-dept at &lt;a href="https://www.hashicorp.com/blog/announcing-terraform-0-12"&gt;terraform blogs&lt;/a&gt;. The focus of this blog post will be  the new features released and how to use them. You can find the code used in this &lt;a href="https://github.com/simplytunde/tutorial/tree/master/terraform"&gt;Github repo&lt;/a&gt;. Below is the content of the ec2 main.tf.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"test_ec2"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./ec2_module"&lt;/span&gt;
      &lt;span class="c1"&gt;//I am passing the subnet object instead of the id&lt;/span&gt;
      &lt;span class="nx"&gt;subnet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="nx"&gt;instance_tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Name"&lt;/span&gt;
          &lt;span class="nx"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Test"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Environment"&lt;/span&gt;
          &lt;span class="nx"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"prd"&lt;/span&gt;
        &lt;span class="p"&gt;}&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;Here is the content of the ec2 module;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;most_recent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"virtualization-type"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hvm"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;owners&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"099720109477"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Canonical&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ubuntu&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;user_data&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;templatefile&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${path.module}/userdata.tpl"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;instance_tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_tags&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_tags&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
       &lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_type"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_tags"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"subnet"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  For expression
&lt;/h3&gt;

&lt;p&gt;From my perspective, this is one of the best feature of 0.12 which allows you to iterate over a list or map and you can  do whatever you want with each item. From above, you can see that we generated the instance tags property from the user passed in  list of maps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;tags = {&lt;/span&gt;
     &lt;span class="s"&gt;for tag in var.instance_tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="s"&gt;tag.Key =&amp;gt; tag.Value&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  First class expression
&lt;/h3&gt;

&lt;p&gt;You can see from above that we did not have to interpolate over the variables or object values instead they were used directly as first class variable. This will save some ink and allows for more complex operational usage with terraform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;ami           = data.aws_ami.ubuntu.id&lt;/span&gt;
  &lt;span class="s"&gt;instance_type = "t2.micro"&lt;/span&gt;
  &lt;span class="s"&gt;subnet_id  = var.subnet.id&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Rich Value Type
&lt;/h3&gt;

&lt;p&gt;My impression of this feature so far is that we can have user-defined type and existing type are supported as first class type without quote. We defined a type that expects map with id attribute and if passing a non-matching object, it will be rejected which is pretty cool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;variable "instance_tags" {&lt;/span&gt;
     &lt;span class="s"&gt;type = list&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="s"&gt;variable "subnet" {&lt;/span&gt;
    &lt;span class="s"&gt;type = object({&lt;/span&gt;
        &lt;span class="s"&gt;id = string&lt;/span&gt;
    &lt;span class="s"&gt;})&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  New Type Interpolation
&lt;/h3&gt;

&lt;p&gt;New terraform now gives you the capability to loop in your user data. For our example, here is the userdata;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

%{ for tag in instance_tags~}
cat ${tag.Key}=${tag.Value}
%{ endfor ~}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We were able to use forloop to go over the tags and use it in instance user data which is lovely without having to through hacks.&lt;/p&gt;

&lt;p&gt;One other feature that was not discussed here is the &lt;em&gt;dynamic block&lt;/em&gt; which you can checkout on terraform &lt;a href="https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each"&gt;blog page&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
    </item>
    <item>
      <title>Logging with AWS Kubernetes EKS Cluster</title>
      <dc:creator>Tunde Oladipupo</dc:creator>
      <pubDate>Fri, 24 May 2019 02:33:38 +0000</pubDate>
      <link>https://forem.com/simplytunde/logging-with-aws-kubernetes-eks-cluster-1m5l</link>
      <guid>https://forem.com/simplytunde/logging-with-aws-kubernetes-eks-cluster-1m5l</guid>
      <description>&lt;h2&gt;
  
  
  Logs
&lt;/h2&gt;

&lt;p&gt;EKS is the managed kubernetes offering by AWS that saves you the stress of managing your own control plane with a twist of offboarding some controls like what goes on in your control. The feature was not available when the service went GA but was recently made available recently. Here are the kinds of logs that it provides;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API server component logs: You know that component of your cluster that validates requests, provides api rest endpoint and so on? These are the logs from the apiserver which are very critical when trying to diagnose things like why your pods are not creating, admission controller issues etc.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;E0523 03:27:22.258958 1 memcache.go:134] couldn't get resource list for metrics.k8s.io/v1beta1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;the server is currently unable to handle the request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Audit Logs: People make changes in your cluster and you want to know who, what and when. This logs gives you the ability to this.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kind"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Event"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apiVersion"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audit.k8s.io/v1beta1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata"&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;creationTimestamp"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2019-05-23T02:08:34Z"&lt;/span&gt;
    &lt;span class="pi"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;level"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Request"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2019-05-23T02:08:34Z"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auditID"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;84662c40-8d4f-4d3e-99b2-0d4005e44375"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stage"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ResponseComplete"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requestURI"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/v1/namespaces/default/services/kubernetes"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verb"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user"&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;username"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system:apiserver"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uid"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2d8ad7ed-25ed-4f37-a2f0-416d2af705e9"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;groups"&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;system:masters"&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;sourceIPs"&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;::1"&lt;/span&gt;
    &lt;span class="pi"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;userAgent"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kube-apiserver/v1.12.6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(linux/amd64)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;kubernetes/d69f1bf"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;objectRef"&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;resource"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;services"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;namespace"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kubernetes"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apiVersion"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;v1"&lt;/span&gt;
    &lt;span class="pi"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;responseStatus"&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;metadata"&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;code"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;200&lt;/span&gt;
    &lt;span class="pi"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requestReceivedTimestamp"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2019-05-23T02:08:34.498973Z"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stageTimestamp"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2019-05-23T02:08:34.501446Z"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;annotations"&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;authorization.k8s.io/decision"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allow"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorization.k8s.io/reason"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
    &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;

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



&lt;ul&gt;
&lt;li&gt;Authenticator Logs: EKS uses this thing called aws-iam-authenticator to guess what? Authenticate against the EKS cluster using AWS credentials and roles. These logs contains event from these activities
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;time="2019-05-16T22:19:48Z" level=info msg="Using assumed role for EC2 API" roleARN="arn:aws:iam::523447765480:role/idaas-kubernetes-cluster-idauto-dev-masters-role"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Controller manager: For those familiar with kubernetes objects such as Deployments, Replicas etc; these are managed by controllers which ships with kubernetes controller manager. To see what these controllers are doing under the hood, you need these.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;E0523 02:07:55.486872 1 horizontal.go:212] failed to compute desired number of replicas based on listed metrics for Deployment/routing/rapididentity-default-backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;failed to get memory utilization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;unable to get metrics for resource memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;unable to fetch metrics from resource metrics API&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;the server is currently unable to handle the request (get pods.metrics.k8s.io)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Scheduler: This component of the control plane does what it name says, put pods on the right node after factoring a number of constraints and resources available. To see information on how this component is making its decision, check these logs.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;E0523 02:07:55.486872 1 horizontal.go:212] failed to compute desired number of replicas based on listed metrics for Deployment/routing/rapididentity-default-backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;failed to get memory utilization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;unable to get metrics for resource memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;unable to fetch metrics from resource metrics API&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;the server is currently unable to handle the request (get pods.metrics.k8s.io)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Enabling Logs
&lt;/h1&gt;

&lt;p&gt;You can easily enable the logs in your EKS cluser console and AWS updates your cluster to enable those logs to ship to cloudwatch. The corresponding cloudwatch log group will be displayed in your console. For those using terraform to provision their cluster, you can just pass in the types of logs that you want to provision and also create the log group to ship it to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;resource "aws_eks_cluster" "my_cluster" {&lt;/span&gt;
  &lt;span class="s"&gt;depends_on = ["aws_cloudwatch_log_group.eks_log_group"]&lt;/span&gt;
  &lt;span class="s"&gt;enabled_cluster_log_types = ["api", "audit"]&lt;/span&gt;
  &lt;span class="s"&gt;name                      = "${var.cluster_name}"&lt;/span&gt;
  &lt;span class="s"&gt;# ... other configuration ...&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>aws</category>
      <category>eks</category>
    </item>
  </channel>
</rss>
