
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
 <channel>
   <title></title>
   <link>/</link>
   <description>Recent content on </description>
   <generator>Hugo -- gohugo.io</generator>
   <lastBuildDate>Mon, 07 Oct 2024 00:00:00 +0000</lastBuildDate>
   
       <atom:link href="/index.xml" rel="self" type="application/rss+xml" />
   
   
     <item>
       <title>tstorage (Time series embedded db)</title>
       <link>/post/tstorage/</link>
       <pubDate>Mon, 07 Oct 2024 00:00:00 +0000</pubDate>
       
       <guid>/post/tstorage/</guid>
       <description>&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;#project-info&#34;&gt;Project Info&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#example&#34;&gt;Example&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#internal-document&#34;&gt;Internal Document&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;project-info&#34;&gt;Project Info&lt;/h2&gt;&lt;p&gt;Embedded &lt;a href=&#34;https://github.com/nakabonne/tstorage&#34;&gt;time series database&lt;/a&gt; for usage in a Go application.&lt;/p&gt;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;&lt;p&gt;Example on how to use the &lt;code&gt;tstorage&lt;/code&gt; project can be found &lt;a href=&#34;https://github.com/nanikjava/timeseriesdb&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&#34;internal-document&#34;&gt;Internal Document&lt;/h2&gt;&lt;p&gt;Google doc diagram and explanation can be found inside &lt;a href=&#34;https://docs.google.com/presentation/d/1di6S73kUc1Q65hMpZy8CSnGXTAqrJQBM6bq59qm5tl4/edit?usp=sharing&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The document contains the following information:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Structure of &lt;code&gt;tstorage.memoryPartition&lt;/code&gt; which is used as container to collect metric information in memory&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/tstorage/high_level_memory_partition.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Breakdown of data stored inside &lt;code&gt;tstorage.memoryPartition&lt;/code&gt; in terms of metrics.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/tstorage/tstorage_memory_partition.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Diagram outlining the structure of &lt;code&gt;tstorage.storage&lt;/code&gt; showing the linked list information of all parititions (memory and disk).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/tstorage/tstorage_storage.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Steps breakdown of when a new partition is created.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/tstorage/new_partition_flow.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Splitting of reading partition file from disk into memory mapped and &lt;code&gt;meta.json&lt;/code&gt; into &lt;code&gt;meta&lt;/code&gt; structure.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/tstorage/mapping_files.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Internal representation of the &lt;a href=&#34;https://www.vldb.org/pvldb/vol8/p1816-teller.pdf&#34;&gt;Gorilla&lt;/a&gt; compression&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/tstorage/gorilla_compression.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Go Concurrency Notes</title>
       <link>/post/concurrency/</link>
       <pubDate>Fri, 19 Apr 2024 00:00:00 +0000</pubDate>
       
       <guid>/post/concurrency/</guid>
       <description>&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;#restricting-writers&#34;&gt;Restricting Writers&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#architecture&#34;&gt;Architecture&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;#a1&#34;&gt;A1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#a2&#34;&gt;A2&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;restricting-writers&#34;&gt;Restricting Writers&lt;/h2&gt;&lt;h3 id=&#34;scenario&#34;&gt;Scenario&lt;/h3&gt;&lt;p&gt;Building library that perform expensive I/O operation (eg: writing to a file). The library uses a writer code to write the data and it limits the number of writers to the number of CPU cores. This will safeguard the library write operation to work correctly and consistently in the event if the caller is calling the writer in an uncontrollable manner. Imagine an app that calls the writer in 100 goroutines in the hope it speeds up the write operation, which in reality does not happen as I/O operation are bound to the speed of the I/O peripherals.&lt;/p&gt;&lt;h3 id=&#34;solution&#34;&gt;Solution&lt;/h3&gt;&lt;p&gt;The caller calls the writer function in a normal way. This will works normal in a sequential manner, the number of channels does not make any difference. All 10 calling will be processed.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;package mainimport (&amp;quot;log&amp;quot;&amp;quot;time&amp;quot;)type storage struct {workersLimitCh chan struct{}}func (s *storage) InsertRows(i int) error {insert := func() error {j := idefer func() { &amp;lt;-s.workersLimitCh }()log.Println(&amp;quot;Sleeping...&amp;quot;, j)time.Sleep(2 * time.Second)return nil}log.Println(&amp;quot;Selecting...&amp;quot;)select {case s.workersLimitCh &amp;lt;- struct{}{}:log.Println(&amp;quot;insert()....&amp;quot;)return insert()default:log.Println(&amp;quot;defaulting...&amp;quot;)}return nil}func main() {s := storage{}s.workersLimitCh = make(chan struct{}, 10)for i := 0; i &amp;lt;= 10; i++ {s.InsertRows(i)}for {}}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The caller spins up goroutine to call the writer function. Even when the client spins up 10 goroutine to call the function, the function will limit it to only the number of channels available (which is 4). The rest of the 6 goroutine will be ignored.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;package mainimport (&amp;quot;log&amp;quot;&amp;quot;time&amp;quot;)type storage struct {workersLimitCh chan struct{}}func (s *storage) InsertRows(i int) error {insert := func() error {j := idefer func() { &amp;lt;-s.workersLimitCh }()log.Println(&amp;quot;Sleeping...&amp;quot;, j)time.Sleep(2 * time.Second)log.Println(&amp;quot;Done Sleeping...&amp;quot;, j)return nil}log.Println(&amp;quot;Selecting...&amp;quot;)select {case s.workersLimitCh &amp;lt;- struct{}{}:log.Println(&amp;quot;insert()....&amp;quot;)return insert()default:log.Println(&amp;quot;defaulting...&amp;quot;)}return nil}func main() {s := storage{}s.workersLimitCh = make(chan struct{}, 4)for i := 0; i &amp;lt;= 10; i++ {go func(i int) {s.InsertRows(i)}(i)}for {}}&lt;/code&gt;&lt;/pre&gt;</description>
     </item>
   
     <item>
       <title>In-Depth with Ollama</title>
       <link>/post/ollama/</link>
       <pubDate>Fri, 19 Apr 2024 00:00:00 +0000</pubDate>
       
       <guid>/post/ollama/</guid>
       <description>&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;#ollama&#34;&gt;Ollama&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#architecture&#34;&gt;Architecture&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;#llamacpp-or-llama&#34;&gt;llama.cpp or llama&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#ollama-or-llamago&#34;&gt;ollama or llama.go&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#source-layout&#34;&gt;Source Layout&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;#building-source&#34;&gt;Building Source&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#running-ollama&#34;&gt;Running Ollama&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#packaging&#34;&gt;Packaging&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#ollama-internals&#34;&gt;Ollama Internals&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;#debugging&#34;&gt;Debugging&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#ollama-to-llama&#34;&gt;Ollama to llama&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#llama-endpoints&#34;&gt;Llama Endpoints&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#model&#34;&gt;Model&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;#gguf&#34;&gt;GGUF&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;ollama&#34;&gt;Ollama&lt;/h2&gt;&lt;p&gt;The &lt;a href=&#34;https://github.com/ollama/ollama&#34;&gt;Ollama project&lt;/a&gt; is a Go project that has gained a lot of traction with 52,000 stars and forked more than 3600 times. The project can be used as a standalone application to interact with different large language models.. Not only that but the project makes it easy to interface for using the LLM functionality (eg: chat) by exposing REST API.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure1.png&#34; alt=&#34;figure1&#34; /&gt;&lt;/p&gt;&lt;h3 id=&#34;architecture&#34;&gt;Architecture&lt;/h3&gt;&lt;p&gt;The diagram shows the high level architecture between the application (&lt;code&gt;ollama&lt;/code&gt; and &lt;code&gt;llama&lt;/code&gt;) with the large language model. The &lt;code&gt;ollama&lt;/code&gt; project works like a thin wrapper to the &lt;code&gt;llama&lt;/code&gt; project which is responsible for interacting with the model.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure2.png&#34; alt=&#34;figure2&#34; /&gt;&lt;/p&gt;&lt;p&gt;We will make reference in article to both &lt;code&gt;llama&lt;/code&gt; and &lt;code&gt;ollama&lt;/code&gt; as they both serve different purposes even working together as a single unit.&lt;/p&gt;&lt;h4 id=&#34;llama-cpp-or-llama&#34;&gt;llama.cpp or llama&lt;/h4&gt;&lt;p&gt;In Figure-1 we can see that the ollama (Go) is run as a normal process. The llama.cpp will be run as a child process of ollama when a request comes in to load the model. The interaction with llama.cpp (&lt;a href=&#34;https://github.com/ggerganov/llama.cpp&#34;&gt;https://github.com/ggerganov/llama.cpp&lt;/a&gt;) project is via http. The llama.cpp project is an inference project for LLAMA (and other models).&lt;/p&gt;&lt;p&gt;An inference project is simply a project that involves working with the Large Language Model (LLM). Each model in the LLM has its own way of interacting with systems. So, in an inference project, we use the LLM to do different tasks, like understanding text or generating new content. It&amp;rsquo;s like using a tool for specific jobs, but each tool works a bit differently.&lt;/p&gt;&lt;p&gt;The interaction that is happening internally inside llama.cpp for example,  is not by calling functions to a large language model, but rather through a series of calculations that are fed into memory to be calculated. These calculations can nest deep in several layers of calculation.&lt;/p&gt;&lt;p&gt;To get a better visualization of how models works here is a very good interactive website that walked through the input/output parameters performed internally by llm &lt;a href=&#34;https://bbycroft.net/llm&#34;&gt;https://bbycroft.net/llm&lt;/a&gt;&lt;/p&gt;&lt;h4 id=&#34;ollama-or-llama-go&#34;&gt;ollama or llama.go&lt;/h4&gt;&lt;p&gt;The llama.go project simplifies working with Large Language Models (LLMs) by offering the following features:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Local Model Execution:&lt;/strong&gt; Easily download and run LLM models on your computer&amp;rsquo;s CPU or GPU. The project supports a variety of models tailored to different tasks.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;REST API Access:&lt;/strong&gt; Access the models through a user-friendly REST API, making it simple to integrate them into your applications. This allows for features like chat functionality and natural language processing.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility Across Systems:&lt;/strong&gt; llama.go works seamlessly across different operating systems and hardware architectures, ensuring compatibility regardless of your setup.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mac Applications:&lt;/strong&gt; Specific applications are available for macOS users, providing a local interface to interact with LLM models. These applications offer similar features to ChatGPT but for local use on Mac devices.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;With &lt;code&gt;llama.go&lt;/code&gt;, users can effortlessly harness the capabilities of LLM models for various tasks, with flexibility, ease of use, and compatibility in mind.&lt;/p&gt;&lt;p&gt;Complete list of the models can be found in this link &lt;a href=&#34;https://github.com/ollama/ollama?tab=readme-ov-file#model-library&#34;&gt;https://github.com/ollama/ollama?tab=readme-ov-file#model-library&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&#34;source-layout&#34;&gt;Source Layout&lt;/h2&gt;&lt;p&gt;The following &lt;strong&gt;main&lt;/strong&gt; branch shows the directories of the &lt;code&gt;ollama&lt;/code&gt; source code&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure3.png&#34; alt=&#34;figure3&#34; /&gt;&lt;/p&gt;&lt;p&gt;We will take a look at some of the directories to explain what kind of source code it host:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Directory&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;app&lt;/td&gt;&lt;td&gt;Build app for Windows platform&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;auth&lt;/td&gt;&lt;td&gt;Supporting package for authorization key&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cmd&lt;/td&gt;&lt;td&gt;CLI handlers for the different options available by ollama&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;convert&lt;/td&gt;&lt;td&gt;Conversion function to create model based on Gemma and Mistral&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;gpu&lt;/td&gt;&lt;td&gt;GPU interfaces for different graphic cards and operating system&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;integration&lt;/td&gt;&lt;td&gt;Integration tests&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;llm&lt;/td&gt;&lt;td&gt;Native integration layer between &lt;code&gt;llama.cpp&lt;/code&gt; and &lt;code&gt;ollama&lt;/code&gt;. This directory contains the crux of the logic that llama provides by interacting with the &lt;code&gt;llama.cpp&lt;/code&gt; project.&lt;br&gt;&lt;/br&gt;The &lt;code&gt;llama.cpp&lt;/code&gt; source code lives inside this directory as can be seen in the screenshot below&lt;br&gt;&lt;/br&gt; &lt;img src=&#34;./static/media/ollama/figure4.png&#34; alt=&#34;figure4&#34; /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;macapp&lt;/td&gt;&lt;td&gt;Electron based app for Mac platform&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;openai&lt;/td&gt;&lt;td&gt;Provides middleware for partial compatibility with the OpenAI REST API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;parser&lt;/td&gt;&lt;td&gt;HTTP handler and functions for creating model&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;scripts&lt;/td&gt;&lt;td&gt;Different build scripts for operating systems&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;server&lt;/td&gt;&lt;td&gt;Contains server related function relevant to models&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id=&#34;building-source&#34;&gt;Building Source&lt;/h2&gt;&lt;p&gt;To build the source code we will need to use the latest Go compiler, in this article we are using &lt;code&gt;1.22.1&lt;/code&gt;. The build and packaging process is done by executing the following command in the root directory of the project:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;go generate ./...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The generate command perform the following steps:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Execute operating system specific script. This article uses Linux OS so it will use the &lt;code&gt;gen_linux.sh&lt;/code&gt; script which is specified inside generate_linux.go source:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;package generate//go:generate bash ./gen_linux.sh&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The bash script will checkout &lt;code&gt;llama.cpp&lt;/code&gt; submodule from &lt;a href=&#34;https://github.com/ggerganov/llama.cpp.git&#34;&gt;https://github.com/ggerganov/llama.cpp.git&lt;/a&gt; into &lt;code&gt;llm/llama.cpp&lt;/code&gt; directory as shown in the screenshot&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure5.png&#34; alt=&#34;figure5&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Once successfully checked out the next step will be to perform file patching using the patch file inside &lt;strong&gt;ollama/llm/patches&lt;/strong&gt; directory.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Following are the log snippets from the output of running go generate command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;+ set -o pipefail+ echo &#39;Starting linux generate script&#39;Starting linux generate script...-- Build files have been written to: /home/nanik/Downloads/GoProjects/ollama/llm/build/linux/x86_64_static...-- Build files have been written to: /home/nanik/Downloads/GoProjects/ollama/llm/build/linux/x86_64/cpu...[100%] Built target ollama_llama_server...+ gzip -n --best -f ../build/linux/x86_64/cpu/bin/ollama_llama_server...+ gzip -n --best -f ../build/linux/x86_64/cpu_avx/bin/ollama_llama_server...+ gzip -n --best -f ../build/linux/x86_64/cpu_avx2/bin/ollama_llama_server...+ cd ../llama.cpp/+ git checkout CMakeLists.txtUpdated 1 path from the index++ cd ../build/linux/x86_64/cpu_avx2/..++ echo cpu cpu_avx cpu_avx2+ echo &#39;go generate completed.  LLM runners: cpu cpu_avx cpu_avx2&#39;go generate completed.  LLM runners: cpu cpu_avx cpu_avx2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On completion the &lt;strong&gt;build&lt;/strong&gt; directory will look like the following on a Linux machine&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure6.png&#34; alt=&#34;figure6&#34; /&gt;&lt;/p&gt;&lt;p&gt;The next command to run is now to build the Go binary using the following command from root directory:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;go build .&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The build command will produce an executable file called &lt;code&gt;ollama&lt;/code&gt; that also contains the &lt;code&gt;.gz&lt;/code&gt; files produced earlier by the &lt;strong&gt;go generate&lt;/strong&gt; command which contains the &lt;code&gt;llama.cpp&lt;/code&gt; project.&lt;/p&gt;&lt;h3 id=&#34;running-ollama&#34;&gt;Running Ollama&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;ollama&lt;/code&gt; project runs as an http server that accepts requests for a number of things related to the models. To get started open a terminal window and run it using the following command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ollama serve&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The application will start up printing the following log in the console:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;time=2024-04-08T23:51:13.450+10:00 level=INFO source=images.go:793 msg=&amp;quot;total blobs: 6&amp;quot;time=2024-04-08T23:51:13.451+10:00 level=INFO source=images.go:800 msg=&amp;quot;total unused blobs removed: 0&amp;quot;[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.[GIN-debug] [WARNING] Running in &amp;quot;debug&amp;quot; mode. Switch to &amp;quot;release&amp;quot; mode in production. - using env:export GIN_MODE=release - using code:gin.SetMode(gin.ReleaseMode)[GIN-debug] POST   /api/pull                 --&amp;gt; github.com/ollama/ollama/server.PullModelHandler (5 handlers)…[GIN-debug] HEAD   /api/version              --&amp;gt; github.com/ollama/ollama/server.(*Server).GenerateRoutes.func2 (5 handlers)…time=2024-04-08T23:51:13.480+10:00 level=WARN source=amd_linux.go:367 msg=&amp;quot;amdgpu detected, but no compatible rocm library found.  Either install rocm v6, or follow manual install instructions at https://github.com/ollama/ollama/blob/main/docs/linux.md#manual-install&amp;quot;time=2024-04-08T23:51:13.480+10:00 level=WARN source=amd_linux.go:99 msg=&amp;quot;unable to verify rocm library, will use cpu: no suitable rocm found, falling back to CPU&amp;quot;time=2024-04-08T23:51:13.480+10:00 level=INFO source=routes.go:1144 msg=&amp;quot;no GPU detected&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The server is now ready to accept requests. The same &lt;b&gt;ollama&lt;/b&gt; application is also used to communicate with the server. Open another terminal window and run the following command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ollama run llama2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The command will communicate with the server and download the &lt;code&gt;llama2&lt;/code&gt; model to be run locally, when the application successfully download and initialize the model it will give you a prompt that you can type to asked any question as shown below:&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure7.png&#34; alt=&#34;figure7&#34; /&gt;&lt;/p&gt;&lt;p&gt;The &lt;code&gt;ollama&lt;/code&gt; application provide several commands that you can use shown below:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Commands&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;serve&lt;/td&gt;&lt;td&gt;Start ollama&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;create&lt;/td&gt;&lt;td&gt;Create a model from a Modelfile&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;show&lt;/td&gt;&lt;td&gt;Show information for a model&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;run&lt;/td&gt;&lt;td&gt;Run a model&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;pull&lt;/td&gt;&lt;td&gt;Pull a model from a registry&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;push&lt;/td&gt;&lt;td&gt;Push a model to a registry&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;list&lt;/td&gt;&lt;td&gt;List models&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cp&lt;/td&gt;&lt;td&gt;Copy a model&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;rm&lt;/td&gt;&lt;td&gt;Remove a model&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h3 id=&#34;packaging&#34;&gt;Packaging&lt;/h3&gt;&lt;p&gt;As mentioned previously the ollama binary file is packaged with the llama.cpp binary. The build process embeds these binary files into the final binary ollama file. The following screenshot shows the different generated files for an AMD processor with AVX support.&lt;/p&gt;&lt;p&gt;|  |  | ||&amp;mdash;&amp;mdash;&amp;mdash;-|&amp;mdash;&amp;mdash;&amp;mdash;-| &amp;ndash; || &lt;img src=&#34;./static/media/ollama/figure8.png&#34; alt=&#34;figure8&#34; /&gt; | &lt;img src=&#34;./static/media/ollama/figure9.png&#34; alt=&#34;figure9&#34; /&gt; | &lt;img src=&#34;./static/media/ollama/figure10.png&#34; alt=&#34;figure10&#34; /&gt; ||  |  | |&lt;/p&gt;&lt;p&gt;The above screenshot shows 3 different &lt;code&gt;.gz&lt;/code&gt; files generated for normal CPU, AVX and AVX2, and all of them are named &lt;code&gt;ollama_llama_server.gz&lt;/code&gt;. These files are packaged together into the final ollama binary file. This is done by using the &lt;code&gt;embed&lt;/code&gt; standard library as shown in the code snippet below.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;package llmimport &amp;quot;embed&amp;quot;//go:embed build/linux/*/*/bin/*var libEmbed embed.FS&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;go:embed&lt;/code&gt; specifies the files that will be packaged which in this case is under &lt;code&gt;build/&lt;/code&gt; directory.&lt;/p&gt;&lt;h2 id=&#34;ollama-internals&#34;&gt;Ollama Internals&lt;/h2&gt;&lt;p&gt;As explained previously the &lt;code&gt;ollama&lt;/code&gt; application is run as an http server that accepts request, the following tables shows the different endpoints that are available:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;HTTP Method&lt;/th&gt;&lt;th&gt;Url&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/pull&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/generate&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/chat&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/embeddings&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/create&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/push&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/copy&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DELETE&lt;/td&gt;&lt;td&gt;/api/delete&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/show&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/api/blobs/:digest&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HEAD&lt;/td&gt;&lt;td&gt;/api/blobs/:digest&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POST&lt;/td&gt;&lt;td&gt;/v1/chat/completions&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/api/tags&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/api/version&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HEAD&lt;/td&gt;&lt;td&gt;/&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HEAD&lt;/td&gt;&lt;td&gt;/api/tags&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HEAD&lt;/td&gt;&lt;td&gt;/api/version&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The commands that are available when running &lt;code&gt;ollama&lt;/code&gt; use the above url endpoints, for example: running &lt;code&gt;ollama run llama2&lt;/code&gt; will call the the &lt;em&gt;/api/pull&lt;/em&gt; endpoint to download the model and then it uses the &lt;em&gt;/api/chat&lt;/em&gt; to accept chat requests and respond to it.&lt;/p&gt;&lt;p&gt;With the availability of the different endpoints, &lt;code&gt;ollama&lt;/code&gt; gives the flexibility to develop tools of our own using simple tools like cURL or any programming language.&lt;/p&gt;&lt;h3 id=&#34;debugging&#34;&gt;Debugging&lt;/h3&gt;&lt;p&gt;Ollama provides a debugging flag that can be turned on when running it. These flags provide verbose log information on certain internal parts of the application. The following table outlined some of the available flags:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Flag&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;OLLAMA_DEBUG&lt;/td&gt;&lt;td&gt;true&lt;/td&gt;&lt;td&gt;Provide debug log information for ollama application&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLAMA_TRACE&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Provide debug log information for llama&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GGML_DEBUG&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;For example if we want to debug some issues in ollama we can turn on the debug flag by using the following command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;OLLAMA_DEBUG=true ollama serve&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You will get more debug log information as shown below:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;...time=2024-04-09T00:06:25.637+10:00 level=DEBUG source=payload.go:160 msg=extracting variant=cpu file=build/linux/x86_64/cpu/bin/ollama_llama_server.gztime=2024-04-09T00:06:25.637+10:00 level=DEBUG source=payload.go:160 msg=extracting variant=cpu_avx file=build/linux/x86_64/cpu_avx/bin/ollama_llama_server.gztime=2024-04-09T00:06:25.637+10:00 level=DEBUG source=payload.go:160 msg=extracting variant=cpu_avx2 file=build/linux/x86_64/cpu_avx2/bin/ollama_llama_server.gztime=2024-04-09T00:06:25.658+10:00 level=DEBUG source=payload.go:68 msg=&amp;quot;availableServers : found&amp;quot; file=/tmp/ollama3078763984/runners/cputime=2024-04-09T00:06:25.658+10:00 level=DEBUG source=payload.go:68 msg=&amp;quot;availableServers : found&amp;quot; file=/tmp/ollama3078763984/runners/cpu_avxtime=2024-04-09T00:06:25.658+10:00 level=DEBUG source=payload.go:68 msg=&amp;quot;availableServers : found&amp;quot; file=/tmp/ollama3078763984/runners/cpu_avx2time=2024-04-09T00:06:25.658+10:00 level=INFO source=payload.go:41 msg=&amp;quot;Dynamic LLM libraries [cpu cpu_avx cpu_avx2]&amp;quot;time=2024-04-09T00:06:25.658+10:00 level=DEBUG source=payload.go:42 msg=&amp;quot;Override detection logic by setting OLLAMA_LLM_LIBRARY&amp;quot;time=2024-04-09T00:06:25.658+10:00 level=INFO source=gpu.go:121 msg=&amp;quot;Detecting GPU type&amp;quot;time=2024-04-09T00:06:25.658+10:00 level=INFO source=gpu.go:268 msg=&amp;quot;Searching for GPU management library libcudart.so*&amp;quot;time=2024-04-09T00:06:25.658+10:00 level=DEBUG source=gpu.go:286 msg=&amp;quot;gpu management search paths: [/tmp/ollama3078763984/runners/cuda*/libcudart.so* … /home/nanik/Downloads/GoProjects/ollama/libcudart.so**]&amp;quot;time=2024-04-09T00:06:25.667+10:00 level=INFO source=gpu.go:314 msg=&amp;quot;Discovered GPU libraries: []&amp;quot;...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To enable more verbose logging from the &lt;code&gt;llama&lt;/code&gt; project we need to pass in the following flag before running the &lt;code&gt;go generate&lt;/code&gt; command to build the native application:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;export CGO_CFLAGS=&amp;quot;-g&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Must be wondering how does the log looks like when we use the -g above, below can see the log snippets when the &lt;code&gt;llama&lt;/code&gt; application is processing a chat request:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;time=2024-04-09T08:34:19.787+10:00 level=DEBUG source=server.go:432 msg=&amp;quot;llama runner started in 24.340054 seconds&amp;quot;time=2024-04-09T08:34:19.789+10:00 level=DEBUG source=prompt.go:172 msg=&amp;quot;prompt now fits in context window&amp;quot; required=1 window=2048[GIN] 2024/04/09 - 08:34:19 | 200 | 24.578298317s |       127.0.0.1 | POST     &amp;quot;/api/chat&amp;quot;{&amp;quot;function&amp;quot;:&amp;quot;get_new_id&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:254,&amp;quot;msg&amp;quot;:&amp;quot;new task id&amp;quot;,&amp;quot;new_id&amp;quot;:7,&amp;quot;tid&amp;quot;:&amp;quot;133124421846592&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;add_waiting_task_id&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:397,&amp;quot;msg&amp;quot;:&amp;quot;waiting for task id&amp;quot;,&amp;quot;task_id&amp;quot;:7,&amp;quot;tid&amp;quot;:&amp;quot;133124421846592&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;start_loop&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:302,&amp;quot;msg&amp;quot;:&amp;quot;new task may arrive&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;133129545471872&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;start_loop&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:314,&amp;quot;msg&amp;quot;:&amp;quot;callback_new_task&amp;quot;,&amp;quot;task_id&amp;quot;:7,&amp;quot;tid&amp;quot;:&amp;quot;133129545471872&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;process_single_task&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:1502,&amp;quot;msg&amp;quot;:&amp;quot;slot data&amp;quot;,&amp;quot;n_idle_slots&amp;quot;:1,&amp;quot;n_processing_slots&amp;quot;:0,&amp;quot;task_id&amp;quot;:7,&amp;quot;tid&amp;quot;:&amp;quot;133129545471872&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;process_single_task&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:1507,&amp;quot;msg&amp;quot;:&amp;quot;slot data&amp;quot;,&amp;quot;n_idle_slots&amp;quot;:1,&amp;quot;n_processing_slots&amp;quot;:0,&amp;quot;slots&amp;quot;:[{&amp;quot;dynatemp_exponent&amp;quot;:1.0,&amp;quot;dynatemp_range&amp;quot;:0.0,&amp;quot;frequency_penalty&amp;quot;:0.0,&amp;quot;grammar&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;id&amp;quot;:0,&amp;quot;ignore_eos&amp;quot;:false,&amp;quot;logit_bias&amp;quot;:[],&amp;quot;min_keep&amp;quot;:0,&amp;quot;min_p&amp;quot;:0.05000000074505806,&amp;quot;mirostat&amp;quot;:0,&amp;quot;mirostat_eta&amp;quot;:0.10000000149011612,&amp;quot;mirostat_tau&amp;quot;:5.0,&amp;quot;model&amp;quot;:&amp;quot;/home/nanik/.ollama/models/blobs/sha256-8934d96d3f08982e95922b2b7a2c626a1fe873d7c3b06e8e56d7bc0a1fef9246&amp;quot;,&amp;quot;n_ctx&amp;quot;:2048,&amp;quot;n_keep&amp;quot;:0,&amp;quot;n_predict&amp;quot;:-1,&amp;quot;n_probs&amp;quot;:0,&amp;quot;next_token&amp;quot;:{&amp;quot;has_next_token&amp;quot;:true,&amp;quot;n_remain&amp;quot;:-1,&amp;quot;num_tokens_predicted&amp;quot;:0,&amp;quot;stopped_eos&amp;quot;:false,&amp;quot;stopped_limit&amp;quot;:false,&amp;quot;stopped_word&amp;quot;:false,&amp;quot;stopping_word&amp;quot;:&amp;quot;&amp;quot;},&amp;quot;penalize_nl&amp;quot;:false,&amp;quot;penalty_prompt_tokens&amp;quot;:[],&amp;quot;presence_penalty&amp;quot;:0.0,&amp;quot;prompt&amp;quot;:null,&amp;quot;repeat_last_n&amp;quot;:64,&amp;quot;repeat_penalty&amp;quot;:1.0,&amp;quot;samplers&amp;quot;:[&amp;quot;top_k&amp;quot;,&amp;quot;tfs_z&amp;quot;,&amp;quot;typical_p&amp;quot;,&amp;quot;top_p&amp;quot;,&amp;quot;min_p&amp;quot;,&amp;quot;temperature&amp;quot;],&amp;quot;seed&amp;quot;:4294967295,&amp;quot;state&amp;quot;:0,&amp;quot;stop&amp;quot;:[],&amp;quot;stream&amp;quot;:true,&amp;quot;task_id&amp;quot;:-1,&amp;quot;temperature&amp;quot;:0.800000011920929,&amp;quot;tfs_z&amp;quot;:1.0,&amp;quot;top_k&amp;quot;:40,&amp;quot;top_p&amp;quot;:0.949999988079071,&amp;quot;typical_p&amp;quot;:1.0,&amp;quot;use_penalty_prompt_tokens&amp;quot;:false}],&amp;quot;task_id&amp;quot;:7,&amp;quot;tid&amp;quot;:&amp;quot;133129545471872&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}...{&amp;quot;function&amp;quot;:&amp;quot;log_server_request&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:2730,&amp;quot;method&amp;quot;:&amp;quot;GET&amp;quot;,&amp;quot;msg&amp;quot;:&amp;quot;request&amp;quot;,&amp;quot;params&amp;quot;:{},&amp;quot;path&amp;quot;:&amp;quot;/health&amp;quot;,&amp;quot;remote_addr&amp;quot;:&amp;quot;127.0.0.1&amp;quot;,&amp;quot;remote_port&amp;quot;:37158,&amp;quot;status&amp;quot;:200,&amp;quot;tid&amp;quot;:&amp;quot;133124421846592&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;log_server_request&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:2739,&amp;quot;msg&amp;quot;:&amp;quot;request&amp;quot;,&amp;quot;request&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;response&amp;quot;:&amp;quot;{\&amp;quot;slots_idle\&amp;quot;:1,\&amp;quot;slots_processing\&amp;quot;:0,\&amp;quot;status\&amp;quot;:\&amp;quot;ok\&amp;quot;}&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;133124421846592&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;get_new_id&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:254,&amp;quot;msg&amp;quot;:&amp;quot;new task id&amp;quot;,&amp;quot;new_id&amp;quot;:8,&amp;quot;tid&amp;quot;:&amp;quot;133124421846592&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;add_waiting_task_id&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:397,&amp;quot;msg&amp;quot;:&amp;quot;waiting for task id&amp;quot;,&amp;quot;task_id&amp;quot;:8,&amp;quot;tid&amp;quot;:&amp;quot;133124421846592&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}...{&amp;quot;function&amp;quot;:&amp;quot;start_loop&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:317,&amp;quot;msg&amp;quot;:&amp;quot;update_multitasks&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;133129545471872&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;start_loop&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:336,&amp;quot;msg&amp;quot;:&amp;quot;callback_run_slots&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;133129545471872&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;start_loop&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;VERB&amp;quot;,&amp;quot;line&amp;quot;:339,&amp;quot;msg&amp;quot;:&amp;quot;wait for new task&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;133129545471872&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}{&amp;quot;function&amp;quot;:&amp;quot;log_server_request&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:2730,&amp;quot;method&amp;quot;:&amp;quot;GET&amp;quot;,&amp;quot;msg&amp;quot;:&amp;quot;request&amp;quot;,&amp;quot;params&amp;quot;:{},&amp;quot;path&amp;quot;:&amp;quot;/health&amp;quot;,&amp;quot;remote_addr&amp;quot;:&amp;quot;127.0.0.1&amp;quot;,&amp;quot;remote_port&amp;quot;:37158,&amp;quot;status&amp;quot;:200,&amp;quot;tid&amp;quot;:&amp;quot;133124421846592&amp;quot;,&amp;quot;timestamp&amp;quot;:1712615664}...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The log looks like gibberish as there are a lot of messages, but these messages are very useful when troubleshooting or learning how the interaction with the models works.&lt;/p&gt;&lt;h3 id=&#34;ollama-to-llama&#34;&gt;Ollama to Llama&lt;/h3&gt;&lt;p&gt;So far we have explored the &lt;code&gt;ollama&lt;/code&gt; source code and looked at compiling and running it locally. In this section we will go deeper on how it works internally.&lt;/p&gt;&lt;p&gt;We know now that the way the application is architected is to communicate via http to the &lt;code&gt;llama&lt;/code&gt; project that is run as a child process as shown in the diagram below&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure11.png&#34; alt=&#34;figure11&#34; /&gt;&lt;/p&gt;&lt;p&gt;So what does the actual process look like ?, first let’s use the command &lt;code&gt;ps aux | grep -i ollama&lt;/code&gt; to get the PID of the &lt;code&gt;ollama&lt;/code&gt; running in the local machine which is shown in the screenshot below. The PID shown is &lt;code&gt;3180960&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure12.png&#34; alt=&#34;figure12&#34; /&gt;&lt;/p&gt;&lt;p&gt;Using the command &lt;code&gt;pstree -a 3180960&lt;/code&gt; we will be able to see the tree structure of the process as shown below&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure13.png&#34; alt=&#34;figure13&#34; /&gt;&lt;/p&gt;&lt;p&gt;The diagram shows the &lt;code&gt;ollama&lt;/code&gt; spawning a child process executing the &lt;code&gt;llama&lt;/code&gt; project which is packaged with the file name &lt;code&gt;ollama_llama_server&lt;/code&gt;. The child process is executed by passing several command line parameters used to initialize the LLM models, logging, etc.&lt;/p&gt;&lt;p&gt;Fascinating to observe how the Llama application spawns multiple threads upon receiving a chat request. The threads are used for managing the processing of data to and from the model, as shown in the screenshot provided.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure14.png&#34; alt=&#34;figure14&#34; /&gt;&lt;/p&gt;&lt;p&gt;How do we know which port &lt;code&gt;llama&lt;/code&gt; is running on ?, this is shown in the log when you access the model by running _ollama run &lt;model_name&gt;_.&lt;/p&gt;&lt;p&gt;Below is a sample log on how it looks like on my local machine where it shows that the &lt;code&gt;llama&lt;/code&gt; server is running on port &lt;code&gt;4767&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;...{&amp;quot;function&amp;quot;:&amp;quot;initialize&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:448,&amp;quot;msg&amp;quot;:&amp;quot;initializing slots&amp;quot;,&amp;quot;n_slots&amp;quot;:1,&amp;quot;tid&amp;quot;:&amp;quot;137254119753600&amp;quot;,&amp;quot;timestamp&amp;quot;:1713529242}{&amp;quot;function&amp;quot;:&amp;quot;initialize&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:457,&amp;quot;msg&amp;quot;:&amp;quot;new slot&amp;quot;,&amp;quot;n_ctx_slot&amp;quot;:2048,&amp;quot;slot_id&amp;quot;:0,&amp;quot;tid&amp;quot;:&amp;quot;137254119753600&amp;quot;,&amp;quot;timestamp&amp;quot;:1713529242}{&amp;quot;function&amp;quot;:&amp;quot;main&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:3064,&amp;quot;msg&amp;quot;:&amp;quot;model loaded&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;137254119753600&amp;quot;,&amp;quot;timestamp&amp;quot;:1713529242}{&amp;quot;function&amp;quot;:&amp;quot;main&amp;quot;,&amp;quot;hostname&amp;quot;:&amp;quot;127.0.0.1&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:3267,&amp;quot;msg&amp;quot;:&amp;quot;HTTP server listening&amp;quot;,&amp;quot;n_threads_http&amp;quot;:&amp;quot;15&amp;quot;,&amp;quot;port&amp;quot;:&amp;quot;4767&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;137254119753600&amp;quot;,&amp;quot;timestamp&amp;quot;:1713529242}...&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;llama-endpoints&#34;&gt;Llama Endpoints&lt;/h4&gt;&lt;p&gt;When the &lt;code&gt;llama&lt;/code&gt; application is launched, it operates as a server capable of handling standard HTTP requests. In this scenario, it awaits connections from &lt;code&gt;ollama&lt;/code&gt;. Following are the endpoints that are exposed by &lt;code&gt;llama&lt;/code&gt;:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;HTTP Method&lt;/th&gt;&lt;th&gt;Url&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/health&lt;/td&gt;&lt;td&gt;Check health status of &lt;code&gt;llama&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/slots&lt;/td&gt;&lt;td&gt;Obtain information about the slots initialized internally&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/metrics&lt;/td&gt;&lt;td&gt;Used to get metric information about processed tokens&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/completion&lt;/td&gt;&lt;td&gt;Used for chat functionality&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/tokenize&lt;/td&gt;&lt;td&gt;Used to tokenize the information input by the user&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/detokenize&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GET&lt;/td&gt;&lt;td&gt;/embdedding&lt;/td&gt;&lt;td&gt;Used for RAG based applications&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h4 id=&#34;slots&#34;&gt;Slots&lt;/h4&gt;&lt;p&gt;Internally &lt;code&gt;llama&lt;/code&gt; processes token by the number of allocated slots available, for eg - if there is 1 slot allocated then &lt;code&gt;llama&lt;/code&gt; will process 1 token at a time.&lt;/p&gt;&lt;p&gt;The diagram below shows the high level flow when the &lt;em&gt;/completions&lt;/em&gt; endpoint is called, this endpoint is used for chat. The slots are initialized when the endpoint is called, and once it is initialized it will go through the &lt;code&gt;Decoding Process&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure15.png&#34; alt=&#34;figure15&#34; /&gt;&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;Decoding Process&lt;/strong&gt; is the brain of the operation performed inside the llama process. Basically what it does is it prepares the model which is now in memory to perform calculation in different layers until it gets an output.&lt;/p&gt;&lt;p&gt;Once output is obtained it will send the output to the caller, in this case the caller of the /completions endpoint.The &lt;strong&gt;Decoding Process&lt;/strong&gt; will keep on going until there are no more output returned from the model or it is said that the process has stopped processing token, which means it has reached the end.&lt;/p&gt;&lt;p&gt;Accessing the llama endpoint using the following cURL command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;curl http://localhost:&amp;lt;llama_port&amp;gt;/slots&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Will show you information about the slot information:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;[  {    &amp;quot;dynatemp_exponent&amp;quot;: 1,    &amp;quot;dynatemp_range&amp;quot;: 0,    &amp;quot;frequency_penalty&amp;quot;: 0,    &amp;quot;grammar&amp;quot;: &amp;quot;&amp;quot;,    &amp;quot;id&amp;quot;: 0,    &amp;quot;ignore_eos&amp;quot;: false,    &amp;quot;logit_bias&amp;quot;: [],    &amp;quot;min_keep&amp;quot;: 0,    &amp;quot;min_p&amp;quot;: 0.05000000074505806,    &amp;quot;mirostat&amp;quot;: 0,    &amp;quot;mirostat_eta&amp;quot;: 0.10000000149011612,    &amp;quot;mirostat_tau&amp;quot;: 5,    &amp;quot;model&amp;quot;: &amp;quot;/home/nanik/.ollama/models/blobs/sha256-8934d96d3f08982e95922b2b7a2c626a1fe873d7c3b06e8e56d7bc0a1fef9246&amp;quot;,    &amp;quot;n_ctx&amp;quot;: 2048,    &amp;quot;n_keep&amp;quot;: 0,    &amp;quot;n_predict&amp;quot;: -1,    &amp;quot;n_probs&amp;quot;: 0,    &amp;quot;next_token&amp;quot;: {      &amp;quot;has_next_token&amp;quot;: true,      &amp;quot;n_remain&amp;quot;: -1,      &amp;quot;num_tokens_predicted&amp;quot;: 0,      &amp;quot;stopped_eos&amp;quot;: false,      &amp;quot;stopped_limit&amp;quot;: false,      &amp;quot;stopped_word&amp;quot;: false,      &amp;quot;stopping_word&amp;quot;: &amp;quot;&amp;quot;    },    &amp;quot;penalize_nl&amp;quot;: false,    &amp;quot;penalty_prompt_tokens&amp;quot;: [],    &amp;quot;presence_penalty&amp;quot;: 0,    &amp;quot;prompt&amp;quot;: null,    &amp;quot;repeat_last_n&amp;quot;: 64,    &amp;quot;repeat_penalty&amp;quot;: 1,    &amp;quot;samplers&amp;quot;: [      &amp;quot;top_k&amp;quot;,      &amp;quot;tfs_z&amp;quot;,      &amp;quot;typical_p&amp;quot;,      &amp;quot;top_p&amp;quot;,      &amp;quot;min_p&amp;quot;,      &amp;quot;temperature&amp;quot;    ],    &amp;quot;seed&amp;quot;: 4294967295,    &amp;quot;state&amp;quot;: 0,    &amp;quot;stop&amp;quot;: [],    &amp;quot;stream&amp;quot;: true,    &amp;quot;task_id&amp;quot;: -1,    &amp;quot;temperature&amp;quot;: 0.800000011920929,    &amp;quot;tfs_z&amp;quot;: 1,    &amp;quot;top_k&amp;quot;: 40,    &amp;quot;top_p&amp;quot;: 0.949999988079071,    &amp;quot;typical_p&amp;quot;: 1,    &amp;quot;use_penalty_prompt_tokens&amp;quot;: false  }]&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;model&#34;&gt;Model&lt;/h4&gt;&lt;p&gt;The diagram shows how the model looks like internally as it contains different metadata information describing the model such as license, weight, tensors, etc.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure16.png&#34; alt=&#34;figure16&#34; /&gt;&lt;/p&gt;&lt;p&gt;In simple terms &lt;code&gt;Tensors&lt;/code&gt; are mathematical formulas that are used to process input to derive the required output. Every model have layers of this tensors built-in internally that are used to perform complex calculation. Data that need to be processed are converted into tokens which will be feed into the model to extract the relevant value which are again re-converted to text.&lt;/p&gt;&lt;p&gt;In the example of the model used by &lt;code&gt;ollama&lt;/code&gt; the llama2 model have in total 291 tensors. The following &lt;code&gt;ollama&lt;/code&gt; example log shows the tensor information read from llama2 model&lt;/p&gt;&lt;pre&gt;&lt;code&gt;...{&amp;quot;function&amp;quot;:&amp;quot;load_model&amp;quot;,&amp;quot;level&amp;quot;:&amp;quot;INFO&amp;quot;,&amp;quot;line&amp;quot;:403,&amp;quot;msg&amp;quot;:&amp;quot;llama_init_from_gpt_params&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;136660906297216&amp;quot;,&amp;quot;timestamp&amp;quot;:1713528385}llama_model_loader: loaded meta data with 23 key-value pairs and 291 tensors from /home/nanik/.ollama/models/blobs/sha256-8934d96d3f08982e95922b2b7a2c626a1fe873d7c3b06e8e56d7bc0a1fef9246 (version GGUF V3 (latest))llama_model_loader: - tensor    0, split  0:                token_embd.weight q4_0     [  4096, 32000,     1,     1 ]llama_model_loader: - tensor    1, split  0:           blk.0.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor    2, split  0:            blk.0.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]...llama_model_loader: - tensor  164, split  0:            blk.4.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  165, split  0:            blk.4.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  166, split  0:              blk.4.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  167, split  0:            blk.4.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  168, split  0:              blk.4.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  169, split  0:         blk.4.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  170, split  0:              blk.4.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  171, split  0:              blk.4.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  172, split  0:           blk.5.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  173, split  0:            blk.5.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  174, split  0:            blk.5.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  175, split  0:              blk.5.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  176, split  0:            blk.5.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  177, split  0:              blk.5.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  178, split  0:         blk.5.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  179, split  0:              blk.5.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  180, split  0:              blk.5.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  181, split  0:           blk.6.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  182, split  0:            blk.6.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  183, split  0:            blk.6.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  184, split  0:              blk.6.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  185, split  0:            blk.6.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  186, split  0:              blk.6.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  187, split  0:         blk.6.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  188, split  0:              blk.6.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  189, split  0:              blk.6.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  190, split  0:           blk.7.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  191, split  0:            blk.7.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  192, split  0:            blk.7.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  193, split  0:              blk.7.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  194, split  0:            blk.7.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  195, split  0:              blk.7.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  196, split  0:         blk.7.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  197, split  0:              blk.7.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  198, split  0:              blk.7.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  199, split  0:           blk.8.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  200, split  0:            blk.8.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  201, split  0:            blk.8.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  202, split  0:              blk.8.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  203, split  0:            blk.8.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  204, split  0:              blk.8.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  205, split  0:         blk.8.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  206, split  0:              blk.8.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  207, split  0:              blk.8.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  208, split  0:           blk.9.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  209, split  0:            blk.9.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  210, split  0:            blk.9.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  211, split  0:              blk.9.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  212, split  0:            blk.9.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  213, split  0:              blk.9.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  214, split  0:         blk.9.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  215, split  0:              blk.9.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  216, split  0:              blk.9.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  217, split  0:                    output.weight q6_K     [  4096, 32000,     1,     1 ]llama_model_loader: - tensor  218, split  0:          blk.24.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  219, split  0:           blk.24.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  220, split  0:           blk.24.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  221, split  0:             blk.24.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  222, split  0:           blk.24.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  223, split  0:             blk.24.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  224, split  0:        blk.24.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  225, split  0:             blk.24.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  226, split  0:             blk.24.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  227, split  0:          blk.25.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  228, split  0:           blk.25.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  229, split  0:           blk.25.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  230, split  0:             blk.25.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  231, split  0:           blk.25.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  232, split  0:             blk.25.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  233, split  0:        blk.25.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  234, split  0:             blk.25.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  235, split  0:             blk.25.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  236, split  0:          blk.26.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  237, split  0:           blk.26.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  238, split  0:           blk.26.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  239, split  0:             blk.26.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  240, split  0:           blk.26.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  241, split  0:             blk.26.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  242, split  0:        blk.26.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  243, split  0:             blk.26.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  244, split  0:             blk.26.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  245, split  0:          blk.27.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  246, split  0:           blk.27.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]...llama_model_loader: - tensor  269, split  0:        blk.29.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  270, split  0:             blk.29.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  271, split  0:             blk.29.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  272, split  0:          blk.30.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  273, split  0:           blk.30.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  274, split  0:           blk.30.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  275, split  0:             blk.30.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  276, split  0:           blk.30.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  277, split  0:             blk.30.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  278, split  0:        blk.30.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  279, split  0:             blk.30.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  280, split  0:             blk.30.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  281, split  0:          blk.31.attn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  282, split  0:           blk.31.ffn_down.weight q4_0     [ 11008,  4096,     1,     1 ]llama_model_loader: - tensor  283, split  0:           blk.31.ffn_gate.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  284, split  0:             blk.31.ffn_up.weight q4_0     [  4096, 11008,     1,     1 ]llama_model_loader: - tensor  285, split  0:           blk.31.ffn_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: - tensor  286, split  0:             blk.31.attn_k.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  287, split  0:        blk.31.attn_output.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  288, split  0:             blk.31.attn_q.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  289, split  0:             blk.31.attn_v.weight q4_0     [  4096,  4096,     1,     1 ]llama_model_loader: - tensor  290, split  0:               output_norm.weight f32      [  4096,     1,     1,     1 ]llama_model_loader: Dumping metadata keys/values. Note: KV overrides do not apply in this output....&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Models that are compatible with &lt;code&gt;llama.cpp&lt;/code&gt; must be in GGUF format and can be searched using the following link &lt;a href=&#34;https://huggingface.co/models?sort=trending&amp;amp;search=gguf&#34;&gt;https://huggingface.co/models?sort=trending&amp;amp;search=gguf&lt;/a&gt;&lt;/p&gt;&lt;h4 id=&#34;gguf&#34;&gt;GGUF&lt;/h4&gt;&lt;p&gt;We know now that model that can be used by &lt;code&gt;llama&lt;/code&gt; have to be in GGUF format, so what is it ?. According to the author &lt;a href=&#34;https://github.com/ggerganov/ggml/blob/master/docs/gguf.md&#34;&gt;https://github.com/ggerganov/ggml/blob/master/docs/gguf.md&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;GGUF is a file format for storing models for inference with GGML and executors based on GGML. GGUF is a binary format that is designed for fast loading and saving of models, and for ease of reading. Models are traditionally developed using PyTorch or another framework, and then converted to GGUF for use in GGML.&lt;/code&gt;`&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./static/media/ollama/figure17.png&#34; alt=&#34;figure17&#34; /&gt;&lt;/p&gt;&lt;p&gt;The following website provide an in-depth explanation about the format and how the model works internally &lt;a href=&#34;https://vickiboykis.com/2024/02/28/gguf-the-long-way-around/&#34;&gt;https://vickiboykis.com/2024/02/28/gguf-the-long-way-around/&lt;/a&gt;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Concurrent map in Go</title>
       <link>/post/concurrentmap/</link>
       <pubDate>Thu, 11 Mar 2021 00:00:00 +0000</pubDate>
       
       <guid>/post/concurrentmap/</guid>
       <description>&lt;p&gt;From &lt;a href=&#34;https://golang.org/doc/faq#atomic_maps&#34;&gt;golang faq&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;Why are map operations not defined to be atomic?&lt;/h4&gt;&lt;div class=&#34;boxtextoverflow&#34;&gt;After long discussion it was decided that the typical use of maps did not require safe access from multiple goroutines, and in those cases where it did, the map was probably part of some larger data structure or computation that was already synchronized. Therefore requiring that all map operations grab a mutex would slow down most programs and add safety to few. This was not an easy decision, however, since it means uncontrolled map access can crash the program. &lt;br&gt;&lt;/br&gt;The language does not preclude atomic map updates. When required, such as when hosting an untrusted program, the implementation could interlock map access.&lt;br&gt;&lt;/br&gt;Map access is unsafe only when updates are occurring. As long as all goroutines are only reading—looking up elements in the map, including iterating through it using a for range loop—and not changing the map by assigning to elements or doing deletions, it is safe for them to access the map concurrently without synchronization.&lt;br&gt;&lt;/br&gt;As an aid to correct map use, some implementations of the language contain a special check that automatically reports at run time when a map is modified unsafely by concurrent execution. &lt;/div&gt;&lt;p&gt;Other languages such as Java provides map implementation that supports concurrent read/write.&lt;/p&gt;&lt;p&gt;Time will come when we will need to design apps that requires map to be read in different part of the app requiring concurrent read and write. Conceptually to implement a map that supports concurrent read/write is done by introducing some sort of synchronisation. This article goes through few ways on what to use if an app require to have concurrent read/write map functionality.&lt;/p&gt;&lt;h2 id=&#34;concurrent-map&#34;&gt;concurrent-map&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/orcaman/concurrent-map&#34;&gt;concurrent-map&lt;/a&gt; is quite an old project last updated 2months ago. In terms of implementation it still works.&lt;/p&gt;&lt;p&gt;Internally the framework is using struct called &lt;strong&gt;&lt;em&gt;ConcurrentMapShared&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ConcurrentMapShared&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;items&lt;/span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}&lt;span style=&#34;color:#a6e22e&#34;&gt;sync&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RWMutex&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// Read Write mutex, guards access to internal map.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Internally the library creates 32 different buckets of the &lt;strong&gt;&lt;em&gt;ConcurrentMapShared&lt;/em&gt;&lt;/strong&gt; type and use sharding when it does reading/writing values.&lt;/p&gt;&lt;p&gt;Using the library is very simple in app as shown below.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;New&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;elephant&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Animal&lt;/span&gt;{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;elephant&amp;#34;&lt;/span&gt;}&lt;span style=&#34;color:#a6e22e&#34;&gt;monkey&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Animal&lt;/span&gt;{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;monkey&amp;#34;&lt;/span&gt;}&lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;elephant&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;elephant&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;monkey&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;monkey&lt;/span&gt;)}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;ristretto&#34;&gt;ristretto&lt;/h2&gt;&lt;p&gt;Another option is to use cache library. Most cache libraries stores data in a map as follows&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For this article we going to take a look at &lt;a href=&#34;https://github.com/dgraph-io/ristretto&#34;&gt;Ristretto&lt;/a&gt; project. According to the project&lt;/p&gt;&lt;div class=&#34;boxtextoverflow&#34;&gt;Ristretto is a fast, concurrent cache library built with a focus on performance and correctness.&lt;/div&gt;&lt;p&gt;The library is not built specifically to address map based concurrency issue. However, if we look at the implementation it can pretty much do what a concurrent map can.&lt;/p&gt;&lt;p&gt;The function calls are not exactly the same like a map operation, nevertheless it is quite close.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/dgraph-io/ristretto&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ristretto&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewCache&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ristretto&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;NumCounters&lt;/span&gt;:        &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;,&lt;span style=&#34;color:#a6e22e&#34;&gt;MaxCost&lt;/span&gt;:            &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;,&lt;span style=&#34;color:#a6e22e&#34;&gt;BufferItems&lt;/span&gt;:        &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;,&lt;span style=&#34;color:#a6e22e&#34;&gt;IgnoreInternalCost&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,})&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)}&lt;span style=&#34;color:#a6e22e&#34;&gt;valid&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;valid&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Stored successfully&amp;#34;&lt;/span&gt;)}&lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Millisecond&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Get not successful&amp;#34;&lt;/span&gt;)} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;str&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%v&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;str&lt;/span&gt;)}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cache library are designed to be asynchronous in nature as there is no hurry for the data to be made available directly. Unlike map when you store something you will get it back directly. Hence, the &lt;code&gt;time.sleep(..)&lt;/code&gt; in the code. If the &lt;code&gt;time.sleep&lt;/code&gt; code is removed the app would never find the key.&lt;/p&gt;&lt;p&gt;This kind of cache library are very focused on performance and are memory efficient which helped if the app is going to store big sets of data. As a bonus concurrency is built into the library which is something the app does not have to worry about.&lt;/p&gt;&lt;p&gt;Good &lt;a href=&#34;https://dgraph.io/blog/post/introducing-ristretto-high-perf-go-cache/&#34;&gt;reading material&lt;/a&gt; about the project including performance comparison with other open source cache libraries.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>go-workers</title>
       <link>/post/goworkers/</link>
       <pubDate>Tue, 09 Mar 2021 00:00:00 +0000</pubDate>
       
       <guid>/post/goworkers/</guid>
       <description>&lt;p&gt;&lt;a href=&#34;https://github.com/catmullet/go-workers&#34;&gt;go-workers&lt;/a&gt; is an open source project that helped developers in making it easier to build concurrency into their app. The project is suitable for small to medium project. The project removes developers from the headache of worrying about channels, etc.&lt;/p&gt;&lt;p&gt;Developers just have to define the workers that it need to do work asynchronously and different workers can work together passing data in and out between them. We defined our worker as follows:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and we need to have the implementation of &lt;code&gt;Work&lt;/code&gt; like follows:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;wo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {....}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we have implementation ready we can execute it using the library as follows:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewWorker&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;,  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;SingleWorker&lt;/span&gt;{}, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The worker object now ready to receive messages by using the following command:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;send&lt;/span&gt;(&amp;lt;&lt;span style=&#34;color:#a6e22e&#34;&gt;can_send_anything&lt;/span&gt;&amp;gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following example shows how 2 workers processing the same data independently.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/catmullet/go-workers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;path/filepath&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Background&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Now&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Create&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Join&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;TempDir&lt;/span&gt;(), &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;output.txt&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)}&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewWorker&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;NewWorker&lt;/span&gt;(), &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;SetWriterOut&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;workerTwo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewWorker&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;NewTestWorkerObject&lt;/span&gt;(), &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;workerTwo&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;InFrom&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SetWriterOut&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Send&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;totalTime&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Since&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Milliseconds&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;total time %dms\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;totalTime&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {}&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewTestWorker&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewWorker&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt;{}}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewTestWorkerObject&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;NewTestWorker&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;NewTestWorker&lt;/span&gt;{}}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;wo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;NewTestWorker&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt;.(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Out&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;wo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt;.(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following is an example on using the library to GET data from &lt;a href=&#34;https://cat-fact.herokuapp.com/facts&#34;&gt;cat-fact&lt;/a&gt; every 5 seconds.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/catmullet/go-workers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os/signal&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;syscall&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Background&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewWorker&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;NewSingleWorker&lt;/span&gt;(), &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;SetWriterOut&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Stdout&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Signal&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;signal&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Notify&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Interrupt&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;syscall&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SIGTERM&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)}()&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;workerOne&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Send&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&gt;)}}&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SingleWorker&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewSingleWorker&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;SingleWorker&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;SingleWorker&lt;/span&gt;{}}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;wo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;SingleWorker&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Work&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;worker&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Worker&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;download&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;download&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;resp&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://cat-fact.herokuapp.com/facts&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatalln&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)}&lt;span style=&#34;color:#75715e&#34;&gt;//We Read the response body on the line below.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;body&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ioutil&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ReadAll&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;resp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Body&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatalln&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)}&lt;span style=&#34;color:#75715e&#34;&gt;//Convert the body to type string&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sb&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; string(&lt;span style=&#34;color:#a6e22e&#34;&gt;body&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;sb&lt;/span&gt;)}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
     </item>
   
     <item>
       <title>Dissecting minict</title>
       <link>/post/minict/</link>
       <pubDate>Mon, 04 Jan 2021 00:00:00 +0000</pubDate>
       
       <guid>/post/minict/</guid>
       <description>&lt;p&gt;minict is a small interesting project that shows how containers works, here is the &lt;a href=&#34;https://github.com/Ripolak/minict&#34;&gt;link to the github&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;You can think of the project as Docker v0.0.1 that provide very simple functionality to play around with containers.&lt;/p&gt;&lt;p&gt;Here are some of the functionality it provides out-of-the box&lt;/p&gt;&lt;pre&gt;&lt;code&gt;COMMANDS:   pull             Pull an image from Dockerhub or a different container registry.   run              Run a new container.   start            Start an existing container that was exited.   rm               Remove an existing container.   list-containers  List all current containers.   list-images      List all images.   help, h          Shows a list of commands or help for one command&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This article will tear down the project to look at how it works internally and to see how it is able to provide the container functionality using other open source projects.&lt;/p&gt;&lt;h2 id=&#34;pull&#34;&gt;pull&lt;/h2&gt;&lt;p&gt;This command is to pull container image from &lt;em&gt;&lt;em&gt;docker.io&lt;/em&gt;&lt;/em&gt; registry and store it locally. This command should be executed first before any other command.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;minict pull --image ubuntu:20.04 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following is the log output (to enable more verbose logging look under the Hacking section)&lt;/p&gt;&lt;pre&gt;&lt;code&gt;DEBU[0000] reference rewritten from &#39;docker.io/library/ubuntu:20.04&#39; to &#39;docker.io/library/ubuntu:20.04&#39; DEBU[0000] Trying to pull &amp;quot;docker.io/library/ubuntu:20.04&amp;quot; DEBU[0000] Credentials not found                        DEBU[0000] Using registries.d directory /etc/containers/registries.d for sigstore configuration DEBU[0000]  No signature storage configuration found for docker.io/library/ubuntu:20.04 DEBU[0000] Looking for TLS certificates and private keys in /etc/docker/certs.d/docker.io DEBU[0000] GET https://registry-1.docker.io/v2/         DEBU[0001] Ping https://registry-1.docker.io/v2/ status 401 DEBU[0001] GET https://auth.docker.io/token?scope=repository%3Alibrary%2Fubuntu%3Apull&amp;amp;service=registry.docker.io DEBU[0004] GET https://registry-1.docker.io/v2/library/ubuntu/manifests/20.04 DEBU[0005] Using blob info cache at /var/lib/containers/cache/blob-info-cache-v1.boltdb DEBU[0005] Source is a manifest list; copying (only) instance sha256:4e4bc990609ed865e07afc8427c30ffdddca5153fd4e82c20d8f0783a291e241 DEBU[0005] GET https://registry-1.docker.io/v2/library/ubuntu/manifests/sha256:4e4bc990609ed865e07afc8427c30ffdddca5153fd4e82c20d8f0783a291e241 DEBU[0006] IsRunningImageAllowed for image docker:docker.io/library/ubuntu:20.04 DEBU[0006]  Using default policy section                DEBU[0006]  Requirement 0: allowed                      DEBU[0006] Overall: allowed                             Getting image source signaturesDEBU[0006] Manifest has MIME type application/vnd.docker.distribution.manifest.v2+json, ordered candidate list [application/vnd.oci.image.manifest.v1+json] DEBU[0006] Downloading /v2/library/ubuntu/blobs/sha256:da7391352a9bb76b292a568c066aa4c3cbae8d494e6a3c68e3c596d34f7c75f8 DEBU[0006] GET https://registry-1.docker.io/v2/library/ubuntu/blobs/sha256:da7391352a9bb76b292a568c066aa4c3cbae8d494e6a3c68e3c596d34f7c75f8 DEBU[0009] Detected compression format gzip             DEBU[0009] Using original blob without modification     Copying blob da7391352a9b [======================================] 27.2MiB / 27.2MiBDEBU[0043] Downloading /v2/library/ubuntu/blobs/sha256:14428a6d4bcdba49a64127900a0691fb00a3f329aced25eb77e3b65646638f8d Copying blob da7391352a9b doneDEBU[0044] Detected compression format gzip             DEBU[0044] Using original blob without modification     DEBU[0044] Downloading /v2/library/ubuntu/blobs/sha256:2c2d948710f21ad82dce71743b1654b45acb5c059cf5c19da491582cef6f2601 Copying blob da7391352a9b doneCopying blob 14428a6d4bcd doneCopying blob da7391352a9b doneCopying blob 14428a6d4bcd doneCopying blob 2c2d948710f2 doneDEBU[0046] Downloading /v2/library/ubuntu/blobs/sha256:f643c72bc25212974c16f3348b3a898b1ec1eb13ec1539e10a103e6e217eb2f1 DEBU[0046] GET https://registry-1.docker.io/v2/library/ubuntu/blobs/sha256:f643c72bc25212974c16f3348b3a898b1ec1eb13ec1539e10a103e6e217eb2f1 DEBU[0047] No compression detected                      DEBU[0047] Using original blob without modification     Copying config aa23411143 doneWriting manifest to image destinationStoring signatures2021/01/05 20:05:27  info Image pulled successfully.Process finished with exit code 0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The image is downloaded inside &lt;strong&gt;/var/lib/minict/images&lt;/strong&gt; and it looks like the following&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;/var/lib/minict/├── containers└── images    └── ubuntu        ├── blobs        │   └── sha256        │       ├── 14428a6d4bcdba49a64127900a0691fb00a3f329aced25eb77e3b65646638f8d        │       ├── 2c2d948710f21ad82dce71743b1654b45acb5c059cf5c19da491582cef6f2601        │       ├── 5d52e1388dedc5da07eebd41b0b1c189183c537be51b9a9d6d5e82385373b2f6        │       ├── aa23411143b1e053a8458b3ea4252fb14570a0621ba0e3d26f6143616a874db1        │       └── da7391352a9bb76b292a568c066aa4c3cbae8d494e6a3c68e3c596d34f7c75f8        ├── index.json        └── oci-layout&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following outlined the different files downloaded from the pull process.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;index.json&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;This file contains information about the image (eg: platform)&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;schemaVersion:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;manifests:&lt;/span&gt; [      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;mediaType&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/vnd.oci.image.manifest.v1+json&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;digest&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:5d52e1388dedc5da07eebd41b0b1c189183c537be51b9a9d6d5e82385373b2f6&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;658&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;: {          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;org.opencontainers.image.ref.name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;20.04&amp;#34;&lt;/span&gt;        },        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;platform&amp;#34;&lt;/span&gt;: {          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;architecture&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;amd64&amp;#34;&lt;/span&gt;,          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;linux&amp;#34;&lt;/span&gt;        }      }    ]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;oci-layout&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;This file contains information about the oci-layout information used to store the image&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;imageLayoutVersion:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;blobs/sha256&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;5d52e1388dedc5da07eebd41b0b1c189183c537be51b9a9d6d5e82385373b2f6&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;This file contains information about the files that has been downloaded including size, type and shasum&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;schemaVersion:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;config:&lt;/span&gt; {      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;mediaType&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/vnd.oci.image.config.v1+json&amp;#34;&lt;/span&gt;,      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;digest&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:aa23411143b1e053a8458b3ea4252fb14570a0621ba0e3d26f6143616a874db1&amp;#34;&lt;/span&gt;,      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2427&lt;/span&gt;    }    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;layers:&lt;/span&gt; [      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;mediaType&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/vnd.oci.image.layer.v1.tar+gzip&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;digest&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:da7391352a9bb76b292a568c066aa4c3cbae8d494e6a3c68e3c596d34f7c75f8&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;28563271&lt;/span&gt;      },      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;mediaType&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/vnd.oci.image.layer.v1.tar+gzip&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;digest&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:14428a6d4bcdba49a64127900a0691fb00a3f329aced25eb77e3b65646638f8d&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;847&lt;/span&gt;      },      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;mediaType&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/vnd.oci.image.layer.v1.tar+gzip&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;digest&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:2c2d948710f21ad82dce71743b1654b45acb5c059cf5c19da491582cef6f2601&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;162&lt;/span&gt;      }    ]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;aa23411143b1e053a8458b3ea4252fb14570a0621ba0e3d26f6143616a874db1&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;This file contains information about the container, for example: it contains information about the command that will be executed when the container startsup, in our example it will be &lt;strong&gt;&lt;em&gt;/bin/bash&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;created:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2020-11-25T22:25:29.546718343Z&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;architecture:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;amd64&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;os:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;linux&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;config:&lt;/span&gt; {      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Env&amp;#34;&lt;/span&gt;: [        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&amp;#34;&lt;/span&gt;      ],      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Cmd&amp;#34;&lt;/span&gt;: [        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt;      ]    }    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;rootfs:&lt;/span&gt; {      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;layers&amp;#34;&lt;/span&gt;,      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;diff_ids&amp;#34;&lt;/span&gt;: [        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:bacd3af13903e13a43fe87b6944acd1ff21024132aad6e74b4452d984fb1a99a&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:9069f84dbbe96d4c50a656a05bbe6b6892722b0d1116a8f7fd9d274f4e991bf6&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sha256:f6253634dc78da2f2e3bee9c8063593f880dc35d701307f30f65553e0f50c18c&amp;#34;&lt;/span&gt;      ]    }    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;history:&lt;/span&gt; [      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2020-11-25T22:25:26.245907708Z&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created_by&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/bin/sh -c #(nop) ADD file:4f15c4475fbafb3fe335e415e3ea1ac416c34af911fcdfe273c5759438aa8eb4 in / &amp;#34;&lt;/span&gt;      },      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2020-11-25T22:25:27.346756278Z&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created_by&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/bin/sh -c set -xe \t\t&amp;amp;&amp;amp; echo &amp;#39;#!/bin/sh&amp;#39; &amp;gt; /usr/sbin/policy-rc.d \t&amp;amp;&amp;amp; echo &amp;#39;exit 101&amp;#39; &amp;gt;&amp;gt; /usr/sbin/policy-rc.d \t&amp;amp;&amp;amp; chmod +x /usr/sbin/policy-rc.d \t\t&amp;amp;&amp;amp; dpkg-divert --local --rename --add /sbin/initctl \t&amp;amp;&amp;amp; cp -a /usr/sbin/policy-rc.d /sbin/initctl \t&amp;amp;&amp;amp; sed -i &amp;#39;s/^exit.*/exit 0/&amp;#39; /sbin/initctl \t\t&amp;amp;&amp;amp; echo &amp;#39;force-unsafe-io&amp;#39; &amp;gt; /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \t\t&amp;amp;&amp;amp; echo &amp;#39;DPkg::Post-Invoke { \&amp;#34;rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\&amp;#34;; };&amp;#39; &amp;gt; /etc/apt/apt.conf.d/docker-clean \t&amp;amp;&amp;amp; echo &amp;#39;APT::Update::Post-Invoke { \&amp;#34;rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\&amp;#34;; };&amp;#39; &amp;gt;&amp;gt; /etc/apt/apt.conf.d/docker-clean \t&amp;amp;&amp;amp; echo &amp;#39;Dir::Cache::pkgcache \&amp;#34;\&amp;#34;; Dir::Cache::srcpkgcache \&amp;#34;\&amp;#34;;&amp;#39; &amp;gt;&amp;gt; /etc/apt/apt.conf.d/docker-clean \t\t&amp;amp;&amp;amp; echo &amp;#39;Acquire::Languages \&amp;#34;none\&amp;#34;;&amp;#39; &amp;gt; /etc/apt/apt.conf.d/docker-no-languages \t\t&amp;amp;&amp;amp; echo &amp;#39;Acquire::GzipIndexes \&amp;#34;true\&amp;#34;; Acquire::CompressionTypes::Order:: \&amp;#34;gz\&amp;#34;;&amp;#39; &amp;gt; /etc/apt/apt.conf.d/docker-gzip-indexes \t\t&amp;amp;&amp;amp; echo &amp;#39;Apt::AutoRemove::SuggestsImportant \&amp;#34;false\&amp;#34;;&amp;#39; &amp;gt; /etc/apt/apt.conf.d/docker-autoremove-suggests&amp;#34;&lt;/span&gt;      },      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2020-11-25T22:25:28.342445422Z&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created_by&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/bin/sh -c [ -z \&amp;#34;$(apt-get indextargets)\&amp;#34; ]&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;empty_layer&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;      },      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2020-11-25T22:25:29.343142847Z&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created_by&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/bin/sh -c mkdir -p /run/systemd &amp;amp;&amp;amp; echo &amp;#39;docker&amp;#39; &amp;gt; /run/systemd/container&amp;#34;&lt;/span&gt;      },      {        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2020-11-25T22:25:29.546718343Z&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created_by&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/bin/sh -c #(nop)  CMD [\&amp;#34;/bin/bash\&amp;#34;]&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;empty_layer&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;      }    ]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code uses library from  &lt;a href=&#34;https://github.com/containers/image&#34;&gt;&lt;strong&gt;github.com/containers/image&lt;/strong&gt;&lt;/a&gt; to download and store the image from a remote registry. This library is quite extensive and provide a lot of functionality to work with OCI based images, in order it&amp;rsquo;s functionality there is another tool that uses this library extensively called &lt;a href=&#34;https://github.com/containers/skopeo&#34;&gt;skopeo&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&#34;run&#34;&gt;run&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;minict run --image ubuntu:20.04 --name ubuntu-nanik &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command is to run the downloaded images as container. In our example we are running the ubuntu:20.04 image that we have previously downloaded, the container will be given label ubuntu-nanik.&lt;/p&gt;&lt;p&gt;Following is the output showing minict is reading the image files and trying to start it up.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;2021/01/05 20:00:38  info Container process exited. It can be started again using the &#39;start&#39; option.2021/01/05 20:00:38  info unpacking bundle ...     2021/01/05 20:00:38  info unpack rootfs: /var/lib/minict/containers/ubuntu-nanik/rootfs2021/01/05 20:00:38  info unpack layer: sha256:da7391352a9bb76b292a568c066aa4c3cbae8d494e6a3c68e3c596d34f7c75f82021/01/05 20:00:39  info unpack layer: sha256:14428a6d4bcdba49a64127900a0691fb00a3f329aced25eb77e3b65646638f8d2021/01/05 20:00:39  info unpack layer: sha256:2c2d948710f21ad82dce71743b1654b45acb5c059cf5c19da491582cef6f26012021/01/05 20:00:39  info ... done                 2021/01/05 20:00:39  info computing filesystem manifest ...2021/01/05 20:00:40  info ... done                 2021/01/05 20:00:40  info unpacked image bundle: /var/lib/minict/containers/ubuntu-nanik2021/01/05 20:00:40 Failed to mount tmpfs to /dev due to invalid argument2021/01/05 20:00:40 Failed to mount devpts to /dev/pts due to no such file or directory2021/01/05 20:00:40 Failed to mount shm to /dev/shm due to no such file or directory2021/01/05 20:00:40 Failed to mount mqueue to /dev/mqueue due to no such file or directory&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the container is up and running you will be given bash command to work with.&lt;/p&gt;&lt;p&gt;The run command is using the &lt;a href=&#34;https://github.com/opencontainers/umoci&#34;&gt;umoci&lt;/a&gt; project to work with containers. The way the umoci library works to start an image as container is as follows&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Perform validation for:&lt;ul&gt;&lt;li&gt;check to make sure the the oci-layout file is valid&lt;/li&gt;&lt;li&gt;the blobs directory exist&lt;/li&gt;&lt;li&gt;index.json file exist&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Do unpacking when using the Unpack(..) function as follows:&lt;ul&gt;&lt;li&gt;read the index.json&lt;/li&gt;&lt;li&gt;convert the layer information (from 5d52e1388dedc5da07eebd41b0b1c189183c537be51b9a9d6d5e82385373b2f6 file) to internal struct&lt;/li&gt;&lt;li&gt;create all the necessary directories inside /var/lib/minict/containers/ubuntu-nanik to host the filesystem (including rootfs)&lt;/li&gt;&lt;li&gt;unpack filesystem from all the image files into /rootfs&lt;/li&gt;&lt;li&gt;create config.json containing the following information&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;{&amp;#34;ociVersion&amp;#34;: &amp;#34;1.0.0&amp;#34;,&amp;#34;process&amp;#34;: {        &amp;#34;terminal&amp;#34;: true,        &amp;#34;user&amp;#34;: {                &amp;#34;uid&amp;#34;: 0,                &amp;#34;gid&amp;#34;: 0        },        &amp;#34;args&amp;#34;: [                &amp;#34;/bin/bash&amp;#34;        ],        &amp;#34;env&amp;#34;: [                &amp;#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&amp;#34;,                &amp;#34;TERM=xterm&amp;#34;,                &amp;#34;HOME=/root&amp;#34;        ],        &amp;#34;cwd&amp;#34;: &amp;#34;/&amp;#34;,        &amp;#34;capabilities&amp;#34;: {                &amp;#34;bounding&amp;#34;: [                        &amp;#34;CAP_AUDIT_WRITE&amp;#34;,                        &amp;#34;CAP_KILL&amp;#34;,                        &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;                ],                &amp;#34;effective&amp;#34;: [                        &amp;#34;CAP_AUDIT_WRITE&amp;#34;,                        &amp;#34;CAP_KILL&amp;#34;,                        &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;                ],                &amp;#34;inheritable&amp;#34;: [                        &amp;#34;CAP_AUDIT_WRITE&amp;#34;,                        &amp;#34;CAP_KILL&amp;#34;,                        &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;                ],                &amp;#34;permitted&amp;#34;: [                        &amp;#34;CAP_AUDIT_WRITE&amp;#34;,                        &amp;#34;CAP_KILL&amp;#34;,                        &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;                ],                &amp;#34;ambient&amp;#34;: [                        &amp;#34;CAP_AUDIT_WRITE&amp;#34;,                        &amp;#34;CAP_KILL&amp;#34;,                        &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;                ]        },        &amp;#34;rlimits&amp;#34;: [                {                        &amp;#34;type&amp;#34;: &amp;#34;RLIMIT_NOFILE&amp;#34;,                        &amp;#34;hard&amp;#34;: 1024,                        &amp;#34;soft&amp;#34;: 1024                }        ],        &amp;#34;noNewPrivileges&amp;#34;: true},&amp;#34;root&amp;#34;: {        &amp;#34;path&amp;#34;: &amp;#34;rootfs&amp;#34;},&amp;#34;hostname&amp;#34;: &amp;#34;umoci-default&amp;#34;,&amp;#34;mounts&amp;#34;: [        {                &amp;#34;destination&amp;#34;: &amp;#34;/proc&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;proc&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;proc&amp;#34;        },        {                &amp;#34;destination&amp;#34;: &amp;#34;/dev&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;options&amp;#34;: [                        &amp;#34;nosuid&amp;#34;,                        &amp;#34;strictatime&amp;#34;,                        &amp;#34;mode=755&amp;#34;,                        &amp;#34;size=65536k&amp;#34;                ]        },        {                &amp;#34;destination&amp;#34;: &amp;#34;/dev/pts&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;devpts&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;devpts&amp;#34;,                &amp;#34;options&amp;#34;: [                        &amp;#34;nosuid&amp;#34;,                        &amp;#34;noexec&amp;#34;,                        &amp;#34;newinstance&amp;#34;,                        &amp;#34;ptmxmode=0666&amp;#34;,                        &amp;#34;mode=0620&amp;#34;                ]        },        {                &amp;#34;destination&amp;#34;: &amp;#34;/dev/shm&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;shm&amp;#34;,                &amp;#34;options&amp;#34;: [                        &amp;#34;nosuid&amp;#34;,                        &amp;#34;noexec&amp;#34;,                        &amp;#34;nodev&amp;#34;,                        &amp;#34;mode=1777&amp;#34;,                        &amp;#34;size=65536k&amp;#34;                ]        },        {                &amp;#34;destination&amp;#34;: &amp;#34;/dev/mqueue&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;mqueue&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;mqueue&amp;#34;,                &amp;#34;options&amp;#34;: [                        &amp;#34;nosuid&amp;#34;,                        &amp;#34;noexec&amp;#34;,                        &amp;#34;nodev&amp;#34;                ]        },        {                &amp;#34;destination&amp;#34;: &amp;#34;/sys&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;bind&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;/sys&amp;#34;,                &amp;#34;options&amp;#34;: [                        &amp;#34;rbind&amp;#34;,                        &amp;#34;nosuid&amp;#34;,                        &amp;#34;noexec&amp;#34;,                        &amp;#34;nodev&amp;#34;,                        &amp;#34;ro&amp;#34;                ]        },        {                &amp;#34;destination&amp;#34;: &amp;#34;/etc/resolv.conf&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;bind&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;/etc/resolv.conf&amp;#34;,                &amp;#34;options&amp;#34;: [                        &amp;#34;noexec&amp;#34;,                        &amp;#34;nosuid&amp;#34;,                        &amp;#34;rbind&amp;#34;,                        &amp;#34;ro&amp;#34;                ]        }],&amp;#34;annotations&amp;#34;: {        &amp;#34;org.opencontainers.image.architecture&amp;#34;: &amp;#34;amd64&amp;#34;,        &amp;#34;org.opencontainers.image.author&amp;#34;: &amp;#34;&amp;#34;,        &amp;#34;org.opencontainers.image.created&amp;#34;: &amp;#34;2020-11-25T22:25:29.546718343Z&amp;#34;,        &amp;#34;org.opencontainers.image.exposedPorts&amp;#34;: &amp;#34;&amp;#34;,        &amp;#34;org.opencontainers.image.os&amp;#34;: &amp;#34;linux&amp;#34;,        &amp;#34;org.opencontainers.image.stopSignal&amp;#34;: &amp;#34;&amp;#34;},&amp;#34;linux&amp;#34;: {        &amp;#34;namespaces&amp;#34;: [                {                        &amp;#34;type&amp;#34;: &amp;#34;pid&amp;#34;                },                {                        &amp;#34;type&amp;#34;: &amp;#34;ipc&amp;#34;                },                {                        &amp;#34;type&amp;#34;: &amp;#34;uts&amp;#34;                },                {                        &amp;#34;type&amp;#34;: &amp;#34;mount&amp;#34;                },                {                        &amp;#34;type&amp;#34;: &amp;#34;user&amp;#34;                }        ],        &amp;#34;maskedPaths&amp;#34;: [                &amp;#34;/proc/kcore&amp;#34;,                &amp;#34;/proc/latency_stats&amp;#34;,                &amp;#34;/proc/timer_list&amp;#34;,                &amp;#34;/proc/timer_stats&amp;#34;,                &amp;#34;/proc/sched_debug&amp;#34;,                &amp;#34;/sys/firmware&amp;#34;,                &amp;#34;/proc/scsi&amp;#34;        ],        &amp;#34;readonlyPaths&amp;#34;: [                &amp;#34;/proc/asound&amp;#34;,                &amp;#34;/proc/bus&amp;#34;,                &amp;#34;/proc/fs&amp;#34;,                &amp;#34;/proc/irq&amp;#34;,                &amp;#34;/proc/sys&amp;#34;,                &amp;#34;/proc/sysrq-trigger&amp;#34;        ]}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;read config.json to construct internal config object&lt;/li&gt;&lt;li&gt;construct the command that will be executed to run the container and apply namespaces&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;hacking&#34;&gt;Hacking&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Add the following code inside oci/pull.go under function func PullImage(..) to enable the download reporting&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;copy&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Image&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;policyContext&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;destRef&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;srcRef&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;copy&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Options&lt;/span&gt;{ &lt;span style=&#34;color:#a6e22e&#34;&gt;ReportWriter&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Stdout&lt;/span&gt;})&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Add the following inside main.go to increase the logging level&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;logrus&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SetLevel&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>gvisor</title>
       <link>/post/runsc/</link>
       <pubDate>Fri, 02 Oct 2020 00:00:00 +0000</pubDate>
       
       <guid>/post/runsc/</guid>
       <description>&lt;p&gt;This article will explain about the container runtime called &lt;a href=&#34;http://www.gvisor.dev&#34;&gt;gvisor&lt;/a&gt;. The article focus more on how Sentry provides extra security layer to gvisor and how it intercepts system calls and interact with the application running inside container.&lt;/p&gt;&lt;h2 id=&#34;building-gvisor&#34;&gt;Building gvisor&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Make sure your docker is working properly as the build system required docker container to build the binaries.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Build gvisor issuing the command&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;make runsc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;the binary is located inside  ./bazel-gvisor/bazel-out/k8-opt/bin/runsc/linux_amd64_pure_stripped copy the runsc binary to&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;/usr/local/bin/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Copy the following to a file called daemon.json inside /etc/docker&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;default-runtime&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runsc&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;runtimes&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;runc-local&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runc&amp;#34;&lt;/span&gt;},&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;runsc&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/local/bin/runsc&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;runtimeArgs&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;--debug-log=/tmp/runsc/&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;--debug&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;--strace&amp;#34;&lt;/span&gt;]}}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Run the following docker command to test runsc&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;docker run --runtime&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;runsc -it ubuntu  dmesg  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The result will be as follows&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;[    0.000000] Starting gVisor...[    0.380255] Letting the watchdogs out...[    0.671842] Waiting for children...[    1.111248] Moving files to filing cabinet...[    1.537250] Checking naughty and nice process list...[    1.632947] Creating process schedule...[    2.025866] Mounting deweydecimalfs...[    2.054713] Reading process obituaries...[    2.239299] Daemonizing children...[    2.485680] Reticulating splines...[    2.558058] Consulting tar man page...[    2.741916] Ready!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Run the following to test docker using the normal runc&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;docker run --privileged  --runtime&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;runc-local -it ubuntu  dmesg&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The result is as follows&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;[    0.000000] microcode: microcode updated early to revision 0x2f, date = 2019-11-12[    0.000000] Linux version 5.4.0-7642-generic (buildd@lcy01-amd64-007) (gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)) #46~1598628707~20.04~040157c-Ubuntu SMP Fri Aug 28 18:02:16 UTC  (Ubuntu 5.4.0-7642.46~1598628707~20.04~040157c-generic 5.4.44)[    0.000000] Command line: BOOT_IMAGE=/vmlinuz-5.4.0-7642-generic root=/dev/mapper/data-root ro quiet splash vt.handoff=7[    0.000000] KERNEL supported cpus:[    0.000000]   Intel GenuineIntel[    0.000000]   AMD AuthenticAMD[    0.000000]   Hygon HygonGenuine[    0.000000]   Centaur CentaurHauls............&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;h2 id=&#34;sentry-the-secret-sauce&#34;&gt;Sentry the &amp;lsquo;Secret Sauce&amp;rsquo;&lt;/h2&gt;&lt;p&gt;Noticed the difference in output that you get running runsc compared to runc ?. The dmesg output from runsc shows that the kernel that it is running is NOT the host kernel, unlike what we see in the output when using runc. This is the &amp;lsquo;special sauce&amp;rsquo; about gvisor.&lt;/p&gt;&lt;p&gt;gvisor provides a &amp;lsquo;usermode&amp;rsquo; Linux Kernel or known as UML. Inside runsc there is a sub-module called Sentry which act as thin layer of kernel, this does not mean that it&amp;rsquo;s job is to replace Kernel. Sentry provide an extra layer of &amp;lsquo;safety&amp;rsquo; that intercepts system calls from application that is running inside a container. This prevents the application from having any direct interaction with the host through syscalls.&lt;/p&gt;&lt;p&gt;gVisor supports two methods of redirecting syscalls    * ptrace-mode - uses ptrace in the Linux kernel to forward syscalls to the sentry and    * KVM-mode - uses KVM to trap syscalls before they hit the Linux kernel so they can be forwarded to the sentry.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;https://gvisor.dev/docs/Layers.png&#34; alt=&#34;alt text&#34; /&gt;&lt;/p&gt;&lt;p&gt;Read the &lt;a href=&#34;https://gvisor.dev/docs/&#34;&gt;gvisor docs&lt;/a&gt; to get more intro about what is it all about and what kind of security it provides&lt;/p&gt;&lt;h2 id=&#34;internals&#34;&gt;Internals&lt;/h2&gt;&lt;p&gt;We will discuss more in details at how gvisor really works internally. This is based on my personal experiment and research, so there could be some information that is not correct.&lt;/p&gt;&lt;p&gt;Following are some of the topics and concepts that you need to understand to really understand how Sentry works and the security functionality it provides for gvisor.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/VDSO&#34;&gt;vDSO&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Seccomp&#34;&gt;Seccomp&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Ptrace&#34;&gt;ptrace&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://refspecs.linuxfoundation.org/LSB_1.3.0/IA64/spec/auxiliaryvector.html&#34;&gt;ELF Auxiliary Vectors&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://man7.org/linux/man-pages/man2/syscalls.2.html&#34;&gt;syscalls&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To get a better understand how the whole container stack works (docker, containerd, etc) refer to my &lt;a href=&#34;https://nanikgolang.netlify.app/post/containers/&#34;&gt;other posting&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&#34;execution&#34;&gt;Execution&lt;/h3&gt;&lt;p&gt;When container is launched using runsc it does what is shown in the diagram below&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/runsc/execution.jpg&#34; alt=&#34;alt text&#34; /&gt;&lt;/p&gt;&lt;p&gt;What the diagram shows there are few things that is happening behind the scenes before your container is executed. The first command that is triggered by docker to run runsc is as follows&lt;/p&gt;&lt;pre&gt;&lt;code&gt;/usr/local/bin/runsc --debug-log=/tmp/runsc/ --debug --strace --root /var/run/docker/runtime-runc/moby --log /run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af/log.json --log-format json create --bundle /run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af --pid-file /run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af/init.pid --console-socket /tmp/pty993587804/pty.sock e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Following on executing the above command runsc will executed itself few times as follows sequence:&lt;/p&gt;&lt;p&gt;(1) execute gofer for setting up Capabilities for directories&lt;/p&gt;&lt;pre&gt;&lt;code&gt;/proc/self/exe --root=/var/run/docker/runtime-runc/moby --debug=true --log=/run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af/log.json --log-format=json --debug-log=/tmp/runsc/ --strace=true --log-fd=3 --debug-log-fd=4 gofer --bundle /run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af --spec-fd=5 --mounts-fd=6 --io-fds=7 --io-fds=8 --io-fds=9 --io-fds=10&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(2) execute gofer to run as normal&lt;/p&gt;&lt;pre&gt;&lt;code&gt;/proc/self/exe --root=/var/run/docker/runtime-runc/moby --debug=true --log=/run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af/log.json --log-format=json --debug-log=/tmp/runsc/ --strace=true --log-fd=3 --debug-log-fd=4 gofer --bundle /run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af --spec-fd=5 --mounts-fd=6 --io-fds=7 --io-fds=8 --io-fds=9 --io-fds=10 --apply-caps=false --setup-root=false&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(3) execute sandbox to setup root&lt;/p&gt;&lt;pre&gt;&lt;code&gt;/proc/self/exe --root=/var/run/docker/runtime-runc/moby --debug=true --log=/run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af/log.json --log-format=json --debug-log=/tmp/runsc/ --strace=true --log-fd=3 --debug-log-fd=4 boot --bundle=/run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af --controller-fd=5 --mounts-fd=6 --spec-fd=7 --start-sync-fd=8 --io-fds=9 --io-fds=10 --io-fds=11 --io-fds=12 --stdio-fds=13 --stdio-fds=14 --stdio-fds=15 --setup-root --cpu-num 4 e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(4) execute sandbox to setup everything else (Sentry, ptrace, etc)&lt;/p&gt;&lt;pre&gt;&lt;code&gt;/proc/self/exe --root=/var/run/docker/runtime-runc/moby --debug=true --log=/run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af/log.json --log-format=json --debug-log=/tmp/runsc/ --strace=true --log-fd=3 --debug-log-fd=4 boot --bundle=/run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af --controller-fd=5 --mounts-fd=6 --spec-fd=7 --start-sync-fd=8 --io-fds=9 --io-fds=10 --io-fds=11 --io-fds=12 --stdio-fds=13 --stdio-fds=14 --stdio-fds=15 --cpu-num 4 e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(5) start container to run the sandbox along with the container and it&amp;rsquo;s application&lt;/p&gt;&lt;pre&gt;&lt;code&gt;/usr/local/bin/runsc --debug-log=/tmp/runsc/ --debug --strace --root /var/run/docker/runtime-runc/moby --log /run/containerd/io.containerd.runtime.v2.task/moby/e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af/log.json --log-format json start e488ee2bef4cfa13e82dc38c7e7db759ad3a8f89e02218a0339adb79a47193af&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following diagram shows the different process that was created during the lifecycle of runsc. The number in the diagram inside bracket is the PID of the runsc process when it was running.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/runsc/differentthreadsexecution.jpg&#34; alt=&#34;alt text&#34; /&gt;&lt;/p&gt;&lt;h3 id=&#34;vdso&#34;&gt;vDSO&lt;/h3&gt;&lt;p&gt;vdso stands for virtual ELF dynamic shared object. It is a small shared library that the kernel automatically maps into the address space of ALL user-space applications. The reason why we have vdso is to make syscall faster, but due to it&amp;rsquo;s small space only 4 different functions are provided&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;clock_gettimegetcpugettimeofdaytime&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Sentry implement it&amp;rsquo;s own VDSO which is located inside vdso directory in the source code.&lt;/p&gt;&lt;p&gt;When application is loaded into memory to be executed the ELF loader populate the vdso address using the auxiliary vectors. These vectors are the mechanism to transfer some OS specific information to the program interpreter (e.g. ld) and the process. This task is normally done by the elf loader in Linux but in gvisor it is done by sentry/loader package. These vectors are put on the process stack along with other information like argc, argv, envp. After stack initialization, normal stack will look something like this:&lt;/p&gt;&lt;p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;position            content                     size (bytes) + comment------------------------------------------------------------------------stack pointer -&amp;gt;  [ argc = number of args ]     4            [ argv[0] (pointer) ]         4   (program name)            [ argv[1] (pointer) ]         4            [ argv[..] (pointer) ]        4 * x            [ argv[n - 1] (pointer) ]     4            [ argv[n] (pointer) ]         4   (= NULL)            [ envp[0] (pointer) ]         4            [ envp[1] (pointer) ]         4            [ envp[..] (pointer) ]        4            [ envp[term] (pointer) ]      4   (= NULL)            [ auxv[0] (Elf32_auxv_t) ]    8            [ auxv[1] (Elf32_auxv_t) ]    8            [ auxv[..] (Elf32_auxv_t) ]   8            [ auxv[term] (Elf32_auxv_t) ] 8   (= AT_NULL vector)            [ padding ]                   0 - 16            [ argument ASCIIZ strings ]   &amp;gt;= 0            [ environment ASCIIZ str. ]   &amp;gt;= 0(0xbffffffc)      [ end marker ]                4   (= NULL)(0xc0000000)      &amp;lt; bottom of stack &amp;gt;           0   (virtual)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;In Sentry all the heavy lifting of the vDSO, etc are done inside the loader.go during the time when application is being loaded into memory as shown below.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;pkg&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sentry&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;loader&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;loader&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt;]&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Load&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;args&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LoadArgs&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;extraAuxv&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;vdso&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;VDSO&lt;/span&gt;) (&lt;span style=&#34;color:#a6e22e&#34;&gt;abi&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;OS&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;syserr&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Error&lt;/span&gt;) {&lt;span style=&#34;color:#75715e&#34;&gt;// Load the executable itself.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;loaded&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ac&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;newArgv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;loadExecutable&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;args&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Add generic auxv entries.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;auxv&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; append(&lt;span style=&#34;color:#a6e22e&#34;&gt;loaded&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;auxv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Auxv&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_UID&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;usermem&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Addr&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RealKUID&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;In&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;UserNamespace&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;OrOverflow&lt;/span&gt;())},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_EUID&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;usermem&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Addr&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;EffectiveKUID&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;In&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;UserNamespace&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;OrOverflow&lt;/span&gt;())},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_GID&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;usermem&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Addr&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RealKGID&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;In&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;UserNamespace&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;OrOverflow&lt;/span&gt;())},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_EGID&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;usermem&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Addr&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;EffectiveKGID&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;In&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;UserNamespace&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;OrOverflow&lt;/span&gt;())},&lt;span style=&#34;color:#75715e&#34;&gt;// The conditions that require AT_SECURE = 1 never arise. See&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// kernel.Task.updateCredsForExecLocked.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_SECURE&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_CLKTCK&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;CLOCKS_PER_SEC&lt;/span&gt;},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_EXECFN&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;execfn&lt;/span&gt;},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_RANDOM&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;random&lt;/span&gt;},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_PAGESZ&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;usermem&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;PageSize&lt;/span&gt;},&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_SYSINFO_EHDR&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;vdsoAddr&lt;/span&gt;},}&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;auxv&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;auxv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;extraAuxv&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;sl&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;stack&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Load&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;newArgv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;args&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Envv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;auxv&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;specifically this particular line of code which sets the vDSO address&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;arch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AuxEntry&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;linux&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;AT_SYSINFO_EHDR&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;vdsoAddr&lt;/span&gt;},&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;seccomp&#34;&gt;Seccomp&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;seccomp (short for secure computing mode) is a computer security facility in the Linux kernel. seccomp allows a process to make a one-way transition into a &amp;#34;secure&amp;#34; state where it cannot make any system calls except exit(), sigreturn(), read() and write() to already-open file descriptors. Should it attempt any other system calls, the kernel will terminate the process with SIGKILL or SIGSYS.[1][2] In this sense, it does not virtualize the system&amp;#39;s resources but isolates the process from them entirely. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;gvisor is known as &amp;lsquo;seccomp on steroids&amp;rsquo; because it uses seccomp to setup security filters. Which means that any application running inside a container is not calling the host kernel, but instead it will be calling gvisor kernel.&lt;/p&gt;&lt;p&gt;Following is an example of the seccomp filters that are installed by gvisor (obtained from the log)&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;I0929 04:00:54.926295       1 seccomp.go:61] Installing seccomp filters for 58 syscalls (action=kill process)D0929 04:00:54.926349       1 seccomp.go:171] syscall filter read: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926371       1 seccomp.go:171] syscall filter write: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926388       1 seccomp.go:171] syscall filter close: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926398       1 seccomp.go:171] syscall filter fstat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926408       1 seccomp.go:171] syscall filter lseek: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926582       1 seccomp.go:171] syscall filter mmap: [( * * * == 0x1 ) ( * * * == 0x22 ) ( * * * == 0x32 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926612       1 seccomp.go:171] syscall filter mprotect: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926619       1 seccomp.go:171] syscall filter munmap: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926624       1 seccomp.go:171] syscall filter rt_sigprocmask: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926630       1 seccomp.go:171] syscall filter rt_sigreturn: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926636       1 seccomp.go:171] syscall filter pread64: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926641       1 seccomp.go:171] syscall filter pwrite64: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926647       1 seccomp.go:171] syscall filter sched_yield: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926652       1 seccomp.go:171] syscall filter madvise: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926658       1 seccomp.go:171] syscall filter dup: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926666       1 seccomp.go:171] syscall filter nanosleep: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926675       1 seccomp.go:171] syscall filter getpid: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926681       1 seccomp.go:171] syscall filter accept: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926687       1 seccomp.go:171] syscall filter sendmsg: [( * * == 0x0 ) ( * * == 0x4040 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926697       1 seccomp.go:171] syscall filter recvmsg: [( * * == 0x60 ) ( * * == 0x62 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926710       1 seccomp.go:171] syscall filter shutdown: [( * == 0x2 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926717       1 seccomp.go:171] syscall filter socketpair: [( == 0x1 == 0x80005 == 0x0 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926725       1 seccomp.go:171] syscall filter clone: [( == 0xd0f00 * == 0x0 == 0x0 * ) ( == 0x50f00 * == 0x0 == 0x0 * )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926741       1 seccomp.go:171] syscall filter exit: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926754       1 seccomp.go:171] syscall filter fcntl: [( * == 0x3 ) ( * == 0x4 ) ( * == 0x1 ) ( * == 0x409 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926768       1 seccomp.go:171] syscall filter fsync: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926773       1 seccomp.go:171] syscall filter ftruncate: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926779       1 seccomp.go:171] syscall filter fchmod: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926785       1 seccomp.go:171] syscall filter gettimeofday: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926790       1 seccomp.go:171] syscall filter sigaltstack: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926801       1 seccomp.go:171] syscall filter fstatfs: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926808       1 seccomp.go:171] syscall filter mlock: [( * == 0x1000 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926815       1 seccomp.go:171] syscall filter arch_prctl: [( == 0x1002 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926828       1 seccomp.go:171] syscall filter gettid: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926842       1 seccomp.go:171] syscall filter futex: [( * == 0x80 * * == 0x0 ) ( * == 0x81 * * == 0x0 ) ( * == 0x0 * * ) ( * == 0x1 * * )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926859       1 seccomp.go:171] syscall filter getdents64: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926866       1 seccomp.go:171] syscall filter restart_syscall: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926872       1 seccomp.go:171] syscall filter clock_gettime: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926877       1 seccomp.go:171] syscall filter exit_group: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926886       1 seccomp.go:171] syscall filter epoll_ctl: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926892       1 seccomp.go:171] syscall filter tgkill: [( == 0x1 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926904       1 seccomp.go:171] syscall filter openat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926910       1 seccomp.go:171] syscall filter mkdirat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926916       1 seccomp.go:171] syscall filter mknodat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926921       1 seccomp.go:171] syscall filter fchownat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926927       1 seccomp.go:171] syscall filter newfstatat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926932       1 seccomp.go:171] syscall filter unlinkat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926938       1 seccomp.go:171] syscall filter renameat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926943       1 seccomp.go:171] syscall filter linkat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926949       1 seccomp.go:171] syscall filter symlinkat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926954       1 seccomp.go:171] syscall filter readlinkat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926960       1 seccomp.go:171] syscall filter ppoll: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926965       1 seccomp.go:171] syscall filter utimensat: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926973       1 seccomp.go:171] syscall filter epoll_pwait: [( * * * * == 0x0 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926987       1 seccomp.go:171] syscall filter fallocate: [( * == 0x0 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.926995       1 seccomp.go:171] syscall filter eventfd2: [( == 0x0 == 0x0 )] =&amp;gt; 0x616c6c6f77D0929 04:00:54.927008       1 seccomp.go:171] syscall filter getrandom: [] =&amp;gt; 0x616c6c6f77D0929 04:00:54.927019       1 seccomp.go:171] syscall filter memfd_create: [] =&amp;gt; 0x616c6c6f77&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;syscalls&#34;&gt;Syscalls&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;./media/runsc/gvisorkernelsyscall.png&#34; alt=&#34;gvisorkernelsyscall&#34; /&gt;&lt;/p&gt;&lt;p&gt;As can be seen from the above diagram when the container app is doing syscall it will be using the syscalls that is inside Sentry and not the host kernel.&lt;/p&gt;&lt;p&gt;When running a container using runsc run&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;cat /proc/self/maps&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will see the following memory maps&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;562059612000-562059614000 r--p 00000000 00:0e 19                         /usr/bin/cat562059614000-562059619000 r-xp 00002000 00:0e 19                         /usr/bin/cat562059619000-56205961c000 r--p 00007000 00:0e 19                         /usr/bin/cat56205961c000-56205961d000 r--p 00009000 00:0e 19                         /usr/bin/cat56205961d000-56205961e000 rw-p 0000a000 00:0e 19                         /usr/bin/cat56205961e000-56205963f000 rw-p 00000000 00:00 0                          [heap]7f74f24eb000-7f74f2ceb000 rw-p 00000000 00:00 0                          [stack]7f986152b000-7f986154d000 rw-p 00000000 00:00 0 7f986154d000-7f9861572000 r--p 00000000 00:0e 30                         /usr/lib/x86_64-linux-gnu/libc-2.31.so7f9861572000-7f98616ea000 r-xp 00025000 00:0e 30                         /usr/lib/x86_64-linux-gnu/libc-2.31.so7f98616ea000-7f9861734000 r--p 0019d000 00:0e 30                         /usr/lib/x86_64-linux-gnu/libc-2.31.so7f9861734000-7f9861735000 ---p 001e7000 00:0e 30                         /usr/lib/x86_64-linux-gnu/libc-2.31.so7f9861735000-7f9861738000 r--p 001e7000 00:0e 30                         /usr/lib/x86_64-linux-gnu/libc-2.31.so7f9861738000-7f986173b000 rw-p 001ea000 00:0e 30                         /usr/lib/x86_64-linux-gnu/libc-2.31.so7f986173b000-7f9861741000 rw-p 00000000 00:00 0 7f9861743000-7f9861744000 r--p 00000000 00:00 0                          [vvar]7f9861744000-7f9861746000 r-xp 00000000 00:00 0 7f9861746000-7f9861747000 r--p 00000000 00:0e 27                         /usr/lib/x86_64-linux-gnu/ld-2.31.so7f9861747000-7f986176a000 r-xp 00001000 00:0e 27                         /usr/lib/x86_64-linux-gnu/ld-2.31.so7f986176a000-7f9861772000 r--p 00024000 00:0e 27                         /usr/lib/x86_64-linux-gnu/ld-2.31.so7f9861773000-7f9861774000 r--p 0002c000 00:0e 27                         /usr/lib/x86_64-linux-gnu/ld-2.31.so7f9861774000-7f9861775000 rw-p 0002d000 00:0e 27                         /usr/lib/x86_64-linux-gnu/ld-2.31.so7f9861775000-7f9861776000 rw-p 00000000 00:00 0 ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;in comparison following is from local Linux&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;55b8227e4000-55b8227e6000 r--p 00000000 fd:01 11272329                   /usr/bin/cat55b8227e6000-55b8227eb000 r-xp 00002000 fd:01 11272329                   /usr/bin/cat55b8227eb000-55b8227ee000 r--p 00007000 fd:01 11272329                   /usr/bin/cat55b8227ee000-55b8227ef000 r--p 00009000 fd:01 11272329                   /usr/bin/cat55b8227ef000-55b8227f0000 rw-p 0000a000 fd:01 11272329                   /usr/bin/cat55b823606000-55b823627000 rw-p 00000000 00:00 0                          [heap]7f2e3747a000-7f2e3749c000 rw-p 00000000 00:00 0 7f2e3749c000-7f2e38396000 r--p 00000000 fd:01 11409222                   /usr/lib/locale/locale-archive7f2e38396000-7f2e383bb000 r--p 00000000 fd:01 11808327                   /usr/lib/x86_64-linux-gnu/libc-2.31.so7f2e383bb000-7f2e38533000 r-xp 00025000 fd:01 11808327                   /usr/lib/x86_64-linux-gnu/libc-2.31.so7f2e38533000-7f2e3857d000 r--p 0019d000 fd:01 11808327                   /usr/lib/x86_64-linux-gnu/libc-2.31.so7f2e3857d000-7f2e3857e000 ---p 001e7000 fd:01 11808327                   /usr/lib/x86_64-linux-gnu/libc-2.31.so7f2e3857e000-7f2e38581000 r--p 001e7000 fd:01 11808327                   /usr/lib/x86_64-linux-gnu/libc-2.31.so7f2e38581000-7f2e38584000 rw-p 001ea000 fd:01 11808327                   /usr/lib/x86_64-linux-gnu/libc-2.31.so7f2e38584000-7f2e3858a000 rw-p 00000000 00:00 0 7f2e385a0000-7f2e385a1000 r--p 00000000 fd:01 11800376                   /usr/lib/x86_64-linux-gnu/ld-2.31.so7f2e385a1000-7f2e385c4000 r-xp 00001000 fd:01 11800376                   /usr/lib/x86_64-linux-gnu/ld-2.31.so7f2e385c4000-7f2e385cc000 r--p 00024000 fd:01 11800376                   /usr/lib/x86_64-linux-gnu/ld-2.31.so7f2e385cd000-7f2e385ce000 r--p 0002c000 fd:01 11800376                   /usr/lib/x86_64-linux-gnu/ld-2.31.so7f2e385ce000-7f2e385cf000 rw-p 0002d000 fd:01 11800376                   /usr/lib/x86_64-linux-gnu/ld-2.31.so7f2e385cf000-7f2e385d0000 rw-p 00000000 00:00 0 7fffbe390000-7fffbe3b1000 rw-p 00000000 00:00 0                          [stack]7fffbe3bd000-7fffbe3c0000 r--p 00000000 00:00 0                          [vvar]7fffbe3c0000-7fffbe3c1000 r-xp 00000000 00:00 0                          [vdso]ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;loading-executing-and-switching-app-kernel&#34;&gt;Loading, Executing and Switching app/kernel&lt;/h3&gt;&lt;p&gt;Since Sentry works like a Linux kernel it is responsible in reading, loading and executing the executable that the container is going to run. This means it provides functionality like how an &lt;a href=&#34;https://en.wikipedia.org/wiki/Executable_and_Linkable_Format&#34;&gt;ELF loader&lt;/a&gt; does in Linux. The kernel code can be found inside sentry/kernel folder&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/runsc/loadImageAndExecute.jpg&#34; alt=&#34;loadImageAndExecute&#34; /&gt;&lt;/p&gt;&lt;p&gt;As shown in the diagram below when the application is doing a system call (eg: writing to a file, console, etc) it will raise a signal that will be intercepted by Sentry. Once the system call is done byt Sentry it goes back to the application, and the cycle continue.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/runsc/switchingbetweenkernelapp.jpg&#34; alt=&#34;switchingbetweenkernelapp&#34; /&gt;&lt;/p&gt;&lt;p&gt;This is possible with the help of ptrace.&lt;/p&gt;&lt;h3 id=&#34;ptrace&#34;&gt;ptrace&lt;/h3&gt;&lt;p&gt;When gvisor starts up it create what is called &amp;lsquo;master&amp;rsquo; thread and it creates different thread by cloning this &amp;lsquo;master&amp;rsquo; thread and it enable ptracing on the thread to enable it to capture system calls when the application is run.&lt;/p&gt;&lt;p&gt;Basically the application is &amp;lsquo;wrapped&amp;rsquo; inside a goroutine that is part of gvisor and this way gvisor (including Sentry) has capability to control the application.&lt;/p&gt;&lt;h3 id=&#34;log&#34;&gt;Log&lt;/h3&gt;&lt;p&gt;Following is log that shows the main functionality of running the app and it&amp;rsquo;s interaction with Sentry. The log message is not the full logs generated by gvisor, only the one that is interesting (which has my name attached to it) is shown here.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;I1002 20:55:52.477178   57407 container.go:328] Nanik - container.NewI1002 20:55:52.477202   57407 container.go:868] Nanik - createGoferProcessI1002 10:55:52.517996   57434 loader.go:491] Nanik - createPlatformI1002 10:55:52.518030   57434 ptrace.go:207] Nanik - ptrace.NewI1002 10:55:52.518359   57434 subprocess_linux.go:135] Nanik - beforeForkI1002 10:55:52.518557   57434 subprocess_linux.go:150] Nanik - afterFork pid &amp;amp; tgid 57454I1002 10:55:52.519704   57434 subprocess_amd64.go:238] Nanik - Attempt an emulation.I1002 10:55:52.519733   57434 subprocess_amd64.go:243] Nanik -  t.waitI1002 10:55:52.519747   57434 subprocess_amd64.go:262] Nanik -  NOT syscallEvent | syscall.SIGTRAPI1002 10:55:52.519752   57434 subprocess_amd64.go:238] Nanik - Attempt an emulation.I1002 10:55:52.519759   57434 subprocess_amd64.go:243] Nanik -  t.waitI1002 10:55:52.519769   57434 subprocess_amd64.go:246] Nanik -  syscallEvent | syscall.SIGTRAPI1002 10:55:52.519921   57434 subprocess_linux.go:55] Nanik - createStubI1002 10:55:52.520130   57434 subprocess_linux.go:135] Nanik - beforeForkI1002 10:55:52.520263   57434 subprocess_linux.go:150] Nanik - afterFork pid &amp;amp; tgid 57455I1002 10:55:52.520605   57434 ptrace_unsafe.go:125] Nanik - clone..cloning 57455 -- 57455I1002 10:55:52.520694   57434 subprocess.go:178] Nanik - requests to create threads...cloning the firstThread 57455I1002 10:55:52.752987   57434 loader.go:581] Nanik - run  l.createContainerProcess(true, l.sandboxID, &amp;amp;l.root, ep);I1002 10:55:52.753274   57434 loader.go:734] Nanik - setupContainerFSI1002 10:55:52.784717   57434 path.go:37] Nanik - ResolveExecutablePath args &amp;amp;{Filename: File:&amp;lt;nil&amp;gt; Argv:[/hello] Envv:[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=a8e612468f0b] WorkingDirectory:/ Credentials:0xc0002b85a0 FDTable:   fd:0 =&amp;gt; name host:[1]I1002 10:55:52.784827   57434 path.go:48] Nanik - ResolveExecutablePath path.IsAbs(name)I1002 10:55:52.785174   57434 loader.go:755] Nanik - createContainerProcess l.k.CreateProcess(info.procArgs) {Filename:/hello File:&amp;lt;nil&amp;gt; Argv:[/hello] Envv:[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=a8e612468f0b HOME=/] WorkingDirectory:/ Credentials:0xc0002b85a0 FDTable:       fd:0 =&amp;gt; name host:[1]I1002 10:55:52.788418   57434 loader.go:180] Nanik - loadExecutable elfMagicI1002 10:55:52.788437   57434 elf.go:643] Nanik - loadELF for /hello I1002 10:55:52.789010   57434 task_start.go:243] Nanik - assignTIDsLocked 1I1002 10:55:52.789870   57434 kernel.go:1068] Nanik - Kernel Start()I1002 10:55:52.789899   57434 task_start.go:307] Nanik - task_start Start 1I1002 10:55:52.789959   57434 task_run.go:70] Nanik - run task_run.go 1I1002 10:55:52.790006   57434 task_usermem.go:35] Nanik - task_usermem ActivateI1002 10:55:52.790172   57434 ptrace_unsafe.go:125] Nanik - clone..cloning 57455 -- 57455I1002 10:55:52.793677   57434 subprocess.go:178] Nanik - requests to create threads...cloning the firstThread 57455I1002 10:55:52.793942   57434 subprocess_linux.go:254] Nanik - createStub 57515I1002 10:55:52.794118   57434 ptrace_unsafe.go:125] Nanik - clone..cloning 57515 -- 57515I1002 10:55:52.794232   57434 subprocess.go:178] Nanik - requests to create threads...cloning the firstThread 57515I1002 10:55:52.794447   57434 task_run.go:81] Nanik - run task_run.go t.interruptSelf()  1I1002 10:55:52.794482   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.794508   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.794529   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.794540   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.794549   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.794598   57434 ptrace_unsafe.go:125] Nanik - clone..cloning 57515 -- 57515I1002 10:55:52.794691   57434 subprocess.go:178] Nanik - requests to create threads...cloning the firstThread 57515I1002 10:55:52.794789   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518I1002 10:55:52.794947   57434 subprocess.go:558] Nanik - after t.waitI1002 10:55:52.794966   57434 subprocess.go:561] Nanik - Refresh all registersI1002 10:55:52.794980   57434 subprocess.go:589] Nanik - outside Is it a system call?I1002 10:55:52.795038   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.795051   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.795061   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.795075   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518I1002 10:55:52.795123   57434 subprocess.go:558] Nanik - after t.waitI1002 10:55:52.795138   57434 subprocess.go:561] Nanik - Refresh all registersI1002 10:55:52.795152   57434 subprocess.go:589] Nanik - outside Is it a system call?I1002 10:55:52.795194   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.795206   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.795215   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.795232   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518I1002 10:55:52.795273   57434 subprocess.go:558] Nanik - after t.waitI1002 10:55:52.795285   57434 subprocess.go:561] Nanik - Refresh all registersI1002 10:55:52.795298   57434 subprocess.go:589] Nanik - outside Is it a system call?I1002 10:55:52.795338   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.795350   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.795359   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.795372   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518I1002 10:55:52.795403   57434 subprocess.go:558] Nanik - after t.waitI1002 10:55:52.795414   57434 subprocess.go:561] Nanik - Refresh all registersI1002 10:55:52.795427   57434 subprocess.go:589] Nanik - outside Is it a system call?I1002 10:55:52.795466   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.795478   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.795494   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.795508   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518I1002 10:55:52.795547   57434 subprocess.go:558] Nanik - after t.waitI1002 10:55:52.795561   57434 subprocess.go:561] Nanik - Refresh all registersI1002 10:55:52.795575   57434 subprocess.go:579] Nanik - a system callI1002 10:55:52.795592   57434 task_syscall.go:200] Nanik -  doSyscallEnter 158I1002 10:55:52.795685   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.795722   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.795733   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.795748   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518I1002 10:55:52.795781   57434 subprocess.go:558] Nanik - after t.waitI1002 10:55:52.795793   57434 subprocess.go:561] Nanik - Refresh all registersI1002 10:55:52.795807   57434 subprocess.go:579] Nanik - a system callI1002 10:55:52.795820   57434 task_syscall.go:200] Nanik -  doSyscallEnter 218I1002 10:55:52.795863   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.795872   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.795880   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.795894   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518..........I1002 10:55:52.796112   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.796130   57434 ptrace.go:103] Nanik - going to go inside switchToAppI1002 10:55:52.796147   57434 subprocess.go:495] Nanik -switchToAppI1002 10:55:52.796170   57434 subprocess.go:547] Nanik - NOT isSingleStepping 57518I1002 10:55:52.796219   57434 subprocess.go:558] Nanik - after t.waitI1002 10:55:52.796247   57434 subprocess.go:561] Nanik - Refresh all registersI1002 10:55:52.796283   57434 subprocess.go:579] Nanik - a system callI1002 10:55:52.796305   57434 task_syscall.go:200] Nanik -  doSyscallEnter 231I1002 10:55:52.796642   57434 task_run.go:97] Nanik -  executeI1002 10:55:52.796683   57434 task_run.go:97] Nanik -  execute......&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The command ran to generate the above log is as follows&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;docker run --runtime&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;runsc hello-world &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;other-notes&#34;&gt;Other Notes&lt;/h3&gt;&lt;p&gt;gettimeofday() on Linux is what&amp;rsquo;s called a vsyscall and/or vdso.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;0x00000034f408c2d4 : mov    $0xffffffffff600000,%rax0x00000034f408c2db : callq  *%rax&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The address 0xffffffffff600000 is the vsyscall page (on x86_64). The mechanism maps a specific kernel-created code page into user memory, so that a few &amp;ldquo;syscalls&amp;rdquo; can be made without the overhead of a user/kernel context switch, but rather as &amp;ldquo;ordinary&amp;rdquo; function call.&lt;/p&gt;&lt;p&gt;Syscalls generally create a lot of overhead, and given the abundance of gettimeofday() calls, one would prefer not to use a syscall. To that end, Linux kernel may map one or two special areas into each program, called vdso and vsyscall. Your implementation of gettimeofday() seems to be using vsyscall:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;mov    $0xffffffffff600000,%rax&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the standard address of vsyscall map. Try cat /proc/self/maps to see that mapping. The idea behind vsyscall is that kernel provides fast user-space implementations of some functions, and libc just calls them.&lt;/p&gt;&lt;p&gt;Read this nice article for more details.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/7266813/how-does-the-gettimeofday-syscall-work&#34;&gt;https://stackoverflow.com/questions/7266813/how-does-the-gettimeofday-syscall-work&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://lwn.net/Articles/604287/&#34;&gt;https://lwn.net/Articles/604287/&lt;/a&gt; and &lt;a href=&#34;https://lwn.net/Articles/604515/&#34;&gt;https://lwn.net/Articles/604515/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&#34;resources&#34;&gt;Resources&lt;/h3&gt;&lt;h4 id=&#34;gvisor&#34;&gt;&lt;strong&gt;gvisor&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://research.cs.wisc.edu/multifacet/papers/vee20_blending.pdf&#34;&gt;https://research.cs.wisc.edu/multifacet/papers/vee20_blending.pdf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://blog.loof.fr/2018/06/gvisor-in-depth.html&#34;&gt;https://blog.loof.fr/2018/06/gvisor-in-depth.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.oreilly.com/library/view/user-mode-linux/0131865056/&#34;&gt;User Mode Linux is a good book&lt;/a&gt; and gvisor application kernel works the same like that.&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://wenboshen.org/posts/2018-12-01-sectainer.html&#34;&gt;https://wenboshen.org/posts/2018-12-01-sectainer.html&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;This is straight forward, sentry process acts as tracer while application process is the tracee. Application process system call will stop by PTRACE and wait for sentry to handle. Sentry can emulate the system call, replace the real system with getpid(), and return.&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://archive.fosdem.org/2020/schedule/event/containers_k8s_runtimes/attachments/slides/3751/export/events/attachments/containers_k8s_runtimes/slides/3751/below_kubernetes.pdf&#34;&gt;https://archive.fosdem.org/2020/schedule/event/containers_k8s_runtimes/attachments/slides/3751/export/events/attachments/containers_k8s_runtimes/slides/3751/below_kubernetes.pdf&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://groups.google.com/g/gvisor-users/c/15FfcCilupo/m/9ARSLnH3BQAJ&#34;&gt;Understanding about Ring and Sentry&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://wenboshen.org/posts/2018-12-25-gvisor-inside.html#sentry&#34;&gt;Inside gvisor&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&#34;seccomp-1&#34;&gt;&lt;strong&gt;Seccomp&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://blog.selectel.com/containers-security-seccomp/&#34;&gt;https://blog.selectel.com/containers-security-seccomp/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://eigenstate.org/notes/seccomp&#34;&gt;https://eigenstate.org/notes/seccomp&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&#34;ptrace-1&#34;&gt;&lt;strong&gt;ptrace&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/FuzzyLogic/gotrace/tree/master&#34;&gt;Excellent sample from Liz Rice&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/lunixbochs/ghostrace&#34;&gt;Another good example&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&#34;user-mode-linux-linux-in-general&#34;&gt;&lt;strong&gt;user mode Linux &amp;amp; Linux in general&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://christine.website/blog/howto-usermode-linux-2019-07-07&#34;&gt;https://christine.website/blog/howto-usermode-linux-2019-07-07&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/firecracker-microvm/firecracker/blob/master/docs/rootfs-and-kernel-setup.md&#34;&gt;https://github.com/firecracker-microvm/firecracker/blob/master/docs/rootfs-and-kernel-setup.md&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://david942j.blogspot.com/2018/10/note-learning-kvm-implement-your-own.html&#34;&gt;https://david942j.blogspot.com/2018/10/note-learning-kvm-implement-your-own.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/18717016/what-are-ring-0-and-ring-3-in-the-context-of-operating-systems&#34;&gt;This explains what the different rings means in OS context&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Linux uses Ring 0 (Kernel mode) and 3 (user mode)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/22054578/how-to-run-a-program-without-an-operating-system/32483545#32483545&#34;&gt;Article on how to run program without an operating system&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/cirosantilli/x86-bare-metal-examples&#34;&gt;Very good resource to learn bare metal OS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://filippo.io/linux-syscall-table/&#34;&gt;Searchable Linux Syscall Table for x86 and x86_64&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://www.gabriel.urdhr.fr/2015/01/22/elf-linking/&#34;&gt;ELF internal for dynamic and static&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>go-rest-api project</title>
       <link>/post/go-rest-api-projects/</link>
       <pubDate>Sun, 15 Mar 2020 00:00:00 +0000</pubDate>
       
       <guid>/post/go-rest-api-projects/</guid>
       <description>&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/golang-standards/project-layout&#34;&gt;https://github.com/golang-standards/project-layout&lt;/a&gt;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Janos Web Utility</title>
       <link>/post/janosweb/</link>
       <pubDate>Sun, 08 Mar 2020 00:00:00 +0000</pubDate>
       
       <guid>/post/janosweb/</guid>
       <description>&lt;p&gt;Reference: &lt;a href=&#34;https://github.com/janos/web&#34;&gt;https://github.com/janos/web&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    ├── client│   ├── api│   └── http├── file-server├── log│   └── access├── maintenance├── minifier├── recovery├── server├── servers│   ├── grpc│   │   └── internal│   │       └── hello│   ├── http│   └── quic└── templates&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Framework revolves around Handlers&lt;/p&gt;&lt;h2 id=&#34;samples&#34;&gt;Samples&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;file-server&lt;ul&gt;&lt;li&gt;hasher.go&lt;ul&gt;&lt;li&gt;hashing functions&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;options.go&lt;ul&gt;&lt;li&gt;contains struct defining handler and other http server related options&lt;/li&gt;&lt;li&gt;contains global var for handler such as DefaultNotFoundHandler, DefaultForbiddenHandler and DefaultInternalServerErrorHandler&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;server.go&lt;ul&gt;&lt;li&gt;HashedPath &amp;ndash;&amp;gt; create hashed path from a string&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;recovery&lt;ul&gt;&lt;li&gt;recovery.go&lt;ul&gt;&lt;li&gt;provide handler and other utility for handling &amp;lsquo;panic&amp;rsquo; situation in http server environment&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;server&lt;ul&gt;&lt;li&gt;internal.go&lt;ul&gt;&lt;li&gt;provide lots of internal handlers for troubleshooting - /status, /data, /debug/pprof. The handler are triggered when specify the port in  Options.ListenInternal&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;handlers.go&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;servers/http&lt;ul&gt;&lt;li&gt;http.go - code that takes care of http related functionality - servers, request, handlers, etc&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;resenje.org/logging&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;recovery&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;resenje.org/recovery&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;resenje.org/web/server&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; (    &lt;span style=&#34;color:#a6e22e&#34;&gt;responseBody&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;----- response body -----&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;handler&lt;/span&gt;      = &lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;HandlerFunc&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ResponseWriter&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Request&lt;/span&gt;) {        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fprint&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;responseBody&lt;/span&gt;)    }))&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {    &lt;span style=&#34;color:#a6e22e&#34;&gt;rs&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;recovery&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Service&lt;/span&gt;{}    &lt;span style=&#34;color:#a6e22e&#34;&gt;logger&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;logging&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;GetLogger&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;logger&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SetLevel&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;o&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Options&lt;/span&gt;{        &lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;:               &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;servertest&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;Version&lt;/span&gt;:            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;BuildInfo&lt;/span&gt;:          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;buildinfo&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;ListenInternal&lt;/span&gt;:     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;localhost:9200&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;ListenInternalTLS&lt;/span&gt;:  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;InternalTLSCert&lt;/span&gt;:    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;InternalTLSKey&lt;/span&gt;:     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;ACMECertsDir&lt;/span&gt;:       &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;ACMECertsEmail&lt;/span&gt;:     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;EmailService&lt;/span&gt;:       &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;RecoveryService&lt;/span&gt;:    &lt;span style=&#34;color:#a6e22e&#34;&gt;rs&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;MaintenanceService&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;Logger&lt;/span&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;logger&lt;/span&gt;,    }    &lt;span style=&#34;color:#a6e22e&#34;&gt;ho&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;HTTPOptions&lt;/span&gt;{        &lt;span style=&#34;color:#a6e22e&#34;&gt;Handlers&lt;/span&gt;:     &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;:         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;Listen&lt;/span&gt;:       &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;localhost:9000&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;ListenTLS&lt;/span&gt;:    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;TLSCerts&lt;/span&gt;:     &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;IdleTimeout&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;ReadTimeout&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;WriteTimeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,    }    &lt;span style=&#34;color:#a6e22e&#34;&gt;ho&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SetHandler&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;handler&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;ss&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;New&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;o&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;ss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WithHTTP&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ho&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;ss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Serve&lt;/span&gt;()    &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
     </item>
   
     <item>
       <title>Internals of Container Networking</title>
       <link>/post/containernetworking/</link>
       <pubDate>Wed, 26 Feb 2020 00:00:00 +0000</pubDate>
       
       <guid>/post/containernetworking/</guid>
       <description>&lt;ul&gt;&lt;li&gt;&lt;p&gt;References:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://thenewstack.io/container-networking-landscape-cni-coreos-cnm-docker/&#34;&gt;https://thenewstack.io/container-networking-landscape-cni-coreos-cnm-docker/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.edureka.co/blog/docker-networking/&#34;&gt;https://www.edureka.co/blog/docker-networking/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://blogs.igalia.com/dpino/2016/04/10/network-namespaces/&#34;&gt;https://blogs.igalia.com/dpino/2016/04/10/network-namespaces/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/31265993/docker-networking-namespace-not-visible-in-ip-netns-list&#34;&gt;https://stackoverflow.com/questions/31265993/docker-networking-namespace-not-visible-in-ip-netns-list&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://medium.com/@Mark.io/https-medium-com-mark-io-network-setup-with-runc-containers-46b5a9cc4c5b&#34;&gt;https://medium.com/@Mark.io/https-medium-com-mark-io-network-setup-with-runc-containers-46b5a9cc4c5b&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;There are 2 different ways network are setup and used in container world:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;CNM (Container Network Model) or CNI (Container Network Interface)&lt;/li&gt;&lt;li&gt;CNI implementation github.com/containernetworking/plugins/&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;CNI plugins available&lt;/p&gt;&lt;ul&gt;&lt;li&gt;IPAM&lt;ul&gt;&lt;li&gt;dhcp&lt;/li&gt;&lt;li&gt;host-local&lt;/li&gt;&lt;li&gt;static&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Main&lt;ul&gt;&lt;li&gt;bridge&lt;/li&gt;&lt;li&gt;host-device&lt;/li&gt;&lt;li&gt;windows&lt;/li&gt;&lt;li&gt;ipvlan&lt;/li&gt;&lt;li&gt;vlan&lt;/li&gt;&lt;li&gt;loopback&lt;/li&gt;&lt;li&gt;ptp&lt;/li&gt;&lt;li&gt;macvlan&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Meta&lt;ul&gt;&lt;li&gt;bandwidth&lt;/li&gt;&lt;li&gt;portmap&lt;/li&gt;&lt;li&gt;firewall&lt;/li&gt;&lt;li&gt;sbr&lt;/li&gt;&lt;li&gt;flannel&lt;/li&gt;&lt;li&gt;tuning&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;CNI network are implemented as plugins github.com/containernetworking/plugins. The plugins are configured by calling the cni executable and passing a configuration file outlining the network setup config like the one below&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    {    &amp;#34;cniVersion&amp;#34;: &amp;#34;0.4.0&amp;#34;,    &amp;#34;name&amp;#34;: &amp;#34;openfaas-cni-bridge&amp;#34;,    &amp;#34;plugins&amp;#34;: [      {        &amp;#34;type&amp;#34;: &amp;#34;bridge&amp;#34;,        &amp;#34;bridge&amp;#34;: &amp;#34;openfaas0&amp;#34;,        &amp;#34;isGateway&amp;#34;: true,        &amp;#34;ipMasq&amp;#34;: true,        &amp;#34;ipam&amp;#34;: {            &amp;#34;type&amp;#34;: &amp;#34;host-local&amp;#34;,            &amp;#34;subnet&amp;#34;: &amp;#34;10.62.0.0/16&amp;#34;,            &amp;#34;routes&amp;#34;: [ { &amp;#34;dst&amp;#34;: &amp;#34;0.0.0.0/0&amp;#34; } ]               }      },      {        &amp;#34;type&amp;#34;: &amp;#34;firewall&amp;#34;      }    ]}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;reading the config file the &amp;lsquo;bridge&amp;rsquo; plugin will be executed (which resides inside /opt/cni/bin directory).&lt;/p&gt;&lt;ul&gt;&lt;li&gt;go client implementation resides in &lt;a href=&#34;https://github.com/containerd/go-cni&#34;&gt;https://github.com/containerd/go-cni&lt;/a&gt; the project support&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In Linux environment network are configured and managed using &lt;a href=&#34;https://en.wikipedia.org/wiki/Netlink&#34;&gt;netlink&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;containerd uses CNI&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Docker uses CNM&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Docker uses CNM which uses the libnetwork project.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The libnetwork project uses netlink call to create network virtual connection (endpoints, etc). Docker create different namespaces required for isolation as shown in the example below&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    docker container listCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMESbbea5d31d581        ubuntu:latest       &amp;#34;/bin/bash&amp;#34;         13 seconds ago      Up 12 seconds                           peaceful_faraday&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    docker inspect -f &amp;#39;{{.State.Pid}}&amp;#39; bbea5d31d58119025&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    sudo ls /proc/19025/ns/ -latotal 0dr-x--x--x 2 root root 0 Feb 06 21:08 .dr-xr-xr-x 9 root root 0 Feb 06 21:07 ..lrwxrwxrwx 1 root root 0 Feb 06 21:08 cgroup -&amp;gt; &amp;#39;cgroup:[4026531835]&amp;#39;lrwxrwxrwx 1 root root 0 Feb 06 21:08 ipc -&amp;gt; &amp;#39;ipc:[4026533665]&amp;#39;lrwxrwxrwx 1 root root 0 Feb 06 21:08 mnt -&amp;gt; &amp;#39;mnt:[4026533663]&amp;#39;lrwxrwxrwx 1 root root 0 Feb 06 21:08 net -&amp;gt; &amp;#39;net:[4026532008]&amp;#39;lrwxrwxrwx 1 root root 0 Feb 06 21:08 pid -&amp;gt; &amp;#39;pid:[4026533666]&amp;#39;lrwxrwxrwx 1 root root 0 Feb 06 21:08 pid_for_children -&amp;gt; &amp;#39;pid:[4026533666]&amp;#39;lrwxrwxrwx 1 root root 0 Feb 06 21:08 user -&amp;gt; &amp;#39;user:[4026531837]&amp;#39;lrwxrwxrwx 1 root root 0 Feb 06 12:08 uts -&amp;gt; &amp;#39;uts:[4026533664]&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However running the &amp;lsquo;ip&amp;rsquo; command does not find the namespace, as Docker does not create the symlink under the /var/run/netns folder. The &amp;lsquo;ip&amp;rsquo; command looked under /var/run/netns for inspecting network namespaces. To allow us to use &amp;lsquo;ip&amp;rsquo; tool we can symlink the process as follows&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    # (as root)pid=$(docker inspect -f &amp;#39;{{.State.Pid}}&amp;#39; ${container_id})mkdir -p /var/run/netns/ln -sfT /proc/$pid/ns/net /var/run/netns/$container_id# e.g. show stats about eth0 inside the container ip netns exec &amp;#34;${container_id}&amp;#34; ip -s link show eth0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another alternative is to use the &amp;lsquo;nsenter&amp;rsquo; tool, this does not requires creating symlink:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;sudo nsenter -t &amp;lt;container_pid&amp;gt; -n &amp;lt;command&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Can use &amp;lsquo;ip monitor&amp;rsquo; to look at the netlink activity:&lt;/li&gt;&lt;/ul&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;sudo ip monitor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following output shows the activity performed inside netlink when the command &amp;lsquo;docker network rm  test&amp;rsquo; is executed&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Deleted dev br-b076a0ef8a35 lladdr 02:42:fb:1c:c1:e4 PERMANENTDeleted dev br-b076a0ef8a35 lladdr 02:42:fb:1c:c1:e4 PERMANENT9: br-b076a0ef8a35: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noqueue state DOWN group default     link/ether 02:42:fb:1c:c1:e4 brd ff:ff:ff:ff:ff:ffDeleted 224.0.0.22 dev br-b076a0ef8a35 lladdr 01:00:5e:00:00:16 NOARPDeleted 224.0.0.251 dev br-b076a0ef8a35 lladdr 01:00:5e:00:00:fb NOARPDeleted 9: br-b076a0ef8a35    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-b076a0ef8a35       valid_lft forever preferred_lft foreverDeleted local 172.18.0.1 dev br-b076a0ef8a35 table local proto kernel scope host src 172.18.0.1 Deleted inet br-b076a0ef8a35 Deleted inet6 br-b076a0ef8a35 Deleted 9: br-b076a0ef8a35: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default     link/ether 02:42:fb:1c:c1:e4 brd ff:ff:ff:ff:ff:ff&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Docker takes care of setting up the network namespace for containers by utilizing the project github.com/vishvananda/netlink. The netlink project provides all the necessary API to setup network infrastructure via netlink&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;containerd uses the same method to create network for containers, the only difference it uses a different API than Docker. The CNI API is used internally by containerd, the shim&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Tools&lt;/p&gt;&lt;ul&gt;&lt;li&gt;nsenter&lt;/li&gt;&lt;li&gt;ip&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>First look at the internals of containerd and runc</title>
       <link>/post/containers/</link>
       <pubDate>Sun, 05 Jan 2020 00:00:00 +0000</pubDate>
       
       <guid>/post/containers/</guid>
       <description>&lt;h1&gt;containerd&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Following slides outline the role containerd plays including what kind of services it provides.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./media/containerd/containerd_a_role_in_container_ecosystem.png&#34; alt=&#34;ContaierDLayer&#34; /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/containerd/what_is_containerd.png&#34; alt=&#34;WhatIsContainerD&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Understand what is and isn&amp;rsquo;t provide inside containerd. This &lt;a href=&#34;https://containerd.io/scope/&#34;&gt;document&lt;/a&gt; provide the full scope of the project&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;History &lt;a href=&#34;https://github.com/containerd/containerd/issues/362&#34;&gt;background&lt;/a&gt; on the reason why networking was left out from containerd&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;containerd-shim&lt;/strong&gt; &amp;ndash; After runc runs the container, it exits (allowing us to not have any long-running processes responsible for our containers). The shim is the component which sits between containerd and runc to facilitate this. Containers does not died when dockerd orcontainerd died as it is &amp;lsquo;attached&amp;rsquo; to the containerd-shim process. The containerd-shim process job is to monitor stdin(out) and report back the error code returned from exiting the container&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Some of containerd Makefile task:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;make bin/containerd-shim&lt;/em&gt; &amp;ndash; building the containerd-shim app&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Following are some explanation about containerd source code:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;cmd/containerd&lt;/em&gt;                &amp;ndash; contains the containerd daemon source code&lt;/li&gt;&lt;li&gt;&lt;em&gt;cmd/containerd-shim&lt;/em&gt;           &amp;ndash; containerd-shim code&lt;/li&gt;&lt;li&gt;&lt;em&gt;cmd/containerd-shim-runc-v1&lt;/em&gt;   &amp;ndash; containerd-shim-v1 code&lt;/li&gt;&lt;li&gt;&lt;em&gt;cmd/containerd-shim-runc-v2&lt;/em&gt;   &amp;ndash; containerd-shim-v2 code&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Examples how to use containerd&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Running ubuntu interactively&lt;ul&gt;&lt;li&gt;Make sure image is pulled using &amp;lsquo;ctr image pull&amp;rsquo;&lt;/li&gt;&lt;li&gt;Run the following commands to run it interactively and kill&lt;ul&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr run -t docker.io/library/ubuntu:latest u2&lt;/strong&gt; [ run the image ]&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr container info ubuntulatest&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;{    &amp;#34;ID&amp;#34;: &amp;#34;ubuntulatest&amp;#34;,    &amp;#34;Labels&amp;#34;: {        &amp;#34;io.containerd.image.config.stop-signal&amp;#34;: &amp;#34;SIGTERM&amp;#34;    },    &amp;#34;Image&amp;#34;: &amp;#34;docker.io/library/ubuntu:latest&amp;#34;,    &amp;#34;Runtime&amp;#34;: {        &amp;#34;Name&amp;#34;: &amp;#34;io.containerd.runc.v2&amp;#34;,        &amp;#34;Options&amp;#34;: {            &amp;#34;type_url&amp;#34;: &amp;#34;containerd.runc.v1.Options&amp;#34;        }    },    &amp;#34;SnapshotKey&amp;#34;: &amp;#34;ubuntulatest&amp;#34;,    &amp;#34;Snapshotter&amp;#34;: &amp;#34;overlayfs&amp;#34;,    &amp;#34;CreatedAt&amp;#34;: &amp;#34;2020-01-01T00:24:30.509643667Z&amp;#34;,    &amp;#34;UpdatedAt&amp;#34;: &amp;#34;2020-01-01T00:24:30.509643667Z&amp;#34;,    &amp;#34;Extensions&amp;#34;: null,    &amp;#34;Spec&amp;#34;: {        &amp;#34;ociVersion&amp;#34;: &amp;#34;1.0.1-dev&amp;#34;,        &amp;#34;process&amp;#34;: {            &amp;#34;user&amp;#34;: {                &amp;#34;uid&amp;#34;: 0,                &amp;#34;gid&amp;#34;: 0            },            &amp;#34;args&amp;#34;: [                &amp;#34;/bin/bash&amp;#34;            ],            &amp;#34;env&amp;#34;: [                &amp;#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&amp;#34;            ],            &amp;#34;cwd&amp;#34;: &amp;#34;/&amp;#34;,            &amp;#34;capabilities&amp;#34;: {                &amp;#34;bounding&amp;#34;: [                    &amp;#34;CAP_CHOWN&amp;#34;,                    &amp;#34;CAP_DAC_OVERRIDE&amp;#34;,                    &amp;#34;CAP_FSETID&amp;#34;,                    &amp;#34;CAP_FOWNER&amp;#34;,                    &amp;#34;CAP_MKNOD&amp;#34;,                    &amp;#34;CAP_NET_RAW&amp;#34;,                    &amp;#34;CAP_SETGID&amp;#34;,                    &amp;#34;CAP_SETUID&amp;#34;,                    &amp;#34;CAP_SETFCAP&amp;#34;,                    &amp;#34;CAP_SETPCAP&amp;#34;,                    &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;,                    &amp;#34;CAP_SYS_CHROOT&amp;#34;,                    &amp;#34;CAP_KILL&amp;#34;,                    &amp;#34;CAP_AUDIT_WRITE&amp;#34;                ],                &amp;#34;effective&amp;#34;: [                    &amp;#34;CAP_CHOWN&amp;#34;,                    &amp;#34;CAP_DAC_OVERRIDE&amp;#34;,                    &amp;#34;CAP_FSETID&amp;#34;,                    &amp;#34;CAP_FOWNER&amp;#34;,                    &amp;#34;CAP_MKNOD&amp;#34;,                    &amp;#34;CAP_NET_RAW&amp;#34;,                    &amp;#34;CAP_SETGID&amp;#34;,                    &amp;#34;CAP_SETUID&amp;#34;,                    &amp;#34;CAP_SETFCAP&amp;#34;,                    &amp;#34;CAP_SETPCAP&amp;#34;,                    &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;,                    &amp;#34;CAP_SYS_CHROOT&amp;#34;,                    &amp;#34;CAP_KILL&amp;#34;,                    &amp;#34;CAP_AUDIT_WRITE&amp;#34;                ],                &amp;#34;inheritable&amp;#34;: [                    &amp;#34;CAP_CHOWN&amp;#34;,                    &amp;#34;CAP_DAC_OVERRIDE&amp;#34;,                    &amp;#34;CAP_FSETID&amp;#34;,                    &amp;#34;CAP_FOWNER&amp;#34;,                    &amp;#34;CAP_MKNOD&amp;#34;,                    &amp;#34;CAP_NET_RAW&amp;#34;,                    &amp;#34;CAP_SETGID&amp;#34;,                    &amp;#34;CAP_SETUID&amp;#34;,                    &amp;#34;CAP_SETFCAP&amp;#34;,                    &amp;#34;CAP_SETPCAP&amp;#34;,                    &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;,                    &amp;#34;CAP_SYS_CHROOT&amp;#34;,                    &amp;#34;CAP_KILL&amp;#34;,                    &amp;#34;CAP_AUDIT_WRITE&amp;#34;                ],                &amp;#34;permitted&amp;#34;: [                    &amp;#34;CAP_CHOWN&amp;#34;,                    &amp;#34;CAP_DAC_OVERRIDE&amp;#34;,                    &amp;#34;CAP_FSETID&amp;#34;,                    &amp;#34;CAP_FOWNER&amp;#34;,                    &amp;#34;CAP_MKNOD&amp;#34;,                    &amp;#34;CAP_NET_RAW&amp;#34;,                    &amp;#34;CAP_SETGID&amp;#34;,                    &amp;#34;CAP_SETUID&amp;#34;,                    &amp;#34;CAP_SETFCAP&amp;#34;,                    &amp;#34;CAP_SETPCAP&amp;#34;,                    &amp;#34;CAP_NET_BIND_SERVICE&amp;#34;,                    &amp;#34;CAP_SYS_CHROOT&amp;#34;,                    &amp;#34;CAP_KILL&amp;#34;,                    &amp;#34;CAP_AUDIT_WRITE&amp;#34;                ]            },            &amp;#34;rlimits&amp;#34;: [                {                    &amp;#34;type&amp;#34;: &amp;#34;RLIMIT_NOFILE&amp;#34;,                    &amp;#34;hard&amp;#34;: 1024,                    &amp;#34;soft&amp;#34;: 1024                }            ],            &amp;#34;noNewPrivileges&amp;#34;: true        },        &amp;#34;root&amp;#34;: {            &amp;#34;path&amp;#34;: &amp;#34;rootfs&amp;#34;        },        &amp;#34;mounts&amp;#34;: [            {                &amp;#34;destination&amp;#34;: &amp;#34;/proc&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;proc&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;proc&amp;#34;,                &amp;#34;options&amp;#34;: [                    &amp;#34;nosuid&amp;#34;,                    &amp;#34;noexec&amp;#34;,                    &amp;#34;nodev&amp;#34;                ]            },            {                &amp;#34;destination&amp;#34;: &amp;#34;/dev&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;options&amp;#34;: [                    &amp;#34;nosuid&amp;#34;,                    &amp;#34;strictatime&amp;#34;,                    &amp;#34;mode=755&amp;#34;,                    &amp;#34;size=65536k&amp;#34;                ]            },            {                &amp;#34;destination&amp;#34;: &amp;#34;/dev/pts&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;devpts&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;devpts&amp;#34;,                &amp;#34;options&amp;#34;: [                    &amp;#34;nosuid&amp;#34;,                    &amp;#34;noexec&amp;#34;,                    &amp;#34;newinstance&amp;#34;,                    &amp;#34;ptmxmode=0666&amp;#34;,                    &amp;#34;mode=0620&amp;#34;,                    &amp;#34;gid=5&amp;#34;                ]            },            {                &amp;#34;destination&amp;#34;: &amp;#34;/dev/shm&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;shm&amp;#34;,                &amp;#34;options&amp;#34;: [                    &amp;#34;nosuid&amp;#34;,                    &amp;#34;noexec&amp;#34;,                    &amp;#34;nodev&amp;#34;,                    &amp;#34;mode=1777&amp;#34;,                    &amp;#34;size=65536k&amp;#34;                ]            },            {                &amp;#34;destination&amp;#34;: &amp;#34;/dev/mqueue&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;mqueue&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;mqueue&amp;#34;,                &amp;#34;options&amp;#34;: [                    &amp;#34;nosuid&amp;#34;,                    &amp;#34;noexec&amp;#34;,                    &amp;#34;nodev&amp;#34;                ]            },            {                &amp;#34;destination&amp;#34;: &amp;#34;/sys&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;sysfs&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;sysfs&amp;#34;,                &amp;#34;options&amp;#34;: [                    &amp;#34;nosuid&amp;#34;,                    &amp;#34;noexec&amp;#34;,                    &amp;#34;nodev&amp;#34;,                    &amp;#34;ro&amp;#34;                ]            },            {                &amp;#34;destination&amp;#34;: &amp;#34;/run&amp;#34;,                &amp;#34;type&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;source&amp;#34;: &amp;#34;tmpfs&amp;#34;,                &amp;#34;options&amp;#34;: [                    &amp;#34;nosuid&amp;#34;,                    &amp;#34;strictatime&amp;#34;,                    &amp;#34;mode=755&amp;#34;,                    &amp;#34;size=65536k&amp;#34;                ]            }        ],        &amp;#34;linux&amp;#34;: {            &amp;#34;resources&amp;#34;: {                &amp;#34;devices&amp;#34;: [                    {                        &amp;#34;allow&amp;#34;: false,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 1,                        &amp;#34;minor&amp;#34;: 3,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 1,                        &amp;#34;minor&amp;#34;: 8,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 1,                        &amp;#34;minor&amp;#34;: 7,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 5,                        &amp;#34;minor&amp;#34;: 0,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 1,                        &amp;#34;minor&amp;#34;: 5,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 1,                        &amp;#34;minor&amp;#34;: 9,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 5,                        &amp;#34;minor&amp;#34;: 1,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 136,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 5,                        &amp;#34;minor&amp;#34;: 2,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    },                    {                        &amp;#34;allow&amp;#34;: true,                        &amp;#34;type&amp;#34;: &amp;#34;c&amp;#34;,                        &amp;#34;major&amp;#34;: 10,                        &amp;#34;minor&amp;#34;: 200,                        &amp;#34;access&amp;#34;: &amp;#34;rwm&amp;#34;                    }                ]            },            &amp;#34;cgroupsPath&amp;#34;: &amp;#34;/default/ubuntulatest&amp;#34;,            &amp;#34;namespaces&amp;#34;: [                {                    &amp;#34;type&amp;#34;: &amp;#34;pid&amp;#34;                },                {                    &amp;#34;type&amp;#34;: &amp;#34;ipc&amp;#34;                },                {                    &amp;#34;type&amp;#34;: &amp;#34;uts&amp;#34;                },                {                    &amp;#34;type&amp;#34;: &amp;#34;mount&amp;#34;                },                {                    &amp;#34;type&amp;#34;: &amp;#34;network&amp;#34;                }            ],            &amp;#34;maskedPaths&amp;#34;: [                &amp;#34;/proc/acpi&amp;#34;,                &amp;#34;/proc/asound&amp;#34;,                &amp;#34;/proc/kcore&amp;#34;,                &amp;#34;/proc/keys&amp;#34;,                &amp;#34;/proc/latency_stats&amp;#34;,                &amp;#34;/proc/timer_list&amp;#34;,                &amp;#34;/proc/timer_stats&amp;#34;,                &amp;#34;/proc/sched_debug&amp;#34;,                &amp;#34;/sys/firmware&amp;#34;,                &amp;#34;/proc/scsi&amp;#34;            ],            &amp;#34;readonlyPaths&amp;#34;: [                &amp;#34;/proc/bus&amp;#34;,                &amp;#34;/proc/fs&amp;#34;,                &amp;#34;/proc/irq&amp;#34;,                &amp;#34;/proc/sys&amp;#34;,                &amp;#34;/proc/sysrq-trigger&amp;#34;            ]        }    }}            &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr  t metrics ubuntulatest&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;ID              TIMESTAMP                                  ubuntulatest    2020-01-01 00:29:16.295322149 +0000 UTC    METRIC                   VALUE                                                                                memory.usage_in_bytes    1433600                                                                              memory.limit_in_bytes    9223372036854771712                                                                  memory.stat.cache        0                                                                                    cpuacct.usage            19273664                                                                             cpuacct.usage_percpu     [205817 2386548 4771841 148926 5529908 227097 2037362 0 2107441 0 1017213 841511]    pids.current             1                                                                                    pids.limit               0             &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr  shim  &amp;ndash;id ubuntulatest state&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;{    &amp;#34;id&amp;#34;: &amp;#34;ubuntulatest&amp;#34;,    &amp;#34;bundle&amp;#34;: &amp;#34;/run/containerd/io.containerd.runtime.v2.task/default/ubuntulatest&amp;#34;,    &amp;#34;pid&amp;#34;: 16032,    &amp;#34;status&amp;#34;: 2,    &amp;#34;stdin&amp;#34;: &amp;#34;/run/containerd/fifo/249557939/ubuntulatest-stdin&amp;#34;,    &amp;#34;stdout&amp;#34;: &amp;#34;/run/containerd/fifo/249557939/ubuntulatest-stdout&amp;#34;,    &amp;#34;stderr&amp;#34;: &amp;#34;/run/containerd/fifo/249557939/ubuntulatest-stderr&amp;#34;,    &amp;#34;exited_at&amp;#34;: &amp;#34;0001-01-01T00:00:00Z&amp;#34;}             &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr t kill u2&lt;/strong&gt;                                 [ kill the container labelled u2 ]&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Another example to download hello world&lt;ul&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr image pull docker.io/library/hello-world:latest&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;docker.io/library/hello-world:latest:                                             resolved       |++++++++++++++++++++++++++++++++++++++| index-sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064:    done           |++++++++++++++++++++++++++++++++++++++| manifest-sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a: done           |++++++++++++++++++++++++++++++++++++++| layer-sha256:1b930d010525941c1d56ec53b97bd057a67ae1865eebf042686d2a2d18271ced:    done           |++++++++++++++++++++++++++++++++++++++| config-sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e:   done           |++++++++++++++++++++++++++++++++++++++| elapsed: 3.7 s                                                                    total:  4.8 Ki (1.3 KiB/s)                                       unpacking linux/amd64 sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr container create docker.io/library/hello-world:latest demo&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sudo ./ctr task start demo&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;containerd utilise kernel feature called &amp;lsquo;reaper&amp;rsquo; to reparent the container proces to the shim&lt;img src=&#34;./media/containerd/pr_set_child_reaper.png&#34; alt=&#34;ContaierDLayer&#34; /&gt;Following shows the process structure when running a container using containerd&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;nanik     7741  3230  0  2019 ?        00:02:54  \_ /usr/libexec/gnome-terminal-servernanik     7750  7741  0  2019 pts/1    00:00:00  |   \_ bash..........nanik    19294  7741  0 13:45 pts/5    00:00:00  |   \_ bashroot      5123 19294  0 17:51 pts/5    00:00:00  |   |   \_ sudo ./ctr run -t docker.io/library/ubuntu:latest u13root      5124  5123  0 17:51 pts/5    00:00:00  |   |       \_ ./ctr run -t docker.io/library/ubuntu:latest u13nanik    18313  7741  0 16:11 pts/11   00:00:00  |   \_ bash.........................root      5884  3230  0 17:52 ?        00:00:00  \_ /usr/bin/containerd-shim-runc-v2 -namespace default -id u13 -address /run/containerd/containerd.sockroot      5906  5884  0 17:52 ?        00:00:00      \_ /bin/bash..........    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;As can be seen containerd uses shim called &amp;lsquo;containerd-shim-run-v2&amp;rsquo;. Runc has been terminated after running the container and the shim takes over as the parent of the container. Containerd supports shim v2&lt;br /&gt;&lt;img src=&#34;./media/containerd/shim_v2.png&#34; alt=&#34;ContaierDLayer&#34; /&gt;&lt;/p&gt;&lt;p&gt;The shim is executed out-of-process (executed with exec(..)) and the following are used to execute it:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt; 0 = {string} &amp;#34;-namespace&amp;#34; 1 = {string} &amp;#34;default&amp;#34; 2 = {string} &amp;#34;-address&amp;#34; 3 = {string} &amp;#34;/run/containerd/containerd.sock&amp;#34; 4 = {string} &amp;#34;-publish-binary&amp;#34; 5 = {string} &amp;#34;/tmp/___containerd&amp;#34; 6 = {string} &amp;#34;-id&amp;#34; 7 = {string} &amp;#34;u8&amp;#34; 8 = {string} &amp;#34;-debug&amp;#34; 9 = {string} &amp;#34;start&amp;#34;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;The /tmp/__containerid contains the containerd executable.&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://groups.google.com/forum/#!topic/docker-dev/zaZFlvIx1_k&#34;&gt;Comment by Michael Crosby about shim&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;The shim allows for daemonless containers.  It basically sits as the parent of the container&amp;#39;s process to facilitate a few things.First it allows the runtimes, i.e. runc,to exit after it starts the container.  This way we don&amp;#39;t have to have the long running runtime processes for containers.  When you start mysql you should only see the mysql process and the shim.Second it keeps the STDIO and other fds open for the container incase containerd and/or docker both die.  If the shim was not running then the parent side of the pipes or the TTY master would be closed and the container would exit.  Finally it allows the container&amp;#39;s exit status to be reported back to a higher level tool like docker without having the be the actual parent of the container&amp;#39;s process and do a wait.      &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;containerd uses FIFO for reporting event and exit code and also for stdout and stdin&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;/run/containerd/fifo/195093460/&amp;lt;something_something&amp;gt;_stdout/run/containerd/fifo/195093460/&amp;lt;something_something&amp;gt;_stdin  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;runc&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;A lightweight binary that supports the OCI runtime-spec for running containers. Deals with the low-level interfacing with Linux capabilities like cgroups, namespaces, etc&amp;hellip;&lt;/li&gt;&lt;li&gt;runc looked for temp directory using &amp;ldquo;XDG_RUNTIME_DIR&amp;rdquo; eg:/run/user/1000/runc/&lt;/li&gt;&lt;li&gt;runc have heavy dependencies on libcontainer.&lt;/li&gt;&lt;li&gt;&lt;p&gt;How &amp;lsquo;runc&amp;rsquo; is used/executed inside containerd ?. Following are some explanation:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Containerd runs as a server where it receive GRPC command. The ctr CLI tool is the way to send command to run, stop, etc containers in containerd&lt;/li&gt;&lt;li&gt;When containerd receive command as such&lt;strong&gt;sudo ./ctr run  -t docker.io/library/ubuntu:latest  u67&lt;/strong&gt;, it will go through &lt;strong&gt;services/tasks/service.go&lt;/strong&gt; source code to prepare all the necessary data to spin off &amp;lsquo;containerd-shim-runc-v2&amp;rsquo; executable.&lt;/li&gt;&lt;li&gt;Following is an example of the executable argument prepared when executing &amp;lsquo;containerd-shim-runc-v2&amp;rsquo;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt; 0 = {string} &amp;#34;-namespace&amp;#34; 1 = {string} &amp;#34;default&amp;#34; 2 = {string} &amp;#34;-address&amp;#34; 3 = {string} &amp;#34;/run/containerd/containerd.sock&amp;#34; 4 = {string} &amp;#34;-publish-binary&amp;#34; 5 = {string} &amp;#34;/tmp/___containerd&amp;#34; 6 = {string} &amp;#34;-id&amp;#34; 7 = {string} &amp;#34;u8&amp;#34; 8 = {string} &amp;#34;-debug&amp;#34; 9 = {string} &amp;#34;start&amp;#34;       &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Full command used  &amp;ndash; &lt;strong&gt;/usr/bin/containerd-shim-runc-v2 -namespace default -id u67 -address /run/containerd/containerd.sock&lt;/strong&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Following are the log output (debug log were added to trace soure code)  when &amp;lsquo;containerd-shim-runc-v2&amp;rsquo; is running:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;time=&amp;#34;2020-01-02T23:38:00.438682328+11:00&amp;#34; level=info msg=setupDumpStacks...time=&amp;#34;2020-01-02T23:38:00.438927931+11:00&amp;#34; level=info msg=&amp;#34;calling newServer...&amp;#34;time=&amp;#34;2020-01-02T23:38:00.439033554+11:00&amp;#34; level=info msg=&amp;#34;registering ttrpc server&amp;#34;time=&amp;#34;2020-01-02T23:38:00.439097725+11:00&amp;#34; level=info msg=&amp;#34;calling serve...&amp;#34;time=&amp;#34;2020-01-02T23:38:00.439198636+11:00&amp;#34; level=info msg=&amp;#34;calling handleSignals...&amp;#34;time=&amp;#34;2020-01-02T23:38:00.439220268+11:00&amp;#34; level=info msg=&amp;#34;nanik starting signal loop&amp;#34; namespace=default path=/run/containerd/io.containerd.runtime.v2.task/default/u67 pid=17162time=&amp;#34;2020-01-02T23:38:00.439861913+11:00&amp;#34; level=info msg=&amp;#34;Create is called inside  RegisterTaskService&amp;#34;time=&amp;#34;2020-01-02T23:38:00.439974576+11:00&amp;#34; level=info msg=&amp;#34;container NANIK &amp;#34;time=&amp;#34;2020-01-02T23:38:00.440214591+11:00&amp;#34; level=info msg=&amp;#34;--- CreateTaskRequest  &amp;amp;CreateTaskRequest{ID:u67,Bundle:/run/containerd/io.containerd.runtime.v2.task/default/u67,Rootfs:[&amp;amp;types.Mount{Type:overlay,Source:overlay,Target:,Options:[workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/133/work upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/133/fs lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/4/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/3/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/2/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/1/fs],XXX_unrecognized:[],}],Terminal:true,Stdin:/run/containerd/fifo/383837931/u67-stdin,Stdout:/run/containerd/fifo/383837931/u67-stdout,Stderr:,Checkpoint:,ParentCheckpoint:,Options:&amp;amp;types1.Any{TypeUrl:containerd.runc.v1.Options,Value:[],XXX_unrecognized:[],},XXX_unrecognized:[],}&amp;#34;time=&amp;#34;2020-01-02T23:38:00.440329033+11:00&amp;#34; level=info msg=&amp;#34;--- rootfs  /run/containerd/io.containerd.runtime.v2.task/default/u67/rootfs&amp;#34;time=&amp;#34;2020-01-02T23:38:00.440350982+11:00&amp;#34; level=info msg=&amp;#34;--- opts.BinaryName  &amp;#34;time=&amp;#34;2020-01-02T23:38:00.440367236+11:00&amp;#34; level=info msg=&amp;#34;--- opts.Bundle  /run/containerd/io.containerd.runtime.v2.task/default/u67&amp;#34;time=&amp;#34;2020-01-02T23:38:00.441364775+11:00&amp;#34; level=info msg=&amp;#34;--- calling p.create with context.Background.WithValue(type namespaces.namespaceKey, val default).WithValue(type metadata.mdOutgoingKey, val &amp;lt;not Stringer&amp;gt;).WithValue(type ttrpc.metadataKey, val &amp;lt;not Stringer&amp;gt;).WithValue(type shim.OptsKey, val &amp;lt;not Stringer&amp;gt;).WithValue(type log.loggerKey, val &amp;lt;not Stringer&amp;gt;).WithCancel.WithCancel AND ... &amp;#34;time=&amp;#34;2020-01-02T23:38:00.441809346+11:00&amp;#34; level=info msg=&amp;#34;------- inside init.gocontext.Background.WithValue(type namespaces.namespaceKey, val default).WithValue(type metadata.mdOutgoingKey, val &amp;lt;not Stringer&amp;gt;).WithValue(type ttrpc.metadataKey, val &amp;lt;not Stringer&amp;gt;).WithValue(type shim.OptsKey, val &amp;lt;not Stringer&amp;gt;).WithValue(type log.loggerKey, val &amp;lt;not Stringer&amp;gt;).WithCancel.WithCancel/run/containerd/io.containerd.runtime.v2.task/default/u67&amp;amp;{&amp;lt;nil&amp;gt; /run/containerd/io.containerd.runtime.v2.task/default/u67/init.pid 0xc000154520 false false false []}&amp;#34; runtime=io.containerd.runc.v2time=&amp;#34;2020-01-02T23:38:00.503607036+11:00&amp;#34; level=info msg=&amp;#34;Start is called inside  RegisterTaskService&amp;#34;time=&amp;#34;2020-01-02T23:38:00.503640676+11:00&amp;#34; level=info msg=&amp;#34;v2/service Start&amp;#34;ime=&amp;#34;2020-01-02T17:33:35.454812846+11:00&amp;#34; level=info msg=&amp;#34;v2/service Delete&amp;#34;       &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The final function that will execute &amp;lsquo;runc&amp;rsquo; is inside &lt;strong&gt;containerd/go-runc/runc.go&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;func (r *Runc) Create(context context.Context, id, bundle string, opts *CreateOpts) error {}      &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Logging code was added inside the &lt;strong&gt;Create(..)&lt;/strong&gt; function and following is the output:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;--- args  [create --bundle /run/containerd/io.containerd.runtime.v2.task/default/u67]--- cmd  /home/nanik/AndroidProjects/docker/docker/runc --root /run/containerd/runc/default --log /run/containerd/io.containerd.runtime.v2.task/default/u67/log.json --log-format json create--bundle /run/containerd/io.containerd.runtime.v2.task/default/u67 --pid-file /run/containerd/io.containerd.runtime.v2.task/default/u67/init.pid --console-socket /tmp/pty415594316/pty.sock u67The command used to execute &amp;#39;runc&amp;#39; is as follows&amp;#34;/home/nanik/AndroidProjects/docker/docker/runc --root /run/containerd/runc/default --log /run/containerd/io.containerd.runtime.v2.task/default/u67/log.json --log-format json create --bundle /run/containerd/io.containerd.runtime.v2.task/default/u67 --pid-file /run/containerd/io.containerd.runtime.v2.task/default/u67/init.pid --console-socket /tmp/pty415594316/pty.sock u67&amp;#34;     &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To use runc to see docker containers that are running&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;sudo ./runc --root /run/docker/runtime-runc/moby  list ID                                                                 PID         STATUS      BUNDLE                                                                                                                 CREATED                          OWNERf182f95645673b94af95495ea4c2a7c0f58dcce523f3d4e7174d7e482e136e08   12212       running     /run/containerd/io.containerd.runtime.v1.linux/moby/f182f95645673b94af95495ea4c2a7c0f58dcce523f3d4e7174d7e482e136e08   2020-01-05T21:28:05.371871841Z   root  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/57009928/runc-and-ctr-commands-do-not-show-docker-images-and-containers&#34;&gt;Good explanation from here&lt;/a&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;The runtime (runc) uses so-called runtime root directory to store and obtain the information about containers. Under this root directory, runc places sub-directories (one per container), and each of them contains the state.json file, where the container state description resides.The default location for runtime root directory is either /run/runc (for non-rootless containers) or $XDG_RUNTIME_DIR/runc (for rootless containers) - the latter also usually points to somewhere under /run (e.g. /run/user/$UID/runc).When the container engine invokes runc, it may override the default runtime root directory and specify the custom one (--root option of runc). Docker uses this possibility, e.g. on my box, it specifies /run/docker/runtime-runc/moby as the runtime root.That said, to make runc list see your Docker containers, you have to point it to Docker&amp;#39;s runtime root directory by specifying --root option. Also, given that Docker containers are not rootless by default, you will need the appropriate privileges to access the runtime root (e.g. with sudo).    So, that&amp;#39;s how this should work:    $ docker run -d alpine sleep 1000    4acd4af5ba8da324b7a902618aeb3fd0b8fce39db5285546e1f80169f157fc69    $ sudo runc --root /run/docker/runtime-runc/moby/ list    ID                                                                 PID         STATUS      BUNDLE                                                                                                                               CREATED                          OWNER    4acd4af5ba8da324b7a902618aeb3fd0b8fce39db5285546e1f80169f157fc69   18372       running     /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/4acd4af5ba8da324b7a902618aeb3fd0b8fce39db5285546e1f80169f157fc69   2019-07-12T17:33:23.401746168Z   rootAs to images, you can not make runc see them, as it has no notion of image at all - instead, it operates on bundles. Creating the bundle (e.g. based on image) is responsibility of the caller (in your case - containerd).  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;libcontainer&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Library used inside runc for container operation&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/42696589/libcontainer-runc-and-nsenter-bootstrap/42697174&#34;&gt;Explanation about libcontainer, runc and nsenter&lt;/a&gt;. More &lt;a href=&#34;https://groups.google.com/a/opencontainers.org/forum/#!msg/dev/CC1XH92oMrE/G1GRnBDGCAAJ&#34;&gt;in-depth explanation&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;Docker and lower level&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Docker CLI (docker) - /usr/bin/docker&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Docker is used as a reference to the whole set of docker tools and at the beginning it was a monolith. But now docker-cli is only responsible for user friendly communication with docker.&lt;/p&gt;&lt;p&gt;So the command&amp;rsquo;s like docker build &amp;hellip; docker run &amp;hellip; are handled by Docker CLI and result in the invocation of dockerd API.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dockerd - /usr/bin/dockerd&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The Docker daemon - dockerd listens for Docker API requests and manages host&amp;rsquo;s Container life-cycles by utilizing contanerd&lt;/p&gt;&lt;p&gt;dockerd can listen for Docker Engine API requests via three different types of Socket: unix, tcp, and fd. By default, a unix domain socket is created at /var/run/docker.sock, requiring either root permission, or docker group membership. On Systemd based systems, you can communicate with the daemon via Systemd socket activation, use dockerd -H fd://.&lt;/p&gt;&lt;p&gt;There are many configuration options for the daemon, which are worth to check if you work with docker (dockerd).&lt;/p&gt;&lt;p&gt;My impression is that dockerd is here to serve all the features of Docker (or Docker EE) platform, while actual container life-cycle management is &amp;ldquo;outsourced&amp;rdquo; to containerd.Containerd&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;containerd - /usr/bin/docker-containerd&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;containerd was introduced in Docker 1.11 and since then took main responsibilty of managing containers life-cycle. containerd is the executor for containers, but has a wider scope than just executing containers. So it also take care of:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Image push and pullManaging of storageOf course executing of Containers by calling runc with the right parameters to run containers...Managing of network primitives for interfacesManagement of network namespaces containers to join existing namespaces      &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;containerd fully leverages the OCI runtime specification1, image format specifications and OCI reference implementation (runc). Because of its massive adoption, containerd is the industry standard for implementing OCI. It is currently available for Linux and Windows.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;RunC - /usr/bin/docker-runc runc (OCI runtime) can be seen as component of containerd.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;runc is a command line client for running applications packaged according tothe OCI format and is a compliant implementation of the OCI spec.&lt;/p&gt;&lt;p&gt;Containers are configured using bundles. A bundle for a container is a directorythat includes a specification file named &amp;ldquo;config.json&amp;rdquo; and a root filesystem.The root filesystem contains the contents of the container.&lt;/p&gt;&lt;p&gt;Assuming you have an OCI bundle you can execute the container&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;containerd-ctr - /usr/bin/docker-containerd-ctr (docker-)containerd-ctr&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;it&amp;rsquo;s barebone CLI (ctr) designed specifically for development and debugging purpose for direct communication with containerd. It&amp;rsquo;s included in the releases of containerd. By that less interesting for docker users.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;containerd-shim - /usr/bin/docker-containerd-shim&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The shim allows for daemonless containers. According to Michael Crosby it&amp;rsquo;s basically sits as the parent of the container&amp;rsquo;s process to facilitate a few things.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;First it allows the runtimes, i.e. runc,to exit after it starts the container. This way we don&amp;#39;t have to have the long running runtime processes for containers.Second it keeps the STDIO and other fds open for the container in case containerd and/or docker both die. If the shim was not running then the parent side of the pipes or the TTY master would be closed and the container would exit.Finally it allows the container&amp;#39;s exit status to be reported back to a higher level tool like docker without having the be the actual parent of the container&amp;#39;s process and do a wait.    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Complete interaction between docker cli, dockerd, containerd, containerd-shim and runc&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;dockerd is sent POST Containers Create    ↳ dockerd finds the requested image    ↳ A container object is created and stored for future use    ↳ Directories on the file system are setup for use by the containerdockerd is sent a POST Containers Start    ↳ An OCI spec is created for the container    ↳ containerd is contacted to create the container        ↳ containerd stores the container spec in a database    ↳ containerd is contacted to start the container        ↳  containerd creates a task for the container            ↳  The task uses a shim to call runc create        ↳  containerd starts the task            ↳  The task uses the shim to call runc start        ↳ The shim / containerd continue to monitor the container until completion&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;Running container with runc&lt;/h1&gt;&lt;p&gt;This following is step-by-step example on how to run OCI compliant image using runc. We going to use docker in this example.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Checkout the &lt;strong&gt;runc&lt;/strong&gt; project from &lt;a href=&#34;https://github.com/opencontainers/runc&#34;&gt;https://github.com/opencontainers/runc&lt;/a&gt; and build it by running &lt;strong&gt;make&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Download &lt;strong&gt;exportrootfs.sh&lt;/strong&gt; from &lt;a href=&#34;https://github.com/estesp/utils/blob/master/exportrootfs.sh&#34;&gt;https://github.com/estesp/utils/blob/master/exportrootfs.sh&lt;/a&gt; and add it to your PATH. Make sure follow the instruction inside the script to compile uidmapshift.c and include that too in the PATH&lt;/li&gt;&lt;li&gt;Make sure you have pull ubuntu:latest image using docker&lt;/li&gt;&lt;li&gt;Run the image using the docker run command:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;docker run -it ubuntu:latest /bin/bash&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Get the container id using &lt;strong&gt;docker ps&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMESebfbbecaf715        ubuntu:latest       &amp;#34;/bin/bash&amp;#34;         38 minutes ago      Up 38 minutes                           zen_kirch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create another separate directory and cd into that directory. Run the following command&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;sudo env &amp;#34;PATH=$PATH&amp;#34; exportrootfs.sh -u 0 -r 65536 ebf&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;ebf is the container id shown in the output of &lt;strong&gt;docker ps&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;You will have a &lt;strong&gt;roootfs&lt;/strong&gt; directory in your current directory and it will look like the following&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;rootfs├── bin├── boot├── dev├── etc├── home├── lib├── lib64├── media├── mnt├── opt├── proc├── root├── run├── sbin├── srv├── sys├── tmp├── usr└── var&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create the runtime spec using the command&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;runc spec&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;You will see a new file called &lt;strong&gt;config.json&lt;/strong&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Open config.json and modify the &lt;strong&gt;args&lt;/strong&gt; to the following&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    &amp;#34;args&amp;#34;: [    &amp;#34;/bin/bash&amp;#34;],&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Execute the image using the following&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    sudo env &amp;#34;PATH=$PATH&amp;#34; runc run anycontainername&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You will see bash running&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;    root@runc:/# cat /etc/lsb-release DISTRIB_ID=UbuntuDISTRIB_RELEASE=18.04DISTRIB_CODENAME=bionicDISTRIB_DESCRIPTION=&amp;#34;Ubuntu 18.04.3 LTS&amp;#34;root@runc:/# &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As can be seen the runc does not know how to pull, prepare, etc the image. It just knows that there is a root fileysystem with the config.json that it needs to run. The ubuntu container ran by the above example does not have network as this will be taken care by some other project and not by runc.&lt;/p&gt;&lt;p&gt;runc utilize prestart hooks to run some other application required as part of the setup of the containers, as shown in &lt;a href=&#34;https://stackoverflow.com/questions/55064917/network-setup-for-rootless-runc-containers&#34;&gt;here&lt;/a&gt;. The config.json&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;   .   .   .   &amp;#34;hooks&amp;#34;: {        &amp;#34;prestart&amp;#34; : [            {                &amp;#34;path&amp;#34; : &amp;#34;/path/to/netns&amp;#34;,                &amp;#34;args&amp;#34; : [                    &amp;#34;&amp;#34;,                    &amp;#34;--state-dir&amp;#34;, &amp;#34;/path/to/netns/netns-state&amp;#34;                ]            }        ]    },    .    .    .    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;shows the prestart hook that will be executed to setup the networking state using the netns executable. The netns tool is part of the &lt;a href=&#34;http://github.com/genuinetools&#34;&gt;genuinetools&lt;/a&gt; project&lt;/p&gt;&lt;h1&gt;References&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Blogs&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;http://alexander.holbreich.org/docker-components-explained/&#34;&gt;Different parts of Docker explained&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://prefetch.net/blog/2018/02/19/how-the-docker-container-creation-process-works-from-docker-run-to-runc/&#34;&gt;Docker container creation process&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/crosbymichael/dockercon-2016&#34;&gt;Michael Crosby Dockercon source example&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://cameronlonsdale.com/2019/03/25/how-does-docker-work/&#34;&gt;How docker works&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.slideshare.net/PhilEstes&#34;&gt;Good presentation about containers&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://containerd.io/&#34;&gt;Containerd website&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Videos&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=RP40Iv_0yvA&#34;&gt;Traefik v2.0 in Docker + containerd Updates&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=0wEiizErKZw&#34;&gt;Deep Dive into firecracker-containerd&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=cfhnioURGdE&#34;&gt;Containerd: The Universal Container Runtime - Justin Cormack, Docker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=fIRaPGxhsH0&#34;&gt;Looking Under The Hood: containerD&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=ZAhzoz2zJj8&#34;&gt;runc - how it works video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Forums&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/users/7191047/danila-kiver&#34;&gt;Answers to some interesting low-level questions&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Source Code&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/opencontainers/runc&#34;&gt;runc source Code&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/containerd/containerd&#34;&gt;Containerd source code&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Concurrency Design Pattern in Go</title>
       <link>/post/golangconcurrency/</link>
       <pubDate>Mon, 02 Dec 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/golangconcurrency/</guid>
       <description>&lt;h1&gt;Design Patterns&lt;/h1&gt;&lt;p&gt;Concurrency in Golang is quite simple, and it&amp;rsquo;s a powerful tool. Understanding concurrency basic is important before jumping any further. Once basic understanding has been established the next step is to go deeper by looking at using different kind of concurrency patterns. Understanding different concurrency pattern is important to make it easier in picking up the right solution to a certain concurrency problem that we are trying to tackle. Also, it will reduce boilerplate code  .&lt;/p&gt;&lt;h3&gt;Pipeline&lt;/h3&gt;&lt;p&gt;The cascading effect of closing channel (from  close(done)) will ensure that all the other channels inside generator(..), add(..) and multiply (..) will also closed.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(){    &lt;span style=&#34;color:#a6e22e&#34;&gt;generator&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}, &lt;span style=&#34;color:#a6e22e&#34;&gt;integers&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)        &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {            &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; close(&lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt;)            &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;integers&lt;/span&gt; {                &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {                &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;:                    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;:                }            }        }()        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt;    }    &lt;span style=&#34;color:#a6e22e&#34;&gt;multiply&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(        &lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{},        &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;multiplier&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;,    ) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;multipliedStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)        &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {            &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; close(&lt;span style=&#34;color:#a6e22e&#34;&gt;multipliedStream&lt;/span&gt;)            &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt; {                &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {                &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;:                    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;multipliedStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;multiplier&lt;/span&gt;:                }            }        }()        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;multipliedStream&lt;/span&gt;    }    &lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(        &lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{},        &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;,        &lt;span style=&#34;color:#a6e22e&#34;&gt;additive&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;,    ) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;addedStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)        &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {            &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; close(&lt;span style=&#34;color:#a6e22e&#34;&gt;addedStream&lt;/span&gt;)            &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt; {                &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {                &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;:                    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;addedStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;additive&lt;/span&gt;:                }            }        }()        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;addedStream&lt;/span&gt;    }    &lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{})    &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; close(&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;generator&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;pipeline&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;multiply&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;multiply&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;intStream&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;), &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;), &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;v&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;pipeline&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;v&lt;/span&gt;)    } }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Resources:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://blog.golang.org/pipelines&#34;&gt;https://blog.golang.org/pipelines&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Tee-Channel&lt;/h3&gt;&lt;p&gt;Takes a single input channel and an arbitrary number of output channels and duplicates each input into every output. When the input channel is closed, all outputs channels are closed. The &lt;a href=&#34;https://github.com/eapache/channels/blob/master/channels.go#L120&#34;&gt;eapache channels&lt;/a&gt; project provide this kind of pattern. Following code snippet is the implementation.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tee&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SimpleOutChannel&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;outputs&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;SimpleInChannel&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;closeWhenDone&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt;) {&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make([]&lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SelectCase&lt;/span&gt;, len(&lt;span style=&#34;color:#a6e22e&#34;&gt;outputs&lt;/span&gt;))&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;Dir&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SelectSend&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;elem&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Out&lt;/span&gt;() {&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;Chan&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;outputs&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;In&lt;/span&gt;())&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;Send&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;elem&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;chosen&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Select&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;chosen&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;Chan&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)}}&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;closeWhenDone&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;outputs&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;outputs&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()}}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The library uses Golang&amp;rsquo;s internal &lt;a href=&#34;https://golang.org/pkg/reflect/#SelectCase&#34;&gt;SelectCase&lt;/a&gt; package to process multiple channels.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SelectCase&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {    &lt;span style=&#34;color:#a6e22e&#34;&gt;Dir&lt;/span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;SelectDir&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// direction of case&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Chan&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;     &lt;span style=&#34;color:#75715e&#34;&gt;// channel to use (for send or receive)&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Send&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;     &lt;span style=&#34;color:#75715e&#34;&gt;// value to send (for send)&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The SelectCase structure is like a container of channels depending on the direction specified (Dir).&lt;/p&gt;&lt;h3&gt;Fan-in-Fan-out channel&lt;/h3&gt; &lt;p&gt;This pattern collate results from goroutines that have been spawned to do background processing.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {    &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fanIn&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;generator&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;generator&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Bye&amp;#34;&lt;/span&gt;))    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;)    }}&lt;span style=&#34;color:#75715e&#34;&gt;// fanIn is itself a generator&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fanIn&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch1&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ch2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; { &lt;span style=&#34;color:#75715e&#34;&gt;// receives two read-only channels&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;new_ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() { &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;new_ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ch1&lt;/span&gt; } }() &lt;span style=&#34;color:#75715e&#34;&gt;// launch two goroutine while loops to continuously pipe to new channel&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() { &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;new_ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ch2&lt;/span&gt; } }()    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;new_ch&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;generator&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;msg&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; { &lt;span style=&#34;color:#75715e&#34;&gt;// returns receive-only channel&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() { &lt;span style=&#34;color:#75715e&#34;&gt;// anonymous goroutine&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; ; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; {            &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;msg&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;)            &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&gt;)        }    }()    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;}    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Context&lt;/h3&gt;&lt;p&gt;Good for cancelling / terminating goroutine by propagation. In order for this to work effectively the context must be send as part of argument parameters to each of the goroutines. The Done() inside locale(..) method is called as the context.WithTimeout(..) got triggered after 1 second and it propagates all the way to the root context&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sync&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WaitGroup&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WithCancel&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Background&lt;/span&gt;())    &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel&lt;/span&gt;()    &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {        &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Done&lt;/span&gt;()        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;printGreeting&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;); &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {            &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cannot print greeting: %v\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)            &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel&lt;/span&gt;()        }    }()    &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {        &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Done&lt;/span&gt;()        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;printFarewell&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;); &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {            &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cannot print farewell: %v\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)        }    }()    &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Wait&lt;/span&gt;()}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;printGreeting&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {    &lt;span style=&#34;color:#a6e22e&#34;&gt;greeting&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;genGreeting&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;    }    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s world!\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;greeting&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;printFarewell&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {    &lt;span style=&#34;color:#a6e22e&#34;&gt;farewell&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;genFarewell&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;    }    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s world!\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;farewell&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;genGreeting&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;) (&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {    &lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WithTimeout&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel&lt;/span&gt;()    &lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;locale&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;locale&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;); {    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;:        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;locale&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EN/US&amp;#34;&lt;/span&gt;:        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unsupported locale&amp;#34;&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;genFarewell&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;) (&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {    &lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;locale&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;locale&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;); {    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;:        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;locale&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EN/US&amp;#34;&lt;/span&gt;:        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;goodbye&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unsupported locale&amp;#34;&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;locale&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;) (&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {    &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Done&lt;/span&gt;():        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Err&lt;/span&gt;()    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;After&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Minute&lt;/span&gt;):        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Expired&amp;#34;&lt;/span&gt;)    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EN/US&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;h3&gt;Bridge Channel&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.........&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.........&lt;/span&gt;.&lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Error Propagation&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.........&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.........&lt;/span&gt;.&lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;Concurrency Project&lt;/h1&gt;&lt;p&gt;This section will discuss in detail about the &lt;a href=&#34;https://github.com/eapache/go-resiliency&#34;&gt;go-resiliency project&lt;/a&gt;. This project is a very useful project to learn more in-depth about concurrency. There are several different implementations and patterns it implemented that are useful to use in an application. The other project that is useful to learn is the &lt;a href=&#34;https://github.com/eapache/channels&#34;&gt;channels project&lt;/a&gt;, this project is useful to learn different ways using Golang &lt;strong&gt;channels&lt;/strong&gt;.&lt;/p&gt;&lt;h3&gt;Blackhole&lt;/h3&gt;&lt;p&gt;The function of the class is to receive data and discard it and calculated the total number of data it received. This is useful in situation where we want to check if our app concurrency app is receiving the same amount of data as expected.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;channels&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// BlackHole implements the InChannel interface and provides an analogue for the &amp;#34;Discard&amp;#34; variable in&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// the ioutil package - it never blocks, and simply discards every value it reads. The number of items&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// discarded in this way is counted and returned from Len.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewBlackHole&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;:  make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}),&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt;: make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;),}&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;discard&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;In&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{} {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Len&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;val&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;val&lt;/span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt;}}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Cap&lt;/span&gt;() &lt;span style=&#34;color:#a6e22e&#34;&gt;BufferCap&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Infinity&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;() {close(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BlackHole&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;discard&lt;/span&gt;() {&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;:&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt; {close(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;}&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt;:}}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following is a code sample on how to use Blackhole&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;TestBlackHole&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;testing&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;) {&lt;span style=&#34;color:#a6e22e&#34;&gt;discard&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewBlackHole&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;discard&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;In&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;}&lt;span style=&#34;color:#a6e22e&#34;&gt;discard&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;discard&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Len&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Error&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;blackhole expected 1000 was&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;discard&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Len&lt;/span&gt;())}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Deadline&lt;/h3&gt;&lt;p&gt;There are instances where we want our application to do a background process but there is a time limit imposed on it. Following is a sample snippet on how to use this functionality&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ExampleDeadline&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;dl&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;New&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;dl&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Run&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;stopper&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt;{}) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {&lt;span style=&#34;color:#75715e&#34;&gt;// do something possibly slow&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// check stopper function and give up if timed out&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;})&lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ErrTimedOut&lt;/span&gt;:&lt;span style=&#34;color:#75715e&#34;&gt;// execution took too long, oops&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;:&lt;span style=&#34;color:#75715e&#34;&gt;// some other error&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Circuit Breaker&lt;/h3&gt;&lt;p&gt;Implementation is a simple counter measurement of success and failure of a particular task. The only goroutine used is to run the timer to make sure that that there some time limit imposed.  The different states - &lt;strong&gt;closed&lt;/strong&gt;, &lt;strong&gt;half-open&lt;/strong&gt;  and &lt;strong&gt;open&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;closed&lt;/strong&gt; &amp;ndash; close the circuit breaker as all are good&lt;/li&gt;&lt;li&gt;&lt;strong&gt;half-open&lt;/strong&gt; &amp;ndash; transition to this state happens when the timeout timer has expired&lt;/li&gt;&lt;li&gt;&lt;strong&gt;open&lt;/strong&gt; &amp;ndash; transition to this state is triggered when error happens, there could be 2 different scenarios - no of errors reached errors threshold or the current state is half-open (timeout occured)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The function &lt;strong&gt;processResult(..)&lt;/strong&gt; is the main logic performing the transition to different states based on the success and errors threshold criteria.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Breaker&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;processResult&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;panicValue&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}) {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;lock&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Lock&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;lock&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Unlock&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;panicValue&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;state&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;halfOpen&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;successes&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;successes&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;successThreshold&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;closeBreaker&lt;/span&gt;()}}} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;errors&lt;/span&gt; &amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;expiry&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;lastError&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;timeout&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Now&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;After&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;expiry&lt;/span&gt;) {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;errors&lt;/span&gt; = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;}}&lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;state&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;closed&lt;/span&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;errors&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;errors&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;errorThreshold&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;openBreaker&lt;/span&gt;()} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;lastError&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Now&lt;/span&gt;()}&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;halfOpen&lt;/span&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;openBreaker&lt;/span&gt;()}}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following diagram explains in detail how the logic works inside processResult. The diagram breaks down the logic into 2 different category - &lt;strong&gt;success&lt;/strong&gt; and &lt;strong&gt;errors&lt;/strong&gt;. Each category have different logic to transition to different states.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/golangdesignpattern/circuitbreaker.jpg&#34; alt=&#34;batcherchannels&#34; /&gt;&lt;/p&gt;&lt;h3&gt;Batcher&lt;/h3&gt;&lt;p&gt;Below is a high level diagram on how the design pattern interact with the different pieces internally.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/golangdesignpattern/batch.jpg&#34; alt=&#34;batcherchannels&#34; /&gt;&lt;/p&gt;&lt;p&gt;This pattern handle situation where we need to do a particular task but we need to wait X amount of time before running it. For example - we are waiting for all parameteres to be collected together in 1 minute before executing a particular function/task for processing the parameter.&lt;/p&gt;&lt;p&gt;Code uses 2 different channels:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;future&lt;/strong&gt; &amp;ndash; for communication err value received from the executed task&lt;/li&gt;&lt;li&gt;&lt;strong&gt;submit&lt;/strong&gt; &amp;ndash; this channel is used as part of the timeout feature. The channel will be pushed with&lt;ul&gt;&lt;li&gt;parameter that need to be collected to be sent to the targeted task and&lt;/li&gt;&lt;li&gt;future channels that will be used to send the error value&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The &lt;strong&gt;submitWork&lt;/strong&gt; method is the method that is called when there is a duration specified for the timeout as the task need to be executed asynchronously.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Batcher&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;submitWork&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;work&lt;/span&gt;) {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;lock&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Lock&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;lock&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Unlock&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;submit&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;submit&lt;/span&gt; = make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;work&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;batch&lt;/span&gt;()}&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;submit&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The batch() method is the crux of the whole process. The code will keep looping the &lt;em&gt;b.submit&lt;/em&gt; channel to extract the params interface{} and future channel.Code will exit the loop when the &lt;em&gt;b.submit&lt;/em&gt; channel is closed by the the &lt;em&gt;b.timer()&lt;/em&gt; function (as it expired)&lt;/p&gt;&lt;p&gt;Once it&amp;rsquo;s out of the loop it will execute the task by calling &lt;em&gt;b.doWork(..)&lt;/em&gt;  and on completion of the task the error obtained (err) will be push to all the &lt;em&gt;future&lt;/em&gt; channels.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Batcher&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;batch&lt;/span&gt;() {&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;params&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;futures&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;submit&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;timer&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;work&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;params&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;params&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;work&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;param&lt;/span&gt;)   &lt;span style=&#34;color:#a6e22e&#34;&gt;futures&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;futures&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;work&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;future&lt;/span&gt;)}&lt;span style=&#34;color:#a6e22e&#34;&gt;ret&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;doWork&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;params&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;future&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;futures&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;future&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ret&lt;/span&gt;close(&lt;span style=&#34;color:#a6e22e&#34;&gt;future&lt;/span&gt;)}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following diagram outlines the different channels used for this pattern&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/golangdesignpattern/batchchannels.jpg&#34; alt=&#34;batcherchannels&#34; /&gt;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Deploying k8guard (Work in progress)</title>
       <link>/post/k8guard/</link>
       <pubDate>Sun, 01 Dec 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/k8guard/</guid>
       <description>&lt;h1&gt;Deploying k8guard&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Make sure &lt;strong&gt;minikube&lt;/strong&gt; and &lt;strong&gt;kubectl&lt;/strong&gt; is in PATH&lt;/li&gt;&lt;li&gt;&lt;p&gt;Use the following command to start  (v1.11.10  is the lowest version possible that will work with minikube master branch)&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;minikube start --memory &lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt; --kubernetes-version v1.11.10 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;eval &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;minikube docker-env&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;make build-deploy-minikube&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Deploy using the following commands&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl apply -f ./minikube/report/k8guard-report-secrets.yaml.EXAMPLE &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl apply -f ./minikube/action/k8guard-action-secrets.yaml.EXAMPLE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;k8guard-action&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;k8guard-action-configmap.yaml         |         |         |    k8guard-action-deployment.yam             |         |         |          k8guard-action-secrets.yaml.EXAMPLE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;File &lt;strong&gt;k8guard-action-deployment.yaml&lt;/strong&gt; contains deployment information for the k8guard-action app. It uses docker image called &lt;strong&gt;local/k8guard-action&lt;/strong&gt; which is build doing the above mentioned step.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;em&gt;env:&lt;/em&gt; section declared the env variables that will be populated in the EXPORT section of the bash. The value is obtained from the &lt;strong&gt;k8guard-action-configmap.yaml&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;strong&gt;k8guard-action-configmap.yaml&lt;/strong&gt; contains the config map for the different variables&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The following environment variables are found inside the &lt;strong&gt;k8guard-action&lt;/strong&gt; container. These values are populated via the .env file&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;export HOME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/root&amp;#39;&lt;/span&gt;export HOSTNAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;k8guard-action-deployment-67c4db498-j4hvd&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_CASSANDRA_CAPATH&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_CASSANDRA_HOSTS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;k8guard-cassandra-service.default.svc.cluster.local:9042&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_CASSANDRA_KEYSPACE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;k8guardkeyspace&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_CASSANDRA_PASSWORD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;cassandra&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_CASSANDRA_SSL_HOST_VALIDATION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;false&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_CASSANDRA_USERNAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;cassandra&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_DRY_RUN&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;false&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_DURATION_BETWEEN_CHAT_NOTIFICATIONS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;30s&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_DURATION_BETWEEN_NOTIFYING_AGAIN&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;24h&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_DURATION_VIOLATION_EXPIRES&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;120h&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_HIPCHAT_BASE_URL&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_HIPCHAT_ROOM_ID&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_HIPCHAT_TAG_NAMESPACE_OWNER&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_HIPCHAT_TOKEN&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;REPLACE_ME&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_SAFE_MODE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_SMTP_FALLBACK_SEND_TO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;REPLACE@REPLACE_WITH_DOMAIN.COM&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_SMTP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;25&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_SMTP_SEND_FROM&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;DO_NOT_REPLY@REPLACE_WITH_DOMAIN.COM&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_SMTP_SEND_TO_NAMESAPCE_OWNER&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_SMTP_SERVER&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_VIOLATION_EMAIL_FOOTER&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;export K8GUARD_ACTION_WARNING_COUNT_BEFORE_ACTION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;4&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_CREATE_KEYSPACE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_CREATE_TABLES&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.99.115.177:9042&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_SERVICE_PORT_9042_TCP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.99.115.177:9042&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_SERVICE_PORT_9042_TCP_ADDR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.99.115.177&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_SERVICE_PORT_9042_TCP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;9042&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_SERVICE_PORT_9042_TCP_PROTO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_SERVICE_SERVICE_HOST&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.99.115.177&amp;#39;&lt;/span&gt;export K8GUARD_CASSANDRA_SERVICE_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;9042&amp;#39;&lt;/span&gt;export K8GUARD_CLUSTER_NAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;minikube&amp;#39;&lt;/span&gt;export K8GUARD_DISCOVER_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.103.122.8:3000&amp;#39;&lt;/span&gt;export K8GUARD_DISCOVER_SERVICE_PORT_3000_TCP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.103.122.8:3000&amp;#39;&lt;/span&gt;export K8GUARD_DISCOVER_SERVICE_PORT_3000_TCP_ADDR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.103.122.8&amp;#39;&lt;/span&gt;export K8GUARD_DISCOVER_SERVICE_PORT_3000_TCP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3000&amp;#39;&lt;/span&gt;export K8GUARD_DISCOVER_SERVICE_PORT_3000_TCP_PROTO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;export K8GUARD_DISCOVER_SERVICE_SERVICE_HOST&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.103.122.8&amp;#39;&lt;/span&gt;export K8GUARD_DISCOVER_SERVICE_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3000&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_ACTION_TOPIC&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;k8guard-to-action-k8s-lab&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_BROKERS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;k8guard-kafka-service.default.svc.cluster.local:9092&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.106.168.209:2181&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_2181_TCP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.106.168.209:2181&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_2181_TCP_ADDR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.106.168.209&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_2181_TCP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2181&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_2181_TCP_PROTO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_9092_TCP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.106.168.209:9092&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_9092_TCP_ADDR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.106.168.209&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_9092_TCP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;9092&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_PORT_9092_TCP_PROTO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_SERVICE_HOST&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.106.168.209&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2181&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_SERVICE_PORT_KAFKA&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;9092&amp;#39;&lt;/span&gt;export K8GUARD_KAFKA_SERVICE_SERVICE_PORT_ZK&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2181&amp;#39;&lt;/span&gt;export K8GUARD_LOG_LEVEL&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;debug&amp;#39;&lt;/span&gt;export K8GUARD_MEMCACHED_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.100.96.55:11211&amp;#39;&lt;/span&gt;export K8GUARD_MEMCACHED_SERVICE_PORT_11211_TCP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.100.96.55:11211&amp;#39;&lt;/span&gt;export K8GUARD_MEMCACHED_SERVICE_PORT_11211_TCP_ADDR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.100.96.55&amp;#39;&lt;/span&gt;export K8GUARD_MEMCACHED_SERVICE_PORT_11211_TCP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;11211&amp;#39;&lt;/span&gt;export K8GUARD_MEMCACHED_SERVICE_PORT_11211_TCP_PROTO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;export K8GUARD_MEMCACHED_SERVICE_SERVICE_HOST&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.100.96.55&amp;#39;&lt;/span&gt;export K8GUARD_MEMCACHED_SERVICE_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;11211&amp;#39;&lt;/span&gt;export K8GUARD_REPORT_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.105.186.144:3001&amp;#39;&lt;/span&gt;export K8GUARD_REPORT_SERVICE_PORT_3001_TCP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.105.186.144:3001&amp;#39;&lt;/span&gt;export K8GUARD_REPORT_SERVICE_PORT_3001_TCP_ADDR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.105.186.144&amp;#39;&lt;/span&gt;export K8GUARD_REPORT_SERVICE_PORT_3001_TCP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3001&amp;#39;&lt;/span&gt;export K8GUARD_REPORT_SERVICE_PORT_3001_TCP_PROTO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;export K8GUARD_REPORT_SERVICE_SERVICE_HOST&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.105.186.144&amp;#39;&lt;/span&gt;export K8GUARD_REPORT_SERVICE_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3001&amp;#39;&lt;/span&gt;export KUBERNETES_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.96.0.1:443&amp;#39;&lt;/span&gt;export KUBERNETES_PORT_443_TCP&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp://10.96.0.1:443&amp;#39;&lt;/span&gt;export KUBERNETES_PORT_443_TCP_ADDR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.96.0.1&amp;#39;&lt;/span&gt;export KUBERNETES_PORT_443_TCP_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;443&amp;#39;&lt;/span&gt;export KUBERNETES_PORT_443_TCP_PROTO&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;export KUBERNETES_SERVICE_HOST&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10.96.0.1&amp;#39;&lt;/span&gt;export KUBERNETES_SERVICE_PORT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;443&amp;#39;&lt;/span&gt;export KUBERNETES_SERVICE_PORT_HTTPS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;443&amp;#39;&lt;/span&gt;export OLDPWD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/var/log&amp;#39;&lt;/span&gt;export PATH&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&amp;#39;&lt;/span&gt;export PWD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/var&amp;#39;&lt;/span&gt;export SHLVL&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;export TERM&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;xterm&amp;#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Minikube Brain Dump (ALWAYS WIP)</title>
       <link>/post/minikubebraindump/</link>
       <pubDate>Sun, 01 Dec 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/minikubebraindump/</guid>
       <description>&lt;ul&gt;&lt;li&gt;Minikube supports lxc where it has it&amp;rsquo;s own Go bindings called libvirt-go.&lt;/li&gt;&lt;li&gt;Internally libvirt-go provides Go binding for different containers as virtualbox, kvm, etc&lt;/li&gt;&lt;li&gt;&lt;p&gt;Minikube uses different way to interact with different containers as outlined below:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;virtualbox&lt;/strong&gt; &amp;ndash; Calling executable /usr/bin/VboxManage&lt;/li&gt;&lt;li&gt;&lt;strong&gt;kvm2&lt;/strong&gt;       &amp;ndash; Calling &lt;em&gt;docker-machine-driver-kvm2&lt;/em&gt; which is part of minikube and can be found under &lt;strong&gt;cmd/drivers/kvm/main.go&lt;/strong&gt;. The code is using the &lt;em&gt;libvirt&lt;/em&gt; to communicate with kvm&lt;/li&gt;&lt;li&gt;&lt;strong&gt;gvisor&lt;/strong&gt; &amp;ndash; there is some sort of dependencies with &lt;em&gt;containerd&lt;/em&gt; and &lt;em&gt;rpc-statd.service&lt;/em&gt; as this both service is restarted when gvisor has been download and successfully copy over (&lt;a href=&#34;https://github.com/kubernetes/minikube/blob/master/deploy/addons/gvisor/README.md&#34;&gt;https://github.com/kubernetes/minikube/blob/master/deploy/addons/gvisor/README.md&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Without specifying the &lt;em&gt;&amp;ndash;vm-driver&lt;/em&gt; parameter by default minikube uses the kvm driver.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To specify specific container runtime to use inside the VM use the following command:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;start --vm-driver&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;kvm2 --container-runtime&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;cri-o --v&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;we can take a look at the kvm running by using &lt;strong&gt;virt-manager&lt;/strong&gt;. Entering into the machine and executing &lt;em&gt;&lt;strong&gt;systemctl status&lt;/strong&gt;&lt;/em&gt;  will yield the following output&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;    ● minikube        State: degraded         Jobs: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; queued       Failed: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; units        Since: Mon &lt;span style=&#34;color:#ae81ff&#34;&gt;2019&lt;/span&gt;-10-28 &lt;span style=&#34;color:#ae81ff&#34;&gt;21&lt;/span&gt;:14:47 UTC; 4min 25s ago       CGroup: /               ├─init.scope               │ └─1 /sbin/init noembed norestore               ├─kubepods               │ ├─besteffort               │ │ ├─pod66fd795f-401c-4181-9cf0-0c2a17663b81               │ │ │ ├─crio-conmon-cb4126fb3d539269743b654879485e5fa5f1d863896783a307fb43f488d29ac5               │ │ │ │ └─3584 /usr/libexec/crio/conmon --syslog -c cb4126fb3d539269743b654879485e5fa5f1d863896783a307fb43f488d29ac5 -n k8s_POD_kube-proxy-plfd2_kube-system_66fd795f-401c-4181-9cf0-0c2a17663b81_0 -u cb4126fb3d539269743b654879485e5fa5f1d863896783a307fb43f488d29ac5 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/cb4126fb3d539269743b654879485e5fa5f1d863896783a307fb43f488d29ac5/userdata -p /var/run/containers/storage/overlay-containers/cb4126fb3d539269743b654879485e5fa5f1d863896783a307fb43f488d29ac5/userdata/pidfile -l /var/log/pods/kube-system_kube-proxy-plfd2_66fd795f-401c-4181-9cf0-0c2a17663b81/cb4126fb3d539269743b654879485e5fa5f1d863896783a307fb43f488d29ac5.log --exit-dir me-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivotath /var/run/crio --log-level debug --runti--More--                │ │ │ ├─crio-cb4126fb3d539269743b654879485e5fa5f1d863896783a307fb43f488d29ac5               │ │ │ │ └─3598 /pause               │ │ │ ├─crio-conmon-f25ed7b9fb31818f0b8ab6d4cb94baead72a124b8915d92145bbb5ce86811ee2               │ │ │ │ └─3616 /usr/libexec/crio/conmon --syslog -c f25ed7b9fb31818f0b8ab6d4cb94baead72a124b8915d92145bbb5ce86811ee2 -n k8s_kube-proxy_kube-proxy-plfd2_kube-system_66fd795f-401c-4181-9cf0-0c2a17663b81_0 -u f25ed7b9fb31818f0b8ab6d4cb94baead72a124b8915d92145bbb5ce86811ee2 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/f25ed7b9fb31818f0b8ab6d4cb94baead72a124b8915d92145bbb5ce86811ee2/userdata -p /var/run/containers/storage/overlay-containers/f25ed7b9fb31818f0b8ab6d4cb94baead72a124b8915d92145bbb5ce86811ee2/userdata/pidfile -l /var/log/pods/kube-system_kube-proxy-plfd2_66fd795f-401c-4181-9cf0-0c2a17663b81/kube-proxy/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │ │ │ └─crio-f25ed7b9fb31818f0b8ab6d4cb94baead72a124b8915d92145bbb5ce86811ee2               │ │ │   └─3626 /usr/local/bin/kube-proxy --config&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/kube-proxy/config.conf --hostname-override&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;minikube               │ │ ├─pod89ae5909ffeb743f1dfb204f25a829e6               │ │ │ ├─crio-conmon-fa20492d16fce683bd7eeeef02b18abdcd46d9418036f70d9cb0764f60178610               │ │ │ │ └─3079 /usr/libexec/crio/conmon --syslog -c fa20492d16fce683bd7eeeef02b18abdcd46d9418036f70d9cb0764f60178610 -n k8s_POD_etcd-minikube_kube-system_89ae5909ffeb743f1dfb204f25a829e6_0 -u fa20492d16fce683bd7eeeef02b18abdcd46d9418036f70d9cb0764f60178610 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/fa20492d16fce683bd7eeeef02b18abdcd46d9418036f70d9cb0764f60178610/userdata -p /var/run/containers/storage/overlay-containers/fa20492d16fce683bd7eeeef02b18abdcd46d9418036f70d9cb0764f60178610/userdata/pidfile -l /var/log/pods/kube-system_etcd-minikube_89ae5909ffeb743f1dfb204f25a829e6/fa20492d16fce683bd7eeeef02b18abdcd46d9418036f70d9cb0764f60178610.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │ │ │ ├─crio-conmon-42866e6955f0f3d8bde90c9235c1da99498469db636e6a8404208473c2fca3d9               │ │ │ │ └─3273 /usr/libexec/crio/conmon --syslog -c 42866e6955f0f3d8bde90c9235c1da99498469db636e6a8404208473c2fca3d9 -n k8s_etcd_etcd-minikube_kube-system_89ae5909ffeb743f1dfb204f25a829e6_0 -u 42866e6955f0f3d8bde90c9235c1da99498469db636e6a8404208473c2fca3d9 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/42866e6955f0f3d8bde90c9235c1da99498469db636e6a8404208473c2fca3d9/userdata -p /var/run/containers/storage/overlay-containers/42866e6955f0f3d8bde90c9235c1da99498469db636e6a8404208473c2fca3d9/userdata/pidfile -l /var/log/pods/kube-system_etcd-minikube_89ae5909ffeb743f1dfb204f25a829e6/etcd/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │ │ │ ├─crio-fa20492d16fce683bd7eeeef02b18abdcd46d9418036f70d9cb0764f60178610               │ │ │ │ └─3136 /pause               │ │ │ └─crio-42866e6955f0f3d8bde90c9235c1da99498469db636e6a8404208473c2fca3d9               │ │ │   └─3327 etcd --advertise-client-urls&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;https://192.168.39.214:2379 --cert-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/server.crt --client-cert-auth&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true --data-dir&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/etcd --initial-advertise-peer-urls&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;https://192.168.39.214:2380 --initial-cluster&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;minikube&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;https://192.168.39.214:2380 --key-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/server.key --listen-client-urls&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;https://127.0.0.1:2379,https://192.168.39.214:2379 --listen-metrics-urls&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;http://127.0.0.1:2381 --listen-peer-urls&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;https://192.168.39.214:2380 --name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;minikube --peer-cert-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/peer.crt --peer-client-cert-auth&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true --peer-key-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/peer.key --peer-trusted-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.crt --snapshot-count&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt; --trusted-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.crt               │ │ └─pod9a1966c7-8565-4aed-8609-04abe6bdf785               │ │   ├─crio-21627aa0b547296c821ae7432cb4ee4ed22f2a9707c833fc6e3563d8faaf6dd9               │ │   │ └─3870 /storage-provisioner               │ │   ├─crio-conmon-ba42f9d76d11545bedcf8b43f19877145bb27efbfee6d11df061b8373bfe61a9    76d11545bedcf8b43f19877145bb27efbfee6d11df061b8373bfe61a9 -n k8s_POD_storage-provisioner_kube-system_9a1966c7-8565-4aed-8609-04abe6bdf785_0 -u ba42f9d76d11545bedcf8b43f19877145bb27efbfee6d11df061b8373bfe61a9 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/ba42f9d76d11545bedcf8b43f19877145bb27efbfee6d11df061b8373bfe61a9/userdata -p /var/run/containers/storage/overlay-containers/ba42f9d76d11545bedcf8b43f19877145bb27efbfee6d11df061b8373bfe61a9/userdata/pidfile -l /var/log/pods/kube-system_storage-provisioner_9a1966c7-8565-4aed-8609-04abe6bdf785/ba42f9d76d11545bedcf8b43f19877145bb27efbfee6d11df061b8373bfe61a9.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │ │   ├─crio-ba42f9d76d11545bedcf8b43f19877145bb27efbfee6d11df061b8373bfe61a9               │ │   │ └─3840 /pause               │ │   └─crio-conmon-21627aa0b547296c821ae7432cb4ee4ed22f2a9707c833fc6e3563d8faaf6dd9               │ │     └─3859 /usr/libexec/crio/conmon --syslog -c 21627aa0b547296c821ae7432cb4ee4ed22f2a9707c833fc6e3563d8faaf6dd9 -n k8s_storage-provisioner_storage-provisioner_kube-system_9a1966c7-8565-4aed-8609-04abe6bdf785_0 -u 21627aa0b547296c821ae7432cb4ee4ed22f2a9707c833fc6e3563d8faaf6dd9 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/21627aa0b547296c821ae7432cb4ee4ed22f2a9707c833fc6e3563d8faaf6dd9/userdata -p /var/run/containers/storage/overlay-ed-8609-04abe6bdf785/storage-provisioner/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │ └─burstable               │   ├─pod67888a6f41348f1a41e319a7f77279a2               │   │ ├─crio-90f7b48799d7f40bf2f81ba9946e74f15afd7348a515ca00b4367b1e208621af               │   │ │ └─3267 kube-controller-manager --authentication-kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/controller-manager.conf --authorization-kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/controller-manager.conf --bind-address&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;127&lt;/span&gt;.0.0.1 --client-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/ca.crt --cluster-signing-cert-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/ca.crt --cluster-signing-key-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/ca.key --controllers&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;*,bootstrapsigner,tokencleaner --kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/controller-manager.conf --leader-elect&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true --requestheader-client-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/front-proxy-ca.crt --root-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/ca.crt --service-account-private-key-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/sa.key --use-service-account-credentials&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true               │   │ ├─crio-conmon-027e7f3d792498b1e54bfb1b6148c4959d2d366a8af64e3ae5d0ac2aba9679df               │   │ │ └─3096 /usr/libexec/crio/conmon --syslog -c 027e7f3d792498b1e54bfb1b6148c4959d2d366a8af64e3ae5d0ac2aba9679df -n k8s_POD_kube-controller-manager-minikube_kube-system_67888a6f41348f1a41e319a7f77279a2_0 -u 027e7f3d792498br/run/containers/storage/overlay-containers/027e7f3d792498b1e54bfb1b6148c4959d2d366a8af64e3ae5d0ac2aba9679df/userdata -p /var/run/containers/storage/overlay-containers/027e7f3d792498b1e54bfb1b6148c4959d2d366a8af64e3ae5d0ac2aba9679df/userdata/pidfile -l /var/log/pods/kube-system_kube-controller-manager-minikube_67888a6f41348f1a41e319a7f77279a2/027e7f3d792498b1e54bfb1b6148c4959d2d366a8af64e3ae5d0ac2aba9679df.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ ├─crio-conmon-90f7b48799d7f40bf2f81ba9946e74f15afd7348a515ca00b4367b1e208621af               │   │ │ └─3249 /usr/libexec/crio/conmon --syslog -c 90f7b48799d7f40bf2f81ba9946e74f15afd7348a515ca00b4367b1e208621af -n k8s_kube-controller-manager_kube-controller-manager-minikube_kube-system_67888a6f41348f1a41e319a7f77279a2_0 -u 90f7b48799d7f40bf2f81ba9946e74f15afd7348a515ca00b4367b1e208621af -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/90f7b48799d7f40bf2f81ba9946e74f15afd7348a515ca00b4367b1e208621af/userdata -p /var/run/containers/storage/overlay-containers/90f7b48799d7f40bf2f81ba9946e74f15afd7348a515ca00b4367b1e208621af/userdata/pidfile -l /var/log/pods/kube-system_kube-controller-manager-minikube_67888a6f41348f1a41e319a7f77279a2/kube-controller-manager/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ └─crio-027e7f3d792498b1e54bfb1b6148c4959d2d366a8af64e3ae5d0ac2aba9679df               │   │   └─3158 /pause               │   ├─pod288cbfbd5565f92cc63b18bcafb084d5               │   │ ├─crio-conmon-8fedc929a6c2f817e0c7855d588f6aa6a0db7e0bd5df4a7e3baa24ea8ccd0851               │   │ │ └─3217 /usr/libexec/crio/conmon --syslog -c 8fedc929a6c2f817e0c7855d588f6aa6a0db7e0bd5df4a7e3baa24ea8ccd0851 -n k8s_kube-apiserver_kube-apiserver-minikube_kube-system_288cbfbd5565f92cc63b18bcafb084d5_0 -u 8fedc929a6c2f817e0c7855d588f6aa6a0db7e0bd5df4a7e3baa24ea8ccd0851 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/8fedc929a6c2f817e0c7855d588f6aa6a0db7e0bd5df4a7e3baa24ea8ccd0851/userdata -p /var/run/containers/storage/overlay-containers/8fedc929a6c2f817e0c7855d588f6aa6a0db7e0bd5df4a7e3baa24ea8ccd0851/userdata/pidfile -l /var/log/pods/kube-system_kube-apiserver-minikube_288cbfbd5565f92cc63b18bcafb084d5/kube-apiserver/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ ├─crio-8fedc929a6c2f817e0c7855d588f6aa6a0db7e0bd5df4a7e3baa24ea8ccd0851               │   │ │ └─3228 kube-apiserver --advertise-address&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;192&lt;/span&gt;.168.39.214 --allow-privileged&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true --authorization-mode&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;Node,RBAC --client-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/ca.crt --enable-admission-plugins&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota --enable-bootstrap-token-auth&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true --etcd-cafile&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.crt --etcd-cerlib/minikube/certs/apiserver-etcd-client.key --etcd-servers&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;https://127.0.0.1:2379 --insecure-port&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; --kubelet-client-certificate&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/apiserver-kubelet-client.crt --kubelet-client-key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/apiserver-kubelet-client.key --kubelet-preferred-address-types&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;InternalIP,ExternalIP,Hostname --proxy-client-cert-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/front-proxy-client.crt --proxy-client-key-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/front-proxy-client.key --requestheader-allowed-names&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;front-proxy-client --requestheader-client-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/front-proxy-ca.crt --requestheader-extra-headers-prefix&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;X-Remote-Extra- --requestheader-group-headers&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;X-Remote-Group --requestheader-username-headers&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;X-Remote-User --secure-port&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;8443&lt;/span&gt; --service-account-key-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/sa.pub --service-cluster-ip-range&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;.96.0.0/12 --tls-cert-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/apiserver.crt --tls-private-key-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/apiserver.key               │   │ ├─crio-conmon-da45f694e1afffe3d6cbd945e96f9798b34a728243ecd5232fc329f64446bd2d               │   │ │ └─3093 /usr/libexec/crio/conmon --syslog -c da45f694e1afffe3d6cbd945e96f9798b34a728243ecd5232fc329f64446bd2d -n k8s_POD_kube-apiserver-minikube_kube-system_288cbfbd5565f92cc63b18bcafb084d5_0 -u da45f694e1afffe3d6cbd945e96f9798b34a728243ecd5232fc329f64446bd2d -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/da45f694e1afffe3d6cbd945e96f9798b34a728243ecd5232fc329f64446bd2d/userdata -p /var/run/containers/storage/overlay-containers/da45fb084d5/da45f694e1afffe3d6cbd945e96f9798b34a728243ecd5232fc329f64446bd2d.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ └─crio-da45f694e1afffe3d6cbd945e96f9798b34a728243ecd5232fc329f64446bd2d               │   │   └─3124 /pause               │   ├─pod74dea8da17aa6241e5e4f7b2ba4e1d8e               │   │ ├─crio-993cc803be23925d62509f515bf2b3c82defd9c6aaf02ffdfb66f14764396799               │   │ │ └─3302 kube-scheduler --authentication-kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/scheduler.conf --authorization-kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/scheduler.conf --bind-address&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;127&lt;/span&gt;.0.0.1 --kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/scheduler.conf --leader-elect&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true               │   │ ├─crio-conmon-42954baf61955ccb20af54ca4ceb0d29e04c1661a7252c1555aeaa64b75da42f               │   │ │ └─3110 /usr/libexec/crio/conmon --syslog -c 42954baf61955ccb20af54ca4ceb0d29e04c1661a7252c1555aeaa64b75da42f -n k8s_POD_kube-scheduler-minikube_kube-system_74dea8da17aa6241e5e4f7b2ba4e1d8e_0 -u 42954baf61955ccb20af54ca4ceb0d29e04c1661a7252c1555aeaa64b75da42f -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/42954baf61955ccb20af54ca4ceb0d29e04c1661a7252c1555aeaa64b75da42f/userdata -p /var/run/containers/storage/overlay-containers/429544e1d8e/42954baf61955ccb20af54ca4ceb0d29e04c1661a7252c1555aeaa64b75da42f.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ ├─crio-42954baf61955ccb20af54ca4ceb0d29e04c1661a7252c1555aeaa64b75da42f               │   │ │ └─3147 /pause               │   │ └─crio-conmon-993cc803be23925d62509f515bf2b3c82defd9c6aaf02ffdfb66f14764396799               │   │   └─3278 /usr/libexec/crio/conmon --syslog -c 993cc803be23925d62509f515bf2b3c82defd9c6aaf02ffdfb66f14764396799 -n k8s_kube-scheduler_kube-scheduler-minikube_kube-system_74dea8da17aa6241e5e4f7b2ba4e1d8e_0 -u 993cc803be23925d62509f515bf2b3c82defd9c6aaf02ffdfb66f14764396799 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/993cc803be23925d62509f515bf2b3c82defd9c6aaf02ffdfb66f14764396799/userdata -p /var/run/containers/storage/overlay-containers/993cc803be23925d62509f515bf2b3c82defd9c6aaf02ffdfb66f14764396799/userdata/pidfile -l /var/log/pods/kube-system_kube-scheduler-minikube_74dea8da17aa6241e5e4f7b2ba4e1d8e/kube-scheduler/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   ├─poda551ce90-e9ae-412e-b777-2a622a41b3d1               │   │ ├─crio-42bf005600a5ce7b8b99d371a69fbd64bba8fcd112972ef43a7ee5d71ca18897               │   │ │ └─3739 /pause    06708faeafa70077d626278-conmon-0c70b067f98ddadd639a90b776e6947a7d083b66a--More--                │   │ │ └─3915 /usr/libexec/crio/conmon --syslog -c 0c70b067f98ddadd639a90b776e6947a7d083b66a06708faeafa70077d626278 -n k8s_coredns_coredns-5644d7b6d9-lgt6b_kube-system_a551ce90-e9ae-412e-b777-2a622a41b3d1_0 -u 0c70b067f98ddadd639a90b776e6947a7d083b66a06708faeafa70077d626278 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/0c70b067f98ddadd639a90b776e6947a7d083b66a06708faeafa70077d626278/userdata -p /var/run/containers/storage/overlay-containers/0c70b067f98ddadd639a90b776e6947a7d083b66a06708faeafa70077d626278/userdata/pidfile -l /var/log/pods/kube-system_coredns-5644d7b6d9-lgt6b_a551ce90-e9ae-412e-b777-2a622a41b3d1/coredns/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ ├─crio-0c70b067f98ddadd639a90b776e6947a7d083b66a06708faeafa70077d626278               │   │ │ └─3926 /coredns -conf /etc/coredns/Corefile               │   │ └─crio-conmon-42bf005600a5ce7b8b99d371a69fbd64bba8fcd112972ef43a7ee5d71ca18897               │   │   └─3714 /usr/libexec/crio/conmon --syslog -c 42bf005600a5ce7b8b99d371a69fbd64bba8fcd112972ef43a7ee5d71ca18897 -n k8s_POD_coredns-5644d7b6d9-lgt6b_kube-system_a551ce90-e9ae-412e-b777-2a622a41b3d1_0 -u 42bf005600a5ce7b8b99d371a69fbd64bba8fcd112972ef43a7ee5d71ca18897 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/42bf005600a5ce7b8b99d371a69fbd64bba8fcd112972ef43a7ee5d71ca18897/userdata -p /var/run/containers/storage/overlay-containers/ile -l /var/log/pods/kube-system_coredns-5644d7b6d9-lgt6b_a551ce90-e9ae-412e-b777-2a622a41b3d1/42bf005600a5ce7b8b99d371a69fbd64bba8fcd112972ef43a7ee5d71ca18897.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   ├─podc3e29047da86ce6690916750ab69c40b               │   │ ├─crio-conmon-0a85d1a6edd833057f8537f9195fb1aebb0273febb33790a996b58b64cb9bf50               │   │ │ └─3061 /usr/libexec/crio/conmon --syslog -c 0a85d1a6edd833057f8537f9195fb1aebb0273febb33790a996b58b64cb9bf50 -n k8s_POD_kube-addon-manager-minikube_kube-system_c3e29047da86ce6690916750ab69c40b_0 -u 0a85d1a6edd833057f8537f9195fb1aebb0273febb33790a996b58b64cb9bf50 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/0a85d1a6edd833057f8537f9195fb1aebb0273febb33790a996b58b64cb9bf50/userdata -p /var/run/containers/storage/overlay-containers/0a85d1a6edd833057f8537f9195fb1aebb0273febb33790a996b58b64cb9bf50/userdata/pidfile -l /var/log/pods/kube-system_kube-addon-manager-minikube_c3e29047da86ce6690916750ab69c40b/0a85d1a6edd833057f8537f9195fb1aebb0273febb33790a996b58b64cb9bf50.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ ├─crio-conmon-5935820f335661c4ce86e9ef5f97a910b0958f942b2673cf224ee7b80b0c15f2               │   │ │ └─3416 /usr/libexec/crio/conmon --syslog -c 5935820f335661c4ce86e9ef5f97a910b0958f942b2673cf224ee7b80b0c15f2 -n k8s_kube-addon-manager_kube-addon-manager-minikube_kube-system_c3e29047da86ce6690916750ab69c40b_0 ---More-u 5935820f335661c4ce86e9ef5f97a910b0958f942b2673cf224ee7b80b0c15f2 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/5935820f335661c4ce86e9ef5f97a910b0958f942b2673cf224ee7b80b0c15f2/userdata -p /var/run/containers/storage/overlay-containers/5935820f335661c4ce86e9ef5f97a910b0958f942b2673cf224ee7b80b0c15f2/userdata/pidfile -l /var/log/pods/kube-system_kube-addon-manager-minikube_c3e29047da86ce6690916750ab69c40b/kube-addon-manager/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │   │ ├─crio-0a85d1a6edd833057f8537f9195fb1aebb0273febb33790a996b58b64cb9bf50               │   │ │ └─3072 /pause               │   │ └─crio-5935820f335661c4ce86e9ef5f97a910b0958f942b2673cf224ee7b80b0c15f2               │   │   ├─3427 bash /opt/kube-addons.sh               │   │   └─5230 sleep &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;               │   └─poddd190f17-7822-4345-9141-22a797802e0f               │     ├─crio-conmon-1759f8374de60691c19247b1f93dab3f4c42b25e744c8350001de00524a7e059               │     │ └─3724 /usr/libexec/crio/conmon --syslog -c 1759f8374de60691c19247b1f93dab3f4c42b25e744c8350001de00524a7e059 -n k8s_POD_coredns-5644d7b6d9-26x6p_kube-system_dd190f17-7822-4345-9141-22a797802e0f_0 -u 1759f8374de60691c194c8350001de00524a7e059/userdata -p /var/run/containers/storage/overlay-containers/1759f8374de60691c19247b1f93dab3f4c42b25e744c8350001de00524a7e059/userdata/pidfile -l /var/log/pods/kube-system_coredns-5644d7b6d9-26x6p_dd190f17-7822-4345-9141-22a797802e0f/1759f8374de60691c19247b1f93dab3f4c42b25e744c8350001de00524a7e059.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │     ├─crio-conmon-892f3d3545ee21ad95a171ae77636fe40c3983f0566d1439939a04430d64adb0               │     │ └─3969 /usr/libexec/crio/conmon --syslog -c 892f3d3545ee21ad95a171ae77636fe40c3983f0566d1439939a04430d64adb0 -n k8s_coredns_coredns-5644d7b6d9-26x6p_kube-system_dd190f17-7822-4345-9141-22a797802e0f_0 -u 892f3d3545ee21ad95a171ae77636fe40c3983f0566d1439939a04430d64adb0 -r /usr/bin/runc -b /var/run/containers/storage/overlay-containers/892f3d3545ee21ad95a171ae77636fe40c3983f0566d1439939a04430d64adb0/userdata -p /var/run/containers/storage/overlay-containers/892f3d3545ee21ad95a171ae77636fe40c3983f0566d1439939a04430d64adb0/userdata/pidfile -l /var/log/pods/kube-system_coredns-5644d7b6d9-26x6p_dd190f17-7822-4345-9141-22a797802e0f/coredns/0.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level debug --runtime-arg --root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/run/runc --no-pivot               │     ├─crio-1759f8374de60691c19247b1f93dab3f4c42b25e744c8350001de00524a7e059               │     │ └─3760 /pause               │     └─crio-892f3d3545ee21ad95a171ae77636fe40c3983f0566d1439939a04430d64adb0               │       └─3980 /coredns -conf /etc/coredns/Corefile               └─system.slice                 ├─nfs-mountd.service                 │ └─1660 /usr/sbin/rpc.mountd                 ├─systemd-timesyncd.service                 │ └─1636 /usr/lib/systemd/systemd-timesyncd                 ├─crio.service                 │ └─2049 /usr/bin/crio --log-level&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;debug --insecure-registry &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;.96.0.0/12                 ├─dbus.service                 │ └─1685 /usr/bin/dbus-daemon --system --address&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;systemd: --nofork --nopidfile --systemd-activation --syslog-only                 ├─sshd.service                 │ └─1770 /usr/sbin/sshd -D -e                 ├─kubelet.service                 │ └─3011 /var/lib/minikube/binaries/v1.16.2/kubelet --authorization-mode&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;Webhook --bootstrap-kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;cgroupfs --client-ca-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/ca.crt --cluster-dns&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;.96.0.10 --cluster-domain&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;cluster.local --container-runtime&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;remote --container-runtime-endpoint&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/run/crio/crio.sock --fail-swap-on&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;false --hostname-override&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;minikube --image-service-endpoint&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/run/crio/crio.sock --kubeconfig&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/kubelet.conf --network-plugin&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;cni --node-ip&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;192&lt;/span&gt;.168.39.214 --pod-manifest-path&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/etc/kubernetes/manifests --runtime-request-timeout&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;15m                 ├─system-serial&lt;span style=&#34;color:#ae81ff&#34;&gt;\x&lt;/span&gt;2dgetty.slice                 │ └─serial-getty@ttyS0.service                 │   ├─1678 -sh                 │   ├─5263 systemctl status                 │   └─5264 /bin/more                 ├─system-getty.slice                 │ └─getty@tty1.service                 │   └─1679 /sbin/getty -L tty1 &lt;span style=&#34;color:#ae81ff&#34;&gt;115200&lt;/span&gt; vt100                 ├─rpcbind.service                 │ └─1677 /usr/bin/rpcbind                 ├─systemd-logind.service                 │ └─1688 /usr/lib/systemd/systemd-logind                 ├─systemd-resolved.service                 │ └─1656 /usr/lib/systemd/systemd-resolved                 ├─systemd-udevd.service                 │ └─1640 /usr/lib/systemd/systemd-udevd                 ├─systemd-journald.service                 │ └─1093 /usr/lib/systemd/systemd-journald                 └─systemd-networkd.service                   └─1649 /usr/lib/systemd/systemd-networkd    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;When running &lt;em&gt;cri-o&lt;/em&gt; container use the following command to view images&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;crictl images&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;IMAGE                                     TAG                 IMAGE ID            SIZEgcr.io/k8s-minikube/storage-provisioner   v1.8.1              4689081edb103       &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;.8MBk8s.gcr.io/coredns                        &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;.6.2               bf261d1579144       &lt;span style=&#34;color:#ae81ff&#34;&gt;44&lt;/span&gt;.2MBk8s.gcr.io/etcd                           &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;.3.15-0            b2756210eeabf       248MBk8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64    &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;.14.13             6dc8ef8287d38       &lt;span style=&#34;color:#ae81ff&#34;&gt;41&lt;/span&gt;.6MBk8s.gcr.io/k8s-dns-kube-dns-amd64         &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;.14.13             55a3c5209c5ea       &lt;span style=&#34;color:#ae81ff&#34;&gt;51&lt;/span&gt;.4MBk8s.gcr.io/k8s-dns-sidecar-amd64          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;.14.13             4b2e93f0133d3       &lt;span style=&#34;color:#ae81ff&#34;&gt;43&lt;/span&gt;.1MBk8s.gcr.io/kube-addon-manager             v9.0                119701e77cbc4       &lt;span style=&#34;color:#ae81ff&#34;&gt;84&lt;/span&gt;.7MBk8s.gcr.io/kube-addon-manager             v9.0.2              bd12a212f9dcb       &lt;span style=&#34;color:#ae81ff&#34;&gt;84&lt;/span&gt;.7MBk8s.gcr.io/kube-apiserver                 v1.16.2             c2c9a0406787c       219MBk8s.gcr.io/kube-controller-manager        v1.16.2             6e4bffa46d70b       165MBk8s.gcr.io/kube-proxy                     v1.16.2             8454cbe08dc9f       &lt;span style=&#34;color:#ae81ff&#34;&gt;87&lt;/span&gt;.9MBk8s.gcr.io/kube-scheduler                 v1.16.2             ebac1ae204a2c       &lt;span style=&#34;color:#ae81ff&#34;&gt;88&lt;/span&gt;.8MBk8s.gcr.io/kubernetes-dashboard-amd64     v1.10.1             f9aed6605b814       122MBk8s.gcr.io/pause                          &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;.1                 da86e6ba6ca19       747kB&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;and to view running container use the following command:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;crictl  ps&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;CONTAINER           IMAGE                                                                                                   CREATED             STATE               NAME                      ATTEMPT             POD ID892f3d3545ee2       bf261d157914477ee1a5969d28ec687f3fbfc9fb5a664b22df78e57023b0e03b                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; minutes ago       Running             coredns                   &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   1759f8374de600c70b067f98dd       bf261d157914477ee1a5969d28ec687f3fbfc9fb5a664b22df78e57023b0e03b                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; minutes ago       Running             coredns                   &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   42bf005600a5c21627aa0b5472       4689081edb103a9e8174bf23a255bfbe0b2d9ed82edc907abab6989d1c60f02c                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; minutes ago       Running             storage-provisioner       &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   ba42f9d76d115f25ed7b9fb318       8454cbe08dc9ff820283939d1e509af7746256a3fc0511999c7e29ed8f29f852                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; minutes ago       Running             kube-proxy                &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   cb4126fb3d5395935820f33566       k8s.gcr.io/kube-addon-manager@sha256:3e315022a842d782a28e729720f21091dde21f1efea28868d65ec595ad871616   &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; minutes ago       Running             kube-addon-manager        &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   0a85d1a6edd8342866e6955f0f       b2756210eeabf84f3221da9959e9483f3919dc2aaab4cd45e7cd072fcbde27ed                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; minutes ago       Running             etcd                      &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   fa20492d16fce993cc803be239       ebac1ae204a2c8d36411792d8bfea34bc82bd733b499ff81ca10e0f6c082d44c                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; minutes ago       Running             kube-scheduler            &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   42954baf6195590f7b48799d7f       6e4bffa46d70bb06f05f9e32d9f73511fe59c0dcd85aa25a56e651c1250b4777                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; minutes ago       Running             kube-controller-manager   &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   027e7f3d792498fedc929a6c2f       c2c9a0406787cbb6b206d082f1085215e9b0c98483b6e3dba3d0df6d4653e7b0                                        &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; minutes ago       Running             kube-apiserver            &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;                   da45f694e1aff&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Few examples available from client-go project that helped to play around with minikube &lt;strong&gt;&lt;em&gt;client-go/examples/&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;JSON structure for Kubernetes can be found inside &lt;strong&gt;k8s.io/kubernetes/staging/src/k8s.io/api/core/v1/types.go&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Testing&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Test cases uses a lot of &amp;lsquo;fake&amp;rsquo; classes that are made available inside &lt;strong&gt;k8s.io/client-go/kubernetes/typed/core/v1/fake&lt;/strong&gt; folder&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;For example to access a pod&amp;rsquo;s log use the following command&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;curl -k --cert ~/.minikube/apiserver.crt --key ~/.minikube/apiserver.key  -v -XGET https://192.168.99.223:8443/api/v1/namespaces/default/pods/demo-788cf8d6f5-6d6qz/log&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;pkg/minikube/service/service.go&lt;/strong&gt;  &amp;ndash;  contains code to connect to kubernetes&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;K8sClient&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; {    &lt;span style=&#34;color:#a6e22e&#34;&gt;GetCoreClient&lt;/span&gt;() (&lt;span style=&#34;color:#a6e22e&#34;&gt;typed_core&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;CoreV1Interface&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;GetClientset&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;timeout&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Duration&lt;/span&gt;) (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;kubernetes&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Clientset&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;)}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To communicate with etcd that is running inside minikube we need to ssh to minikube&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;minikube ssh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Inside minikube we use the following command&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;/hosthome/nanik/Downloads/temp/packages/src/go.etcd.io/etcd/etcdctl/etcdctl --cacert&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.crt --key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.key --cert&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.crt get  --prefix&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;the ca.crt and ca.key resides inside minikube VM&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;    ETCDCTL_API&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;  /hosthome/nanik/Downloads/temp/packages/src/go.etcd.io/etcd/etcdctl/etcdctl --cacert&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.crt --key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.key --cert&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/minikube/certs/etcd/ca.crt get  --from-key &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; --keys-only     &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;will get all the keys stored inside&lt;/p&gt;&lt;p&gt;&lt;strong&gt;/hostname&lt;/strong&gt; &amp;ndash; is the default mount volume created by minikube to access host directory.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&amp;gt;/registry/apiregistration.k8s.io/apiservices/v1&amp;gt;/apiregistration.k8s.io/apiservices/v1.admissionregistration.k8s.io&amp;gt;/apiregistration.k8s.io/apiservices/v1.apiextensions.k8s.io&amp;gt;/apiregistration.k8s.io/apiservices/v1.apps&amp;gt;/apiregistration.k8s.io/apiservices/v1.authentication.k8s.io&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Minikube Integration Testing (Work in progress)</title>
       <link>/post/minikubeintegrationtesting/</link>
       <pubDate>Sun, 01 Dec 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/minikubeintegrationtesting/</guid>
       <description>&lt;p&gt;This article will outline few things that are helpful when running or modifying minikube testing code.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Make sure &lt;strong&gt;kubectl&lt;/strong&gt; is in the PATH&lt;/li&gt;&lt;li&gt;&lt;p&gt;Following command is to disable parallel testing and enable all log output&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;-parallel 1  -test.v&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;the &lt;strong&gt;test.v&lt;/strong&gt; parameter instruct the testing framework to output non-failure messages. The output will not be realtime as it will only be outputted when the test complete.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To run the test use the following command&lt;br /&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;PATH=/home/nanik/Golang/go/bin:/home/nanik/Downloads:/home/nanik/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/var/lib/snapd/snap/bin:/home/nanik/Downloads/ go test   -test.v -tags integration&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;The &lt;strong&gt;/home/nanik/Downloads&lt;/strong&gt; is added to the PATH because that&amp;rsquo;s the location for kubectl and the test cases uses kubectl.&lt;/p&gt;&lt;p&gt;DO NOT USE &lt;em&gt;&lt;strong&gt;-parrallel 1&lt;/strong&gt;&lt;/em&gt; when running ALL the test cases as for some reason it throws an error.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Running &lt;strong&gt;make integration&lt;/strong&gt; command will yield output similar to the following&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;GOOS=&amp;#34;linux&amp;#34; GOARCH=&amp;#34;amd64&amp;#34; go build -tags &amp;#34;container_image_ostree_stub containers_image_openpgp go_getter_nos3 go_getter_nogcs&amp;#34; -ldflags=&amp;#34;-X k8s.io/minikube/pkg/version.version=v1.5.2 -X k8s.io/minikube/pkg/version.isoVersion=v1.5.1 -X k8s.io/minikube/pkg/version.isoPath=minikube/iso -X k8s.io/minikube/pkg/version.gitCommitID=&amp;#34;3322c50ceb4abf795ebb8505f99bbb269a144e21-dirty&amp;#34;&amp;#34; -a -o out/minikube-linux-amd64 k8s.io/minikube/cmd/minikubecp out/minikube-linux-amd64 out/minikubego test -v -test.timeout=60m ./test/integration --tags=&amp;#34;integration container_image_ostree_stub containers_image_openpgp go_getter_nos3 go_getter_nogcs&amp;#34; === RUN   TestDownloadOnly=== RUN   TestDownloadOnly/group=== RUN   TestDownloadOnly/group/v1.11.10=== RUN   TestDownloadOnly/group/v1.16.2=== RUN   TestDownloadOnly/group/v1.16.2#01=== RUN   TestDownloadOnly/group/ExpectedDefaultDriver=== RUN   TestDownloadOnly/group/DeleteAll=== RUN   TestDownloadOnly/group/DeleteAlwaysSucceeds--- PASS: TestDownloadOnly (33.63s)    --- PASS: TestDownloadOnly/group (33.57s)        --- PASS: TestDownloadOnly/group/v1.11.10 (19.74s)            a_serial_test.go:61: (dbg) Run:  out/minikube start --download-only -p download-20191104T082052.238721463-18873 --force --alsologtostderr --kubernetes-version=v1.11.10            a_serial_test.go:61: (dbg) Done: out/minikube start --download-only -p download-20191104T082052.238721463-18873 --force --alsologtostderr --kubernetes-version=v1.11.10: (19.741382231s)        --- PASS: TestDownloadOnly/group/v1.16.2 (13.46s)            a_serial_test.go:63: (dbg) Run:  out/minikube start --download-only -p download-20191104T082052.238721463-18873 --force --alsologtostderr --kubernetes-version=v1.16.2            a_serial_test.go:63: (dbg) Done: out/minikube start --download-only -p download-20191104T082052.238721463-18873 --force --alsologtostderr --kubernetes-version=v1.16.2: (13.460844164s)        --- PASS: TestDownloadOnly/group/v1.16.2#01 (0.27s)            a_serial_test.go:63: (dbg) Run:  out/minikube start --download-only -p download-20191104T082052.238721463-18873 --force --alsologtostderr --kubernetes-version=v1.16.2        --- SKIP: TestDownloadOnly/group/ExpectedDefaultDriver (0.00s)            a_serial_test.go:94: --expected-default-driver is unset, skipping test        --- PASS: TestDownloadOnly/group/DeleteAll (0.06s)            a_serial_test.go:124: (dbg) Run:  out/minikube delete --all        --- PASS: TestDownloadOnly/group/DeleteAlwaysSucceeds (0.03s)            a_serial_test.go:134: (dbg) Run:  out/minikube delete -p download-20191104T082052.238721463-18873    helpers.go:167: (dbg) Run:  out/minikube delete -p download-20191104T082052.238721463-18873=== RUN   TestAddons=== PAUSE TestAddons=== RUN   TestDockerFlags=== PAUSE TestDockerFlags=== RUN   TestKVMDriverInstallOrUpdate=== PAUSE TestKVMDriverInstallOrUpdate=== RUN   TestHyperKitDriverInstallOrUpdate--- SKIP: TestHyperKitDriverInstallOrUpdate (0.00s)    driver_install_or_update_test.go:101: Skip if not darwin.=== RUN   TestFunctional=== RUN   TestFunctional/serial=== RUN   TestFunctional/serial/StartWithProxy=== RUN   TestFunctional/serial/KubeContext=== RUN   TestFunctional/serial/KubectlGetPods=== RUN   TestFunctional/serial/CacheCmd=== PAUSE TestFunctional=== RUN   TestGvisorAddon--- SKIP: TestGvisorAddon (0.00s)    gvisor_addon_test.go:34: skipping test because --gvisor=false=== RUN   TestChangeNoneUser--- SKIP: TestChangeNoneUser (0.00s)    none_test.go:39: Only test none driver.=== RUN   TestStartStop=== PAUSE TestStartStop=== RUN   TestVersionUpgrade=== PAUSE TestVersionUpgrade=== CONT  TestAddons=== CONT  TestStartStop=== CONT  TestFunctional=== CONT  TestVersionUpgrade=== CONT  TestDockerFlags=== RUN   TestFunctional/parallel=== CONT  TestKVMDriverInstallOrUpdate=== RUN   TestFunctional/parallel/AddonManager=== RUN   TestStartStop/group=== PAUSE TestFunctional/parallel/AddonManager=== RUN   TestFunctional/parallel/ComponentHealth=== PAUSE TestFunctional/parallel/ComponentHealth=== RUN   TestStartStop/group/docker=== RUN   TestFunctional/parallel/ConfigCmd=== PAUSE TestFunctional/parallel/ConfigCmd=== RUN   TestFunctional/parallel/DashboardCmd=== PAUSE TestStartStop/group/docker=== RUN   TestStartStop/group/cni=== PAUSE TestFunctional/parallel/DashboardCmd=== RUN   TestFunctional/parallel/DNS=== PAUSE TestStartStop/group/cni=== PAUSE TestFunctional/parallel/DNS=== RUN   TestStartStop/group/containerd=== RUN   TestFunctional/parallel/StatusCmd=== PAUSE TestFunctional/parallel/StatusCmd=== PAUSE TestStartStop/group/containerd=== RUN   TestFunctional/parallel/LogsCmd=== RUN   TestStartStop/group/crio=== PAUSE TestFunctional/parallel/LogsCmd=== RUN   TestFunctional/parallel/MountCmd=== PAUSE TestStartStop/group/crio=== CONT  TestStartStop/group/docker=== PAUSE TestFunctional/parallel/MountCmd=== CONT  TestStartStop/group/containerd=== RUN   TestFunctional/parallel/ProfileCmd=== CONT  TestStartStop/group/crio=== CONT  TestStartStop/group/cni=== PAUSE TestFunctional/parallel/ProfileCmd=== RUN   TestFunctional/parallel/ServiceCmd=== PAUSE TestFunctional/parallel/ServiceCmd=== RUN   TestFunctional/parallel/AddonsCmd=== PAUSE TestFunctional/parallel/AddonsCmd=== RUN   TestFunctional/parallel/PersistentVolumeClaim=== PAUSE TestFunctional/parallel/PersistentVolumeClaim=== RUN   TestFunctional/parallel/TunnelCmd=== PAUSE TestFunctional/parallel/TunnelCmd=== RUN   TestFunctional/parallel/SSHCmd=== PAUSE TestFunctional/parallel/SSHCmd=== RUN   TestFunctional/parallel/MySQL=== PAUSE TestFunctional/parallel/MySQL=== CONT  TestFunctional/parallel/AddonManager=== CONT  TestFunctional/parallel/MySQL=== CONT  TestFunctional/parallel/MountCmd=== CONT  TestFunctional/parallel/DNS    &amp;gt; docker-machine-driver-kvm2.sha256: 65 B / 65 B [-------] 100.00% ? p/s 0s=== CONT  TestFunctional/parallel/ConfigCmd=== CONT  TestFunctional/parallel/DashboardCmd=== CONT  TestFunctional/parallel/LogsCmd=== CONT  TestFunctional/parallel/ComponentHealth=== CONT  TestFunctional/parallel/StatusCmd=== CONT  TestFunctional/parallel/PersistentVolumeClaim    &amp;gt; docker-machine-driver-kvm2: 0 B / 48.57 MiB [_____________] 0.00% ? p/s ?    &amp;gt; docker-machine-driver-kvm2: 33.55 KiB / 48.57 MiB [&amp;gt;______] 0.07% ? p/s ?    &amp;gt; docker-machine-driver-kvm2: 84.55 KiB / 48.57 MiB [&amp;gt;______] 0.17% ? p/s ?    &amp;gt; docker-machine-driver-kvm2: 169.55 KiB / 48.57 MiB  0.34% 282.61 KiB p/s     &amp;gt; docker-machine-driver-kvm2: 169.55 KiB / 48.57 MiB  0.34% 282.61 KiB p/s     &amp;gt; docker-machine-driver-kvm2: 338.52 KiB / 48.57 MiB  0.68% 282.61 KiB p/s     &amp;gt; docker-machine-driver-kvm2: 662.55 KiB / 48.57 MiB  1.33% 317.38 KiB p/s === CONT  TestFunctional/parallel/SSHCmd    &amp;gt; docker-machine-driver-kvm2: 662.55 KiB / 48.57 MiB  1.33% 317.38 KiB p/s === CONT  TestFunctional/parallel/TunnelCmd=== CONT  TestFunctional/parallel/ServiceCmd    &amp;gt; docker-machine-driver-kvm2: 1.31 MiB / 48.57 MiB  2.70% 317.38 KiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 2.13 MiB / 48.57 MiB  4.38% 459.99 KiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 2.30 MiB / 48.57 MiB  4.74% 459.99 KiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 3.35 MiB / 48.57 MiB  6.89% 459.99 KiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 4.44 MiB / 48.57 MiB  9.14% 684.97 KiB p/s ET    &amp;gt;      &amp;gt; .....    &amp;gt; .....=== CONT  TestFunctional/parallel/AddonsCmd=== CONT  TestFunctional/parallel/ProfileCmd    &amp;gt; docker-machine-driver-kvm2: 21.21 MiB / 48.57 MiB  43.66% 1.86 MiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 21.21 MiB / 48.57 MiB  43.66% 2.08 MiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 22.78 MiB / 48.57 MiB  46.91% 2.08 MiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 23.35 MiB / 48.57 MiB  48.06% 2.08 MiB p/s ET    &amp;gt; docker-machine-driver-kvm2: 24.91 MiB / 48.57 MiB  51.28% 2.34 MiB p/s ET        &amp;gt; .....     &amp;gt; .....     &amp;gt; .....    2019/11/04 08:25:30 [DEBUG] GET http://192.168.39.24:318492019/11/04 08:25:38 [DEBUG] GET http://127.0.0.1:38193/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/--- PASS: TestFunctional (254.26s)    --- PASS: TestFunctional/serial (206.43s)        --- PASS: TestFunctional/serial/StartWithProxy (177.80s)            functional_test.go:120: (dbg) Run:  out/minikube start -p functional-20191104T082125.872658733-18873 --wait=false             functional_test.go:120: (dbg) Done: out/minikube start -p functional-20191104T082125.872658733-18873 --wait=false : (2m57.799561087s)        --- PASS: TestFunctional/serial/KubeContext (0.05s)            functional_test.go:138: (dbg) Run:  kubectl config current-context        --- PASS: TestFunctional/serial/KubectlGetPods (0.44s)            functional_test.go:149: (dbg) Run:  kubectl get pod -A        --- PASS: TestFunctional/serial/CacheCmd (28.14s)            functional_test.go:302: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 cache add busybox            functional_test.go:302: (dbg) Done: out/minikube -p functional-20191104T082125.872658733-18873 cache add busybox: (5.119077944s)            functional_test.go:302: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 cache add busybox:1.28.4-glibc            functional_test.go:302: (dbg) Done: out/minikube -p functional-20191104T082125.872658733-18873 cache add busybox:1.28.4-glibc: (5.002939096s)            functional_test.go:302: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 cache add mysql:5.6            functional_test.go:302: (dbg) Done: out/minikube -p functional-20191104T082125.872658733-18873 cache add mysql:5.6: (18.018114782s)    --- PASS: TestFunctional/parallel (0.00s)        --- PASS: TestFunctional/parallel/MountCmd (4.77s)            fn_mount_cmd.go:62: (dbg) daemon: [../../out/minikube mount -p functional-20191104T082125.872658733-18873 /tmp/mounttest209263981:/mount-9p --alsologtostderr -v=1]            fn_mount_cmd.go:96: wrote &amp;#34;test-1572816292301508417&amp;#34; to /tmp/mounttest209263981/created-by-test            fn_mount_cmd.go:96: wrote &amp;#34;test-1572816292301508417&amp;#34; to /tmp/mounttest209263981/created-by-test-removed-by-pod            fn_mount_cmd.go:96: wrote &amp;#34;test-1572816292301508417&amp;#34; to /tmp/mounttest209263981/test-1572816292301508417            fn_mount_cmd.go:104: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh &amp;#34;findmnt -T /mount-9p | grep 9p&amp;#34;            fn_mount_cmd.go:104: (dbg) Non-zero exit: out/minikube -p functional-20191104T082125.872658733-18873 ssh &amp;#34;findmnt -T /mount-9p | grep 9p&amp;#34;: exit status 1 (202.701275ms)                                ** stderr **                 ssh: Process exited with status 1                                ** /stderr **            fn_mount_cmd.go:104: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh &amp;#34;findmnt -T /mount-9p | grep 9p&amp;#34;            fn_mount_cmd.go:118: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh -- ls -la /mount-9p            fn_mount_cmd.go:122: guest mount directory contents                total 2                -rw-r--r-- 1 docker docker 24 Nov  3 21:24 created-by-test                -rw-r--r-- 1 docker docker 24 Nov  3 21:24 created-by-test-removed-by-pod                -rw-r--r-- 1 docker docker 24 Nov  3 21:24 test-1572816292301508417            fn_mount_cmd.go:126: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh cat /mount-9p/test-1572816292301508417            fn_mount_cmd.go:137: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 replace --force -f testdata/busybox-mount-test.yaml            fn_mount_cmd.go:142: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox-mount&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox-mount&amp;#34; [cad31f9d-5fe3-423d-b72c-76365e32eaac] Pending            helpers.go:247: &amp;#34;busybox-mount&amp;#34; [cad31f9d-5fe3-423d-b72c-76365e32eaac] Pending / Ready:ContainersNotReady (containers with unready status: [mount-munger]) / ContainersReady:ContainersNotReady (containers with unready status: [mount-munger])            helpers.go:247: &amp;#34;busybox-mount&amp;#34; [cad31f9d-5fe3-423d-b72c-76365e32eaac] Succeeded: Initialized:PodCompleted / Ready:PodCompleted / ContainersReady:PodCompleted            fn_mount_cmd.go:142: (dbg) pods integration-test=busybox-mount up and healthy within 2.006393812s            fn_mount_cmd.go:158: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 logs busybox-mount            fn_mount_cmd.go:170: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh stat /mount-9p/created-by-test            fn_mount_cmd.go:170: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh stat /mount-9p/created-by-pod            fn_mount_cmd.go:79: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh &amp;#34;sudo umount -f /mount-9p&amp;#34;            fn_mount_cmd.go:83: (dbg) stopping [../../out/minikube mount -p functional-20191104T082125.872658733-18873 /tmp/mounttest209263981:/mount-9p --alsologtostderr -v=1] ...        --- PASS: TestFunctional/parallel/ConfigCmd (0.15s)            functional_test.go:326: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 config unset cpus            functional_test.go:326: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 config get cpus            functional_test.go:326: (dbg) Non-zero exit: out/minikube -p functional-20191104T082125.872658733-18873 config get cpus: exit status 64 (21.49557ms)                                ** stderr **                 Error: specified key could not be found in config                                ** /stderr **            functional_test.go:326: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 config set cpus 2            functional_test.go:326: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 config get cpus            functional_test.go:326: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 config unset cpus            functional_test.go:326: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 config get cpus            functional_test.go:326: (dbg) Non-zero exit: out/minikube -p functional-20191104T082125.872658733-18873 config get cpus: exit status 64 (19.061597ms)                                ** stderr **                 Error: specified key could not be found in config                                ** /stderr **        --- PASS: TestFunctional/parallel/AddonManager (5.06s)            functional_test.go:162: (dbg) waiting for pods with labels &amp;#34;component=kube-addon-manager&amp;#34; in namespace &amp;#34;kube-system&amp;#34; ...            helpers.go:247: &amp;#34;kube-addon-manager-minikube&amp;#34; [713e5c52-a374-40ed-9f57-f14c7d0de26a] Running            functional_test.go:162: (dbg) pods component=kube-addon-manager up and healthy within 5.026986587s        --- PASS: TestFunctional/parallel/LogsCmd (0.59s)            functional_test.go:344: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 logs        --- PASS: TestFunctional/parallel/ComponentHealth (0.07s)            functional_test.go:169: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 get cs -o=json        --- PASS: TestFunctional/parallel/StatusCmd (0.57s)            functional_test.go:194: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 status            functional_test.go:200: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 status -f host:{{.Host}},kublet:{{.Kubelet}},apiserver:{{.APIServer}},kubeconfig:{{.Kubeconfig}}            functional_test.go:210: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 status -o json        --- PASS: TestFunctional/parallel/DNS (8.60s)            functional_test.go:270: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 replace --force -f testdata/busybox.yaml            functional_test.go:275: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox&amp;#34; [24600016-7278-4daa-8a5d-b54f465d0f19] Pending            helpers.go:247: &amp;#34;busybox&amp;#34; [24600016-7278-4daa-8a5d-b54f465d0f19] Pending / Ready:ContainersNotReady (containers with unready status: [busybox]) / ContainersReady:ContainersNotReady (containers with unready status: [busybox])            helpers.go:247: &amp;#34;busybox&amp;#34; [24600016-7278-4daa-8a5d-b54f465d0f19] Running            functional_test.go:275: (dbg) pods integration-test=busybox up and healthy within 8.011521017s            functional_test.go:281: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 exec busybox nslookup kubernetes.default        --- PASS: TestFunctional/parallel/SSHCmd (0.15s)            functional_test.go:537: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 ssh &amp;#34;echo hello&amp;#34;        --- SKIP: TestFunctional/parallel/TunnelCmd (0.01s)            fn_tunnel_cmd.go:47: password required to execute &amp;#39;route&amp;#39;, skipping testTunnel: exit status 1        --- PASS: TestFunctional/parallel/MySQL (12.36s)            functional_test.go:548: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 replace --force -f testdata/mysql.yaml            functional_test.go:555: (dbg) waiting for pods with labels &amp;#34;app=mysql&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;mysql-5787d7b5fc-kqdrj&amp;#34; [90a614ba-f2d8-4318-92ae-6edd7463f14c] Pending            helpers.go:247: &amp;#34;mysql-5787d7b5fc-kqdrj&amp;#34; [90a614ba-f2d8-4318-92ae-6edd7463f14c] Pending / Ready:ContainersNotReady (containers with unready status: [mysql]) / ContainersReady:ContainersNotReady (containers with unready status: [mysql])            helpers.go:247: &amp;#34;mysql-5787d7b5fc-kqdrj&amp;#34; [90a614ba-f2d8-4318-92ae-6edd7463f14c] Running            functional_test.go:555: pod &amp;#34;app=mysql&amp;#34; failed to start: timed out waiting for the condition            helpers.go:292: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 get po -A --show-labels            helpers.go:298: (dbg) kubectl --context functional-20191104T082125.872658733-18873 get po -A --show-labels:                NAMESPACE     NAME                               READY   STATUS      RESTARTS   AGE    LABELS                default       busybox                            1/1     Running     0          5s     integration-test=busybox                default       busybox-mount                      0/1     Completed   0          3s     integration-test=busybox-mount                default       mysql-5787d7b5fc-kqdrj             1/1     Running     0          5s     app=mysql,pod-template-hash=5787d7b5fc                kube-system   coredns-5644d7b6d9-p9dkz           1/1     Running     0          104s   k8s-app=kube-dns,pod-template-hash=5644d7b6d9                kube-system   coredns-5644d7b6d9-wbttz           1/1     Running     0          104s   k8s-app=kube-dns,pod-template-hash=5644d7b6d9                kube-system   etcd-minikube                      1/1     Running     0          41s    component=etcd,tier=control-plane                kube-system   kube-addon-manager-minikube        1/1     Running     0          112s   component=kube-addon-manager,kubernetes.io/minikube-addons=addon-manager,version=v9.0.2                kube-system   kube-apiserver-minikube            1/1     Running     0          34s    component=kube-apiserver,tier=control-plane                kube-system   kube-controller-manager-minikube   1/1     Running     0          37s    component=kube-controller-manager,tier=control-plane                kube-system   kube-proxy-wc5fw                   1/1     Running     0          104s   controller-revision-hash=56ffd4ff47,k8s-app=kube-proxy,pod-template-generation=1                kube-system   kube-scheduler-minikube            1/1     Running     0          26s    component=kube-scheduler,tier=control-plane                kube-system   storage-provisioner                1/1     Running     0          103s   addonmanager.kubernetes.io/mode=Reconcile,integration-test=storage-provisioner            helpers.go:301: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 describe po mysql-5787d7b5fc-kqdrj -n default            helpers.go:305: (dbg) kubectl --context functional-20191104T082125.872658733-18873 describe po mysql-5787d7b5fc-kqdrj -n default:                Name:           mysql-5787d7b5fc-kqdrj                Namespace:      default                Priority:       0                Node:           minikube/192.168.39.24                Start Time:     Mon, 04 Nov 2019 08:24:52 +1100                Labels:         app=mysql                                pod-template-hash=5787d7b5fc                Annotations:    &amp;lt;none&amp;gt;                Status:         Running                IP:             172.17.0.5                Controlled By:  ReplicaSet/mysql-5787d7b5fc                Containers:                  mysql:                    Container ID:   docker://38da7fcc7cc8841b3233ef5fc800c8375602336625daf18456b13eafb40ac7d9                    Image:          mysql:5.6                    Image ID:       docker://sha256:b3983abaa3feff23bf58b849c7c2c0f84862e3a749a3181a0bdd6fcfa023f318                    Port:           3306/TCP                    Host Port:      0/TCP                    State:          Running                      Started:      Mon, 04 Nov 2019 08:24:54 +1100                    Ready:          True                    Restart Count:  0                    Environment:                      MYSQL_ROOT_PASSWORD:  password                    Mounts:                      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s7jh6 (ro)                Conditions:                  Type              Status                  Initialized       True                   Ready             True                   ContainersReady   True                   PodScheduled      True                 Volumes:                  default-token-s7jh6:                    Type:        Secret (a volume populated by a Secret)                    SecretName:  default-token-s7jh6                    Optional:    false                QoS Class:       BestEffort                Node-Selectors:  &amp;lt;none&amp;gt;                Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s                                 node.kubernetes.io/unreachable:NoExecute for 300s                Events:                  Type    Reason     Age        From               Message                  ----    ------     ----       ----               -------                  Normal  Scheduled  &amp;lt;unknown&amp;gt;  default-scheduler  Successfully assigned default/mysql-5787d7b5fc-kqdrj to minikube                  Normal  Pulled     4s         kubelet, minikube  Container image &amp;#34;mysql:5.6&amp;#34; already present on machine                  Normal  Created    4s         kubelet, minikube  Created container mysql                  Normal  Started    3s         kubelet, minikube  Started container mysql            helpers.go:308: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 logs mysql-5787d7b5fc-kqdrj -n default            helpers.go:312: (dbg) kubectl --context functional-20191104T082125.872658733-18873 logs mysql-5787d7b5fc-kqdrj -n default:                2019-11-03 21:24:54+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.6.46-1debian9 started.                2019-11-03 21:24:54+00:00 [Note] [Entrypoint]: Switching to dedicated user &amp;#39;mysql&amp;#39;                2019-11-03 21:24:54+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.6.46-1debian9 started.                2019-11-03 21:24:54+00:00 [Note] [Entrypoint]: Initializing database files                2019-11-03 21:24:54 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).                2019-11-03 21:24:54 0 [Note] Ignoring --secure-file-priv value as server is running with --bootstrap.                2019-11-03 21:24:54 0 [Note] /usr/sbin/mysqld (mysqld 5.6.46) starting as process 49 ...                2019-11-03 21:24:54 49 [Note] InnoDB: Using atomics to ref count buffer pool pages                2019-11-03 21:24:54 49 [Note] InnoDB: The InnoDB memory heap is disabled                2019-11-03 21:24:54 49 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins                2019-11-03 21:24:54 49 [Note] InnoDB: Memory barrier is not used                2019-11-03 21:24:54 49 [Note] InnoDB: Compressed tables use zlib 1.2.11                2019-11-03 21:24:54 49 [Note] InnoDB: Using Linux native AIO                2019-11-03 21:24:54 49 [Note] InnoDB: Using CPU crc32 instructions                2019-11-03 21:24:54 49 [Note] InnoDB: Initializing buffer pool, size = 128.0M                2019-11-03 21:24:54 49 [Note] InnoDB: Completed initialization of buffer pool                2019-11-03 21:24:54 49 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created!                2019-11-03 21:24:54 49 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB                2019-11-03 21:24:54 49 [Note] InnoDB: Database physically writes the file full: wait...                2019-11-03 21:24:54 49 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB                2019-11-03 21:24:54 49 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB                2019-11-03 21:24:55 49 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0                2019-11-03 21:24:55 49 [Warning] InnoDB: New log files created, LSN=45781                2019-11-03 21:24:55 49 [Note] InnoDB: Doublewrite buffer not found: creating new                2019-11-03 21:24:55 49 [Note] InnoDB: Doublewrite buffer created                2019-11-03 21:24:55 49 [Note] InnoDB: 128 rollback segment(s) are active.                2019-11-03 21:24:55 49 [Warning] InnoDB: Creating foreign key constraint system tables.                2019-11-03 21:24:55 49 [Note] InnoDB: Foreign key constraint system tables created                2019-11-03 21:24:55 49 [Note] InnoDB: Creating tablespace and datafile system tables.                2019-11-03 21:24:55 49 [Note] InnoDB: Tablespace and datafile system tables created.                2019-11-03 21:24:55 49 [Note] InnoDB: Waiting for purge to start                2019-11-03 21:24:55 49 [Note] InnoDB: 5.6.46 started; log sequence number 0                2019-11-03 21:24:55 49 [Note] RSA private key file not found: /var/lib/mysql//private_key.pem. Some authentication plugins will not work.                2019-11-03 21:24:55 49 [Note] RSA public key file not found: /var/lib/mysql//public_key.pem. Some authentication plugins will not work.                2019-11-03 21:24:56 49 [Note] Binlog end                2019-11-03 21:24:56 49 [Note] InnoDB: FTS optimize thread exiting.                2019-11-03 21:24:56 49 [Note] InnoDB: Starting shutdown...                2019-11-03 21:24:57 49 [Note] InnoDB: Shutdown completed; log sequence number 1625977                                                2019-11-03 21:24:57 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).                2019-11-03 21:24:57 0 [Note] Ignoring --secure-file-priv value as server is running with --bootstrap.                2019-11-03 21:24:57 0 [Note] /usr/sbin/mysqld (mysqld 5.6.46) starting as process 72 ...                2019-11-03 21:24:57 72 [Note] InnoDB: Using atomics to ref count buffer pool pages                2019-11-03 21:24:57 72 [Note] InnoDB: The InnoDB memory heap is disabled                2019-11-03 21:24:57 72 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins                2019-11-03 21:24:57 72 [Note] InnoDB: Memory barrier is not used                2019-11-03 21:24:57 72 [Note] InnoDB: Compressed tables use zlib 1.2.11                2019-11-03 21:24:57 72 [Note] InnoDB: Using Linux native AIO                2019-11-03 21:24:57 72 [Note] InnoDB: Using CPU crc32 instructions                2019-11-03 21:24:57 72 [Note] InnoDB: Initializing buffer pool, size = 128.0M                2019-11-03 21:24:57 72 [Note] InnoDB: Completed initialization of buffer pool                2019-11-03 21:24:57 72 [Note] InnoDB: Highest supported file format is Barracuda.                2019-11-03 21:24:57 72 [Note] InnoDB: 128 rollback segment(s) are active.                2019-11-03 21:24:57 72 [Note] InnoDB: Waiting for purge to start                2019-11-03 21:24:57 72 [Note] InnoDB: 5.6.46 started; log sequence number 1625977                2019-11-03 21:24:57 72 [Note] RSA private key file not found: /var/lib/mysql//private_key.pem. Some authentication plugins will not work.                2019-11-03 21:24:57 72 [Note] RSA public key file not found: /var/lib/mysql//public_key.pem. Some authentication plugins will not work.                2019-11-03 21:24:57 72 [Note] Binlog end                2019-11-03 21:24:57 72 [Note] InnoDB: FTS optimize thread exiting.                2019-11-03 21:24:57 72 [Note] InnoDB: Starting shutdown...            functional_test.go:555: (dbg) waiting for pods with labels &amp;#34;app=mysql&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;mysql-5787d7b5fc-kqdrj&amp;#34; [90a614ba-f2d8-4318-92ae-6edd7463f14c] Running            functional_test.go:555: (dbg) pods app=mysql up and healthy within 5.005878835s            functional_test.go:559: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 exec mysql-5787d7b5fc-kqdrj -- mysql -ppassword -e &amp;#34;show databases;&amp;#34;        --- PASS: TestFunctional/parallel/AddonsCmd (0.12s)            functional_test.go:478: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 addons list            functional_test.go:492: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 addons list --format &amp;#34;{{.AddonName}}&amp;#34;:&amp;#34;{{.AddonStatus}}&amp;#34;            functional_test.go:506: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 addons list -f &amp;#34;{{.AddonName}}&amp;#34;:&amp;#34;{{.AddonStatus}}&amp;#34;            functional_test.go:520: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 addons list -o json        --- PASS: TestFunctional/parallel/ProfileCmd (0.05s)            functional_test.go:357: (dbg) Run:  out/minikube profile list            functional_test.go:377: (dbg) Run:  out/minikube profile list --output json        --- PASS: TestFunctional/parallel/PersistentVolumeClaim (7.75s)            fn_pvc.go:40: (dbg) waiting for pods with labels &amp;#34;integration-test=storage-provisioner&amp;#34; in namespace &amp;#34;kube-system&amp;#34; ...            helpers.go:247: &amp;#34;storage-provisioner&amp;#34; [6c9c2d17-8119-4170-9544-5a1cbdcc68cc] Running            fn_pvc.go:40: (dbg) pods integration-test=storage-provisioner up and healthy within 5.010901682s            fn_pvc.go:45: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 get storageclass -o=json            fn_pvc.go:65: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 apply -f testdata/pvc.yaml            fn_pvc.go:71: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 get pvc testpvc -o=json            fn_pvc.go:71: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 get pvc testpvc -o=json        --- PASS: TestFunctional/parallel/ServiceCmd (29.28s)            functional_test.go:401: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node            functional_test.go:405: (dbg) Run:  kubectl --context functional-20191104T082125.872658733-18873 expose deployment hello-node --type=NodePort --port=8080            functional_test.go:410: (dbg) waiting for pods with labels &amp;#34;app=hello-node&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;hello-node-7676b5fb8d-nxjqs&amp;#34; [9b3adf91-a112-4dbc-9b19-9d8801af3b43] Pending / Ready:ContainersNotReady (containers with unready status: [hello-node]) / ContainersReady:ContainersNotReady (containers with unready status: [hello-node])            helpers.go:247: &amp;#34;hello-node-7676b5fb8d-nxjqs&amp;#34; [9b3adf91-a112-4dbc-9b19-9d8801af3b43] Running            functional_test.go:410: (dbg) pods app=hello-node up and healthy within 27.004810384s            functional_test.go:414: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 service list            functional_test.go:414: (dbg) Done: out/minikube -p functional-20191104T082125.872658733-18873 service list: (1.640625892s)            functional_test.go:423: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 service --namespace=default --https --url hello-node            functional_test.go:441: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 service hello-node --url --format={{.IP}}            functional_test.go:450: (dbg) Run:  out/minikube -p functional-20191104T082125.872658733-18873 service hello-node --url            functional_test.go:464: url: http://192.168.39.24:31849        --- PASS: TestFunctional/parallel/DashboardCmd (41.31s)            functional_test.go:236: (dbg) daemon: [../../out/minikube dashboard --url -p functional-20191104T082125.872658733-18873 --alsologtostderr -v=1]            functional_test.go:241: (dbg) stopping [../../out/minikube dashboard --url -p functional-20191104T082125.872658733-18873 --alsologtostderr -v=1] ...            helpers.go:387: unable to kill pid 21063: os: process already finished    helpers.go:167: (dbg) Run:  out/minikube delete -p functional-20191104T082125.872658733-18873    helpers.go:167: (dbg) Done: out/minikube delete -p functional-20191104T082125.872658733-18873: (1.601200457s)=== RUN   TestAddons/parallel=== RUN   TestAddons/parallel/Registry=== PAUSE TestAddons/parallel/Registry=== RUN   TestAddons/parallel/Ingress=== PAUSE TestAddons/parallel/Ingress=== CONT  TestAddons/parallel/Registry=== CONT  TestAddons/parallel/Ingress2019/11/04 08:27:50 [DEBUG] GET http://192.168.39.56:5000--- PASS: TestAddons (192.32s)    helpers.go:361: No need to wait for start slot, it is already 2019-11-04 08:24:52.30063752 +1100 AEDT m=+240.074648116    addons_test.go:46: (dbg) Run:  out/minikube start -p addons-20191104T082452.300667929-18873 --wait=false --memory=2600 --alsologtostderr -v=1 --addons=ingress --addons=registry     addons_test.go:46: (dbg) Done: out/minikube start -p addons-20191104T082452.300667929-18873 --wait=false --memory=2600 --alsologtostderr -v=1 --addons=ingress --addons=registry : (2m28.528135985s)    --- PASS: TestAddons/parallel (0.00s)        --- PASS: TestAddons/parallel/Ingress (29.68s)            addons_test.go:97: (dbg) waiting for pods with labels &amp;#34;app.kubernetes.io/name=nginx-ingress-controller&amp;#34; in namespace &amp;#34;kube-system&amp;#34; ...            helpers.go:247: &amp;#34;nginx-ingress-controller-6fc5bcc8c9-pvwsq&amp;#34; [03a32eb7-f4fd-43ad-89f9-73f9c9407f1b] Running / Ready:ContainersNotReady (containers with unready status: [nginx-ingress-controller]) / ContainersReady:ContainersNotReady (containers with unready status: [nginx-ingress-controller])            addons_test.go:97: (dbg) pods app.kubernetes.io/name=nginx-ingress-controller up and healthy within 5.005704761s            addons_test.go:101: (dbg) Run:  kubectl --context addons-20191104T082452.300667929-18873 replace --force -f testdata/nginx-ing.yaml            addons_test.go:101: (dbg) Done: kubectl --context addons-20191104T082452.300667929-18873 replace --force -f testdata/nginx-ing.yaml: (2.671133592s)            addons_test.go:105: (dbg) Run:  kubectl --context addons-20191104T082452.300667929-18873 replace --force -f testdata/nginx-pod-svc.yaml            addons_test.go:110: (dbg) waiting for pods with labels &amp;#34;run=nginx&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;nginx&amp;#34; [21d6e955-3c60-4673-b019-4b25d0af8f9d] Pending / Ready:ContainersNotReady (containers with unready status: [nginx]) / ContainersReady:ContainersNotReady (containers with unready status: [nginx])            helpers.go:247: &amp;#34;nginx&amp;#34; [21d6e955-3c60-4673-b019-4b25d0af8f9d] Running            addons_test.go:110: (dbg) pods run=nginx up and healthy within 21.024403427s            addons_test.go:119: (dbg) Run:  out/minikube -p addons-20191104T082452.300667929-18873 ssh &amp;#34;curl http://127.0.0.1:80 -H &amp;#39;Host: nginx.example.com&amp;#39;&amp;#34;            addons_test.go:136: (dbg) Run:  out/minikube -p addons-20191104T082452.300667929-18873 addons disable ingress --alsologtostderr -v=1        --- PASS: TestAddons/parallel/Registry (30.14s)            addons_test.go:152: registry stabilized in 17.21522ms            addons_test.go:154: (dbg) waiting for pods with labels &amp;#34;actual-registry=true&amp;#34; in namespace &amp;#34;kube-system&amp;#34; ...            helpers.go:247: &amp;#34;registry-qw4s5&amp;#34; [3e6cc7cb-d88f-4a0c-9a83-29c7fbd01596] Running            addons_test.go:154: (dbg) pods actual-registry=true up and healthy within 5.008192127s            addons_test.go:157: (dbg) waiting for pods with labels &amp;#34;registry-proxy=true&amp;#34; in namespace &amp;#34;kube-system&amp;#34; ...            helpers.go:247: &amp;#34;registry-proxy-dd8rs&amp;#34; [f07e58a3-2550-4bd1-bbbe-d0413fee18ab] Running            addons_test.go:157: (dbg) pods registry-proxy=true up and healthy within 5.006662151s            addons_test.go:162: (dbg) Run:  kubectl --context addons-20191104T082452.300667929-18873 delete po -l run=registry-test --now            addons_test.go:167: (dbg) Run:  kubectl --context addons-20191104T082452.300667929-18873 run --rm registry-test --restart=Never --image=busybox -it -- sh -c &amp;#34;wget --spider -S http://registry.kube-system.svc.cluster.local&amp;#34;            addons_test.go:167: (dbg) Done: kubectl --context addons-20191104T082452.300667929-18873 run --rm registry-test --restart=Never --image=busybox -it -- sh -c &amp;#34;wget --spider -S http://registry.kube-system.svc.cluster.local&amp;#34;: (19.592473452s)            addons_test.go:177: (dbg) Run:  out/minikube -p addons-20191104T082452.300667929-18873 ip            addons_test.go:206: (dbg) Run:  out/minikube -p addons-20191104T082452.300667929-18873 addons disable registry --alsologtostderr -v=1    addons_test.go:70: (dbg) Run:  out/minikube stop -p addons-20191104T082452.300667929-18873    addons_test.go:70: (dbg) Done: out/minikube stop -p addons-20191104T082452.300667929-18873: (13.233220482s)    addons_test.go:74: (dbg) Run:  out/minikube addons enable dashboard -p addons-20191104T082452.300667929-18873    addons_test.go:78: (dbg) Run:  out/minikube addons disable dashboard -p addons-20191104T082452.300667929-18873    helpers.go:167: (dbg) Run:  out/minikube delete -p addons-20191104T082452.300667929-18873--- PASS: TestDockerFlags (235.66s)    helpers.go:358: Waiting for start slot at 2019-11-04 08:25:52.300626185 +1100 AEDT m=+300.074636780 (sleeping 59.999921632s)  ...    docker_test.go:42: (dbg) Run:  out/minikube start -p docker-flags-20191104T082552.300971973-18873 --wait=false --docker-env=FOO=BAR --docker-env=BAZ=BAT --docker-opt=debug --docker-opt=icc=true --alsologtostderr -v=5     docker_test.go:42: (dbg) Done: out/minikube start -p docker-flags-20191104T082552.300971973-18873 --wait=false --docker-env=FOO=BAR --docker-env=BAZ=BAT --docker-opt=debug --docker-opt=icc=true --alsologtostderr -v=5 : (2m54.076176539s)    docker_test.go:47: (dbg) Run:  out/minikube -p docker-flags-20191104T082552.300971973-18873 ssh &amp;#34;systemctl show docker --property=Environment --no-pager&amp;#34;    docker_test.go:58: (dbg) Run:  out/minikube -p docker-flags-20191104T082552.300971973-18873 ssh &amp;#34;systemctl show docker --property=ExecStart --no-pager&amp;#34;    helpers.go:167: (dbg) Run:  out/minikube delete -p docker-flags-20191104T082552.300971973-18873    helpers.go:167: (dbg) Done: out/minikube delete -p docker-flags-20191104T082552.300971973-18873: (1.132863792s)--- PASS: TestVersionUpgrade (369.17s)    helpers.go:358: Waiting for start slot at 2019-11-04 08:25:22.300626185 +1100 AEDT m=+270.074636780 (sleeping 29.999935731s)  ...    version_upgrade_test.go:70: (dbg) Run:  /tmp/minikube-release.878849777.exe start -p vupgrade-20191104T082522.300800849-18873 --kubernetes-version=v1.11.10 --alsologtostderr -v=1     version_upgrade_test.go:70: (dbg) Done: /tmp/minikube-release.878849777.exe start -p vupgrade-20191104T082522.300800849-18873 --kubernetes-version=v1.11.10 --alsologtostderr -v=1 : (2m58.197200416s)    version_upgrade_test.go:79: (dbg) Run:  /tmp/minikube-release.878849777.exe stop -p vupgrade-20191104T082522.300800849-18873    version_upgrade_test.go:79: (dbg) Done: /tmp/minikube-release.878849777.exe stop -p vupgrade-20191104T082522.300800849-18873: (14.155612976s)    version_upgrade_test.go:84: (dbg) Run:  /tmp/minikube-release.878849777.exe -p vupgrade-20191104T082522.300800849-18873 status --format={{.Host}}    version_upgrade_test.go:84: (dbg) Non-zero exit: /tmp/minikube-release.878849777.exe -p vupgrade-20191104T082522.300800849-18873 status --format={{.Host}}: exit status 1 (68.698765ms)        -- stdout --        Stopped        -- /stdout --    version_upgrade_test.go:86: status error: exit status 1 (may be ok)    helpers.go:361: No need to wait for start slot, it is already 2019-11-04 08:28:37.164720757 +1100 AEDT m=+464.938731345    version_upgrade_test.go:95: (dbg) Run:  out/minikube start -p vupgrade-20191104T082522.300800849-18873 --kubernetes-version=v1.16.2 --alsologtostderr -v=1     version_upgrade_test.go:95: (dbg) Done: out/minikube start -p vupgrade-20191104T082522.300800849-18873 --kubernetes-version=v1.16.2 --alsologtostderr -v=1 : (2m23.324335645s)    helpers.go:167: (dbg) Run:  out/minikube delete -p vupgrade-20191104T082522.300800849-18873--- PASS: TestStartStop (626.25s)    --- PASS: TestStartStop/group (0.00s)        --- PASS: TestStartStop/group/docker (416.69s)            helpers.go:358: Waiting for start slot at 2019-11-04 08:26:22.300626185 +1100 AEDT m=+330.074636780 (sleeping 1m29.999762906s)  ...            start_stop_delete_test.go:91: (dbg) Run:  out/minikube start -p docker-20191104T082622.300761702-18873 --alsologtostderr -v=3 --wait=true --cache-images=false --kubernetes-version=v1.11.10 --kvm-network=default --kvm-qemu-uri=qemu:///system --disable-driver-mounts --keep-context=false --container-runtime=docker             start_stop_delete_test.go:91: (dbg) Done: out/minikube start -p docker-20191104T082622.300761702-18873 --alsologtostderr -v=3 --wait=true --cache-images=false --kubernetes-version=v1.11.10 --kvm-network=default --kvm-qemu-uri=qemu:///system --disable-driver-mounts --keep-context=false --container-runtime=docker : (3m9.827465706s)            start_stop_delete_test.go:102: (dbg) Run:  kubectl --context docker-20191104T082622.300761702-18873 create -f testdata/busybox.yaml            start_stop_delete_test.go:102: (dbg) Done: kubectl --context docker-20191104T082622.300761702-18873 create -f testdata/busybox.yaml: (1.045195614s)            start_stop_delete_test.go:107: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox&amp;#34; [06dd0c10-fe81-11e9-a894-5c5fdd3720f5] Pending / Ready:ContainersNotReady (containers with unready status: [busybox]) / ContainersReady:ContainersNotReady (containers with unready status: [busybox])            helpers.go:247: &amp;#34;busybox&amp;#34; [06dd0c10-fe81-11e9-a894-5c5fdd3720f5] Running            start_stop_delete_test.go:107: (dbg) pods integration-test=busybox up and healthy within 16.06885973s            start_stop_delete_test.go:113: (dbg) Run:  kubectl --context docker-20191104T082622.300761702-18873 exec busybox -- /bin/sh -c &amp;#34;ulimit -n&amp;#34;            start_stop_delete_test.go:130: (dbg) Run:  out/minikube stop -p docker-20191104T082622.300761702-18873 --alsologtostderr -v=3            start_stop_delete_test.go:130: (dbg) Done: out/minikube stop -p docker-20191104T082622.300761702-18873 --alsologtostderr -v=3: (17.353839074s)            start_stop_delete_test.go:135: (dbg) Run:  out/minikube status --format={{.Host}} -p docker-20191104T082622.300761702-18873            start_stop_delete_test.go:135: (dbg) Non-zero exit: out/minikube status --format={{.Host}} -p docker-20191104T082622.300761702-18873: exit status 1 (37.663869ms)                -- stdout --                Stopped                -- /stdout --            start_stop_delete_test.go:135: status error: exit status 1 (may be ok)            helpers.go:361: No need to wait for start slot, it is already 2019-11-04 08:30:07.029124735 +1100 AEDT m=+554.803135321            start_stop_delete_test.go:141: (dbg) Run:  out/minikube start -p docker-20191104T082622.300761702-18873 --alsologtostderr -v=3 --wait=true --cache-images=false --kubernetes-version=v1.11.10 --kvm-network=default --kvm-qemu-uri=qemu:///system --disable-driver-mounts --keep-context=false --container-runtime=docker             start_stop_delete_test.go:141: (dbg) Done: out/minikube start -p docker-20191104T082622.300761702-18873 --alsologtostderr -v=3 --wait=true --cache-images=false --kubernetes-version=v1.11.10 --kvm-network=default --kvm-qemu-uri=qemu:///system --disable-driver-mounts --keep-context=false --container-runtime=docker : (1m35.29120763s)            start_stop_delete_test.go:149: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox&amp;#34; [06dd0c10-fe81-11e9-a894-5c5fdd3720f5] Running            start_stop_delete_test.go:149: (dbg) pods integration-test=busybox up and healthy within 5.642024689s            start_stop_delete_test.go:153: (dbg) Run:  out/minikube status --format={{.Host}} -p docker-20191104T082622.300761702-18873            helpers.go:167: (dbg) Run:  out/minikube delete -p docker-20191104T082622.300761702-18873        --- PASS: TestStartStop/group/cni (467.93s)            helpers.go:358: Waiting for start slot at 2019-11-04 08:27:52.300626185 +1100 AEDT m=+420.074636780 (sleeping 2m59.999736017s)  ...            start_stop_delete_test.go:91: (dbg) Run:  out/minikube start -p cni-20191104T082752.300771556-18873 --alsologtostderr -v=3 --wait=true --feature-gates ServerSideApply=true --network-plugin=cni --extra-config=kubelet.network-plugin=cni --extra-config=kubeadm.pod-network-cidr=192.168.111.111/16 --kubernetes-version=v1.16.2             start_stop_delete_test.go:91: (dbg) Done: out/minikube start -p cni-20191104T082752.300771556-18873 --alsologtostderr -v=3 --wait=true --feature-gates ServerSideApply=true --network-plugin=cni --extra-config=kubelet.network-plugin=cni --extra-config=kubeadm.pod-network-cidr=192.168.111.111/16 --kubernetes-version=v1.16.2 : (3m50.111617403s)            start_stop_delete_test.go:99: WARNING: cni mode requires additional setup before pods can schedule :(            start_stop_delete_test.go:130: (dbg) Run:  out/minikube stop -p cni-20191104T082752.300771556-18873 --alsologtostderr -v=3            start_stop_delete_test.go:130: (dbg) Done: out/minikube stop -p cni-20191104T082752.300771556-18873 --alsologtostderr -v=3: (13.361886938s)            start_stop_delete_test.go:135: (dbg) Run:  out/minikube status --format={{.Host}} -p cni-20191104T082752.300771556-18873            start_stop_delete_test.go:135: (dbg) Non-zero exit: out/minikube status --format={{.Host}} -p cni-20191104T082752.300771556-18873: exit status 1 (40.269985ms)                -- stdout --                Stopped                -- /stdout --            start_stop_delete_test.go:135: status error: exit status 1 (may be ok)            helpers.go:361: No need to wait for start slot, it is already 2019-11-04 08:31:55.814766655 +1100 AEDT m=+663.588777252            start_stop_delete_test.go:141: (dbg) Run:  out/minikube start -p cni-20191104T082752.300771556-18873 --alsologtostderr -v=3 --wait=true --feature-gates ServerSideApply=true --network-plugin=cni --extra-config=kubelet.network-plugin=cni --extra-config=kubeadm.pod-network-cidr=192.168.111.111/16 --kubernetes-version=v1.16.2             start_stop_delete_test.go:141: (dbg) Done: out/minikube start -p cni-20191104T082752.300771556-18873 --alsologtostderr -v=3 --wait=true --feature-gates ServerSideApply=true --network-plugin=cni --extra-config=kubelet.network-plugin=cni --extra-config=kubeadm.pod-network-cidr=192.168.111.111/16 --kubernetes-version=v1.16.2 : (43.328528439s)            start_stop_delete_test.go:148: WARNING: cni mode requires additional setup before pods can schedule :(            start_stop_delete_test.go:153: (dbg) Run:  out/minikube status --format={{.Host}} -p cni-20191104T082752.300771556-18873            helpers.go:167: (dbg) Run:  out/minikube delete -p cni-20191104T082752.300771556-18873        --- PASS: TestStartStop/group/containerd (555.16s)            helpers.go:358: Waiting for start slot at 2019-11-04 08:26:52.300626185 +1100 AEDT m=+360.074636780 (sleeping 1m59.999750306s)  ...            start_stop_delete_test.go:91: (dbg) Run:  out/minikube start -p containerd-20191104T082652.300780979-18873 --alsologtostderr -v=3 --wait=true --container-runtime=containerd --docker-opt containerd=/var/run/containerd/containerd.sock --apiserver-port=8444             start_stop_delete_test.go:91: (dbg) Done: out/minikube start -p containerd-20191104T082652.300780979-18873 --alsologtostderr -v=3 --wait=true --container-runtime=containerd --docker-opt containerd=/var/run/containerd/containerd.sock --apiserver-port=8444 : (4m29.732924894s)            start_stop_delete_test.go:102: (dbg) Run:  kubectl --context containerd-20191104T082652.300780979-18873 create -f testdata/busybox.yaml            start_stop_delete_test.go:102: (dbg) Done: kubectl --context containerd-20191104T082652.300780979-18873 create -f testdata/busybox.yaml: (3.022589629s)            start_stop_delete_test.go:107: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox&amp;#34; [90846118-a891-4edd-86a1-4df14dbdacdd] Pending            helpers.go:247: &amp;#34;busybox&amp;#34; [90846118-a891-4edd-86a1-4df14dbdacdd] Pending / Ready:ContainersNotReady (containers with unready status: [busybox]) / ContainersReady:ContainersNotReady (containers with unready status: [busybox])            helpers.go:247: &amp;#34;busybox&amp;#34; [90846118-a891-4edd-86a1-4df14dbdacdd] Running            start_stop_delete_test.go:107: (dbg) pods integration-test=busybox up and healthy within 11.883410366s            start_stop_delete_test.go:113: (dbg) Run:  kubectl --context containerd-20191104T082652.300780979-18873 exec busybox -- /bin/sh -c &amp;#34;ulimit -n&amp;#34;            start_stop_delete_test.go:130: (dbg) Run:  out/minikube stop -p containerd-20191104T082652.300780979-18873 --alsologtostderr -v=3            start_stop_delete_test.go:130: (dbg) Done: out/minikube stop -p containerd-20191104T082652.300780979-18873 --alsologtostderr -v=3: (1m31.837876123s)            start_stop_delete_test.go:135: (dbg) Run:  out/minikube status --format={{.Host}} -p containerd-20191104T082652.300780979-18873            start_stop_delete_test.go:135: (dbg) Non-zero exit: out/minikube status --format={{.Host}} -p containerd-20191104T082652.300780979-18873: exit status 1 (35.925354ms)                -- stdout --                Stopped                -- /stdout --            start_stop_delete_test.go:135: status error: exit status 1 (may be ok)            helpers.go:361: No need to wait for start slot, it is already 2019-11-04 08:33:09.026967426 +1100 AEDT m=+736.800978015            start_stop_delete_test.go:141: (dbg) Run:  out/minikube start -p containerd-20191104T082652.300780979-18873 --alsologtostderr -v=3 --wait=true --container-runtime=containerd --docker-opt containerd=/var/run/containerd/containerd.sock --apiserver-port=8444             start_stop_delete_test.go:141: (dbg) Done: out/minikube start -p containerd-20191104T082652.300780979-18873 --alsologtostderr -v=3 --wait=true --container-runtime=containerd --docker-opt containerd=/var/run/containerd/containerd.sock --apiserver-port=8444 : (52.484285038s)            start_stop_delete_test.go:149: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox&amp;#34; [90846118-a891-4edd-86a1-4df14dbdacdd] Running / Ready:ContainersNotReady (containers with unready status: [busybox]) / ContainersReady:ContainersNotReady (containers with unready status: [busybox])            helpers.go:247: &amp;#34;busybox&amp;#34; [90846118-a891-4edd-86a1-4df14dbdacdd] Running            start_stop_delete_test.go:149: (dbg) pods integration-test=busybox up and healthy within 5.008644281s            start_stop_delete_test.go:153: (dbg) Run:  out/minikube status --format={{.Host}} -p containerd-20191104T082652.300780979-18873            helpers.go:167: (dbg) Run:  out/minikube delete -p containerd-20191104T082652.300780979-18873        --- PASS: TestStartStop/group/crio (626.25s)            helpers.go:358: Waiting for start slot at 2019-11-04 08:27:22.300626185 +1100 AEDT m=+390.074636780 (sleeping 2m29.999745542s)  ...            start_stop_delete_test.go:91: (dbg) Run:  out/minikube start -p crio-20191104T082722.304206154-18873 --alsologtostderr -v=3 --wait=true --container-runtime=crio --disable-driver-mounts --extra-config=kubeadm.ignore-preflight-errors=SystemVerification             start_stop_delete_test.go:91: (dbg) Done: out/minikube start -p crio-20191104T082722.304206154-18873 --alsologtostderr -v=3 --wait=true --container-runtime=crio --disable-driver-mounts --extra-config=kubeadm.ignore-preflight-errors=SystemVerification : (4m52.989940404s)            start_stop_delete_test.go:102: (dbg) Run:  kubectl --context crio-20191104T082722.304206154-18873 create -f testdata/busybox.yaml            start_stop_delete_test.go:107: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox&amp;#34; [2660e105-871f-4b5e-8e06-306ee3ed6648] Pending            helpers.go:247: &amp;#34;busybox&amp;#34; [2660e105-871f-4b5e-8e06-306ee3ed6648] Pending / Ready:ContainersNotReady (containers with unready status: [busybox]) / ContainersReady:ContainersNotReady (containers with unready status: [busybox])            helpers.go:247: &amp;#34;busybox&amp;#34; [2660e105-871f-4b5e-8e06-306ee3ed6648] Running            start_stop_delete_test.go:107: (dbg) pods integration-test=busybox up and healthy within 8.510315758s            start_stop_delete_test.go:113: (dbg) Run:  kubectl --context crio-20191104T082722.304206154-18873 exec busybox -- /bin/sh -c &amp;#34;ulimit -n&amp;#34;            start_stop_delete_test.go:130: (dbg) Run:  out/minikube stop -p crio-20191104T082722.304206154-18873 --alsologtostderr -v=3            start_stop_delete_test.go:130: (dbg) Done: out/minikube stop -p crio-20191104T082722.304206154-18873 --alsologtostderr -v=3: (1m32.087370333s)            start_stop_delete_test.go:135: (dbg) Run:  out/minikube status --format={{.Host}} -p crio-20191104T082722.304206154-18873            start_stop_delete_test.go:135: (dbg) Non-zero exit: out/minikube status --format={{.Host}} -p crio-20191104T082722.304206154-18873: exit status 1 (35.519744ms)                -- stdout --                Stopped                -- /stdout --            start_stop_delete_test.go:135: status error: exit status 1 (may be ok)            helpers.go:361: No need to wait for start slot, it is already 2019-11-04 08:33:56.977436358 +1100 AEDT m=+784.751446950            start_stop_delete_test.go:141: (dbg) Run:  out/minikube start -p crio-20191104T082722.304206154-18873 --alsologtostderr -v=3 --wait=true --container-runtime=crio --disable-driver-mounts --extra-config=kubeadm.ignore-preflight-errors=SystemVerification             start_stop_delete_test.go:141: (dbg) Done: out/minikube start -p crio-20191104T082722.304206154-18873 --alsologtostderr -v=3 --wait=true --container-runtime=crio --disable-driver-mounts --extra-config=kubeadm.ignore-preflight-errors=SystemVerification : (1m15.390161848s)            start_stop_delete_test.go:149: (dbg) waiting for pods with labels &amp;#34;integration-test=busybox&amp;#34; in namespace &amp;#34;default&amp;#34; ...            helpers.go:247: &amp;#34;busybox&amp;#34; [2660e105-871f-4b5e-8e06-306ee3ed6648] Running            start_stop_delete_test.go:149: (dbg) pods integration-test=busybox up and healthy within 5.011162349s            start_stop_delete_test.go:153: (dbg) Run:  out/minikube status --format={{.Host}} -p crio-20191104T082722.304206154-18873            helpers.go:167: (dbg) Run:  out/minikube delete -p crio-20191104T082722.304206154-18873PASSok  k8s.io/minikube/test/integration866.327s&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Kubernetes Brain Dump (ALWAYS WIP)</title>
       <link>/post/kubernetesbraindump/</link>
       <pubDate>Sat, 30 Nov 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/kubernetesbraindump/</guid>
       <description>&lt;ul&gt;&lt;li&gt;Linux Network Namespaces is one of the important feature in Linux Kernel that are leveraged by containers like docker and kubernetes. It is used in the CNI (Container Network Interface).&lt;/li&gt;&lt;li&gt;A Kubernetes cluster can be deployed on either physical or virtual machines.&lt;/li&gt;&lt;li&gt;Once you&amp;rsquo;ve created a Deployment, the Kubernetes master schedules mentioned application instances onto individual Nodes in the cluster.&lt;/li&gt;&lt;li&gt;Once the application instances are created, a Kubernetes Deployment Controller continuously monitors those instances. If the Node hosting an instance goes down or is deleted, the Deployment controller replaces the instance with an instance on another Node in the cluster. This provides a self-healing mechanism to address machine failure or maintenance.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Node&lt;/strong&gt; - A node is a VM or a physical computer that serves as a worker machine in a Kubernetes cluster.&lt;/li&gt;&lt;li&gt;Each node has a Kubelet, which is an agent for managing the node and communicating with the Kubernetes master. The node should also have tools for handling container operations, such as Docker or rkt.&lt;/li&gt;&lt;li&gt;A Kubernetes cluster that handles production traffic should have a minimum of three nodes.&lt;/li&gt;&lt;li&gt;The nodes communicate with the master using the Kubernetes API. End users can also use the Kubernetes API directly to interact with the cluster.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Node Components run on every node, maintaining running pods and providing the Kubernetes runtime environment.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;kubelet&lt;/strong&gt; - An agent that runs on each node in the cluster. It makes sure that containers are running in a pod.  The kubelet takes a set of PodSpecs that are provided through various mechanisms and ensures that the containers described in those PodSpecs are running and healthy. The kubelet doesn’t manage containers which were not created by Kubernetes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;kube-proxy&lt;/strong&gt; - kube-proxy is a network proxy that runs on each node in your cluster, implementing part of the Kubernetes Service concept. kube-proxy maintains network rules on nodes. These network rules allow network communication to your Pods from network sessions inside or outside of your cluster. kube-proxy uses the operating system packet filtering layer if there is one and it’s available. Otherwise, kube-proxy forwards the traffic itself.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container Runtime&lt;/strong&gt; - The container runtime is the software that is responsible for running containers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A node is a worker machine in Kubernetes, previously known as a minion. A node may be a VM or physical machine, depending on the cluster. Each node contains the services necessary to run pods and is managed by the master components.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A node’s status contains the following information:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Addresses&lt;/li&gt;&lt;li&gt;Conditions&lt;/li&gt;&lt;li&gt;Capacity and Allocatable&lt;/li&gt;&lt;li&gt;Info&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Node&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Currently, there are three components that interact with the Kubernetes node interface: node controller, kubelet, and kubectl.&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Node Controller&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;The node controller is a Kubernetes master component which manages various aspects of nodes.&lt;/li&gt;&lt;li&gt;Assigning a CIDR block to the node when it is registered (if CIDR assignment is turned on).&lt;/li&gt;&lt;li&gt;Keeping the node controller’s internal list of nodes up to date with the cloud provider’s list of available machines. When running in a cloud environment, whenever a node is unhealthy, the node controller asks the cloud provider if the VM for that node is still available. If not, the node controller deletes the node from its list of nodes.&lt;/li&gt;&lt;li&gt;The node controller is responsible for updating the NodeReady condition of NodeStatus to ConditionUnknown when a node becomes unreachable (i.e. the node controller stops receiving heartbeats for some reason, for example due to the node being down), and then later evicting all the pods from the node (using graceful termination) if the node continues to be unreachable. (The default timeouts are 40s to start reporting ConditionUnknown and 5m after that to start evicting pods.) The node controller checks the state of each node every &amp;ndash;node-monitor-period seconds.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Pod&lt;/h2&gt;    &lt;ul&gt;&lt;li&gt;&lt;strong&gt;Pod&lt;/strong&gt; is something logical and not physical. It is just a logical wrapper for a set of containers with it&amp;rsquo;s resources.  In terms of Docker constructs, a Pod is modelled as a group of Docker containers with shared namespaces and shared filesystem volumes.&lt;/li&gt;&lt;li&gt;Containers within a Pod share an IP address and port space, and can find each other via localhost. They can also communicate with each other using standard inter-process communications like SystemV semaphores or POSIX shared memory. Containers in different Pods have distinct IP addresses and can not communicate by IPC without special configuration. These containers usually communicate with each other via Pod IP addresses.&lt;/li&gt;&lt;li&gt;A Pod is a group of one or more containers (such as Docker containers), with shared storage/network, and a specification for how to run the containers.&lt;/li&gt;&lt;li&gt;A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as &lt;em&gt;docker&lt;/em&gt; or &lt;em&gt;rkt&lt;/em&gt;), and some shared resources for those containers. Those resources include:&lt;ul&gt;&lt;li&gt;Shared storage, as Volumes&lt;/li&gt;&lt;li&gt;Networking, as a unique cluster IP address&lt;/li&gt;&lt;li&gt;Information about how to run each container, such as the container image version or specific ports to use&lt;/li&gt;&lt;li&gt;The containers in a Pod share an IP Address and port space, are always co-located and co-scheduled, and run in a shared context on the same Node.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A Pod always runs on a Node&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster.&lt;/li&gt;&lt;li&gt;Each Node is managed by the Master.&lt;/li&gt;&lt;li&gt;A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster.&lt;/li&gt;&lt;li&gt;The Master&amp;rsquo;s automatic scheduling takes into account the available resources on each Node.&lt;/li&gt;&lt;li&gt;&lt;p&gt;Every Kubernetes Node runs at least:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Kubelet, a process responsible for communication between the Kubernetes Master and the Node; it manages the Pods and the containers running on a machine.&lt;/li&gt;&lt;li&gt;A container runtime (like Docker, rkt) responsible for pulling the container image from a registry, unpacking the container, and running the application.&lt;/li&gt;&lt;li&gt;&lt;p&gt;Containers should only be scheduled together in a single Pod if they are tightly coupled and need to share resources such as disk.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;https://d33wubrfki0l68.cloudfront.net/5cb72d407cbe2755e581b6de757e0d81760d5b86/a9df9/docs/tutorials/kubernetes-basics/public/images/module_03_nodes.svg&#34; alt=&#34;ContainersPods&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The Kubernetes Master is a collection of three processes that run on a single node in your cluster, which is designated as the master node. Those processes are: kube-apiserver, kube-controller-manager and kube-scheduler.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Each individual non-master node in your cluster runs two processes:&lt;ul&gt;&lt;li&gt;kubelet, which communicates with the Kubernetes Master.&lt;/li&gt;&lt;li&gt;kube-proxy, a network proxy which reflects Kubernetes networking services on each node.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Pod Lifecycle&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Container probes&lt;ul&gt;&lt;li&gt;A Probe is a diagnostic performed periodically by the kubelet on a Container. To perform a diagnostic, the kubelet calls a Handler implemented by the Container.&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ExecAction&lt;/strong&gt;: Executes a specified command inside the Container. The diagnostic is considered successful if the command exits with a status code of 0.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;TCPSocketAction&lt;/strong&gt;: Performs a TCP check against the Container’s IP address on a specified port. The diagnostic is considered successful if the port is open.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;HTTPGetAction&lt;/strong&gt;: The diagnostic is considered successful if the response has a status code greater than or equal to 200 and less than 400.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;The kubelet can optionally perform and react to three kinds of probes on running Containers:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;livenessProbe&lt;/strong&gt;: Indicates whether the Container is running. If the liveness probe fails, the kubelet kills the Container, and the Container is subjected to its restart policy. If a Container does not provide a liveness probe, the default state is Success.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;readinessProbe&lt;/strong&gt;: Indicates whether the Container is ready to service requests. If the readiness probe fails, the endpoints controller removes the Pod’s IP address from the endpoints of all Services that match the Pod. The default state of readiness before the initial delay is Failure. If a Container does not provide a readiness probe, the default state is Success.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;startupProbe&lt;/strong&gt;: Indicates whether the application within the Container is started. All other probes are disabled if a startup probe is provided, until it succeeds. If the startup probe fails, the kubelet kills the Container, and the Container is subjected to its restart policy.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Use different kind of pods for different kind of usage:&lt;ul&gt;&lt;li&gt;Use a &lt;strong&gt;Job&lt;/strong&gt; for Pods that are expected to terminate, for example, batch computations. Jobs are appropriate only for Pods with restartPolicy equal to OnFailure or Never.&lt;/li&gt;&lt;li&gt;Use a &lt;strong&gt;ReplicationController&lt;/strong&gt;, &lt;strong&gt;ReplicaSet&lt;/strong&gt;, or &lt;strong&gt;Deployment&lt;/strong&gt; for Pods that are not expected to terminate, for example, web servers. ReplicationControllers are appropriate only for Pods with a restartPolicy of Always.&lt;/li&gt;&lt;li&gt;Use a &lt;strong&gt;DaemonSet&lt;/strong&gt; for Pods that need to run one per machine, because they provide a machine-specific system service.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Init Containers&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A Pod can have one or more init containers, which are run before the app containers are started.&lt;/li&gt;&lt;li&gt;Init containers are exactly like regular containers, except:&lt;ul&gt;&lt;li&gt;Init containers always run to completion.&lt;/li&gt;&lt;li&gt;Each init container must complete successfully before the next one starts.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Kubernetes repeatedly restarts the Pod until the init container succeeds. However, if the Pod has a restartPolicy of &lt;strong&gt;Never&lt;/strong&gt;, Kubernetes does not restart the Pod.&lt;/li&gt;&lt;li&gt;Init containers support all the fields and features of app containers, including resource limits, volumes, and security settings.&lt;/li&gt;&lt;li&gt;Init containers do not support readiness probes because they must run to completion before the Pod can be ready.&lt;/li&gt;&lt;li&gt;If you specify multiple init containers for a Pod, Kubelet runs each init container sequentially. Each init container must succeed before the next can run. When all of the init containers have run to completion, Kubelet initializes the application containers for the Pod and runs them as usual.&lt;/li&gt;&lt;li&gt;Example of defining init containers for a pod. The init containers will keep&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;apiVersion: v1kind: Podmetadata:  name: myapp-pod  labels:    app: myappspec:  containers:  - name: myapp-container    image: busybox:&lt;span style=&#34;color:#ae81ff&#34;&gt;1.28&lt;/span&gt;    command: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sh&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-c&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;echo The app is running! &amp;amp;&amp;amp; sleep 3600&amp;#39;&lt;/span&gt;]  initContainers:  - name: init-myservice    image: busybox:&lt;span style=&#34;color:#ae81ff&#34;&gt;1.28&lt;/span&gt;    command: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sh&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-c&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done&amp;#34;&lt;/span&gt;]  - name: init-mydb    image: busybox:&lt;span style=&#34;color:#ae81ff&#34;&gt;1.28&lt;/span&gt;    command: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sh&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-c&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done&amp;#34;&lt;/span&gt;]---apiVersion: v1kind: Servicemetadata:  name: myservicespec:  ports:  - protocol: TCP    port: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;    targetPort: &lt;span style=&#34;color:#ae81ff&#34;&gt;9376&lt;/span&gt;---apiVersion: v1kind: Servicemetadata:  name: mydbspec:  ports:  - protocol: TCP    port: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;    targetPort: &lt;span style=&#34;color:#ae81ff&#34;&gt;9377&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Pod Preset&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Kubernetes provides an admission controller (PodPreset) which, when enabled, applies Pod Presets to incoming pod creation requests.&lt;/li&gt;&lt;li&gt;When a pod creation request occurs, the system does the following:&lt;ul&gt;&lt;li&gt;Retrieve all &lt;strong&gt;PodPresets&lt;/strong&gt; available for use.&lt;/li&gt;&lt;li&gt;Check if the label selectors of any PodPreset matches the labels on the pod being created.&lt;/li&gt;&lt;li&gt;Attempt to merge the various resources defined by the PodPreset into the Pod being created.&lt;/li&gt;&lt;li&gt;On error, throw an event documenting the merge error on the pod, and create the pod without any injected resources from the PodPreset.&lt;/li&gt;&lt;li&gt;Annotate the resulting modified Pod spec, the annotation is of the form podpreset.admission.kubernetes.io/podpreset-&lt;pod-preset name&gt;: &amp;ldquo;&lt;resource version&gt;&amp;rdquo;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Controllers&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;ReplicaSet&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A ReplicaSet’s purpose is to maintain a stable set of replica Pods running at any given time. As such, it is often used to guarantee the availability of a specified number of identical Pods.&lt;/li&gt;&lt;li&gt;&lt;p&gt;How a ReplicaSet works&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A ReplicaSet is defined with fields, including a selector that specifies how to identify Pods it can acquire, a number of replicas indicating how many Pods it should be maintaining.&lt;/li&gt;&lt;li&gt;A ReplicaSet then fulfills its purpose by creating and deleting Pods as needed to reach the desired number. When a ReplicaSet needs to create new Pods, it uses its Pod template.&lt;/li&gt;&lt;li&gt;A ReplicaSet identifies new Pods to acquire by using its selector.&lt;/li&gt;&lt;li&gt;Example:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;apiVersion: apps/v1kind: ReplicaSetmetadata:  name: frontend  labels:    app: guestbook    tier: frontendspec:  &lt;span style=&#34;color:#75715e&#34;&gt;# modify replicas according to your case&lt;/span&gt;  replicas: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;  selector:    matchLabels:      tier: frontend  template:    metadata:      labels:    tier: frontend    spec:      containers:      - name: php-redis    image: gcr.io/google_samples/gb-frontend:v3&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Make sure when declaring &lt;strong&gt;Pod&lt;/strong&gt; kind: the metadata.labels.tier does not match the one in the ReplicaSet selector.matchLabels.tier field. If it does match the Pod will be obtained as part of the ReplicaSet. Look under &lt;a href=&#34;https://v1-17.docs.kubernetes.io/docs/concepts/workloads/controllers/replicaset&#34;&gt;Non-Template Pod acquisitions&lt;/a&gt; in  for more info.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ReplicationController&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A ReplicationController ensures that a specified number of pod replicas are running at any one time. In other words, a ReplicationController makes sure that a pod or a homogeneous set of pods is always up and available.&lt;/li&gt;&lt;li&gt;A ReplicationController is similar to a process supervisor, but instead of supervising individual processes on a single node, the ReplicationController supervises multiple pods across multiple nodes.&lt;/li&gt;&lt;li&gt;A simple case is to create one ReplicationController object to reliably run one instance of a Pod indefinitely. A more complex use case is to run several identical replicas of a replicated service, such as web servers.&lt;/li&gt;&lt;li&gt;Example:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;apiVersion: v1kind: ReplicationControllermetadata:  name: nginxspec:  replicas: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;  selector:    app: nginx  template:    metadata:      name: nginx      labels:    app: nginx    spec:      containers:      - name: nginx    image: nginx    ports:    - containerPort: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Deployments&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A Deployment provides declarative updates for Pods and ReplicaSets. The Deployment Controller changes the actual state to the desired state at a controlled rate.&lt;/li&gt;&lt;li&gt;You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;apiVersion: apps/v1kind: Deploymentmetadata:  name: nginx-deployment  labels:    app: nginxspec:  replicas: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;  selector:    matchLabels:      app: nginx  template:    metadata:      labels:    app: nginx    spec:      containers:      - name: nginx    image: nginx:&lt;span style=&#34;color:#ae81ff&#34;&gt;1.14.2&lt;/span&gt;    ports:    - containerPort: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Following are the explanation of the meaning of the above example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A Deployment named nginx-deployment is created, indicated by the .metadata.name field.&lt;/li&gt;&lt;li&gt;The Deployment creates three replicated Pods, indicated by the replicas field.&lt;/li&gt;&lt;li&gt;The selector field defines how the Deployment finds which Pods to manage. In this case, you simply select a label that is defined in the Pod template (app: nginx). However, more sophisticated selection rules are possible, as long as the Pod template itself satisfies the rule.&lt;/li&gt;&lt;li&gt;The template field contains the following sub-fields:&lt;ul&gt;&lt;li&gt;The Pods are labeled app: nginxusing the labels field.&lt;/li&gt;&lt;li&gt;The Pod template’s specification, or .template.spec field, indicates that the Pods run one container, nginx, which runs the nginx Docker Hub image at version 1.14.2.&lt;/li&gt;&lt;li&gt;Create one container and name it nginx using the name field.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To see the Deployment rollout status, run&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl rollout status deployment.v1.apps/nginx-deployment.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To see the ReplicaSet (rs) created by the Deployment, run&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl get rs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Updating deployment:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Update the nginx Pods to use the nginx:1.16.1 image instead of the nginx:1.14.2 image.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;nginx:1.16.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;or simply use the following command&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl set image deployment/nginx-deployment nginx&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;nginx:1.16.1 --record&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Alternatively, you can edit the Deployment and change .spec.template.spec.containers[0].image from nginx:1.14.2 to nginx:1.16.1&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl edit deployment.v1.apps/nginx-deployment&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Get details of your Deployment:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl describe deployments&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;For example, suppose you create a Deployment to create 5 replicas of &lt;strong&gt;nginx:1.14.2&lt;/strong&gt;, but then update the Deployment to create 5 replicas of &lt;strong&gt;nginx:1.16.1&lt;/strong&gt;, when only 3 replicas of &lt;strong&gt;nginx:1.14.2&lt;/strong&gt; had been created. In that case, the Deployment immediately starts killing the 3 &lt;strong&gt;nginx:1.14.2&lt;/strong&gt; Pods that it had created, and starts creating &lt;strong&gt;nginx:1.16.1&lt;/strong&gt; Pods. It does not wait for the 5 replicas of &lt;strong&gt;nginx:1.14.2&lt;/strong&gt; to be created before changing course&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Rolling Back a Deployment&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Suppose that you made a typo while updating the Deployment, by putting the image name as nginx:1.161 instead of nginx:1.16.1:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl set image deployment.v1.apps/nginx-deployment nginx&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;nginx:1.161 --record&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The rollout gets stuck. You can verify it by checking the rollout status:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl rollout status deployment.v1.apps/nginx-deployment&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Rolling Back to a Previous Revision&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt; kubectl rollout undo deployment.v1.apps/nginx-deployment&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Scaling a Deployment&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;You can scale a Deployment by using the following command:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl scale deployment.v1.apps/nginx-deployment --replicas&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Assuming horizontal Pod autoscaling is enabled in your cluster, you can setup an autoscaler for your Deployment and choose the minimum and maximum number of Pods you want to run based on the CPU utilization of your existing Pods.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl autoscale deployment.v1.apps/nginx-deployment --min&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; --max&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;15&lt;/span&gt; --cpu-percent&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Pausing and Resuming a Deployment&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Pause by running the following command:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl rollout pause deployment.v1.apps/nginx-deployment&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You can make as many updates as you wish, for example, update the resources that will be used:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl set resources deployment.v1.apps/nginx-deployment -c&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;nginx --limits&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;cpu&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;200m,memory&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512Mi&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Eventually, resume the Deployment and observe a new ReplicaSet coming up with all the new updates:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt; kubectl rollout resume deployment.v1.apps/nginx-deployment&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;StatefulSets&lt;/p&gt;&lt;ul&gt;&lt;li&gt;StatefulSet is the workload API object used to manage stateful applications. Manages the deployment and scaling of a set of Pods , and provides guarantees about the ordering and uniqueness of these Pods. Like a Deployment , a StatefulSet manages Pods that are based on an identical container spec. Unlike a Deployment, a StatefulSet maintains a sticky identity for each of their Pods. These pods are created from the same spec, but are not interchangeable: each has a persistent identifier that it maintains across any rescheduling.&lt;/li&gt;&lt;li&gt;&lt;p&gt;StatefulSets are valuable for applications that require one or more of the following.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Stable, unique network identifiers.&lt;/li&gt;&lt;li&gt;Stable, persistent storage.&lt;/li&gt;&lt;li&gt;Ordered, graceful deployment and scaling.&lt;/li&gt;&lt;li&gt;Ordered, automated rolling updates.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Stable is synonymous with persistence across Pod (re)scheduling. If an application doesn’t require any stable identifiers or ordered deployment, deletion, or scaling, you should deploy your application using a workload object that provides a set of stateless replicas. Deployment or ReplicaSet may be better suited to your stateless needs&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;apiVersion: v1kind: Servicemetadata:  name: nginx  labels:    app: nginxspec:  ports:  - port: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;    name: web  clusterIP: None  selector:    app: nginx---apiVersion: apps/v1kind: StatefulSetmetadata:  name: webspec:  selector:    matchLabels:      app: nginx &lt;span style=&#34;color:#75715e&#34;&gt;# has to match .spec.template.metadata.labels&lt;/span&gt;  serviceName: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;  replicas: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# by default is 1&lt;/span&gt;  template:    metadata:      labels:    app: nginx &lt;span style=&#34;color:#75715e&#34;&gt;# has to match .spec.selector.matchLabels&lt;/span&gt;    spec:      terminationGracePeriodSeconds: &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;      containers:      - name: nginx    image: k8s.gcr.io/nginx-slim:&lt;span style=&#34;color:#ae81ff&#34;&gt;0.8&lt;/span&gt;    ports:    - containerPort: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;      name: web    volumeMounts:    - name: www      mountPath: /usr/share/nginx/html  volumeClaimTemplates:  - metadata:      name: www    spec:      accessModes: [ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ReadWriteOnce&amp;#34;&lt;/span&gt; ]      storageClassName: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;my-storage-class&amp;#34;&lt;/span&gt;      resources:    requests:      storage: 1Gi&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Explanation about the above example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A Headless Service, named &lt;strong&gt;nginx&lt;/strong&gt;, is used to control the network domain.&lt;/li&gt;&lt;li&gt;The StatefulSet, named &lt;strong&gt;web&lt;/strong&gt;, has a Spec that indicates that 3 replicas of the nginx container will be launched in unique Pods.&lt;/li&gt;&lt;li&gt;The &lt;strong&gt;volumeClaimTemplates&lt;/strong&gt; will provide stable storage using &lt;strong&gt;PersistentVolumes&lt;/strong&gt; provisioned by a PersistentVolume Provisioner&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Stable Network ID&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Each Pod in a StatefulSet derives its hostname from the name of the StatefulSet and the ordinal of the Pod.&lt;/li&gt;&lt;li&gt;The pattern for the constructed hostname is &lt;strong&gt;$(statefulset name)-$(ordinal)&lt;/strong&gt;. The example above will create three Pods named &lt;strong&gt;web-0,web-1,web-2&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;A StatefulSet can use a Headless Service to control the domain of its Pods. The domain managed by this Service takes the form: &lt;strong&gt;$(service name).$(namespace).svc.cluster.local&lt;/strong&gt;, where “cluster.local” is the cluster domain.&lt;/li&gt;&lt;li&gt;As each Pod is created, it gets a matching DNS subdomain, taking the form: &lt;strong&gt;$(podname).$(governing service domain)&lt;/strong&gt;, where the governing service is defined by the serviceName field on the StatefulSet.&lt;/li&gt;&lt;li&gt;&lt;p&gt;Here are some examples of choices for Cluster Domain, Service name, StatefulSet name, and how that affects the DNS names for the StatefulSet’s Pods.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/kubernetesbraindump/domain_names.png&#34; alt=&#34;Domains&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Stable Storage&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In the nginx example above, each Pod will receive a single PersistentVolume with a StorageClass of &lt;strong&gt;my-storage-class&lt;/strong&gt; and &lt;strong&gt;1 Gib&lt;/strong&gt; of provisioned storage.&lt;/li&gt;&lt;li&gt;If no StorageClass is specified, then the default StorageClass will be used. When a Pod is (re)scheduled onto a node, its volumeMounts mount the PersistentVolumes associated with its PersistentVolume Claims.&lt;/li&gt;&lt;li&gt;Note that, the PersistentVolumes associated with the Pods’ PersistentVolume Claims are not deleted when the Pods, or StatefulSet are deleted. This must be done manually.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Pod Name Label&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When the StatefulSet Controller creates a Pod, it adds a label, &lt;strong&gt;statefulset.kubernetes.io/pod-name&lt;/strong&gt;, that is set to the name of the Pod. This label allows you to attach a Service to a specific Pod in the StatefulSet&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;DaemonSet&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A DaemonSet ensures that all (or some) Nodes run a copy of a Pod. As nodes are added to the cluster, Pods are added to them. As nodes are removed from the cluster, those Pods are garbage collected. Deleting a DaemonSet will clean up the Pods it created.&lt;/li&gt;&lt;li&gt;Some typical uses of a DaemonSet are:&lt;ul&gt;&lt;li&gt;running a cluster storage daemon, such as glusterd, ceph, on each node.&lt;/li&gt;&lt;li&gt;running a logs collection daemon on every node, such as fluentd or filebeat.&lt;/li&gt;&lt;li&gt;running a node monitoring daemon on every node, such as Prometheus Node Exporter, Flowmill, Sysdig Agent, collectd, Dynatrace OneAgent, AppDynamics Agent, Datadog agent, New Relic agent, Ganglia gmond, Instana Agent or Elastic Metricbeat.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;In a simple case, one DaemonSet, covering all nodes, would be used for each type of daemon. A more complex setup might use multiple DaemonSets for a single type of daemon, but with different flags and/or different memory and cpu requests for different hardware types.&lt;/li&gt;&lt;li&gt;Example:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;apiVersion: apps/v1kind: DaemonSetmetadata:name: fluentd-elasticsearchnamespace: kube-systemlabels:k8s-app: fluentd-loggingspec:selector:matchLabels:  name: fluentd-elasticsearchtemplate:metadata:  labels:name: fluentd-elasticsearchspec:  tolerations:  &lt;span style=&#34;color:#75715e&#34;&gt;# this toleration is to have the daemonset runnable on master nodes&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# remove it if your masters can&amp;#39;t run pods&lt;/span&gt;  - key: node-role.kubernetes.io/mastereffect: NoSchedule  containers:  - name: fluentd-elasticsearchimage: quay.io/fluentd_elasticsearch/fluentd:v2&lt;span style=&#34;color:#ae81ff&#34;&gt;.5.2&lt;/span&gt;resources:  limits:    memory: 200Mi  requests:    cpu: 100m    memory: 200MivolumeMounts:- name: varlog  mountPath: /var/log- name: varlibdockercontainers  mountPath: /var/lib/docker/containers  readOnly: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;  terminationGracePeriodSeconds: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;  volumes:  - name: varloghostPath:  path: /var/log  - name: varlibdockercontainershostPath:  path: /var/lib/docker/containers&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;How Daemon Pods are Scheduled&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Scheduled by default scheduler&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A DaemonSet ensures that all eligible nodes run a copy of a Pod. Normally, the node that a Pod runs on is selected by the Kubernetes scheduler.&lt;/li&gt;&lt;li&gt;However, DaemonSet pods are created and scheduled by the DaemonSet controller instead. That introduces the following issues:&lt;ul&gt;&lt;li&gt;Inconsistent Pod behavior: Normal Pods waiting to be scheduled are created and in Pending state, but DaemonSet pods are not created in Pending state. This is confusing to the user.&lt;/li&gt;&lt;li&gt;Pod preemption is handled by default scheduler. When preemption is enabled, the DaemonSet controller will make scheduling decisions without considering pod priority and preemption.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ScheduleDaemonSetPods&lt;/strong&gt; allows you to schedule DaemonSets using the default scheduler instead of the DaemonSet controller, by adding the NodeAffinity term to the DaemonSet pods, instead of the .spec.nodeName term.&lt;/li&gt;&lt;li&gt;The default scheduler is then used to bind the pod to the target host. If node affinity of the DaemonSet pod already exists, it is replaced. The DaemonSet controller only performs these operations when creating or modifying DaemonSet pods, and no changes are made to the spec.template of the DaemonSet.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;nodeAffinity:  requiredDuringSchedulingIgnoredDuringExecution:    nodeSelectorTerms:    - matchFields:      - key: metadata.name    operator: In    values:    - target-host-name&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Taints and Tolerations&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/kubernetesbraindump/taints_tolerations.png&#34; alt=&#34;TaintsTolerations&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Services&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;A Service in Kubernetes is an abstraction which defines a logical set of Pods and a policy by which to access them. Services enable a loose coupling between dependent Pods. A Service is defined using YAML (preferred) or JSON, like all Kubernetes objects. The set of Pods targeted by a Service is usually determined by a LabelSelector (see below for why you might want a Service without including selector in the spec).&lt;/li&gt;&lt;li&gt;&lt;p&gt;Services can be exposed in different ways by specifying a type in the ServiceSpec:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ClusterIP&lt;/strong&gt; (default) - Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;NodePort&lt;/strong&gt; - Exposes the Service on the same port of each selected Node in the cluster using NAT. Makes a Service accessible from outside the cluster using &lt;NodeIP&gt;:&lt;NodePort&gt;. Superset of ClusterIP.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;LoadBalancer&lt;/strong&gt; - Creates an external load balancer in the current cloud (if supported) and assigns a fixed, external IP to the Service. Superset of NodePort.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ExternalName&lt;/strong&gt; - Exposes the Service using an arbitrary name (specified by externalName in the spec) by returning a CNAME record with the name. No proxy is used. This type requires v1.7 or higher of kube-dns.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Services match a set of Pods using labels and selectors, a grouping primitive that allows logical operation on objects in Kubernetes. Labels are key/value pairs attached to objects and can be used in any number of ways:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Designate objects for development, test, and production&lt;/li&gt;&lt;li&gt;Embed version tags&lt;/li&gt;&lt;li&gt;Classify an object using tags&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;https://d33wubrfki0l68.cloudfront.net/cc38b0f3c0fd94e66495e3a4198f2096cdecd3d5/ace10/docs/tutorials/kubernetes-basics/public/images/module_04_services.svg&#34; alt=&#34;Services&#34; /&gt;&lt;img src=&#34;https://d33wubrfki0l68.cloudfront.net/b964c59cdc1979dd4e1904c25f43745564ef6bee/f3351/docs/tutorials/kubernetes-basics/public/images/module_04_labels.svg&#34; alt=&#34;Services&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Every node in a Kubernetes cluster runs a kube-proxy. kube-proxy is responsible for implementing a form of virtual IP for Services of type other than ExternalName&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;DNS&lt;/p&gt;&lt;ul&gt;&lt;li&gt;For example, if you have a Service called &amp;ldquo;my-service&amp;rdquo; in a Kubernetes Namespace &amp;ldquo;my-ns&amp;rdquo;, the control plane and the DNS Service acting together create a DNS record for &amp;ldquo;my-service.my-ns&amp;rdquo;. Pods in the &amp;ldquo;my-ns&amp;rdquo; Namespace should be able to find it by simply doing a name lookup for my-service (&amp;ldquo;my-service.my-ns&amp;rdquo; would also work). Pods in other Namespaces must qualify the name as my-service.my-ns. These names will resolve to the cluster IP assigned for the Service.&lt;/li&gt;&lt;li&gt;Kubernetes also supports DNS SRV (Service) records for named ports. If the &amp;ldquo;my-service.my-ns&amp;rdquo; Service has a port named &amp;ldquo;http&amp;rdquo; with the protocol set to TCP, you can do a DNS SRV query for _http._tcp.my-service.my-ns to discover the port number for &amp;ldquo;http&amp;rdquo;, as well as the IP address&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Once you’ve set your desired state, the Kubernetes Control Plane makes the cluster’s current state match the desired state via the Pod Lifecycle Event Generator (PLEG). The Kubernetes Control Plane consists of a collection of processes running on your cluster:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The various parts of the Kubernetes Control Plane, such as the Kubernetes Master and kubelet processes, govern how Kubernetes communicates with your cluster. The Control Plane maintains a record of all of the Kubernetes Objects in the system, and runs continuous control loops to manage those objects’ state. At any given time, the Control Plane’s control loops will respond to changes in the cluster and work to make the actual state of all the objects in the system match the desired state that you provided.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Master Components-Master components provide the cluster’s control plane. Master components make global decisions about the cluster (for example, scheduling), and they detect and respond to cluster events (for example, starting up a new pod when a deployment’s replicas field is unsatisfied).  For simplicity, set up scripts typically start all master components on the same machine, and do not run user containers on this machine. See Building High-Availability Clusters for an example multi-master-VM setup.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;kube-apiserver&lt;/strong&gt; - Component on the master that exposes the Kubernetes API. It is the front-end for the Kubernetes control plane.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;etcd&lt;/strong&gt; - Consistent and highly-available key value store used as Kubernetes’ backing store for all cluster data.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;kube-scheduler&lt;/strong&gt; - Component on the master that watches newly created pods that have no node assigned, and selects a node for them to run on.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;kube-controller-manager&lt;/strong&gt; - Component on the master that runs controllers.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;https://d33wubrfki0l68.cloudfront.net/e298a92e2454520dddefc3b4df28ad68f9b91c6f/70d52/images/docs/pre-ccm-arch.png&#34; alt=&#34;KubernetesControllerManager&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Logically, each controller is a separate process, but to reduce complexity, they are all compiled into a single binary and run in a single process. These controllers include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Node Controller: Responsible for noticing and responding when nodes go down.&lt;/li&gt;&lt;li&gt;Replication Controller: Responsible for maintaining the correct number of pods for every replication controller object in the system.&lt;/li&gt;&lt;li&gt;Endpoints Controller: Populates the Endpoints object (that is, joins Services &amp;amp; Pods).&lt;/li&gt;&lt;li&gt;Service Account &amp;amp; Token Controllers: Create default accounts and API access tokens for new namespaces.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;cloud-controller-manager&lt;/strong&gt; - cloud-controller-manager runs controllers that interact with the underlying cloud providers. The cloud-controller-manager binary is an alpha feature introduced in Kubernetes release 1.6.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;cloud-controller-manager runs cloud-provider-specific controller loops only. You must disable these controller loops in the kube-controller-manager. You can disable the controller loops by setting the &amp;ndash;cloud-provider flag to external when starting the kube-controller-manager. cloud-controller-manager allows the cloud vendor’s code and the Kubernetes code to evolve independently of each other. In prior releases, the core Kubernetes code was dependent upon cloud-provider-specific code for functionality. In future releases, code specific to cloud vendors should be maintained by the cloud vendor themselves, and linked to cloud-controller-manager while running Kubernetes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The following controllers have cloud provider dependencies:&lt;/p&gt;&lt;p&gt;[x] &lt;strong&gt;Node Controller&lt;/strong&gt; &amp;ndash; For checking the cloud provider to determine if a node has been deleted in the cloud after it stops responding&lt;/p&gt;&lt;p&gt;[x] &lt;strong&gt;Route Controller&lt;/strong&gt; &amp;ndash; For setting up routes in the underlying cloud infrastructure&lt;/p&gt;&lt;p&gt;[x] &lt;strong&gt;Service Controller&lt;/strong&gt; - For creating, updating and deleting cloud provider load balancers&lt;/p&gt;&lt;p&gt;[x] &lt;strong&gt;Volume Controller&lt;/strong&gt; - For creating, attaching, and mounting volumes, and interacting with the cloud provider to orchestrate volumes&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;https://d33wubrfki0l68.cloudfront.net/518e18713c865fe67a5f23fc64260806d72b38f5/61d75/images/docs/post-ccm-arch.png&#34; alt=&#34;KubernetesControllerManager&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Addons&lt;/h2&gt;&lt;p&gt;Addons use Kubernetes resources (DaemonSet, Deployment, etc) to implement cluster features. Because these are providing cluster-level features, namespaced resources for addons belong within the kube-system namespace.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS&lt;/strong&gt; - While the other addons are not strictly required, all Kubernetes clusters should have cluster DNS, as many examples rely on it. Cluster DNS is a DNS server, in addition to the other DNS server(s) in your environment, which serves DNS records for Kubernetes services. Containers started by Kubernetes automatically include this DNS server in their DNS searches.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web UI (Dashboard)&lt;/strong&gt; - Dashboard is a general purpose, web-based UI for Kubernetes clusters. It allows users to manage and troubleshoot applications running in the cluster, as well as the cluster itself.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container Resource Monitoring&lt;/strong&gt; - Container Resource Monitoring records generic time-series metrics about containers in a central database, and provides a UI for browsing that data.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cluster-level Logging&lt;/strong&gt; - Cluster-level logging mechanism is responsible for saving container logs to a central log store with search/browsing interface.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The basic Kubernetes objects include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Pod&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Service&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Volume&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Namespace&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;kubeadm&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Running &amp;lsquo;kubeadm init&amp;rsquo; will run phases of initialization to setup Kubernetes cluster. The code that break down these steps reside inside app/cmd/phases/init&lt;ul&gt;&lt;li&gt;preflight step reside inside app/preflight&lt;/li&gt;&lt;li&gt;&lt;strong&gt;app/preflight/checks.go&lt;/strong&gt; &amp;ndash; contains lots of checking related to preflight (check port availability, check existence of directory, check app availability in PATH, etc)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;app/cmd/phases&lt;/strong&gt; &amp;ndash; these directory contains code that is tied to the different command line function in kubeadm (eg: phases/init &amp;ndash;&amp;gt; has code that link to &amp;lsquo;kubeadm init&amp;rsquo;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;/init&lt;/strong&gt; &amp;ndash; directory contains code for all the phases when executing &amp;lsquo;kubeadm init&amp;rsquo;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;/join&lt;/strong&gt; &amp;ndash; directory contains code for the &amp;lsquo;kubeadm join&amp;rsquo; command&lt;/li&gt;&lt;li&gt;&lt;strong&gt;/reset&lt;/strong&gt; &amp;ndash; directory contains code for the &amp;lsquo;kubeadm reset&amp;rsquo; command&lt;/li&gt;&lt;li&gt;&lt;strong&gt;/upgrade&lt;/strong&gt; &amp;ndash; directory contains code for the &amp;lsquo;kubeadm upgrade&amp;rsquo; command&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;app/phases&lt;/strong&gt; &amp;ndash; contains code used as part of the kubeadm phases&lt;/li&gt;&lt;li&gt;&lt;strong&gt;app/util/system&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;cgroup_validator&lt;/strong&gt; &amp;ndash; validator for cgroups&lt;/li&gt;&lt;li&gt;&lt;strong&gt;docker_validator&lt;/strong&gt; &amp;ndash; docker validator&lt;/li&gt;&lt;li&gt;&lt;strong&gt;kernel_validator&lt;/strong&gt; &amp;ndash; kernel validator&lt;/li&gt;&lt;li&gt;&lt;strong&gt;os_validator&lt;/strong&gt; &amp;ndash; OS validator (version)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;package_validator&lt;/strong&gt; &amp;ndash; package manager validator&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;csi-container-storage-interface&#34;&gt;CSI (Container Storage Interface)&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Interfacing K8 with storage implementation&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Node&lt;/strong&gt; &amp;ndash;  A host where a workload (such as Pods in Kubernetes) will be running.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Plugin&lt;/strong&gt; - In the CSI world, this points to a service that exposes gRPC endpoints&lt;img src=&#34;https://arslan.io/images/how-to-write-a-container-storage-interface-%28csi%29-plugin-2.jpg&#34; alt=&#34;CSIPicture&#34; /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Specification defines the boundary between the CO and the CSI plugin.&lt;/li&gt;&lt;li&gt;Plugin part actually is separated into two individual plugins.&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Node Plugin&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;The Node plugin is a gRPC server that needs to run on the Node where the volume will be provisioned. So suppose you have a Kubernetes cluster with three nodes where your Pod’s are scheduled, you would deploy this to all three nodes.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Controller Plugin&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;The Controller plugin is a gRPC server that can run anywhere. In terms of a Kubernetes cluster, it can run on any node (even on the master node).These two entities can live in a single binary or you can separate them.&lt;img src=&#34;https://arslan.io/images/how-to-write-a-container-storage-interface-%28csi%29-plugin-3.jpg&#34; alt=&#34;CSIPicture&#34; /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://arslan.io/2018/06/21/how-to-write-a-container-storage-interface-csi-plugin/&#34;&gt;Good example and explanation on how to implement CSI&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=_qfSzrPn9Cs&#34;&gt;https://www.youtube.com/watch?v=_qfSzrPn9Cs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://blogs.igalia.com/dpino/2016/04/10/network-namespaces/&#34;&gt;https://blogs.igalia.com/dpino/2016/04/10/network-namespaces/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/containernetworking/cni/blob/master/SPEC.md&#34;&gt;https://github.com/containernetworking/cni/blob/master/SPEC.md&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/containernetworking/plugins&#34;&gt;https://github.com/containernetworking/plugins&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://medium.com/@vikram.fugro/container-networking-interface-aka-cni-bdfe23f865cf&#34;&gt;show how the CNI works using the containetworking github.com account&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.cncf.io/blog/2017/05/23/cncf-hosts-container-networking-interface-cni/&#34;&gt;specification and implementation of CNI&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.weave.works/docs/net/latest/kubernetes/kube-addon/&#34;&gt;weavenet is network plugin for docker for variety of things (service discovery, etc), this website outlined how to use it as inside kubernetes&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/darshanime/notes/blob/master/kubernetes.org&#34;&gt;Good explanation about how the different parts of Kubernetes works&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;experimenting-with-kubernetes&#34;&gt;Experimenting with Kubernetes&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/hobby-kube/guide&#34;&gt;A good guide on cloud provider&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/luxas/kubernetes-on-arm&#34;&gt;Kubernetes on ARM (ODROID, RPi, Upboard combo)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.trion.de/news/2019/05/06/kubernetes-odroid-n2.html&#34;&gt;Kubernetes on ODROID N2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/PatrickLang/28a05cfd6cf4322d519d04cff0996585&#34;&gt;Setting up a Multi-Arch, Multi OS cluster&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.weave.works/blog/kubernetes-raspberry-pi/&#34;&gt;Kubernetes on Raspberry Pi: Challenges &amp;amp; Advantages&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.mirantis.com/blog/how-install-kubernetes-kubeadm/&#34;&gt;Intalling kubernetes using kubeadm&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://octetz.com/posts/ha-control-plane-k8s-kubeadm&#34;&gt;Kubernetes HA control plane&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;books&#34;&gt;Books&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Programming Kubernetes - OReilly&lt;/li&gt;&lt;li&gt;Kubernetes Patterns    - OReilly&lt;/li&gt;&lt;li&gt;Managing Kubernetes    - OReilly&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Minikube Development</title>
       <link>/post/minikubedev/</link>
       <pubDate>Sat, 30 Nov 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/minikubedev/</guid>
       <description>&lt;p&gt;This document goes through things that are helpful for development purposes&lt;/p&gt;&lt;h2 id=&#34;cache&#34;&gt;cache&lt;/h2&gt;&lt;p&gt;This command is useful to use the local docker image in minikube. Docker images are stored in the local repo and using the cache command allow the image to be uploaded into the VM.&lt;/p&gt;&lt;p&gt;This is useful when doing local development and we want to use the image inside the VM&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Inside minikube source code</title>
       <link>/post/walkingthroughminikubesourcecode/</link>
       <pubDate>Tue, 17 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/walkingthroughminikubesourcecode/</guid>
       <description>&lt;p&gt;&lt;strong&gt;NOTE: The source code discussed in this article is based on &lt;em&gt;master&lt;/em&gt; branch&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;We are going to create a separate brand new GOPATH directory for minikube to demonstrate how to do the whole process fresh from scratch. On my local machine I&amp;rsquo;ve create a directory called &lt;em&gt;minikubegopath&lt;/em&gt; with the following structure&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;.├── bin├── pkg└── src    └── k8s.io&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure are you inside the src/k8s.io directory when cloning minikube&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;git clone https://github.com/kubernetes/minikube&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Open the minikube inside the IDE and set the GOPATH to the new GOPATH directory that have minikube, setup it as shown in the screenshot below&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/minikubesourcecode/minikubesourcecode_setupgopath_ide.png&#34; alt=&#34;MinikubeSourceCodeSettingGoPath&#34; /&gt;&lt;/p&gt;&lt;p&gt;Select the the &lt;em&gt;main.go&lt;/em&gt; file that reside in cmd/minikube directory and hit the run button. You will get an error output as shown below, this is because there are some files that need to be generated and this can be done using the &lt;em&gt;make&lt;/em&gt; command&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/minikubesourcecode/minikubesourcecode_hitrun.png&#34; alt=&#34;MinikubeSourceCodeHitRun&#34; /&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;go: downloading github.com/mattn/go-isatty v0.0.8go: downloading github.com/pkg/profile v0.0.0-20161223203901-3a8809bd8a80go: downloading github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b...............# k8s.io/minikube/pkg/minikube/translate../../pkg/minikube/translate/translate.go:77:12: undefined: AssetCompilation finished with exit code 2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Use the following &lt;em&gt;make&lt;/em&gt; command to generate the files needed&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;make pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You will see the following output&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;which go-bindata || GO111MODULE=off GOBIN=XXXXXXXX/minikubegopath/bin go get github.com/jteeuwen/go-bindata/.......... go-bindata -nomemcopy -o pkg/minikube/assets/assets.go -pkg assets deploy/addons/...gofmt -s -w pkg/minikube/assets/assets.go......GOOS=&amp;#34;linux&amp;#34; GOARCH=&amp;#34;amd64&amp;#34; go build -tags &amp;#34;container_image_ostree_stub containers_image_openpgp&amp;#34; -ldflags=&amp;#34;-X k8s.io/minikube/pkg/version.version=v1.4.0-beta.2 -X k8s.io/minikube/pkg/version.isoVersion=v1.4.0-beta.2 -X k8s.io/minikube/pkg/version.isoPath=minikube/iso -X k8s.io/minikube/pkg/version.gitCommitID=&amp;#34;d1e468085d9af12e5d130a6cb3b2186a5db87a0e-dirty&amp;#34;&amp;#34; -a -o out/minikube-linux-amd64 k8s.io/minikube/cmd/minikube&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following are the generated files&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;pkg/minikube/assets/assets.go --&amp;gt; generate source code to allow loading of addons .yaml filespkg/minikube/translate/translations.go --&amp;gt; generate source code for translations data file&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;Makefile&lt;/h1&gt;&lt;p&gt;Following table explains some of the available tasks:&lt;/p&gt;&lt;table class=&#34;table table-responsive table-dark table-danger&#34;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;pkg/minikube/assets/assets.go&lt;/strong&gt;  ==&amp;gt; generate source code needed to build minikube. Source code generated are used for loading of .yaml file&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;pkg/minikube/translate/translations.go&lt;/strong&gt; ==&amp;gt; generate source code for translations data file&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;minikube-linux-amd64&lt;/strong&gt; ==&amp;gt; generate minikube for Linux 64-bit. Windows task minikube-windows-amd64.exe and MacOS minikube-darwin-amd64&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;out/e2e-linux-amd64&lt;/strong&gt; ==&amp;gt; compile end-to-end testing and minikube binary for testing purposes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;minikube_iso&lt;/strong&gt; ==&amp;gt; used internally to generate the .iso file. Better use the out/minikube.iso&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;iso-menuconfig&lt;/strong&gt; ==&amp;gt; change buildroot configuration for  minikube iso&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;linux-menuconfig&lt;/strong&gt; ==&amp;gt; change kernel configuration for minikube iso&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;all&lt;/strong&gt; ==&amp;gt; compile and generate minikube for the 3 platforms - Linux, Windows and MacOS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;cross&lt;/strong&gt; ==&amp;gt; build minikube for the 3 platforms - Linux, Windows and MacOS&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h1&gt;Source structure&lt;/h1&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;.├── cmd│   ├── drivers│   │   ├── hyperkit│   │   └── kvm│   ├── extract│   ├── gvisor│   ├── minikube│   │   └── cmd│   │       └── config│   └── storage-provisioner├── deploy│   ├── addons│   │   ├── dashboard│   │   ├── efk│   │   ├── freshpod│   │   ├── gpu│   │   ├── gvisor│   │   ├── heapster│   │   ├── ingress│   │   ├── logviewer│   │   ├── metrics-server│   │   ├── registry│   │   ├── registry-creds│   │   ├── storageclass│   │   ├── storage-provisioner│   │   └── storage-provisioner-gluster│   ├── gvisor│   ├── iso│   │   └── minikube-iso│   │       ├── board│   │       │   └── coreos│   │       │       └── minikube│   │       │           └── rootfs-overlay│   │       │               ├── etc│   │       │               │   ├── cni│   │       │               │   │   └── net.d│   │       │               │   ├── docker│   │       │               │   ├── ssh│   │       │               │   ├── systemd│   │       │               │   │   ├── network│   │       │               │   │   └── system│   │       │               │   │       ├── getty.target.wants│   │       │               │   │       └── systemd-timesyncd.service.d│   │       │               │   └── udev│   │       │               │       └── rules.d│   │       │               ├── usr│   │       │               │   └── bin│   │       │               └── var│   │       │                   ├── lib│   │       │                   │   └── boot2docker│   │       │                   ├── log│   │       │                   └── run│   │       │                       └── crio│   │       ├── configs│   │       └── package│   │           ├── automount│   │           ├── cni-bin│   │           ├── cni-plugins-bin│   │           ├── conmon-master│   │           ├── containerd-bin│   │           ├── crictl-bin│   │           ├── crio-bin│   │           ├── docker-bin│   │           ├── gluster│   │           ├── hyperv-daemons│   │           ├── podman│   │           ├── runc-master│   │           └── vbox-guest│   ├── minikube│   └── storage-provisioner├── docs│   └── contributors├── hack│   ├── boilerplate│   ├── help_text│   ├── jenkins│   │   └── installers│   ├── kubernetes_version│   ├── prow│   └── release_notes├── images│   └── logo├── installers│   ├── darwin│   │   └── brew-cask│   ├── linux│   │   ├── archlinux│   │   ├── archlinux-driver│   │   ├── deb│   │   │   ├── kvm2_deb_template│   │   │   │   └── DEBIAN│   │   │   └── minikube_deb_template│   │   │       └── DEBIAN│   │   ├── kvm│   │   └── rpm│   │       ├── kvm2_rpm_template│   │       └── minikube_rpm_template│   └── windows├── pkg│   ├── drivers│   │   ├── hyperkit│   │   ├── kvm│   │   └── none│   ├── gvisor│   ├── initflag│   ├── kapi│   ├── minikube│   │   ├── assets│   │   ├── bootstrapper│   │   │   └── kubeadm│   │   │       └── testdata│   │   │           ├── v1.11│   │   │           ├── v1.12│   │   │           ├── v1.13│   │   │           ├── v1.14│   │   │           ├── v1.15│   │   │           └── v1.16│   │   ├── cluster│   │   ├── command│   │   ├── config│   │   │   └── testdata│   │   ├── constants│   │   ├── cruntime│   │   ├── drivers│   │   │   ├── hyperkit│   │   │   ├── hyperv│   │   │   ├── kvm2│   │   │   ├── none│   │   │   ├── parallels│   │   │   ├── virtualbox│   │   │   ├── vmware│   │   │   └── vmwarefusion│   │   ├── exit│   │   ├── extract│   │   │   └── testdata│   │   ├── kubeconfig│   │   │   └── testdata│   │   │       └── kubeconfig│   │   ├── logs│   │   ├── machine│   │   ├── notify│   │   ├── out│   │   ├── problem│   │   ├── proxy│   │   ├── registry│   │   ├── service│   │   ├── sshutil│   │   ├── storageclass│   │   ├── tests│   │   ├── translate│   │   └── tunnel│   ├── provision│   ├── storage│   ├── util│   │   ├── lock│   │   └── retry│   └── version├── site│   ├── assets│   │   ├── icons│   │   └── scss│   ├── content│   │   └── en│   │       ├── blog│   │       │   ├── news│   │       │   └── releases│   │       ├── community│   │       └── docs│   │           ├── Concepts│   │           ├── Contributing│   │           ├── Examples│   │           ├── Overview│   │           ├── Reference│   │           │   ├── Commands│   │           │   ├── Configuration│   │           │   ├── Drivers│   │           │   │   └── includes│   │           │   └── Networking│   │           ├── Start│   │           │   └── includes│   │           ├── Tasks│   │           │   └── Registry│   │           └── Tutorials│   ├── layouts│   │   ├── partials│   │   │   └── hooks│   │   └── shortcodes│   ├── static│   │   ├── css│   │   └── js│   └── themes│       └── docsy├── test│   └── integration│       └── testdata│           ├── kvm2-driver-older-version│           └── kvm2-driver-without-version├── third_party│   └── go9p│       └── ufs└── translations&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following table are description of the different directories of minikube&amp;rsquo;s source code. &lt;strong&gt;Note: This is by no means a complete list of the source directory structure as master branch do change from time to time&lt;/strong&gt;&lt;/p&gt;&lt;table class=&#34;table table-responsive table-dark table-striped table-bordered&#34;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Directory Name&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;drivers&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;docker-machine plugin code (libvirt and hyperkit)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;cmd/gvisor&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Code to start gvisor and do all the necessary steps to restart the dependencies (containerd, etc)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;minikube&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;minikube cli handling code&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;storage-provisioner&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Main function to trigger the storage provisioner module&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;deploy&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Contains files that are needed to build minikube inside docker&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;deploy/addons&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Lots of minikube addons (*.yaml) inside this directory such as: gvisor → used to securely run pods with untrusted workloads, freshpods → restart container,etc&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;deploy/gvisor&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;contain Dockerfile to run gvisor-addon&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;deploy/iso&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Contains documentation, packages and configuration for building minikube iso. Some of the packages that are included – automount,containerd and many more. It also contains configuration file for building buildroot. Pretty much anything related to building iso in inside this directory&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;deploy/minikube&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Contains few json files related to release&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;deploy/storage-provisioner&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Contain dockerfile to run storage-provisioner&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;hack/jenkins&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Jenkins configuration file&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;hack/kubernetes_version&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Tool to generate Minikube version number&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;hack/release_notes&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Code to create release notes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;installers/darwin&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;script to create Darwin installer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;installers/linux&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Linux – deb, archlinux, rpm, etc&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;installers/windows&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Windows installers&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;pkg/drivers&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Driver related code – kvm, hyperkit&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;site&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Docsy template for generating documents as website&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;test&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Integration test for Minikube&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;go9p&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Go implementation of 9P2000 protocol (9P (or the Plan 9 Filesystem Protocol or Styx) is a network protocol developed for the Plan 9 from Bell Labs distributed operating system as the means of connecting the components of a Plan 9 system. Files are key objects in Plan 9. They represent windows, network connections, processes, and almost anything else available in the operating system. )&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;translations&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Language translation at the moment CN and FR&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;</description>
     </item>
   
     <item>
       <title>Inside minikube ISO</title>
       <link>/post/insideminikubeiso/</link>
       <pubDate>Tue, 10 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/insideminikubeiso/</guid>
       <description>&lt;p&gt;Minikube uses a generated .iso file that is used to bootstrap the VM with it&amp;rsquo;s own &lt;a href=&#34;https://en.wikipedia.org/wiki/Linux_kernel&#34;&gt;kernel&lt;/a&gt; and  &lt;a href=&#34;https://en.wikipedia.org/wiki/Initial_ramdisk&#34;&gt;rootfs&lt;/a&gt;. Once the VM has been initialized properly it will use the .iso to bootstrap the Linux kernel allowing all the different applications to be installed and run. This means that pretty much minikube is running on it&amp;rsquo;s own operating system and does not use any dependencies from the host system (except through the VM)&lt;/p&gt;&lt;h1&gt;Building .iso file&lt;/h1&gt;&lt;p&gt;Building the .iso file for minikube requires docker to be running on your local machine. Internally it uses docker container to build everything (kernel + rootfs) and package it into an .iso file. There are 2 separate make tasks that need to be triggered as shown below:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;buildroot-image: $(ISO_BUILD_IMAGE) # convenient alias to build the docker container$(ISO_BUILD_IMAGE): deploy/iso/minikube-iso/Dockerfiledocker build $(ISO_DOCKER_EXTRA_ARGS) -t $@ -f $&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt; $(dir $&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;)@echo &amp;#34;&amp;#34;@echo &amp;#34;$(@) successfully built&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;out/minikube.iso: $(shell find &amp;#34;deploy/iso/minikube-iso&amp;#34; -type f)ifeq ($(IN_DOCKER),1)$(MAKE) minikube_isoelsedocker run --rm --workdir /mnt --volume $(CURDIR):/mnt $(ISO_DOCKER_EXTRA_ARGS) \--user $(shell id -u):$(shell id -g) --env HOME=/tmp --env IN_DOCKER=1 \$(ISO_BUILD_IMAGE) /usr/bin/make out/minikube.isoendif&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means there are 2 separate tasks that need to be executed&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;make&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;buildroot&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;image&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; | &lt;span style=&#34;color:#a6e22e&#34;&gt;tee&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;buildrootimage&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;txt&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;make&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;minikube&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;iso&lt;/span&gt;   &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; | &lt;span style=&#34;color:#a6e22e&#34;&gt;tee&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;buildminikubeiso&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;txt&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output of the build process will be piped into &lt;em&gt;buildrootimage.txt&lt;/em&gt; and &lt;em&gt;buildminikubeiso.txt&lt;/em&gt; file to make it easy for troubleshooting purposes. Here is a snapshpot of how the output looks like from both the logs&lt;/p&gt;&lt;p&gt;&lt;strong&gt;buildrootimage.txt&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;docker build  -t gcr.io/k8s-minikube/buildroot-image -f deploy/iso/minikube-iso/Dockerfile deploy/iso/minikube-iso/Sending build context to Docker daemon  184.3kBStep 1/6 : FROM ubuntu:18.0418.04: Pulling from library/ubuntu35c102085707: Pulling fs layer251f5509d51d: Pulling fs layer..........8e829fe70a46: Pull complete6001e1789921: Verifying Checksum6001e1789921: Download complete6001e1789921: Pull completeDigest: sha256:d1d454df0f579c6be4d8161d227462d69e163a8ff9d20a847533989cf0c94d90Status: Downloaded newer image for ubuntu:18.04 ---&amp;gt; a2a15febcdf3Step 2/6 : RUN apt-get update &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install -y apt dpkg apt-utils ca-certificates &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get upgrade -y &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install -y build-essential git wget cpio python unzip bc gcc-multilib automake libtool gnupg2 p7zip-full locales rsync dumb-init golang-go libpcre3-dev &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/lib/apt/lists/* ---&amp;gt; Running in 3e3ff8ddac3eGet:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]Get:3 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [766 kB]Get:4 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]Get:5 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]Get:6 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [186 kB]..........Unpacking manpages-dev (4.15-1) ...Selecting previously unselected package p7zip.Preparing to unpack .../153-p7zip_16.02+dfsg-6_amd64.deb ...Unpacking p7zip (16.02+dfsg-6) .............Removing intermediate container 3e3ff8ddac3e ---&amp;gt; 89cfa69b7f86Step 3/6 : RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 ---&amp;gt; Running in e68c807a6dbfRemoving intermediate container e68c807a6dbf ---&amp;gt; c69896a88da3Step 4/6 : ENV LANG en_US.utf8 ---&amp;gt; Running in 58df4bca1563Removing intermediate container 58df4bca1563 ---&amp;gt; c181b08523adStep 5/6 : ENTRYPOINT [&amp;#34;/usr/bin/dumb-init&amp;#34;, &amp;#34;--&amp;#34;] ---&amp;gt; Running in 46918f491955Removing intermediate container 46918f491955 ---&amp;gt; 3e76d78225fcStep 6/6 : CMD [&amp;#34;/bin/bash&amp;#34;] ---&amp;gt; Running in 6cefbf569aadRemoving intermediate container 6cefbf569aad ---&amp;gt; 2217637c1629Successfully built 2217637c1629Successfully tagged gcr.io/k8s-minikube/buildroot-image:latestgcr.io/k8s-minikube/buildroot-image successfully built&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;buildminikubeiso.txt&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;docker run --rm --workdir /mnt --volume /home/nanik/Downloads/temp/packages/src/k8s.io/minikube:/mnt  \--user 1000:1000 --env HOME=/tmp --env IN_DOCKER=1 \gcr.io/k8s-minikube/buildroot-image /usr/bin/make out/minikube.iso/usr/bin/make minikube_isomake[1]: Entering directory &amp;#39;/mnt&amp;#39;echo v1.4.0-beta.0 &amp;gt; deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/etc/VERSIONif [ ! -d ./out/buildroot ]; then \mkdir -p ./out; \git clone --depth=1 --branch=2018.05.3 https://github.com/buildroot/buildroot ./out/buildroot; \fi;Cloning into &amp;#39;./out/buildroot&amp;#39;...Note: checking out &amp;#39;717309783755a883974896ea822675a7bf46da3a&amp;#39;...../usr/bin/make BR2_EXTERNAL=../../deploy/iso/minikube-iso minikube_defconfig -C ./out/buildroot................&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;Using Virtualbox&lt;/h1&gt;&lt;p&gt;Just for fun let&amp;rsquo;s try to run the .iso file by ourself using the VirtualBox.&lt;/p&gt;&lt;p&gt;Start the VirtualBox UI from your local machine&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/buildingiso/building_iso_minikube_virtualbox_startup.png&#34; alt=&#34;BuildingISOVirtualboxStartup&#34; /&gt;&lt;/p&gt;&lt;p&gt;Create and configure virtual machine using the same setting as shown in the screenshot&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/buildingiso/building_iso_minikube_machine_setting.png&#34; alt=&#34;BuildingISOVMSetting&#34; /&gt;&lt;/p&gt;&lt;p&gt;Make sure you specify the newly generated .iso file from your local build like the below screenshot&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/buildingiso/building_iso_minikube_setup_iso_file.png&#34; alt=&#34;BuildingISOSetupISOFile&#34; /&gt;&lt;/p&gt;&lt;p&gt;Once configured properly starts up the VM and you will see output similar to the following screenshot&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/buildingiso/building_iso_minikube_kernel_bootup.png&#34; alt=&#34;BuildingISOKernelStartup&#34; /&gt;&lt;/p&gt;&lt;p&gt;When the kernel startup properly the screen will show the prompt as shown the following screenshot. Enter &lt;strong&gt;root&lt;/strong&gt; as the username and you will be inside the bash environment&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/buildingiso/building_iso_minikube_login.png&#34; alt=&#34;BuildingISOLoginScreen&#34; /&gt;&lt;/p&gt;&lt;p&gt;Even though you are able to run the .iso file the VM is still in it&amp;rsquo;s raw form as there are no Kubernetes app or configuration installed. So pretty much this is just an empty OS wihtout Kubernetes.&lt;/p&gt;&lt;p&gt;By going through through this exercise you now have a better idea the gaps that minikube try to fill in. Minikube fills in the gap by automating the whole process until the whole thing is up and running.&lt;/p&gt;&lt;h1&gt;Dissecting minikube .iso file&lt;/h1&gt;&lt;p&gt;Now that we have successfully generate and use the freshly build iso file, it&amp;rsquo;s time to dissect and take a look inside it. The iso file is a ISO9660 file which means it can be mounted to a local directory.&lt;/p&gt;&lt;p&gt;You can create any directory anywhere you like and mount the iso file, in my case I have created a directory /home/nanik/Downloads/playwithiso/mountiso and used the following command to mount the file&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sudo&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mount&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;o&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;loop&lt;/span&gt; .&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;minikube&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;iso&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;home&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;nanik&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Downloads&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;playwithiso&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mountiso&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the mount command successfully executed you will see the following tree structure&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;├── boot│   ├── bzImage│   └── initrd├── boot.catalog└── isolinux    ├── isolinux.bin    ├── isolinux.cfg    └── ldlinux.c32&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;as can be see the iso file contain the rootfs (initrd) and kernel (bzImage) along with the the &lt;a href=&#34;https://wiki.syslinux.org/wiki/index.php?title=Doc/isolinux&#34;&gt;ISOLINUX bootloader&lt;/a&gt; files&lt;/p&gt;&lt;h1&gt;Chroot&lt;/h1&gt;&lt;p&gt;To further having fun with the iso file let&amp;rsquo;s use the rootfs to boot into it using &lt;a href=&#34;https://en.wikipedia.org/wiki/Chroot&#34;&gt;chroot&lt;/a&gt;. Copy the initrd file from the mounted directory described on the previous section and use the following command to unzip it&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;bunzip2&lt;/span&gt; .&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;initrd&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;the initrd will be unzipped to a file called initrd.out, use the following command to unpack the file&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;cpio&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;idv&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#a6e22e&#34;&gt;initrd&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;the file will be unpacked to the following tree structure&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;├── bin -&amp;gt; usr/bin├── dev├── etc│   ├── cni│   ├── containerd│   ├── containers│   ├── crio│   ├── dbus-1│   ├── docker│   ├── glusterfs│   ├── init.d│   ├── iproute2│   ├── kernel│   ├── lvm│   ├── modules-load.d│   ├── pam.d│   ├── profile.d│   ├── ssh│   ├── ssl│   ├── sudoers.d│   ├── sysconfig│   ├── sysctl.d│   ├── systemd│   ├── tmpfiles.d│   ├── udev│   ├── vmware-tools│   ├── X11│   └── xdg├── home│   └── docker├── lib -&amp;gt; usr/lib├── lib64 -&amp;gt; lib├── media├── mnt├── opt│   └── cni├── proc├── root├── run│   ├── crio│   ├── dbus│   ├── gluster│   ├── nfs│   └── sudo├── sbin -&amp;gt; usr/sbin├── srv├── sys├── tmp├── usr│   ├── bin│   ├── etc│   ├── lib│   ├── lib64 -&amp;gt; lib│   ├── libexec│   ├── sbin│   └── share└── var    ├── empty    ├── lib    ├── log    └── run -&amp;gt; ../run&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure you are inside the extracted directory and use the following command to chroot into it&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sudo&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;chroot&lt;/span&gt; .&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;you will get bash prompt as follows&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;bash&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;4.4&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;#&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To come out from the bash just type exit.&lt;/p&gt;&lt;h1&gt;Using local build .iso file&lt;/h1&gt;&lt;p&gt;The following command specified minikube to use locally built iso file&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;minikube&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;start&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;--&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;iso&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;=&lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;:&lt;span style=&#34;color:#f92672&#34;&gt;///&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;home&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;nanik&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Downloads&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;temp&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;packages&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;k8s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;io&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;minikube&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;minikube&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;iso&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Below is the log output&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;😄  minikube v0.0.0-unset on Ubuntu xx.xx🔥  Creating virtualbox VM (CPUs=2, Memory=2000MB, Disk=20000MB) ...Downloading /home/nanik/.minikube/cache/boot2docker.iso from file:///home/nanik/Downloads/temp/packages/src/k8s.io/minikube/out/minikube.iso...Creating VirtualBox VM...Creating SSH key...Starting the VM...Check network to re-create if needed...Waiting for an IP...Setting Docker configuration on the remote daemon...Waiting for SSH to be available...Detecting the provisioner...🐳  Preparing Kubernetes v1.16.0-beta.1 on Docker 18.09.8 ...🚜  Pulling images ...🚀  Launching Kubernetes ... ⌛  Waiting for: apiserver proxy etcd scheduler controller dns🏄  Done! kubectl is now configured to use &amp;#34;minikube&amp;#34;💡  For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NOTE: notice the message Downloading /home/nanik/.minikube/cache/boot2docker.iso the process behind this message is actually using the specified minikube.iso and copying it to boot2docker.iso&lt;/p&gt;&lt;h1&gt;Reference&lt;/h1&gt;&lt;p&gt;&lt;a href=&#34;https://minikube.sigs.k8s.io/docs/contributing/iso/&#34;&gt;Contributing minikube iso&lt;/a&gt;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Minikube Startup Process</title>
       <link>/post/howminikubeworks/</link>
       <pubDate>Fri, 06 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/howminikubeworks/</guid>
       <description>&lt;h1&gt;Overview&lt;/h1&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/kubernetes/minikube&#34;&gt;Minikube&lt;/a&gt; is called cluster-in-a-box and the reason why it is called that is because it contains everything that you will need to run cluster on a local environment. The tool is good to get a head strat into the Kubernetes world.&lt;/p&gt;&lt;p&gt;Kubernetes as a project is a collection of tools that works together to deliver container clustering solution. The difference with minikube is that as a developer we don&amp;rsquo;t have to worry installing the different projects together as it&amp;rsquo;s neatly packaged into a simple file that can be run directly.&lt;/p&gt;&lt;p&gt;This article will outlined the different steps that minikube goes through until it starts up and running ready to be used for deploying application. This article assume you have successfully gone through the steps outlined in the &lt;a href=&#34;https://nanikjava.github.io/post/minikube/&#34;&gt;Building and hacking minikube &lt;/a&gt; article.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE: This article is using VirtualBox so there are some explanation which are VirtualBox specific&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h1&gt;Startup Flow&lt;/h1&gt;&lt;p&gt;Following are the startup process when minikube starts up:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Download .iso file if it is not available locally&lt;/li&gt;&lt;li&gt;Extract boot2docker.iso from the downloaded .iso file&lt;/li&gt;&lt;li&gt;Create on-the-fly certificate to be used for ssh purposes&lt;/li&gt;&lt;li&gt;Create VirtualBox VM file with specified configuration&lt;/li&gt;&lt;li&gt;Setup storage to mount boot2docker.iso file&lt;/li&gt;&lt;li&gt;Setup network related configuration (IP, DHCP, etc)&lt;/li&gt;&lt;li&gt;Setup SSH inside the VM&lt;/li&gt;&lt;li&gt;Startup VM&lt;/li&gt;&lt;li&gt;Setup /etc/hostname, /etc/hosts&lt;/li&gt;&lt;li&gt;Setup systemd relevant files to allow docker to start properly&lt;/li&gt;&lt;li&gt;Prepare Kubernetes and Docker&lt;/li&gt;&lt;li&gt;Download all the relevant Kubernetes files - kubelet, kubeadm, etc&lt;/li&gt;&lt;li&gt;Pulling docker images for the different packages needed for Kubernetes&lt;/li&gt;&lt;li&gt;Start up different services such as - etcd, scheduler, controller, apiserver, etc&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;All configuration, keys, iso image, etc that are used to prepare minikube are available inside $HOME/.minikube. Following is how the directory structure looks like&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;├── [4.0K]  addons├── [1.3K]  apiserver.crt├── [1.6K]  apiserver.key├── [4.0K]  cache│   ├── [4.0K]  images│   │   ├── [4.0K]  gcr.io│   │   │   └── [4.0K]  k8s-minikube│   │   │       └── [ 20M]  storage-provisioner_v1.8.1│   │   └── [4.0K]  k8s.gcr.io│   │       ├── [ 12M]  coredns_1.3.1│   │       ├── [ 73M]  etcd_3.3.10│   │       ├── [ 11M]  k8s-dns-dnsmasq-nanny-amd64_1.14.13│   │       ├── [ 14M]  k8s-dns-kube-dns-amd64_1.14.13│   │       ├── [ 12M]  k8s-dns-sidecar-amd64_1.14.13│   │       ├── [ 29M]  kube-addon-manager_v9.0│   │       ├── [ 47M]  kube-apiserver_v1.15.2│   │       ├── [ 46M]  kube-controller-manager_v1.15.2│   │       ├── [ 29M]  kube-proxy_v1.15.2│   │       ├── [ 43M]  kubernetes-dashboard-amd64_v1.10.1│   │       ├── [ 28M]  kube-scheduler_v1.15.2│   │       └── [312K]  pause_3.1│   ├── [4.0K]  iso│   │   └── [131M]  minikube-v1.3.0.iso│   └── [4.0K]  v1.15.2│       ├── [ 38M]  kubeadm│       └── [114M]  kubelet├── [1.0K]  ca.crt├── [1.6K]  ca.key├── [1.0K]  ca.pem├── [1.0K]  cert.pem├── [4.0K]  certs│   ├── [1.6K]  ca-key.pem│   ├── [1.0K]  ca.pem│   ├── [1.0K]  cert.pem│   └── [1.6K]  key.pem├── [1.1K]  client.crt├── [1.6K]  client.key├── [4.0K]  config├── [4.0K]  files├── [1.6K]  key.pem├── [  29]  last_update_check├── [4.0K]  logs├── [4.0K]  machines│   ├── [4.0K]  minikube│   │   ├── [131M]  boot2docker.iso│   │   ├── [2.7K]  config.json│   │   ├── [2.0G]  disk.vmdk│   │   ├── [1.6K]  id_rsa│   │   ├── [ 381]  id_rsa.pub│   │   └── [4.0K]  minikube│   │       ├── [4.0K]  Logs│   │       │   └── [ 80K]  VBox.log│   │       ├── [3.7K]  minikube.vbox│   │       └── [3.6K]  minikube.vbox-prev│   ├── [1.6K]  server-key.pem│   └── [1.1K]  server.pem├── [4.0K]  profiles│   └── [4.0K]  minikube│       └── [1.5K]  config.json├── [1.0K]  proxy-client-ca.crt├── [1.6K]  proxy-client-ca.key├── [1.1K]  proxy-client.crt└── [1.6K]  proxy-client.key&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr /&gt;&lt;h1&gt;Inside VirtualBox&lt;/h1&gt;&lt;p&gt;Once minikube is up and running we can ssh into the VM. Setup the configuration as shown in the screenshot below&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/minikube_ssh.png&#34; alt=&#34;MinikubeSSH&#34; /&gt;&lt;/p&gt;&lt;p&gt;You will get output that looks like the following and it will display a minikube shell for you to work inside the VM.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;COMMAND: /usr/bin/VBoxManage showvminfo minikube --machinereadableSTDOUT:{name=&amp;#34;minikube&amp;#34;groups=&amp;#34;/&amp;#34;ostype=&amp;#34;Linux 2.6 / 3.x / 4.x (64-bit)&amp;#34;UUID=&amp;#34;xxxxxx&amp;#34;CfgFile=&amp;#34;/home/nanik/.minikube/machines/minikube/minikube/minikube.vbox&amp;#34;SnapFldr=&amp;#34;/home/nanik/.minikube/machines/minikube/minikube/Snapshots&amp;#34;LogFldr=&amp;#34;/home/nanik/.minikube/machines/minikube/minikube/Logs&amp;#34;............}STDERR:{}Using SSH client type: native....                         _             _                        _         _ ( )           ( )             ___ ___  (_)  ___  (_)| |/&amp;#39;)  _   _ | |_      __  /&amp;#39; _ ` _ `\| |/&amp;#39; _ `\| || , &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;  ( ) ( )| &amp;#39;_`\  /&amp;#39;__`\| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/&amp;#39;(_,__/&amp;#39;`\____)$ &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Executing the following ps command&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sudo&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ps&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;A&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;will show the different process that is currently running inside the VM. As can be seen there are a number of Kubernetes service that are running.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;  PID TTY          TIME CMD    1 ?        00:00:19 systemd    2 ?        00:00:00 kthreadd    3 ?        00:00:01 kworker/0:0    4 ?        00:00:00 kworker/0:0H    6 ?        00:00:00 mm_percpu_wq   18 ?        00:00:00 netns   19 ?        00:00:00 kauditd  371 ?        00:00:00 oom_reaper  455 ?        00:00:00 writeback  456 ?        00:00:00 kcompactd0  458 ?        00:00:00 crypto  459 ?        00:00:00 kblockd  518 ?        00:00:00 ata_sff  535 ?        00:00:00 md..... 1223 ?        00:00:00 sshd 1225 ?        00:00:00 sshd 1226 pts/0    00:00:00 bash 1241 ?        00:00:00 ipv6_addrconf 1246 ?        00:00:00 ceph-msgr ..... 2014 tty1     00:00:00 getty 2018 ?        00:00:00 rpcbind 2028 ?        00:00:03 VBoxService 2033 ?        00:00:01 kworker/0:1H 2059 ?        00:00:00 lockd 2182 ?        00:00:00 sshd  ..... 2369 ?        00:04:42 dockerd 2376 ?        00:02:10 containerd 3644 ?        00:00:00 containerd-shim 3648 ?        00:00:00 containerd-shim 3656 ?        00:00:00 containerd-shim 3665 ?        00:00:00 containerd-shim 3719 ?        00:00:00 pause 3725 ?        00:00:00 pause 3732 ?        00:00:00 pause 3734 ?        00:00:00 pause 3865 ?        00:00:00 containerd-shim  ..... 3939 ?        00:07:46 kube-apiserver 3948 ?        00:00:00 bash 3970 ?        00:04:27 etcd 3975 ?        00:00:23 kube-scheduler 4321 ?        00:00:00 containerd-shim 4351 ?        00:00:00 containerd-shim 4361 ?        00:00:00 containerd-shim  ..... 4470 ?        00:00:00 containerd-shim 4498 ?        00:00:12 kube-proxy 4811 ?        00:00:00 containerd-shim 4829 ?        00:00:47 coredns 4864 ?        00:00:00 containerd-shim 4882 ?        00:00:00 pause 4906 ?        00:00:00 containerd-shim 4925 ?        00:00:07 storage-provisi 4996 ?        00:00:00 containerd-shim 5013 ?        00:00:51 coredns29243 ?        00:00:23 kubelet29441 ?        00:00:00 containerd-shim  .....29483 ?        00:00:00 containerd-shim29499 ?        00:00:10 kube-controller&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s query docker and see what are the images that are available inside the VM&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;$ docker image listREPOSITORY                                TAG                 IMAGE ID            CREATED             SIZEk8s.gcr.io/kube-scheduler                 v1.15.2             88fa9cb27bd2        4 weeks ago         81.1MBk8s.gcr.io/kube-controller-manager        v1.15.2             9f5df470155d        4 weeks ago         159MBk8s.gcr.io/kube-apiserver                 v1.15.2             34a53be6c9a7        4 weeks ago         207MBk8s.gcr.io/kube-proxy                     v1.15.2             167bbf6c9338        4 weeks ago         82.4MBk8s.gcr.io/kube-addon-manager             v9.0                119701e77cbc        7 months ago        83.1MBk8s.gcr.io/coredns                        1.3.1               eb516548c180        7 months ago        40.3MBk8s.gcr.io/kubernetes-dashboard-amd64     v1.10.1             f9aed6605b81        8 months ago        122MBk8s.gcr.io/etcd                           3.3.10              2c4adeb21b4f        9 months ago        258MBk8s.gcr.io/k8s-dns-sidecar-amd64          1.14.13             4b2e93f0133d        11 months ago       42.9MBk8s.gcr.io/k8s-dns-kube-dns-amd64         1.14.13             55a3c5209c5e        11 months ago       51.2MBk8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64    1.14.13             6dc8ef8287d3        11 months ago       41.4MBk8s.gcr.io/pause                          3.1                 da86e6ba6ca1        20 months ago       742kBgcr.io/k8s-minikube/storage-provisioner   v1.8.1              4689081edb10        22 months ago       80.8MB&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Minikube cod uses VirtualBox&amp;rsquo;s CLI command called VBoxManage, which resides inside /usr/bin. Following log snippets show some of the call that are performed when minikube starts up&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;......COMMAND: /usr/bin/VBoxManage --version......COMMAND: /usr/bin/VBoxManage list hostonlyifs......Downloading /home/nanik/.minikube/cache/boot2docker.iso from file:///home/nanik/.minikube/cache/iso/minikube-v1.3.0.iso...Creating VirtualBox VM...Creating SSH key...Creating disk image...Creating 20000 MB hard disk image...Writing magic tar headerWriting SSH key tar headerCalling inner createDiskImage&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;amp;&lt;/span&gt;{/usr/bin/VBoxManage [/usr/bin/VBoxManage convertfromraw stdin /home/nanik/.minikube/machines/minikube/disk.vmdk 20971520000 --format VMDK] [] ......}Starting commandCopying to stdinFilling zeroesClosing STDINWaiting on cmdCOMMAND: /usr/bin/VBoxManage createvm --basefolder /home/nanik/.minikube/machines/minikube --name minikube --register......COMMAND: /usr/bin/VBoxManage modifyvm minikube --firmware bios --bioslogofadein off --bioslogofadeout off --bioslogodisplaytime 0 --biosbootmenu disabled --ostype Linux26_64 --cpus 2 --memory 2000 --acpi on --ioapic on --rtcuseutc on --natdnshostresolver1 on --natdnsproxy1 off --cpuhotplug off --pae on --hpet on --hwvirtex on --nestedpaging on --largepages on --vtxvpid on --accelerate3d off --boot1 dvd......COMMAND: /usr/bin/VBoxManage modifyvm minikube --nic1 nat --nictype1 virtio --cableconnected1 on......COMMAND: /usr/bin/VBoxManage storagectl minikube --name SATA --add sata --hostiocache on......COMMAND: /usr/bin/VBoxManage storageattach minikube --storagectl SATA --port 0 --device 0 --type dvddrive --medium /home/nanik/.minikube/machines/minikube/boot2docker.iso......COMMAND: /usr/bin/VBoxManage storageattach minikube --storagectl SATA --port 1 --device 0 --type hdd --medium /home/nanik/.minikube/machines/minikube/disk.vmdk......COMMAND: /usr/bin/VBoxManage guestproperty set minikube /VirtualBox/GuestAdd/SharedFolders/MountPrefix /......COMMAND: /usr/bin/VBoxManage guestproperty set minikube /VirtualBox/GuestAdd/SharedFolders/MountDir /......setting up shareDir &amp;#39;/home&amp;#39; -&amp;gt; &amp;#39;hosthome&amp;#39;COMMAND: /usr/bin/VBoxManage sharedfolder add minikube --name hosthome --hostpath /home --automount......COMMAND: /usr/bin/VBoxManage setextradata minikube VBoxInternal2/SharedFoldersEnableSymlinksCreate/hosthome 1......Starting the VM...COMMAND: /usr/bin/VBoxManage showvminfo minikube --machinereadable......Check network to re-create if needed...COMMAND: /usr/bin/VBoxManage list hostonlyifs......Searching for hostonly interface for IPv4: xxxxx and Mask: xxxxxFound: vboxnet0COMMAND: /usr/bin/VBoxManage list dhcpservers......Removing orphan DHCP servers...COMMAND: /usr/bin/VBoxManage list hostonlyifs......Adding/Modifying DHCP server &amp;#34;xxxxxxx&amp;#34; with address range &amp;#34;xxxx&amp;#34; - &amp;#34;yyyyy&amp;#34;...COMMAND: /usr/bin/VBoxManage list dhcpservers......&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
     </item>
   
     <item>
       <title>Building and hacking minikube</title>
       <link>/post/minikube/</link>
       <pubDate>Thu, 05 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/minikube/</guid>
       <description>&lt;p&gt;This document will outline the internals on minikube. It will outline how minikube works and what are the steps involved in running it inside an IDE. Having the ability to run inside the IDE will give the power of more better understanding by stepping through the code.&lt;/p&gt;&lt;p&gt;Minikube makes heavy use of VM and out of the box it supports VMs such as VirtualBox, Hyperkit, etc. We going to go through the VirtualBox setup in Linux environment for this article.&lt;/p&gt;&lt;h2 id=&#34;prerequisite&#34;&gt;Prerequisite&lt;/h2&gt;&lt;p&gt;Minikube has dependencies on packages that will need to be installed on your local dev machine. The best way to ensure that you have all the relevant packages installed is to run through the Quickstart &lt;a href=&#34;https://kubernetes.io/docs/setup/learning-environment/minikube/&#34;&gt;steps&lt;/a&gt; on minikube tutorial website. Once you are able to run minikube on it&amp;rsquo;s own on your dev machine you should be able to run and debug it without any problem from inside the IDE.&lt;/p&gt;&lt;h2 id=&#34;building-minikube&#34;&gt;Building minikube&lt;/h2&gt;&lt;p&gt;This article will be using GoLand IDE as it provide a lot of features that makes development in Go very easy. You can download the IDE &lt;a href=&#34;https://www.jetbrains.com/go/&#34;&gt;here&lt;/a&gt; and install the IDE using the instruction outline on the website.&lt;/p&gt;&lt;p&gt;The GOPATH used in this article has been set to /home/nanik/Downloads/temp/packages&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/gopath_structure.png&#34; alt=&#34;GoPathStructure&#34; /&gt;&lt;/p&gt;&lt;p&gt;Completing the IDE installation checkout minikube into your GOPATH directory. On my local machine the minikube is stored under $GOPATH/src/k8s.io/minikube directory, as shows on the following screenshot&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/minikube_ide.png&#34; alt=&#34;GoPathStructure&#34; /&gt;&lt;/p&gt;&lt;p&gt;We need to setup the vendor directory for minikube by executing the following command&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;GO111MODULE&lt;/span&gt;=&lt;span style=&#34;color:#a6e22e&#34;&gt;on&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mod&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;vendor&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You will see vendor/ directory under the minikube source code.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/go_mod_vendor.png&#34; alt=&#34;GoPathStructure&#34; /&gt;&lt;/p&gt;&lt;p&gt;Before running minikube there are code that need to be generated by executing the make command. On your terminal execute the following command&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;make&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The other step that need to be done is to set the correct version of the .iso file that will be used by minikube. This .iso file will be automatically downloaded when minikube starts up. The version need to be set inside the file version.go under pkg/version directory as shown below, set it to v1.3.0&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/set_isoversion.png&#34; alt=&#34;isoversion&#34; /&gt;&lt;/p&gt;&lt;p&gt;Once the make build is complete the minikube code is not ready. The main function to execute minikube is inside the file main.go under the cmd/minikube directory&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/minikube_main_function.png&#34; alt=&#34;GoPathStructure&#34; /&gt;&lt;/p&gt;&lt;p&gt;Following is the directory structure of minikube source code (the screenshot shows 2 level deep directory tree)&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;├── cmd│   ├── drivers│   ├── extract│   ├── gvisor│   ├── minikube│   └── storage-provisioner├── deploy│   ├── addons│   ├── gvisor│   ├── iso│   ├── minikube│   └── storage-provisioner├── docs│   └── contributors├── hack│   ├── boilerplate│   ├── help_text│   ├── jenkins│   ├── kubernetes_version│   ├── prow│   └── release_notes├── images│   └── logo├── installers│   ├── darwin│   ├── linux│   └── windows├── out├── pkg│   ├── drivers│   ├── gvisor│   ├── initflag│   ├── kapi│   ├── minikube│   ├── provision│   ├── storage│   ├── util│   └── version├── site│   ├── assets│   ├── content│   ├── layouts│   ├── resources│   ├── static│   └── themes├── test│   └── integration├── third_party│   └── go9p├── translations└── vendor    ├── cloud.google.com    ├── github.com    ├── golang.org    ├── google.golang.org    ├── go.opencensus.io    ├── gopkg.in    ├── k8s.io    └── sigs.k8s.io&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we are ready to run the minikube. Use the parameter start as part of the program argument as shown in the screenshot&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/minikube_start_configuration.png&#34; alt=&#34;minikubestartconfiguration&#34; /&gt;&lt;/p&gt;&lt;p&gt;The parameter &amp;ndash;v=7  used is to provide verbose logging to help in troubleshooting in case of issues. The log output will look somewhat like the following&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;😄  minikube v0.0.0-unset on ......💡  Tip: Use &amp;#39;minikube start -p &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;&amp;gt;&amp;#39; to create a new cluster, or &amp;#39;minikube delete&amp;#39; to delete this one.COMMAND: /usr/bin/VBoxManage showvminfo minikube --machinereadableSTDOUT:{name=&amp;#34;minikube&amp;#34;groups=&amp;#34;/&amp;#34;ostype=&amp;#34;Linux 2.6 / 3.x / 4.x (64-bit)&amp;#34;UUID=&amp;#34;.....&amp;#34;CfgFile=&amp;#34;/home/nanik/.minikube/machines/minikube/minikube/minikube.vbox&amp;#34;SnapFldr=&amp;#34;/home/nanik/.minikube/machines/minikube/minikube/Snapshots&amp;#34;LogFldr=&amp;#34;/home/nanik/.minikube/machines/minikube/minikube/Logs&amp;#34;hardwareuuid=&amp;#34;.....&amp;#34;memory=2000....................................END SSH🔄  Relaunching Kubernetes using kubeadm ... ⌛  Waiting for: apiserver proxy etcd scheduler controller dns🏄  Done! kubectl is now configured to use &amp;#34;minikube&amp;#34;💡  For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once minikube has been ran successfully the application will exit as the VM now run in the bacground complete will the relevant kubernetes components installed inside it. To see the background process use the following command to peek into minikube running process on your machine&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ps&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;A&lt;/span&gt; | &lt;span style=&#34;color:#a6e22e&#34;&gt;grep&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;vb&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;you will see output similar to the following&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;..........28685 ?        00:00:51 VBoxXPCOMIPCD28690 ?        00:02:35 VBoxSVC28824 ?        15:53:35 VBoxHeadless28841 ?        00:00:06 VBoxNetDHCP&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now to confirm that all working well we need to execute command using minikube to check the cluster status. Use the following program argument to do this&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/minikube_status.png&#34; alt=&#34;minikubestatus&#34; /&gt;&lt;/p&gt;&lt;p&gt;You will get output that shows the following&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;host: Runningkubelet: Runningapiserver: Runningkubectl: Correctly Configured: pointing to minikube-vm at xx.xx.xx.xxs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you are ready to start playing around with minikube source code.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Deploying to Minikube(Work in progress)</title>
       <link>/post/deployingtominikube/</link>
       <pubDate>Sun, 01 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/deployingtominikube/</guid>
       <description>&lt;p&gt;We will deploy 2 different projects in this article. One is a simple single command line application and another is a web app that requires database. We will be using the skaffold project as it will make it easy to do continous deployment&lt;/p&gt;&lt;h1&gt;Launching minikube&lt;/h1&gt;&lt;h1&gt;Deployment&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;deploying via IDE&lt;/li&gt;&lt;li&gt;deploying via CLI&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;deploying-hello-world&#34;&gt;Deploying hello-world&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://kubernetes.io/docs/setup/learning-environment/minikube/&#34;&gt;https://kubernetes.io/docs/setup/learning-environment/minikube/&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;kubectl run hello-minikube &amp;ndash;image=k8s.gcr.io/echoserver:1.10 &amp;ndash;port=8080&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;kubectl expose deployment hello-minikube &amp;ndash;type=NodePort&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;kubectl get pod&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;minikube service hello-minikube &amp;ndash;url&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;k8-tools&#34;&gt;K8 Tools&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;skaffold - continues local development/deployment in k8 for golang&lt;/li&gt;&lt;li&gt;k8guard  - example to show deploying different applications inside k8 ( &lt;a href=&#34;https://k8guard.github.io/deploy/minikube/&#34;&gt;https://k8guard.github.io/deploy/minikube/&lt;/a&gt; )&lt;/li&gt;&lt;li&gt;ko       - Build and deploy Go applications on Kubernetes ( &lt;a href=&#34;https://github.com/google/ko&#34;&gt;https://github.com/google/ko&lt;/a&gt; )&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Golang</title>
       <link>/post/golang/</link>
       <pubDate>Sun, 01 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/golang/</guid>
       <description>&lt;p&gt;Following are some of the thing that need to be remembered when programming in Golang. This information is taken from variety of sources.&lt;/p&gt;&lt;hr /&gt;&lt;h2 id=&#34;variables&#34;&gt;Variables&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;For variable naming, omit words that are obvious given a variable&amp;rsquo;s type declaration or otherwise clear from the surrounding context. Following is not a good example&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;returnSlice&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make([]&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;, len(&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;))&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Variable names in Go should be short rather than long. This is especially true for local variables with limited scope. Prefer c to lineCount. Prefer i to sliceIndex.&lt;/li&gt;&lt;li&gt;The basic rule: the further from its declaration that a name is used, the more descriptive the name must be. For a method receiver, one or two letters is sufficient. Common variables such as loop indices and readers can be a single letter (i, r). More unusual things and global variables need more descriptive names.&lt;/li&gt;&lt;li&gt;For example, &amp;ldquo;URL&amp;rdquo; should appear as &amp;ldquo;URL&amp;rdquo; or &amp;ldquo;url&amp;rdquo; (as in &amp;ldquo;urlPony&amp;rdquo;, or &amp;ldquo;URLPony&amp;rdquo;), never as &amp;ldquo;Url&amp;rdquo;. ServeHTTP not ServeHttp.&lt;/li&gt;&lt;li&gt;For identifiers with multiple initialized &amp;ldquo;words&amp;rdquo;, use for example &amp;ldquo;xmlHTTPRequest&amp;rdquo; or &amp;ldquo;XMLHTTPRequest&amp;rdquo;.&lt;/li&gt;&lt;li&gt;Have a reasonable number of parameters and reasonably short variable names.&lt;/li&gt;&lt;li&gt;Having one doubled up field in the struct makes the test data difficult to scan. Following is not a good example :&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;prefix&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;postfix&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Declare empty slices as&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;declares&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;slice&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt;) &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;and not&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;{} (&lt;span style=&#34;color:#a6e22e&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;non&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;but&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;zero&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt;)            &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;interfaces-receivers&#34;&gt;Interfaces &amp;amp; Receivers&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;The following snippets shows how to do &amp;lsquo;force checking&amp;rsquo; of contact between &lt;strong&gt;type interface&lt;/strong&gt; and &lt;strong&gt;type struct&lt;/strong&gt;.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ValueConverter&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;ConvertValue&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;v&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}) (&lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;boolType&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt;{}&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Bool&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;boolType&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ValueConverter&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;boolType&lt;/span&gt;{}  &lt;span style=&#34;color:#f92672&#34;&gt;--&lt;/span&gt;&amp;gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;boolType&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Bool&amp;#34;&lt;/span&gt; }&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;boolType&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;ConvertValue&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{}) (&lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;.}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;the above provides a static (compile time) check that boolType satisfies the ValueConverter interface. The _ used as a name of the variable tells the compiler to effectively discard the RHS value, but to type-check it and evaluate it if it has any side effects, but the anonymous variable per se doesn&amp;rsquo;t take any process space.&lt;/p&gt;&lt;p&gt;It is a handy construct when developing and the method set of an interface and/or the methods implemented by a type are frequently changed. The construct serves as a guard against forgetting to match the method sets of a type and of an interface where the intent is to have them compatible. It effectively prevents to go install a broken (intermediate) version with such omission.&lt;/p&gt;&lt;p&gt;Another example (taken from &lt;strong&gt;&lt;a href=&#34;https://github.com/Kong/kuma/tree/master/pkg/core/discovery&#34;&gt;https://github.com/Kong/kuma/tree/master/pkg/core/discovery&lt;/a&gt;&lt;/strong&gt;) where the &lt;em&gt;sink.go&lt;/em&gt; enforce the contract inside the &lt;em&gt;interfaces.go&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;sink.go&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;discovery&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (        &lt;span style=&#34;color:#a6e22e&#34;&gt;mesh_core&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/Kong/kuma/pkg/core/resources/apis/mesh&amp;#34;&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;core_model&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/Kong/kuma/pkg/core/resources/model&amp;#34;&lt;/span&gt;    )    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySource&lt;/span&gt; = &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySink&lt;/span&gt;{}    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoveryConsumer&lt;/span&gt; = &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySink&lt;/span&gt;{}    &lt;span style=&#34;color:#75715e&#34;&gt;// DiscoverySink is both a source and a consumer of discovery information.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySink&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneConsumer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneDiscoveryConsumer&lt;/span&gt;    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySink&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;AddConsumer&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;consumer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoveryConsumer&lt;/span&gt;) {        &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneConsumer&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;consumer&lt;/span&gt;    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySink&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;OnDataplaneUpdate&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;dataplane&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mesh_core&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneResource&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneConsumer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneConsumer&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;OnDataplaneUpdate&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;dataplane&lt;/span&gt;)        }        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySink&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;OnDataplaneDelete&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;core_model&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ResourceKey&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneConsumer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneConsumer&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;OnDataplaneDelete&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt;)        }        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;interfaces.go&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;discovery&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (        &lt;span style=&#34;color:#a6e22e&#34;&gt;discovery_proto&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/Kong/kuma/api/discovery/v1alpha1&amp;#34;&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;mesh_core&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/Kong/kuma/pkg/core/resources/apis/mesh&amp;#34;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/Kong/kuma/pkg/core/resources/model&amp;#34;&lt;/span&gt;    )    &lt;span style=&#34;color:#75715e&#34;&gt;// DiscoverySource is a source of discovery information, i.e. Services and Workloads.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoverySource&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;AddConsumer&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoveryConsumer&lt;/span&gt;)    }    &lt;span style=&#34;color:#75715e&#34;&gt;// ServiceInfo combines original proto object with auxiliary information.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ServiceInfo&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;Service&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;discovery_proto&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Service&lt;/span&gt;    }    &lt;span style=&#34;color:#75715e&#34;&gt;// WorkloadInfo combines original proto object with auxiliary information.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;WorkloadInfo&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;Workload&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;discovery_proto&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Workload&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;Desc&lt;/span&gt;     &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;WorkloadDescription&lt;/span&gt;    }    &lt;span style=&#34;color:#75715e&#34;&gt;// WorkloadDescription represents auxiliary information about a Workload.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;WorkloadDescription&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;Version&lt;/span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;Endpoints&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;WorkloadEndpoint&lt;/span&gt;    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;WorkloadEndpoint&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;Port&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32&lt;/span&gt;    }    &lt;span style=&#34;color:#75715e&#34;&gt;// DiscoveryConsumer is a consumer of discovery information, i.e. Services and Workloads.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoveryConsumer&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneDiscoveryConsumer&lt;/span&gt;    }    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneDiscoveryConsumer&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;OnDataplaneUpdate&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mesh_core&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DataplaneResource&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;OnDataplaneDelete&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;model&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ResourceKey&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values. The implementing package should return concrete (usually pointer or struct) types: that way, new methods can be added to implementations without requiring extensive refactoring.&lt;/li&gt;&lt;li&gt;Design the API so that it can be tested using the public API of the real implementation.&lt;/li&gt;&lt;li&gt;Do not define interfaces before they are used: without a realistic example of usage, it is too difficult to see whether an interface is even necessary, let alone what methods it ought to contain.&lt;/li&gt;&lt;li&gt;&lt;p&gt;Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;consumer&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// consumer.go&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Thing&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; { &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;consumer&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// consumer_test.go&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fakeThinger&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt;{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fakeThinger&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Thing&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; { &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;fakeThinger&lt;/span&gt;{&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;}) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt; { &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Instead of doing this&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// DO NOT DO IT!!!&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;producer&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Thing&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; }    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;defaultThinger&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt;{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;defaultThinger&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Thing&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; { &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewThinger&lt;/span&gt;() &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;defaultThinger&lt;/span&gt;{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; } }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&amp;hellip;better do this&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;producer&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt;{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Thing&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; { &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; }    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewThinger&lt;/span&gt;() &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Thinger&lt;/span&gt;{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt; } }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In Go, the receiver of a method is just another parameter and therefore, should be named accordingly. The name need not be as descriptive as that of a method argument, as its role is obvious and serves no documentary purpose. It can be very short as it will appear on almost every line of every method of the type; familiarity admits brevity. Be consistent, too: if you call the receiver &amp;ldquo;c&amp;rdquo; in one method, don&amp;rsquo;t call it &amp;ldquo;cl&amp;rdquo; in another.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;If in doubt, use a pointer, but there are times when a value receiver makes sense, usually for reasons of efficiency, such as for small unchanging structs or values of basic type. Some useful guidelines:&lt;ul&gt;&lt;li&gt;&lt;em&gt;&lt;strong&gt;NO POINTER&lt;/strong&gt;&lt;/em&gt; for the following:&lt;ul&gt;&lt;li&gt;If the receiver is a map, func or chan, don&amp;rsquo;t use a pointer to them. If the receiver is a slice and the method doesn&amp;rsquo;t reslice or reallocate the slice, don&amp;rsquo;t use a pointer to it.&lt;/li&gt;&lt;li&gt;If the receiver is a small array or struct that is naturally a value type (for instance, something like the time.Time type), with no mutable fields and no pointers, or is just a simple basic type such as int or string, a value receiver makes sense. A value receiver can reduce the amount of garbage that can be generated; if a value is passed to a value method, an on-stack copy can be used instead of allocating on the heap. (The compiler tries to be smart about avoiding this allocation, but it can&amp;rsquo;t always succeed.) Don&amp;rsquo;t choose a value receiver type for this reason without profiling first.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;&lt;strong&gt;USE POINTER&lt;/strong&gt;&lt;/em&gt; for the following:&lt;ul&gt;&lt;li&gt;If the method needs to mutate the receiver, the receiver must be a pointer.&lt;/li&gt;&lt;li&gt;If the receiver is a struct that contains a sync.Mutex or similar synchronizing field, the receiver must be a pointer to avoid copying.&lt;/li&gt;&lt;li&gt;If the receiver is a large struct or array, a pointer receiver is more efficient. How large is large? Assume it&amp;rsquo;s equivalent to passing all its elements as arguments to the method. If that feels too large, it&amp;rsquo;s also too large for the receiver.&lt;/li&gt;&lt;li&gt;Can function or methods, either concurrently or when called from this method, be mutating the receiver? A value type creates a copy of the receiver when the method is invoked, so outside updates will not be applied to this receiver. If changes must be visible in the original receiver, the receiver must be a pointer.&lt;/li&gt;&lt;li&gt;If the receiver is a struct, array or slice and any of its elements is a pointer to something that might be mutating, prefer a pointer receiver, as it will make the intention more clear to the reader.&lt;/li&gt;&lt;li&gt;Finally, when in doubt, use a pointer receiver.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Compile-time checking&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Compile-time check to assert this config matches requirements.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setup&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;KeyManagerProvider&lt;/span&gt; = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setup&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;BlobStorageConfigProvider&lt;/span&gt; = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setup&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DBConfigProvider&lt;/span&gt; = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;the above is to check whether the Config object implement the function defined in KeyManagerProvider, BlobStorageConfigProvider and DBConfigProvider.&lt;/p&gt;&lt;p&gt;The (*Config)(nil) is to do the verification between the interface and struct WITHOUT allocating any memory. See below for more examples&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Compile-time checking examples&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;I&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{ &lt;span style=&#34;color:#a6e22e&#34;&gt;M&lt;/span&gt;() }&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt;{}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;M&lt;/span&gt;() {}&lt;span style=&#34;color:#75715e&#34;&gt;//func (*T) M() {} //var _ I = T{}: T does not implement I (M method has pointer receiver)&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {  &lt;span style=&#34;color:#75715e&#34;&gt;//avoids allocation of memory&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;I&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;{}       &lt;span style=&#34;color:#75715e&#34;&gt;// Verify that T implements I.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;I&lt;/span&gt; = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;) &lt;span style=&#34;color:#75715e&#34;&gt;// Verify that *T implements I.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;//allocation of memory&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;I&lt;/span&gt; = &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;{}      &lt;span style=&#34;color:#75715e&#34;&gt;// Verify that &amp;amp;T implements I.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;I&lt;/span&gt; = new(&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;)    &lt;span style=&#34;color:#75715e&#34;&gt;// Verify that new(T) implements I.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Compile-time checking examples&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; (        &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;blobref&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;StreamingFetcher&lt;/span&gt; = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;CachingFetcher&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)        &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;blobref&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SeekFetcher&lt;/span&gt;      = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;CachingFetcher&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)        &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;blobref&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;StreamingFetcher&lt;/span&gt; = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DiskCache&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)        &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;blobref&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SeekFetcher&lt;/span&gt;      = (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DiskCache&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;))&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Ensure compiler checks:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;That CachingFether implements public functions of StreamingFetcher and SeekFetcher.&lt;/li&gt;&lt;li&gt;RHS portion uses a pointer constructor syntax with a nil parameter. What does this syntax mean in Go language ?&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Type Casting for checking. The following is based on the example from &lt;strong&gt;github.com/google/exposure-notifications-server&lt;/strong&gt;. The &lt;strong&gt;KeyManagerProvider&lt;/strong&gt; is an interface as follows (found inside &lt;strong&gt;setup.go&lt;/strong&gt;)&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;KeyManagerProvider&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;KeyManager&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;strong&gt;Config&lt;/strong&gt; object is defined as follows (found inside &lt;strong&gt;config.go&lt;/strong&gt;)&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;Database&lt;/span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;database&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;WorkerTimeout&lt;/span&gt;     &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Duration&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`envconfig:&amp;#34;WORKER_TIMEOUT&amp;#34; default:&amp;#34;5m&amp;#34;`&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;KeyManager&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;the struct implement the &lt;strong&gt;KeyManager()&lt;/strong&gt; function. The &lt;strong&gt;setup.Setup(..)&lt;/strong&gt; function is defined as follows&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Setup&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DBConfigProvider&lt;/span&gt;) (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;serverenv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ServerEnv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Defer&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;it is called as follows from export/main.go&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;export&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Config&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;env&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;closer&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setup&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Setup&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;the following code inside Setup(..) will be analysed (found inside setup.go)&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt;.(&lt;span style=&#34;color:#a6e22e&#34;&gt;KeyManagerProvider&lt;/span&gt;); &lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; {&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;}&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;is actually a way to check whether the passed config parameter implemented the function &lt;strong&gt;&amp;lsquo;KeyManager()&amp;rsquo;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Tests should fail with helpful messages saying what was wrong, with what inputs, what was actually got, and what was expected.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;got&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;want&lt;/span&gt; {    &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Foo(%q) = %d; want %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;tt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;got&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;tt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;want&lt;/span&gt;) &lt;span style=&#34;color:#75715e&#34;&gt;// or Fatalf, if test can&amp;#39;t test anything more past this point&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;comments&#34;&gt;Comments&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;For comments use // instead of /* */&lt;/li&gt;&lt;li&gt;Start comment with the name of the function&lt;/li&gt;&lt;li&gt;All top-level, exported names should have doc comments, as should non-trivial unexported type or function declarations.&lt;/li&gt;&lt;li&gt;For readability, move the comment to appear on it&amp;rsquo;s own line before the variable. Following is NOT a good example&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt; &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;OutPrefix&lt;/span&gt;   = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;gt; &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;OutPrefix&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;notes&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;output&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Package comments, like all comments to be presented by godoc, must appear adjacent to the package clause, with no blank line.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// Package math provides basic constants and mathematical functions.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;math&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt; &lt;span style=&#34;color:#75715e&#34;&gt;/*&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;Package template implements data-driven templates for generating textual&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;output such as HTML.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;....&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;*/&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;template&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;For &amp;ldquo;package main&amp;rdquo; comments, other styles of comment are fine after the binary name. For example, for a package main in the directory seedgen you could write:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// Binary seedgen ...&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Command seedgen ...&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Program seedgen ...&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// The seedgen command ...&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// The seedgen program ...&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Seedgen ..&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;If a function returns two or three parameters of the same type, or if the meaning of a result isn&amp;rsquo;t clear from context, adding names may be useful in some contexts.&lt;/li&gt;&lt;li&gt;Don&amp;rsquo;t name result parameters just to avoid declaring a var inside the function; that trades off a minor implementation brevity at the cost of unnecessary API verbosity.&lt;/li&gt;&lt;li&gt;Naked returns are okay if the function is a handful of lines. Once it&amp;rsquo;s a medium sized function, be explicit with your return values. Corollary: it&amp;rsquo;s not worth it to name result parameters just because it enables you to use naked returns. Clarity of docs is always more important than saving a line or two in your function.&lt;/li&gt;&lt;li&gt;Don&amp;rsquo;t pass pointers as function arguments just to save a few bytes, however This advice does not apply to large structs, or even small structs that might grow.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;error-handling&#34;&gt;Error Handling&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Don&amp;rsquo;t use panic for normal error handling. Use error and multiple return values.&lt;/li&gt;&lt;li&gt;Error strings should not be capitalized (unless beginning with proper nouns or acronyms) or end with punctuation&lt;/li&gt;&lt;li&gt;Do not discard errors using _ variables. Handle the error, return it, or, in truly exceptional situations, panic.&lt;/li&gt;&lt;li&gt;&lt;p&gt;Do not use return value such as in C using -1 to flag error. Function can return multiple result so use one of the returned result to flag if there is an error. Eg:&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Lookup&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt;  {    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;no value for %q&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Parse&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;This is recommended&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {    &lt;span style=&#34;color:#75715e&#34;&gt;// error handling&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// or continue, etc.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;normal&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;code&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; instead of&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {    &lt;span style=&#34;color:#75715e&#34;&gt;// error handling&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {    &lt;span style=&#34;color:#75715e&#34;&gt;// normal code&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;packages&#34;&gt;Packages&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Avoid renaming imports except to avoid a name collision; good package names should not require renaming. In the event of collision, prefer to rename the most local or project-specific import.&lt;/li&gt;&lt;li&gt;Packages that are imported only for their side effects (using the syntax import _ &amp;ldquo;pkg&amp;rdquo;) should only be imported in the main package of a program, or in tests that require them.&lt;/li&gt;&lt;li&gt;In this case, the test file cannot be in package foo because it uses bar/testutil, which imports foo. So we use the &amp;lsquo;import .&amp;rsquo; form to let the file pretend to be part of package foo even though it is not. Except for this one case, do not use import . in your programs. It makes the programs much harder to read because it is unclear whether a name like Quux is a top-level identifier in the current package or in an imported package.&lt;/li&gt;&lt;li&gt;Avoid meaningless package names like util, common, misc, api, types, and interfaces&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2 id=&#34;concurrency&#34;&gt;Concurrency&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://blog.gopheracademy.com/advent-2019/directional-channels/&#34;&gt;This article&lt;/a&gt; explain in simple ways on how the directional nature of the channel works. The article details the different direction that a channel can have.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// SliceIterChan returns each element of a slice on a channel for concurrent&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// consumption, closing the channel on completion&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SliceIterChan&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; {        &lt;span style=&#34;color:#a6e22e&#34;&gt;outChan&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)        &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {            &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt; {                &lt;span style=&#34;color:#a6e22e&#34;&gt;outChan&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;s&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;]            }            close(&lt;span style=&#34;color:#a6e22e&#34;&gt;outChan&lt;/span&gt;)        }()        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;outChan&lt;/span&gt;    }    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The article explains&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Diving into the implementation, the function creates a bidirectional channel for its own use, and then all it needs to do to ensure that it has full control over writing to and closing the channel is to return it, whereupon it will be converted into a read-only channel automatically.&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Following are excerpts from &lt;a href=&#34;https://github.com/golang/go/wiki/LearnConcurrency&#34;&gt;this&lt;/a&gt; and &lt;a href=&#34;https://golang.org/ref/spec#Send_statements&#34;&gt;this&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Both the channel and the value expression are evaluated before communication begins.&lt;/li&gt;&lt;li&gt;Communication blocks until the send can proceed.&lt;/li&gt;&lt;li&gt;A send on an unbuffered channel can proceed if a receiver is ready.&lt;/li&gt;&lt;li&gt;A send on a buffered channel can proceed if there is room in the buffer.&lt;/li&gt;&lt;li&gt;A send on a closed channel proceeds by causing a run-time panic.&lt;/li&gt;&lt;li&gt;Communication on nil channels can never proceed, a select with only nil channels and no default case blocks forever.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;repeatFn&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(    &lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{},    &lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{},) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{} {    &lt;span style=&#34;color:#a6e22e&#34;&gt;valueStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt;{})    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {        &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; close(&lt;span style=&#34;color:#a6e22e&#34;&gt;valueStream&lt;/span&gt;)        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; {            &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {            &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;done&lt;/span&gt;:                &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;valueStream&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt;():            }        }    }()    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;valueStream&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One of repeatFn(..) argument is to receive &amp;lsquo;done&amp;rsquo; variable that the repeatFn(..) will use as a flag to exit from the functionThe value of the receive operation &amp;lt;-ch is the value received from the channel ch. The expression blocks until a value is available. Receiving from a nil channel blocks forever. A receive operation on a closed channel can always proceed immediately, yielding the element type&amp;rsquo;s zero value after any previously sent values have been received.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Following are questions to answer in order to have a better understanding how the whole multi-threading channel based works in Go. These are not an exhaustive list but a starting point that will help to stir in the right direction.&lt;ul&gt;&lt;li&gt;How do we call goroutine inside a function ?&lt;/li&gt;&lt;li&gt;When using goroutine inside a function how will the code flow ?&lt;/li&gt;&lt;li&gt;How does the &lt;strong&gt;for(..) range&lt;/strong&gt; loops works with channels ? how does it differ than normal for(..) counter loop&lt;/li&gt;&lt;li&gt;How to use the &lt;strong&gt;select{ case : }&lt;/strong&gt; operator with channels ?&lt;/li&gt;&lt;li&gt;When closing channel is it closed AFTER operation is done ?&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Send the channel that your function want to receive the data from&lt;br /&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;First&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;query&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;,  &lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Result&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;replicas&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Search&lt;/span&gt;){        &lt;span style=&#34;color:#a6e22e&#34;&gt;collating&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Result&lt;/span&gt;)        &lt;span style=&#34;color:#a6e22e&#34;&gt;searchReplica&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;collating&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Result&lt;/span&gt;) {             &lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;replicas&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;](&lt;span style=&#34;color:#a6e22e&#34;&gt;query&lt;/span&gt;)         }        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;replicas&lt;/span&gt; {            &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;searchReplica&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;,&lt;span style=&#34;color:#a6e22e&#34;&gt;collating&lt;/span&gt;)        }    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;in the above example the First(..) method&amp;rsquo;s param is a channel parameter &amp;lsquo;c&amp;rsquo;, it uses this channel to send data that will be read by the caller function.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Use timeout as much as possible to avoid the app from &amp;lsquo;hang&amp;rsquo; mode. Having timeout enable troubleshooting as function will automatically terminate after certain amount of time.&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;timeout&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;After&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;800&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Millisecond&lt;/span&gt;)    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; {        &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {        &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;timeout&lt;/span&gt;:            &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;timed out&amp;#34;&lt;/span&gt;)            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;        }    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If we close the channel and we try to read data (even AFTER reading the data) no exception thrown&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(){    &lt;span style=&#34;color:#75715e&#34;&gt;// size chosen to ensure it never gets filled up completely.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)     &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {        &lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TESTING from function 1&amp;#34;&lt;/span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; close(&lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt;)    }()    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Obtained  1&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Millisecond&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;----------------&amp;#34;&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Obtained  2&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt;)}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If we DO NOT close the channel and try to read data (AFTER reading the data) deadlock exception will be thrown&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(){    &lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#75715e&#34;&gt;// size chosen to ensure it never gets filled up completely.&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {        &lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TESTING from function 1&amp;#34;&lt;/span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;//defer close(threadChannel)&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    }()    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Obtained  1&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Millisecond&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;----------------&amp;#34;&lt;/span&gt;)    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Obtained  2&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;threadChannel&lt;/span&gt;)}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ALWAYS close(..) the channel to stop the go func(..) running and resides in memory. Without closing the channel possibility of memory leak and/or deadlock is high&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mechanism should always be in place to make sure that the parent can instruct the child goroutine to cancel it&amp;rsquo;s operation.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Goroutine&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;When you spawn goroutines, make it clear when or whether - they exit.&lt;/li&gt;&lt;li&gt;Goroutines can leak by blocking on channel sends or receives: the garbage collector will not terminate a goroutine even if the channels it is blocked on are unreachable.&lt;/li&gt;&lt;li&gt;Even when goroutines do not leak, leaving them in-flight when they are no longer needed can cause other subtle and hard-to-diagnose problems.&lt;/li&gt;&lt;li&gt;Try to keep concurrent code simple enough that goroutine lifetimes are obvious. If that just isn&amp;rsquo;t feasible, document when and why the goroutines exit.&lt;/li&gt;&lt;li&gt;&lt;em&gt;DO NOT&lt;/em&gt; use package &lt;strong&gt;math/rand&lt;/strong&gt; to generate keys, instead, use &lt;strong&gt;crypto/rand&amp;rsquo;s Reader&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;Every time running a goroutine(..) we must think how it will finish. What will be the trigger to return or exit from the gorotine&lt;/li&gt;&lt;li&gt;At any time we want to to send data into a channel make sure the channel variable is send as parameter to the called method&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Select packages&lt;/h2&gt;&lt;p&gt;Following is an example to use &lt;strong&gt;SelectCase&lt;/strong&gt; in situation where there are multiple channels to process&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;reflect&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;produce&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) {&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;j&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;j&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;j&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprint&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;j&lt;/span&gt;)}close(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;)}&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;numChans&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;chans&lt;/span&gt; = []&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;{}&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#a6e22e&#34;&gt;numChans&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;chans&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;chans&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;produce&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)}&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make([]&lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SelectCase&lt;/span&gt;, len(&lt;span style=&#34;color:#a6e22e&#34;&gt;chans&lt;/span&gt;))&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;chans&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;] = &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SelectCase&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;Dir&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SelectRecv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Chan&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;)}}&lt;span style=&#34;color:#a6e22e&#34;&gt;remaining&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;remaining&lt;/span&gt; &amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;chosen&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Select&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;)&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; {&lt;span style=&#34;color:#75715e&#34;&gt;// The chosen channel has been closed, so zero out the channel to disable the case&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;chosen&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;Chan&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;remaining&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;}&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Read from channel %#v and received %s\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;chans&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;chosen&lt;/span&gt;], &lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;())}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;SelectCase&lt;/strong&gt; can be used to receive or send data.&lt;/p&gt;&lt;p&gt;To use it to receive data use the SelectRecv direction&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;] = &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SelectCase&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;Dir&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SelectRecv&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Chan&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt;)}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;the &lt;em&gt;Chan&lt;/em&gt; will point to the channel that will be used to receive the data.&lt;/p&gt;&lt;p&gt;To read the data use the following&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;chosen&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reflect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Select&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cases&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;the &lt;em&gt;value&lt;/em&gt; variable will contain the data from the channel&lt;/p&gt;&lt;p&gt;&lt;h1&gt;References&lt;/h1&gt;* &lt;a href=&#34;http://peter.bourgon.org/go-in-production/#testing-and-validation&#34;&gt;Best practises in Golang&lt;/a&gt;* &lt;a href=&#34;https://github.com/kubernetes/minikube/pull/5718#discussion_r339308904&#34;&gt;Lesson learned from contributing minikube&lt;/a&gt;* &lt;a href=&#34;https://github.com/golang/go/wiki/CodeReviewComments&#34;&gt;Code Review Best Practises Golang&lt;/a&gt;* &lt;a href=&#34;https://github.com/cristaloleg/go-advices&#34;&gt;Go Advices&lt;/a&gt;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Minikube commands (Work in progress)</title>
       <link>/post/minikubeparameters/</link>
       <pubDate>Sun, 01 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/minikubeparameters/</guid>
       <description>&lt;p&gt;Following are the commands available for minikube.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;Basic Commands:  start          Starts a local kubernetes cluster  status         Gets the status of a local kubernetes cluster  stop           Stops a running local kubernetes cluster  delete         Deletes a local kubernetes cluster  dashboard      Access the kubernetes dashboard running within the minikube clusterImages Commands:  docker-env     Sets up docker env variables; similar to &amp;#39;$(docker-machine env)&amp;#39;  cache          Add or delete an image from the local cache.Configuration and Management Commands:  addons         Modify minikube&amp;#39;s kubernetes addons  config         Modify minikube config  profile        Profile gets or sets the current minikube profile  update-context Verify the IP address of the running cluster in kubeconfig.Networking and Connectivity Commands:  service        Gets the kubernetes URL(s) for the specified service in your local cluster  tunnel         tunnel makes services of type LoadBalancer accessible on localhostAdvanced Commands:  mount          Mounts the specified directory into minikube  ssh            Log into or run a command on a machine with SSH; similar to &amp;#39;docker-machine ssh&amp;#39;  kubectl        Run kubectlTroubleshooting Commands:  ssh-key        Retrieve the ssh identity key path of the specified cluster  ip             Retrieves the IP address of the running cluster  logs           Gets the logs of the running instance, used for debugging minikube, not user code.  update-check   Print current and latest version number  version        Print the version of minikubeOther Commands:  completion     Outputs minikube shell completion for the given shell (bash or zsh)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The source code for the configurations outlined above can be found inside &lt;em&gt;cmd/minikube/cmd&lt;/em&gt; directory. Noticed how the .go files are named the same as the configuration parameter which makes it easier for identifying the relevant code.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;├── cache.go├── cache_list.go├── completion.go├── dashboard.go├── delete.go├── env.go├── env_test.go├── generate-docs.go├── ip.go├── kubectl.go├── logs.go├── mount.go├── root.go├── root_test.go├── service.go├── service_list.go├── ssh.go├── ssh-key.go├── start.go├── start_test.go├── status.go├── stop.go├── tunnel.go├── update-check.go├── update-context.go└── version.go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The main minikube entry point reside inside &lt;em&gt;cmd/minikube&lt;/em&gt; directory in a file called &lt;strong&gt;main.go&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;regexp&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;)    &lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;span style=&#34;color:#a6e22e&#34;&gt;bridgeLogMessages&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;glog&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Flush&lt;/span&gt;()&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Getenv&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;minikubeEnableProfile&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;profile&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Start&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;profile&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;TraceProfile&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Stop&lt;/span&gt;()}    &lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;cmd&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Execute&lt;/span&gt;()}    &lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;......&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;start&lt;/h1&gt;&lt;p&gt;Command to trigger the minikube starting process. There are varieties of options that you can pass into minikube, most of the parameters are self described.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;      --apiserver-ips=[]: A set of apiserver IP Addresses which are used in the generated certificate for kubernetes.  This can be used if you want to make the apiserver available from outside the machine      --apiserver-name=&amp;#39;minikubeCA&amp;#39;: The apiserver name which is used in the generated certificate for kubernetes.  This can be used if you want to make the apiserver available from outside the machine      --apiserver-names=[]: A set of apiserver names which are used in the generated certificate for kubernetes.  This can be used if you want to make the apiserver available from outside the machine      --apiserver-port=8443: The apiserver listening port      --cache-images=true: If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --vm-driver=none.      --container-runtime=&amp;#39;docker&amp;#39;: The container runtime to be used (docker, crio, containerd).      --cpus=2: Number of CPUs allocated to the minikube VM.      --cri-socket=&amp;#39;&amp;#39;: The cri socket path to be used.      --disable-driver-mounts=false: Disables the filesystem mounts provided by the hypervisors      --disk-size=&amp;#39;20000mb&amp;#39;: Disk size allocated to the minikube VM (format: &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;number&lt;/span&gt;&amp;gt;[&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;unit&lt;/span&gt;&amp;gt;], where unit = b, k, m or g).      --dns-domain=&amp;#39;cluster.local&amp;#39;: The cluster dns domain name used in the kubernetes cluster      --dns-proxy=false: Enable proxy for NAT DNS requests (virtualbox driver only)      --docker-env=[]: Environment variables to pass to the Docker daemon. (format: key=value)      --docker-opt=[]: Specify arbitrary flags to pass to the Docker daemon. (format: key=value)      --download-only=false: If true, only download and cache files for later use - don&amp;#39;t install or start anything.      --embed-certs=false: if true, will embed the certs in kubeconfig.      --enable-default-cni=false: Enable the default CNI plugin (/etc/cni/net.d/k8s.conf). Used in conjunction with &amp;#34;--network-plugin=cni&amp;#34;.      --extra-config=: A set of key=value pairs that describe configuration that may be passed to different components.                The key should be &amp;#39;.&amp;#39; separated, and the first part before the dot is the component to apply the configuration to.                Valid components are: kubelet, kubeadm, apiserver, controller-manager, etcd, proxy, scheduler                Valid kubeadm parameters: ignore-preflight-errors, dry-run, kubeconfig, kubeconfig-dir, node-name, cri-socket, experimental-upload-certs, certificate-key, rootfs, pod-network-cidr      --feature-gates=&amp;#39;&amp;#39;: A set of key=value pairs that describe feature gates for alpha/experimental features.      --force=false: Force minikube to perform possibly dangerous operations      --host-dns-resolver=true: Enable host resolver for NAT DNS requests (virtualbox driver only)      --host-only-cidr=&amp;#39;192.168.99.1/24&amp;#39;: The CIDR to be used for the minikube VM (virtualbox driver only)      --hyperkit-vpnkit-sock=&amp;#39;&amp;#39;: Location of the VPNKit socket used for networking. If empty, disables Hyperkit VPNKitSock, if &amp;#39;auto&amp;#39; uses Docker for Mac VPNKit connection, otherwise uses the specified VSock (hyperkit driver only)      --hyperkit-vsock-ports=[]: List of guest VSock ports that should be exposed as sockets on the host (hyperkit driver only)      --hyperv-virtual-switch=&amp;#39;&amp;#39;: The hyperv virtual switch name. Defaults to first found. (hyperv driver only)      --image-mirror-country=&amp;#39;&amp;#39;: Country code of the image mirror to be used. Leave empty to use the global one. For Chinese mainland users, set it to cn.      --image-repository=&amp;#39;&amp;#39;: Alternative image repository to pull docker images from. This can be used when you have limited access to gcr.io. Set it to &amp;#34;auto&amp;#34; to let minikube decide one for you. For Chinese mainland users, you may use local gcr.io mirrors such as registry.cn-hangzhou.aliyuncs.com/google_containers      --insecure-registry=[]: Insecure Docker registries to pass to the Docker daemon.  The default service CIDR range will automatically be added.      --iso-url=&amp;#39;https://storage.googleapis.com/minikube/iso/minikube-v0.0.0-unset.iso&amp;#39;: Location of the minikube iso.      --keep-context=false: This will keep the existing kubectl context and will create a minikube context.      --kubernetes-version=&amp;#39;v1.16.0-rc.2&amp;#39;: The kubernetes version that the minikube VM will use (ex: v1.2.3)      --kvm-gpu=false: Enable experimental NVIDIA GPU support in minikube      --kvm-hidden=false: Hide the hypervisor signature from the guest in minikube (kvm2 driver only)      --kvm-network=&amp;#39;default&amp;#39;: The KVM network name. (kvm2 driver only)      --kvm-qemu-uri=&amp;#39;qemu:///system&amp;#39;: The KVM QEMU connection URI. (kvm2 driver only)      --memory=&amp;#39;2000mb&amp;#39;: Amount of RAM allocated to the minikube VM (format: &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;number&lt;/span&gt;&amp;gt;[&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;unit&lt;/span&gt;&amp;gt;], where unit = b, k, m or g).      --mount=false: This will start the mount daemon and automatically mount files into minikube.      --mount-string=&amp;#39;/home/nanik:/minikube-host&amp;#39;: The argument to pass the minikube mount command on start.      --native-ssh=true: Use native Golang SSH client (default true). Set to &amp;#39;false&amp;#39; to use the command line &amp;#39;ssh&amp;#39; command when accessing the docker machine. Useful for the machine drivers when they will not start with &amp;#39;Waiting for SSH&amp;#39;.      --network-plugin=&amp;#39;&amp;#39;: The name of the network plugin.      --nfs-share=[]: Local folders to share with Guest via NFS mounts (hyperkit driver only)      --nfs-shares-root=&amp;#39;/nfsshares&amp;#39;: Where to root the NFS Shares, defaults to /nfsshares (hyperkit driver only)      --no-vtx-check=false: Disable checking for the availability of hardware virtualization before the vm is started (virtualbox driver only)      --registry-mirror=[]: Registry mirrors to pass to the Docker daemon      --service-cluster-ip-range=&amp;#39;10.96.0.0/12&amp;#39;: The CIDR to be used for service cluster IPs.      --uuid=&amp;#39;&amp;#39;: Provide VM UUID to restore MAC address (hyperkit driver only)      --vm-driver=&amp;#39;&amp;#39;: Driver is one of: [virtualbox parallels vmwarefusion kvm2 vmware none] (defaults to virtualbox)      --wait=true: Wait until Kubernetes core services are healthy before exiting.      --wait-timeout=6m0s: max time to wait per Kubernetes core services to be healthy.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;start&lt;/em&gt; option source code detecting the different options pass resides inside &lt;strong&gt;cmd/minikube/cmd/start.go&lt;/strong&gt;. Following tables outline some of the commands that require bit more explanation of it&amp;rsquo;s usage&lt;/p&gt;&lt;table class=&#34;table table-responsive table-dark table-danger&#34;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&amp;ndash;enable-default-cni&lt;/strong&gt; &amp;ndash;  using this flag it will use the default cni config inside &lt;em&gt;pkg/minikube/bootstrapper/kubeadm/default_cni.go&lt;/em&gt; which will be stored inside /etc/cni/net.d directory as k8s.conf&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Enabling cache &lt;strong&gt;&amp;ndash;cache-images=true&lt;/strong&gt; when starting up minikube helps in deployment process by caching the images used inside the VM. Following is what local cache looks like. Most files are docker image files.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;├── images│   ├── gcr.io│   │   └── k8s-minikube│   │       ├── storage-provisioner_v1.8.1│   │       └── storage-provisioner_v1.8.1.823687817.tmp│   └── k8s.gcr.io│       ├── coredns_1.3.1│       ├── coredns_1.6.2│       ├── etcd_3.3.10.801406343.tmp│       ├── etcd_3.3.15-0│       ├── k8s-dns-dnsmasq-nanny-amd64_1.14.13│       ├── k8s-dns-kube-dns-amd64_1.14.13│       ├── k8s-dns-kube-dns-amd64_1.14.13.681617407.tmp│       ├── k8s-dns-sidecar-amd64_1.14.13│       ├── kube-addon-manager_v9.0│       ├── kube-addon-manager_v9.0.682111654.tmp│       ├── kube-apiserver_v1.16.0│       ├── kube-apiserver_v1.16.0-rc.2.869485211.tmp│       ├── kube-controller-manager_v1.16.0│       ├── kube-controller-manager_v1.16.0-rc.2│       ├── kube-proxy_v1.16.0│       ├── kube-proxy_v1.16.0-rc.2│       ├── kubernetes-dashboard-amd64_v1.10.1│       ├── kubernetes-dashboard-amd64_v1.10.1.460043582.tmp│       ├── kube-scheduler_v1.16.0│       ├── kube-scheduler_v1.16.0-rc.2│       └── pause_3.1├── iso│   └── minikube-v1.4.0.iso└── v1.16.0    ├── kubeadm    └── kubelet&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;status&lt;/h1&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;Gets the status of a local kubernetes cluster.        Exit status contains the status of minikube&amp;#39;s VM, cluster and kubernetes encoded on it&amp;#39;s bits in this order from rightto left.        Eg: 7 meaning: 1 (for minikube NOK) + 2 (for cluster NOK) + 4 (for kubernetes NOK)Options:      --format=&amp;#39;host: {{.Host}}kubelet: {{.Kubelet}}apiserver: {{.APIServer}}kubectl: {{.Kubeconfig}}&amp;#39;: Go template format string for the status output.  The format for Go templates can be found here:https://golang.org/pkg/text/template/For the list accessible variables for the template, see the struct values here:https://godoc.org/k8s.io/minikube/cmd/minikube/cmd#Status&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;cache&lt;/h1&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;Add or delete an image from the local cache.Available Commands:  add         Add an image to local cache.  delete      Delete an image from the local cache.  list        List all available images from the local cache.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;docker-env&lt;/h1&gt;&lt;p&gt;This command will outputs the necessary environment variable that you need to set to point your local docker to minikube. Following is the output of the command when ran locally&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;export DOCKER_TLS_VERIFY=&amp;#34;1&amp;#34;export DOCKER_HOST=&amp;#34;tcp://192.168.99.127:2376&amp;#34;export DOCKER_CERT_PATH=&amp;#34;/home/nanik/.minikube/certs&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To use the output settings use the following command&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;eval $(minikube docker-env)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the above command is ran everytime you run docker CLI it will communicate with the docker inside minikube.&lt;/p&gt;&lt;h1&gt;addons&lt;/h1&gt;&lt;p&gt;The addons command allow you to enable, disable, etc addons inside minikube&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;Available Commands:  configure   Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). Fora list of available addons use: minikube addons list   disable     Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a listof available addons use: minikube addons list   enable      Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list ofavailable addons use: minikube addons list   list        Lists all available minikube addons as well as their current statuses (enabled/disabled)  open        Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list ofavailable addons use: minikube addons list Options:      --format=&amp;#39;- {{.AddonName}}: {{.AddonStatus}}&amp;#39;: Go template format string for the addon list output.  The format for Go templates can be found here:https://golang.org/pkg/text/template/For the list of accessible variables for the template, see the struct values here:https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#AddonListTemplate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;config&lt;/h1&gt;&lt;p&gt;The below configuration are relevant to the parameter that you specified when you use the &amp;lsquo;start&amp;rsquo; command.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;config modifies minikube config files using subcommands like &amp;#34;minikube config set vm-driver kvm&amp;#34;Configurable fields:  * vm-driver * container-runtime * feature-gates * v * cpus * disk-size * host-only-cidr * memory * log_dir * kubernetes-version * iso-url * WantUpdateNotification * ReminderWaitPeriodInHours * WantReportError * WantReportErrorPrompt * WantKubectlDownloadMsg * WantNoneDriverWarning * profile * bootstrapper * ShowDriverDeprecationNotification * ShowBootstrapperDeprecationNotification * dashboard * addon-manager * default-storageclass * heapster * efk * ingress * insecure-registry * registry * registry-creds * freshpod * default-storageclass * storage-provisioner * storage-provisioner-gluster * metrics-server * nvidia-driver-installer * nvidia-gpu-device-plugin * logviewer * gvisor * hyperv-virtual-switch * disable-driver-mounts * cache * embed-certs * native-sshAvailable Commands:  get         Gets the value of PROPERTY_NAME from the minikube config file  set         Sets an individual value in a minikube config file  unset       unsets an individual value in a minikube config file  view        Display values currently set in the minikube config file&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;service&lt;/h1&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;Gets the kubernetes URL(s) for the specified service in your local cluster. In the case of multiple URLs they will beprinted one at a time.Available Commands:  list        Lists the URLs for the services in your local clusterOptions:      --https=false: Open the service URL with https instead of http      --interval=6: The initial time interval for each check that wait performs in seconds  -n, --namespace=&amp;#39;default&amp;#39;: The service namespace      --url=false: Display the kubernetes service URL in the CLI instead of opening it in the default browser      --wait=20: Amount of time to wait for a service in seconds&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1&gt;mount&lt;/h1&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;Mounts the specified directory into minikube.Options:      --9p-version=&amp;#39;9p2000.L&amp;#39;: Specify the 9p version that the mount should use      --gid=&amp;#39;docker&amp;#39;: Default group id used for the mount      --ip=&amp;#39;&amp;#39;: Specify the ip that the mount should be setup on      --kill=false: Kill the mount process spawned by minikube start      --mode=493: File permissions used for the mount      --msize=262144: The number of bytes to use for 9p packet payload      --options=[]: Additional mount options, such as cache=fscache      --type=&amp;#39;9p&amp;#39;: Specify the mount filesystem type (supported types: 9p)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr /&gt;&lt;h2 id=&#34;minikube-parameters&#34;&gt;Minikube parameters&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;mapping of arguments to source code&lt;/li&gt;&lt;li&gt;references&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://evalle.xyz/posts/configure-kube-apiserver-in-minikube/&#34;&gt;https://evalle.xyz/posts/configure-kube-apiserver-in-minikube/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.marcolancini.it/2019/blog-deploy-kubernetes-lab/&#34;&gt;https://www.marcolancini.it/2019/blog-deploy-kubernetes-lab/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Playing with Docker SDK (Work in progress)</title>
       <link>/post/usingdockerapi/</link>
       <pubDate>Sun, 01 Sep 2019 00:00:00 +0000</pubDate>
       
       <guid>/post/usingdockerapi/</guid>
       <description>&lt;p&gt;This article will walk through on how to use the docker SDK using Go. Docker provide a very rich SDK allowing developers to communicate with the docker daemon.&lt;/p&gt;&lt;h1&gt;Intercepting Docker&lt;/h1&gt;&lt;p&gt;Run the following to intercept&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;socat -v UNIX-LISTEN:/tmp/fake,fork UNIX-CONNECT:/var/run/docker.sock&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the following to make sure docker CLI send command to our proxy in /tmp/fake&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;export DOCKER_HOST=unix:///tmp/fakedocker image list&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output will show as follows&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&amp;gt; 2019/09/12 20:38:27.924464  length=81 from=0 to=80HEAD /_ping HTTP/1.1\rHost: docker\rUser-Agent: Docker-Client/xx.xx.1 (linux)\r\r&amp;lt; 2019/09/12 20:38:27.924817  length=287 from=0 to=286HTTP/1.1 200 OK\rApi-Version: 1.41\rCache-Control: no-cache, no-store, must-revalidate\rContent-Length: 0\rContent-Type: text/plain; charset=utf-8\rDocker-Experimental: false\rOstype: linux\rPragma: no-cache\rServer: Docker/library-import (linux)\rDate: Thu, 12 Sep 2019 10:38:27 GMT\r\r&amp;gt; 2019/09/12 20:38:27.925517  length=92 from=81 to=172GET /v1.40/images/json HTTP/1.1\rHost: docker\rUser-Agent: Docker-Client/xx.xx.1 (linux)\r\r&amp;lt; 2019/09/12 20:38:27.926859  length=889 from=287 to=1175HTTP/1.1 200 OK\rApi-Version: 1.41\rContent-Type: application/json\rDocker-Experimental: false\rOstype: linux\rServer: Docker/library-import (linux)\rDate: Thu, 12 Sep 2019 10:38:27 GMT\rContent-Length: 679\r\r[{&amp;#34;Containers&amp;#34;:-1,&amp;#34;Created&amp;#34;:1568087900,&amp;#34;Id&amp;#34;:.......................&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
     </item>
   
     <item>
       <title></title>
       <link>/post/canva-post-mortem-analysis/</link>
       <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
       
       <guid>/post/canva-post-mortem-analysis/</guid>
       <description>&lt;h2 id=&#34;report&#34;&gt;Report&lt;/h2&gt;&lt;p&gt;Analysis based on the published &lt;a href=&#34;https://www.canva.dev/blog/engineering/canva-incident-report-api-gateway-outage/&#34;&gt;post mortem report by Canva&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The API Gateway cluster failure was caused by multiple factors, including:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A &lt;strong&gt;software deployment&lt;/strong&gt; related to Canva&amp;rsquo;s editor, which contributed to system instability.&lt;/li&gt;&lt;li&gt;A &lt;strong&gt;locking issue&lt;/strong&gt;, potentially affecting &lt;strong&gt;resource availability&lt;/strong&gt; and &lt;strong&gt;request handling&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Network issues&lt;/strong&gt; in Cloudflare, which further disrupted connectivity and compounded the failure.&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;user-and-canva-editor&#34;&gt;User and Canva Editor&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;The Canva Editor is the main UI application that users interact with.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Single Page Application (SPA)&lt;/strong&gt; (assumed built using &lt;strong&gt;TypeScript&lt;/strong&gt; and/or &lt;strong&gt;JavaScript&lt;/strong&gt;).&lt;/li&gt;&lt;li&gt;Symptons:&lt;ul&gt;&lt;li&gt;The page appears to be continuously loading, seemingly waiting for assets to be downloaded.&lt;/li&gt;&lt;li&gt;Users may keep waiting, expecting the application to load eventually.&lt;/li&gt;&lt;li&gt;Users must have been impatience and refreshing the browser repeatedly.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&#34;cloudflare-cf&#34;&gt;Cloudflare (CF)&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;CF uses cache stream (&lt;strong&gt;Concurrent Streaming Acceleration&lt;/strong&gt;) to optimize caching performance. The feature consolidate all user&amp;rsquo;s request requesting the same assets to be batch together and once assets are obtained from origin all the request will get the response.&lt;/li&gt;&lt;li&gt;Since request are not rejected (it&amp;rsquo;s put on hold by CF) so no request errors are logged so not alert are triggered.&lt;/li&gt;&lt;li&gt;Even as there are 270,000 requests waiting in CF queue for the assets there is only 1 connection from CF going to the origin server to get the assets, as the assets has not been cache. Once the assets are cached it is delivered to all of the 270,000 waiting request.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/canva/cf.png&#34; alt=&#34;Cloudflare&#34; /&gt;&lt;/p&gt;&lt;h2 id=&#34;api-gateway&#34;&gt;API Gateway&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;The 270,000 user devices have the latest code running. The number of request hitting the API gateway now triple peak load (1.5 million request/sec).&lt;/li&gt;&lt;li&gt;The running gateways were not able to process the requests successfully as newly introduced telemetry SDK code introduced a new bug that created lock contention.&lt;/li&gt;&lt;li&gt;The lock contention bug magnified the issue as requests are now failing because requests cannot be processed by the available running gateway.&lt;/li&gt;&lt;li&gt;Auto scaling should be able to solve the problem but it was not able to scale up quickly as the number of requests are overhelming the infrastructure.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./static/media/canva/gateway.png&#34; alt=&#34;Gateway&#34; /&gt;&lt;/p&gt;&lt;h2 id=&#34;lock-contention&#34;&gt;Lock Contention&lt;/h2&gt;&lt;p&gt;What is &lt;code&gt;lock contention&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;this refers to a scenario in concurrent programming where multiple threads or processes are contending for access to a shared resource, and there is a high likelihood of conflicts or contention events occurring. &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the context of the Telemtry SDK there is a shared data structure that probably were not intended for concurrent access but the code that usesthe data are accessing it concurrently creating a lock contention.&lt;/p&gt;&lt;p&gt;The post mortem highlight the part where the gateway is indeed doing it&amp;rsquo;s job in an event loop and code running in the event loop should notperform any blocking operation, but in this case it is performing blocking operation producing lock contention.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;The API Gateways use an event loop model, where code running on event loop threads must not perform any blocking operations. &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;./static/media/canva/lock_contention.png&#34; alt=&#34;Cloudflare&#34; /&gt;&lt;/p&gt;&lt;h2 id=&#34;key-takeaways&#34;&gt;Key Takeaways&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Understanding the SDK (even if it is an internally developed) limitation is crucial in using it correctly.&lt;/li&gt;&lt;li&gt;Designing concurrent application is hard so duty of care should be taken to perform proper testing.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Concurrent performance testing&lt;/strong&gt; should be part of the release process. Having standard performance baseline enables tocompare how the application is performing and this can assist in picking up anomaly.&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title></title>
       <link>/post/interfaces/</link>
       <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
       
       <guid>/post/interfaces/</guid>
       <description>&lt;p&gt;The following is a function type with function called ServeHTTP&lt;/p&gt;&lt;pre&gt;&lt;code&gt;type HandlerFunc func(ResponseWriter, *Request)func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {    f(w, r)}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;having function declared as follow&lt;/p&gt;&lt;pre&gt;&lt;code&gt;func final(w http.ResponseWriter, r *http.Request) {    log.Println(&amp;quot;Executing finalHandler&amp;quot;)    w.Write([]byte(&amp;quot;OK&amp;quot;))}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;we can wrap the final(..) function as handler using the following&lt;/p&gt;&lt;pre&gt;&lt;code&gt;finalHandler := http.HandlerFunc(final)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After wrapping, the finalHandler will hace access to the ServerHTTP(..) functionwhich basically is calling the final(&amp;hellip;.) function&lt;/p&gt;&lt;p&gt;This is the way to wrap a function (final) that has the same signatureas the named wrapper function (ServeHTTP). The benefit of doing this is the abilityfor other code to just know the type function (ServeHTTP) and call it with the comfortof knowing that it will call the correct implementation function.&lt;/p&gt;&lt;p&gt;Another example:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;package mainimport (    &amp;quot;fmt&amp;quot;)type MyHandlerFunc  func(string, int)func (f MyHandlerFunc) FunctionOne(s string, i int){    fmt.Println(&amp;quot;FunctionOne = &amp;quot;, s , &amp;quot; with i = &amp;quot;, i)    f(s,i)}func (f MyHandlerFunc) FunctionTwo(s string, i int) {    fmt.Println(&amp;quot;FunctionTwo = &amp;quot;, s, &amp;quot; with i = &amp;quot;, i)    f(s,i)}func normalFunction(s string, i int) {    fmt.Println(&amp;quot;normalFunction = &amp;quot;, s, &amp;quot; with i = &amp;quot;, i)}func main() {    finalHandler := MyHandlerFunc(normalFunction)    finalHandler.FunctionOne(&amp;quot;fromFunctionOne&amp;quot;,10)    finalHandler.FunctionTwo(&amp;quot;fromFunctionTwo&amp;quot;,10)}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Another example:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;package mainimport (    &amp;quot;fmt&amp;quot;    &amp;quot;log&amp;quot;    &amp;quot;net/http&amp;quot;)func middlewareOne(next http.Handler) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        log.Println(&amp;quot;Executing middlewareOne&amp;quot;)        next.ServeHTTP(w, r)        log.Println(&amp;quot;Executing middlewareOne again&amp;quot;)    })}func middlewareTwo(next http.Handler) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        log.Println(&amp;quot;Executing middlewareTwo&amp;quot;)        if r.URL.Path != &amp;quot;/&amp;quot; {            return        }        next.ServeHTTP(w, r)        log.Println(&amp;quot;Executing middlewareTwo again&amp;quot;)    })}func final(w http.ResponseWriter, r *http.Request) {    log.Println(&amp;quot;Executing finalHandler&amp;quot;)    w.Write([]byte(&amp;quot;OK&amp;quot;))}func main() {    finalHandler := http.HandlerFunc(final)    http.Handle(&amp;quot;/&amp;quot;, middlewareOne(middlewareTwo(finalHandler)))    http.ListenAndServe(&amp;quot;:3000&amp;quot;, nil)}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Another example:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;type tokenizer func() (token string, ok bool)func split(s, sep string) tokenizer {    tokens, last := strings.Split(s,sep),0    return func() (string, bool) {        if  len(tokens) == last {            return &amp;quot;&amp;quot;, false        }        last = last+1        return tokens[last-1], true    }}&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;interface-using-inside-github-com-tdewolff-minify&#34;&gt;Interface using inside github.com/tdewolff/minify&lt;/h2&gt;&lt;h2 id=&#34;minifier-go&#34;&gt;minifier.go&lt;/h2&gt;&lt;p&gt;Global variable declared as&lt;/p&gt;&lt;pre&gt;&lt;code&gt;var minifier = minify.New()&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;THe init() function do the following&lt;/p&gt;&lt;pre&gt;&lt;code&gt;func init() {    htmlMinify := &amp;amp;html.Minifier{        KeepWhitespace:   true,        KeepDocumentTags: true,    }    minifier.AddFunc(&amp;quot;text/css&amp;quot;, css.Minify)    minifier.Add(&amp;quot;text/html&amp;quot;, htmlMinify)    minifier.Add(&amp;quot;text/x-template&amp;quot;, htmlMinify)    minifier.AddFunc(&amp;quot;text/javascript&amp;quot;, js.Minify)    minifier.AddFunc(&amp;quot;application/javascript&amp;quot;, js.Minify)    minifier.AddFunc(&amp;quot;application/x-javascript&amp;quot;, js.Minify)    minifier.AddFunc(&amp;quot;image/svg+xml&amp;quot;, svg.Minify)    minifier.AddFuncRegexp(regexp.MustCompile(&amp;quot;[/+]json$&amp;quot;), json.Minify)    minifier.AddFuncRegexp(regexp.MustCompile(&amp;quot;[/+]xml$&amp;quot;), xml.Minify)}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;the code inside init() add the relevant function for the different mime type:eg: for text/css it will call css.minify&lt;/p&gt;&lt;p&gt;The following code is the code that is called in the above .AddFunc(..)&lt;/p&gt;&lt;pre&gt;&lt;code&gt;func Minify(m *minify.M, w io.Writer, r io.Reader, params map[string]string) error {    return (&amp;amp;Minifier{}).Minify(m, w, r, params)}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following code&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(&amp;amp;Minifier{}).Minify(m, w, r, params)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;means to call the .Minify(..) pointer receiver that is part of the Minifier struct type. Following isthe declaration of the pointer receiver&lt;/p&gt;&lt;pre&gt;&lt;code&gt;func (o *Minifier) Minify(m *minify.M, w io.Writer, r io.Reader, params map[string]string) error {    ....    isInline := params != nil &amp;amp;&amp;amp; params[&amp;quot;inline&amp;quot;] == &amp;quot;1&amp;quot;    ....    if err := c.minifyGrammar(); err != nil &amp;amp;&amp;amp; err != io.EOF {        return err    }    return nil}&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;reference-reading&#34;&gt;Reference reading:&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://karthikkaranth.me/blog/functions-implementing-interfaces-in-go/&#34;&gt;https://karthikkaranth.me/blog/functions-implementing-interfaces-in-go/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;http://technosophos.com/2014/05/05/adding-methods-to-function-types-in-go.html&#34;&gt;http://technosophos.com/2014/05/05/adding-methods-to-function-types-in-go.html&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title></title>
       <link>/post/servicemesh/</link>
       <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
       
       <guid>/post/servicemesh/</guid>
       <description>&lt;p&gt;date: &amp;ldquo;2019-11-30&amp;rdquo;title: &amp;ldquo;Service Mesh Brain Dump (ALWAYS WIP)&amp;rdquo;author : &amp;ldquo;Nanik Tolaram (nanikjava@gmail.com)&amp;rdquo;&lt;/p&gt;&lt;hr /&gt;&lt;h1&gt; Service Mesh &lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Resources&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://www.datocms-assets.com/2885/1536681707-consulwhitepaperaug2018.pdf&#34;&gt;Consul whitepaper&lt;/a&gt; that explains about service mesh.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;A service mesh is a software-driven approach to routing and segmentation. The goal is to solve the networking and security challenges of operating microservices and cloud infrastructure. Service mesh solutions bring additional benefits such as failure handling, retries, and network observability. A service mesh is an abstract concept that solves multiple service networking challenges in an integrated way.&lt;/li&gt;&lt;li&gt;Following diagrams show the simplest diagram of what service mesh is all about&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/servicemeshbasic.png&#34; alt=&#34;ServiceMeshBasic&#34; /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/service-mesh-with-side-car.png&#34; alt=&#34;ServiceMeshBasic&#34; /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/servicemeshdiagram.png&#34; alt=&#34;servicemeshdiagram&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A service mesh has two key components&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Control Plane&lt;/strong&gt; &amp;ndash;  The control plane holds the state of the system and plays a coordination role. It provides a centralized registry of where services are running, and the policies that restrict traffic. It must scale to handle tens of thousands of service instances, and efficiently update the data plane in real time.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Data Plane&lt;/strong&gt; &amp;ndash; The data plane is distributed and responsible for transmission of data between different services. It must be high-performance and integrate with the control plane.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Following are some of the projects that perform the above 2 different planes&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Data planes&lt;/strong&gt; &amp;ndash; Linkerd, NGINX, HAProxy, Envoy, Traefik&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Control planes&lt;/strong&gt; &amp;ndash; Istio, Nelson, SmartStack&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ingress&lt;/strong&gt; &amp;ndash; term used for incoming request&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Egress&lt;/strong&gt;  &amp;ndash; term used for outgoing request&lt;/li&gt;&lt;li&gt;&lt;p&gt;By default, proxies handle only intra-service mesh cluster traffic - between the source (upstream) and the destination (downstream) services. To expose a service which is part of service mesh to outside word, you have to enable ingress traffic. Similarly, if a service depends on an external service you may require enabling the egress traffic.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/Service_Mesh_Ingress_Egress.png&#34; alt=&#34;ServiceMeshBasic&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Due to distributed nature of service mesh, a control plane or a similar centralized management utility is desirable. This elps in the management of routing tables, service discovery, and load balancing pools.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/servicemeshcontrolplane.png&#34; alt=&#34;ServiceMeshBasic&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;API Gateway vs Service Mesh&lt;/p&gt;&lt;ul&gt;&lt;li&gt;There is some overlap between API Gateway and Service mesh patterns i.e. request routing, composition, authentication, rate limiting, error handling, monitoring, etc. The primary focus of a service mesh is &lt;strong&gt;service-to-service communication (internal traffic)&lt;/strong&gt;, whereas an API Gateway offers a single entry point for external clients such as a mobile app or a web app used by end-user to access services (external traffic).&lt;/li&gt;&lt;li&gt;Technically one can use API Gateway to facilitate internal service-to-service communication but not without introducing the latency and performance issues. As the composition of services can change over time and should be hidden from external clients - API Gateway makes sure that this complexity is hidden from the external client.&lt;/li&gt;&lt;li&gt;It is important to note that a service mesh can use a &lt;strong&gt;diverse set of protocols (RPC/gRPC/REST)&lt;/strong&gt;, some of which might not be friendly to external clients.&lt;/li&gt;&lt;li&gt;&lt;p&gt;API Gateway can handle multiple types of protocols and if can support protocol translation if required. There is no reason why one can not use API Gateway in front of a service mesh.&lt;/p&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/Service-Mesh-API-Gateway.png&#34; alt=&#34;ServiceMeshBasic&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Remember that even thought we are using container orchestration this will not take care of what microservices will need. Container orchestration does not provide what microservice application need that are specificly relevant for the application such as - finding other microservice application, app-to-app communication (gRPC), app-to-app security (session, token, etc).  Following table outlined the difference&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/containerorchestraionvsservicemesh.png&#34; alt=&#34;containerorchestraionvsservicemesh&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In service mesh architecture we need resiliency features such as circuit breaking, timeouts,  deadlines, etc.&lt;/li&gt;&lt;li&gt;Don&amp;rsquo;t think service mesh as a technology, think of it as an abstract concept that bring services together and mesh them together as a single entity.&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt; Consul &lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Following is a high level diagram showing how consul works as a &lt;strong&gt;control plane&lt;/strong&gt; capacity&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/consulcontrolplane.png&#34; alt=&#34;consulcontrolplane&#34; /&gt;&lt;/p&gt;&lt;h1&gt; Istio &lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Resources&lt;ul&gt;&lt;li&gt;The explanation in this article is extracted from &lt;a href=&#34;https://istio.io/blog/2019/data-plane-setup/&#34;&gt;here&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://medium.com/faun/understanding-how-envoy-sidecar-intercept-and-route-traffic-in-istio-service-mesh-20fea2a78833&#34;&gt;Indepth article about the traffic flow using envoy as sidecar&lt;/a&gt;&lt;/li&gt;&lt;li&gt;An indepth &lt;a href=&#34;https://venilnoronha.io/hand-crafting-a-sidecar-proxy-and-demystifying-istio&#34;&gt;article&lt;/a&gt; on creating your own sidecar proxy for app running in Kubernetes.&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://docs.microsoft.com/en-us/azure/architecture/patterns/&#34;&gt;Cloud patterns&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Using kiali.io with Istio &lt;a href=&#34;https://events19.linuxfoundation.org/wp-content/uploads/2018/07/Introduction-to-Service-Mesh-with-Istio-and-Kiali-OSS-Japan-July-2019.pdf&#34;&gt;presentation&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Istio provides &lt;em&gt;&lt;u&gt;automatic injection&lt;/u&gt;&lt;/em&gt; of sidecar proxy in Kubernetes&lt;/li&gt;&lt;li&gt;Istio control plane consist of - Mixer, Pilot and Citadel.&lt;/li&gt;&lt;li&gt;&lt;p&gt;In simple terms, sidecar injection is adding the configuration of additional containers to the pod template. The added containers needed for the Istio service mesh are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;istio-init This init container is used to setup the iptables rules so that inbound/outbound traffic will go through the sidecar proxy. An init container is different than an app container in following ways:&lt;ul&gt;&lt;li&gt;It runs before an app container is started and it always runs to completion.&lt;/li&gt;&lt;li&gt;If there are many init containers, each should complete with success before the next container is started.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, you can see how this type of container is perfect for a set-up or initialization job which does not need to be a part of the actual application container. In this case, istio-init does just that and sets up the iptables rules. istio-proxy This is the actual sidecar proxy (based on Envoy).* This is done by labelling the namespace where you are deploying the app with &lt;strong&gt;istio-injection=enabled&lt;/strong&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl get namespaces --show-labels&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;NAME           STATUS    AGE       LABELSdefault        Active    40d       &amp;lt;none&amp;gt;istio-dev      Active    19d       istio-injection=enabledistio-system   Active    24d       &amp;lt;none&amp;gt;kube-public    Active    40d       &amp;lt;none&amp;gt;kube-system    Active    40d       &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;For automatic sidecar injection, Istio relies on &lt;strong&gt;Mutating Admission Webhook&lt;/strong&gt;. Following is the instruction used to get the webhook info&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;apiVersion: admissionregistration.k8s.io/v1beta1kind: MutatingWebhookConfigurationmetadata:  annotations:    kubectl.kubernetes.io/last-applied-configuration: |      {&amp;#34;apiVersion&amp;#34;:&amp;#34;admissionregistration.k8s.io/v1beta1&amp;#34;,&amp;#34;kind&amp;#34;:&amp;#34;MutatingWebhookConfiguration&amp;#34;,&amp;#34;metadata&amp;#34;:{&amp;#34;annotations&amp;#34;:{},&amp;#34;labels&amp;#34;:{&amp;#34;app&amp;#34;:&amp;#34;istio-sidecar-injector&amp;#34;,&amp;#34;chart&amp;#34;:&amp;#34;sidecarInjectorWebhook-1.0.1&amp;#34;,&amp;#34;heritage&amp;#34;:&amp;#34;Tiller&amp;#34;,&amp;#34;release&amp;#34;:&amp;#34;istio-remote&amp;#34;},&amp;#34;name&amp;#34;:&amp;#34;istio-sidecar-injector&amp;#34;,&amp;#34;namespace&amp;#34;:&amp;#34;&amp;#34;},&amp;#34;webhooks&amp;#34;:[{&amp;#34;clientConfig&amp;#34;:{&amp;#34;caBundle&amp;#34;:&amp;#34;&amp;#34;,&amp;#34;service&amp;#34;:{&amp;#34;name&amp;#34;:&amp;#34;istio-sidecar-injector&amp;#34;,&amp;#34;namespace&amp;#34;:&amp;#34;istio-system&amp;#34;,&amp;#34;path&amp;#34;:&amp;#34;/inject&amp;#34;}},&amp;#34;failurePolicy&amp;#34;:&amp;#34;Fail&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;sidecar-injector.istio.io&amp;#34;,&amp;#34;namespaceSelector&amp;#34;:{&amp;#34;matchLabels&amp;#34;:{&amp;#34;istio-injection&amp;#34;:&amp;#34;enabled&amp;#34;}},&amp;#34;rules&amp;#34;:[{&amp;#34;apiGroups&amp;#34;:[&amp;#34;&amp;#34;],&amp;#34;apiVersions&amp;#34;:[&amp;#34;v1&amp;#34;],&amp;#34;operations&amp;#34;:[&amp;#34;CREATE&amp;#34;],&amp;#34;resources&amp;#34;:[&amp;#34;pods&amp;#34;]}]}]}  creationTimestamp: 2018-12-10T08:40:15Z  generation: 2  labels:    app: istio-sidecar-injector    chart: sidecarInjectorWebhook-1.0.1    heritage: Tiller    release: istio-remote  name: istio-sidecar-injector  .....webhooks:- clientConfig:    service:      name: istio-sidecar-injector      namespace: istio-system      path: /inject  name: sidecar-injector.istio.io  namespaceSelector:    matchLabels:      istio-injection: enabled  rules:  - apiGroups:    - &amp;#34;&amp;#34;    apiVersions:    - v1    operations:    - CREATE    resources:    - pods&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Can see the webhook &lt;strong&gt;namespaceSelector&lt;/strong&gt; label that is matched for sidecar injection with the label &lt;strong&gt;istio-injection: enabled&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &amp;lsquo;app&amp;rsquo; that is intercepting this request is as follows&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;kubectl get svc --namespace&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;istio-system | grep sidecar-injector&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;istio-sidecar-injector   ClusterIP   &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;.102.70.184   &amp;lt;none&amp;gt;        &lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt;/TCP             24d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Now that we are clear about how a sidecar container and an init container are injected into an application manifest, how does the sidecar proxy grab the inbound and outbound traffic to and from the container? We did briefly mention that it is done by setting up the &lt;strong&gt;iptable&lt;/strong&gt; rules within the pod namespace, which in turn is done by the istio-init container. Now, it is time to verify what actually gets updated within the namespace.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Let’s get into the application pod namespace we deployed in the previous section and looked at the configured iptables. I am going to show an example using &lt;strong&gt;nsenter&lt;/strong&gt;. Alternatively, you can enter the container in a privileged mode to see the same information. For folks without access to the nodes, using exec to get into the sidecar and running iptables is more practical.&lt;/p&gt;&lt;p&gt;Get the pid of the container that has the sidecar proxy running (normally this is our app container)&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;docker inspect b8de099d3510 --format &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{ .State.Pid }}&amp;#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;enter into the container and execute the command&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;nsenter -t &lt;span style=&#34;color:#ae81ff&#34;&gt;4215&lt;/span&gt; -n iptables -t nat -S&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output will be as follows&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;-P PREROUTING ACCEPT-P INPUT ACCEPT-P OUTPUT ACCEPT-P POSTROUTING ACCEPT-N ISTIO_INBOUND-N ISTIO_IN_REDIRECT-N ISTIO_OUTPUT-N ISTIO_REDIRECT-A PREROUTING -p tcp -j ISTIO_INBOUND-A OUTPUT -p tcp -j ISTIO_OUTPUT-A ISTIO_INBOUND -p tcp -m tcp --dport 80 -j ISTIO_IN_REDIRECT-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15001-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -j ISTIO_REDIRECT-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN-A ISTIO_OUTPUT -j ISTIO_REDIRECT-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Internal diagrams&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&#34;./media/servicemesh/istioexpanded.png&#34; alt=&#34;consulcontrolplane&#34; /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Following are resources that gives detail explanation on working with Istio&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://openliberty.io/guides/istio-intro.html#deploying-version-2-of-the-system-microservice&#34;&gt;https://openliberty.io/guides/istio-intro.html#deploying-version-2-of-the-system-microservice&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt; Kuma &lt;/h1&gt;&lt;p&gt;&lt;a href=&#34;https://kuma.io&#34;&gt;Kuma&lt;/a&gt; is an open source service mesh project that provides both control and data plane functionality. The interesting part about this project is the ability to use it for both Kubernetes and non-Kubernetes environment (bare metal and VM).&lt;/p&gt;&lt;p&gt;Following are the steps to run the sample app in kuma:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Run kuma-echo sample app&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Run the kuma-cp run&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Generate Dataplane data&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;echo &amp;#34;type: Dataplane                                                         mesh: defaultname: dp-echo-1networking:  inbound:  - interface: 127.0.0.1:10000:9000    tags:      service: echo&amp;#34; | ./kumactl apply -f -&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Generate the data token using the following&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;./kumactl generate dataplane-token --dataplane&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;dp-echo-1 &amp;gt; /tmp/kuma-dp-echo-1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Run kuma-dp using the generated token as follows&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;./kuma-dp run   --name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;dp-echo-1   --mesh&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;default   --cp-address&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;http://127.0.0.1:5681   --dataplane-token-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/tmp/kuma-dp-echo-1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Debugging through kuma-dp following is the generated configuration used for envoy&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;dynamicResources:  adsConfig:    apiType: GRPC    grpcServices:    - envoyGrpc:        clusterName: ads_cluster  cdsConfig:    ads: {}  ldsConfig:    ads: {}node:  cluster: echo  id: default.dp-echo-1  metadata:    dataplaneTokenPath: /tmp/kuma-dp-echo-1staticResources:  clusters:  - connectTimeout: 1s    http2ProtocolOptions: {}    loadAssignment:      clusterName: ads_cluster      endpoints:      - lbEndpoints:        - endpoint:            address:              socketAddress:                address: localhost                portValue: 5678    name: ads_cluster    type: STRICT_DNS    upstreamConnectionOptions:      tcpKeepalive: {}  - connectTimeout: 1s    http2ProtocolOptions: {}    loadAssignment:      clusterName: access_log_sink      endpoints:      - lbEndpoints:        - endpoint:            address:              pipe:                path: /tmp/kuma-access-logs-dp-echo-1-default.sock    name: access_log_sink    type: STATIC    upstreamConnectionOptions:      tcpKeepalive: {}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;and following is the configuration used to run envoy&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt; 0 = {string} &amp;#34;-c&amp;#34; 1 = {string} &amp;#34;/tmp/kuma-dp-443537827/bootstrap.yaml&amp;#34; 2 = {string} &amp;#34;--drain-time-s&amp;#34; 3 = {string} &amp;#34;30&amp;#34; 4 = {string} &amp;#34;--disable-hot-restart&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;./media/servicemesh/kumahighlevel.jpg&#34; alt=&#34;kumahighlevel&#34; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
 </channel>
</rss>
