<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Hugo Martins</title>
    <link>https://hugomartins.io/</link>
    <description>Hugo Martins</description>    
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sat, 10 Aug 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://hugomartins.io/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Abstractions can be expensive</title>
      <link>https://hugomartins.io/essays/2024/08/abstractions-can-be-expensive/</link>
      <pubDate>Sat, 10 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2024/08/abstractions-can-be-expensive/</guid>
      <description>&lt;p&gt;Daniel Lemire wrote in &lt;em&gt;&lt;a href=&#34;https://lemire.me/blog/2024/06/22/performance-tip-avoid-unnecessary-copies/&#34;&gt;Performance tip: avoid unnecessary copies&lt;/a&gt;&lt;/em&gt;, comparing &lt;a href=&#34;https://bun.sh/&#34;&gt;Bun&lt;/a&gt; to &lt;a href=&#34;https://nodejs.org/en&#34;&gt;Node.js&lt;/a&gt;, about a particular case where copying data becomes expensive:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It turns out that the copy was not happening as part of base64 decoding but in a completely separate function. There is an innocuous function in Node.js called  &lt;code&gt;StringBytes::Size&lt;/code&gt; which basically must provide an upper on the memory needed by the &lt;code&gt;Buffer.from&lt;/code&gt; function.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As shown in the benchmarks, in the piece, Node.js becomes much slower than Bun when computing the same thing (e.g decoding base64). Even though both of these runtimes use the same library, an unsuspicious copy of data deep in the code of Node.js made it more expensive and slower.&lt;/p&gt;
&lt;p&gt;I’ve encountered a similar situation in Go. A service was misbehaving and using too much memory. Profiling and investigating, I narrowed it down to the fact that it was using &lt;a href=&#34;https://pkg.go.dev/io#ReadAll&#34;&gt;io.ReadAll&lt;/a&gt; to transform a response into a slice of bytes (&lt;code&gt;[]byte&lt;/code&gt;). In itself, there is nothing wrong with this idea &lt;em&gt;but&lt;/em&gt; there’s something particular about &lt;code&gt;io.ReadAll&lt;/code&gt; (&lt;a href=&#34;%5Bhttps://cs.opensource.google/go/go/+/go1.22.5:src/io/io.go;l=709%5D(https://cs.opensource.google/go/go/+/refs/tags/go1.20.14:src/io/io.go)&#34;&gt;source&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;func&lt;/span&gt; ReadAll(r Reader) ([]byte, error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	b :&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; make([]byte, &lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;512&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#719e07&#34;&gt;for&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#719e07&#34;&gt;if&lt;/span&gt; len(b) &lt;span style=&#34;color:#719e07&#34;&gt;==&lt;/span&gt; cap(b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#719e07&#34;&gt;//&lt;/span&gt; Add more capacity (let append pick how much)&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			b &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; append(b, &lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;)[:len(b)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#719e07&#34;&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside a &lt;code&gt;for&lt;/code&gt; loop, &lt;code&gt;ReadAll&lt;/code&gt; will validate that the buffer it created (&lt;em&gt;512 bytes&lt;/em&gt;) has enough capacity to store the data. If it doesn’t, it duplicates the size of the existing buffer. This happens until the buffer has enough space to store all of the data. It inherently means we will use &lt;em&gt;a lot more memory&lt;/em&gt; than the original size of the data. All of this might be unexpected.&lt;/p&gt;
&lt;p&gt;If we don’t know the size of the data &lt;em&gt;a priori&lt;/em&gt;, there’s not much we can do to reduce this (&lt;em&gt;I believe&lt;/em&gt;) but, if we do know the size of the buffer, &lt;a href=&#34;https://pkg.go.dev/io#Copy&#34;&gt;io.Copy&lt;/a&gt; might be a good alternative. It allows you to specify the size of the buffer, before writing data to it, avoiding the memory-intensive capacity increases.&lt;/p&gt;
&lt;p&gt;This was true up until, at least, Go 1.20.4. In recent versions, the implementation has changed. But it doesn’t change the underlying fact that this abstraction could potentially be expensive memory-wise, or even contribute to a program performing poorly or misbehaving. As Lemire points out:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The story illustrates why our software is slower than it should be. We have layers of abstractions to fight against. Sometimes you win, sometimes you lose.&lt;/p&gt;
&lt;p&gt;These layers are there for a reason, but they are not free.&lt;/p&gt;
&lt;p&gt;To make matters worse… these abstraction layers often thicken over time… and the friction goes up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is not that the layers are unnecessary: they do good work. They allow us to avoid reimplementing the same things over and over again. They allow us to build on top of several individuals’ expertise and they support frameworks that allow us to be more productive&amp;hellip;but &lt;strong&gt;they are not always free&lt;/strong&gt;, there’s a cost associated with these abstractions. And it is important to keep an eye (&lt;em&gt;and monitoring&lt;/em&gt;) open to the possibility that sometimes, only sometimes, they are more expensive than we are willing to accept.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>On What Lexers Do</title>
      <link>https://hugomartins.io/essays/2023/02/on-what-lexers-do/</link>
      <pubDate>Tue, 21 Feb 2023 15:31:16 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2023/02/on-what-lexers-do/</guid>
      <description>&lt;p&gt;A couple of weeks ago, I’ve started reading &lt;a href=&#34;https://interpreterbook.com/&#34;&gt;Writing An Interpreter In Go&lt;/a&gt;. Reading this book means I’ll be building an interpreter for a language called &lt;code&gt;monkey&lt;/code&gt; (&lt;a href=&#34;https://github.com/caramelomartins/monkeylang&#34;&gt;you can follow my implementation&lt;/a&gt;). It is a topic that I’ve always been curious about but never actually took the plunge and decided to study it.&lt;/p&gt;
&lt;p&gt;I’ve dabbled a little bit with it in university. But we never actually wrote any of the internal tools. We always used generators for the code and focused more on the concepts. Rest assured, I can’t remember most of it by now.&lt;/p&gt;
&lt;p&gt;While reading this book, I reconnected with the basic concepts of how interpreters and compilers work. I&amp;rsquo;ve been taking notes and trying to expand my knowledge with other sources. I’ve always heard that to know something, you need to be able to explain it. I’m trying to do that here.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lexers transform source code into symbols (or tokens).&lt;/strong&gt; They execute what is called “lexical analysis”. From &lt;a href=&#34;app://obsidian.md/Writing%20an%20Interpreter%20in%20Go&#34;&gt;Writing an Interpreter in Go&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(&amp;hellip;) from source code to tokens, is called &amp;ldquo;lexical analysis&amp;rdquo;, or &amp;ldquo;lexing&amp;rdquo; for short. It&amp;rsquo;s done by a lexer (&amp;hellip;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Wikipedia &lt;a href=&#34;https://en.wikipedia.org/wiki/Lexical_analysis&#34;&gt;defines&lt;/a&gt; “lexical analysis” as &lt;em&gt;“the process of converting a sequence of &lt;a href=&#34;https://en.wikipedia.org/wiki/Character_(computing)&#34; title=&#34;Character (computing)&#34;&gt;characters&lt;/a&gt; (…) into a sequence of &lt;em&gt;lexical tokens&lt;/em&gt; (…)”&lt;/em&gt;. This aligns well with what we read in the book.&lt;/p&gt;
&lt;p&gt;So, when we execute a lexer, we transform the source code (&lt;em&gt;text&lt;/em&gt;) into a series of data structures (&lt;em&gt;tokens&lt;/em&gt;). It is an integral component of writing interpreters (or compilers) as we need to transform source code into a representation that we understand and can process in later stages (e.g. parsing).&lt;/p&gt;
&lt;p&gt;As an example, in Go, if we have the statement &lt;code&gt;str := &amp;quot;string&amp;quot;&lt;/code&gt;, we are in the presence of three tokens: an identifier token (&lt;code&gt;str&lt;/code&gt;), an assignment token (&lt;code&gt;:=&lt;/code&gt;) and a string token (&lt;code&gt;string&lt;/code&gt;).  &lt;strong&gt;Tokens are meaningful data structures&lt;/strong&gt;, allowing us to approach source code as data structures, rather than dealing with text inside of interpreters.&lt;/p&gt;
&lt;p&gt;Lexers also help us ignore elements of source code that aren&amp;rsquo;t relevant (e.g. whitespaces in some languages) and focus just on the elements that actually matter to us. After lexing, all irrelevant whitespace has been stripped off. For example, in C or Go, I wouldn’t expect whitespace to appear as tokens after lexing. In Python, where whitespace is relevant, I expect it to be taken into account in lexing.&lt;/p&gt;
&lt;p&gt;One concept I was particularly interested in, as I read, was the fact that &lt;strong&gt;lexers need to look-ahead&lt;/strong&gt;. This isn’t always done the same way, it depends on the approach used, but it is integral to lexing, to be able to resolve conflicts.&lt;/p&gt;
&lt;p&gt;As an example, reading a “=“ sign might represent different things. It can be an equal sign (e.g. assignment) or it can be the start of a comparison (e.g “==“). Without looking ahead, it is impossible to resolve conflicts and accurately know what a given character represents in source code.&lt;/p&gt;
&lt;p&gt;Lexical analysis is only but a small step, in the process of interpreting source code and its results, that will need to be fed into a parser, which will perform additional steps with the tokens.&lt;/p&gt;
&lt;p&gt;It has been a good experience reading these initial sections of &lt;a href=&#34;https://interpreterbook.com/&#34;&gt;Writing An Interpreter In Go&lt;/a&gt; and finally feel I’m starting to understand the basics of these concepts.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Traffic: July to December 2022</title>
      <link>https://hugomartins.io/essays/2023/02/traffic-july-december-2022/</link>
      <pubDate>Tue, 14 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2023/02/traffic-july-december-2022/</guid>
      <description>&lt;p&gt;I’ve kept this tradition of looking back at the traffic every six months since 2021 (&lt;a href=&#34;https://hugomartins.io/essays/2022/07/traffic-january-june-2022/&#34;&gt;here&lt;/a&gt; and &lt;a href=&#34;https://hugomartins.io/essays/2022/01/traffic-july-december-2021/&#34;&gt;here&lt;/a&gt;). This time, it also marks the end of the year, in terms of traffic, which makes this review two-fold: a six-month review along with a yearly review.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://hugomartins.io/images/Stats-July-December-2022.png&#34; alt=&#34;Stats&#34;&gt;&lt;/p&gt;
&lt;p&gt;In total, from July 2022 to December 2022, there were 11868 visitors and 13517 pageviews (~73/day). Google is still the biggest source of traffic, followed by Bing and DuckDuckGo. Compared with the previous month, visitors were down 10%, while pageviews were down 12%.&lt;/p&gt;
&lt;p&gt;This isn’t a surprise to me in any way. I have written &lt;em&gt;only&lt;/em&gt; two essays during this period and I didn’t share any of them broadly, I was actually quite surprised when I noticed the numbers didn’t go down even &lt;em&gt;more&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The top essays have remained the same, throughout this semester, with only a slight change in ranking:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/02/how-to-pass-multiple-values-to-http-query-parameter/&#34;&gt;How To Pass Multiple Parameters To Same Value in Query Strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/01/build-a-terraform-private-registry/&#34;&gt;Building a Private Terraform Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/02/using-require-and-check-in-kotlin/&#34;&gt;Using require and check Functions in Kotlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/03/understanding-differences-between-list-and-mutablelist-in-kotlin/&#34;&gt;Understanding Differences Between List and MutableList in Kotlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2019/12/access-host-resources-minikube/&#34;&gt;How to Access Host Resources in Minikube Pods?&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/02/using-require-and-check-in-kotlin/&#34;&gt;Using require and check Functions in Kotlin&lt;/a&gt; surpassed both &lt;a href=&#34;https://hugomartins.io/essays/2019/12/access-host-resources-minikube/&#34;&gt;How to Access Host Resources in Minikube Pods?&lt;/a&gt; and &lt;a href=&#34;https://hugomartins.io/essays/2021/03/understanding-differences-between-list-and-mutablelist-in-kotlin/&#34;&gt;Understanding Differences Between List and MutableList in Kotlin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Throughout 2022, there were 24994 unique visitors and 28673 pageviews. Most of what was written in 2022 didn’t get much traction, except for &lt;a href=&#34;https://hugomartins.io/essays/2022/02/essential-fields-in-kubernetes-manifests/&#34;&gt;Essential Fields in Kubernetes Manifests&lt;/a&gt;, which seems to have found its way to Top 10 somehow.&lt;/p&gt;
&lt;p&gt;I didn’t share much (or anything) of what I wrote during the entire year, which is something I might want to change in 2023, but some of the things I wrote on the &lt;a href=&#34;https://hugomartins.io/series/ckad/&#34;&gt;journey to CKAD&lt;/a&gt; seemed to have resonated with people, even though I didn’t share them.&lt;/p&gt;
&lt;p&gt;For 2023, I don’t want to necessarily increase traffic but I’d be happy if, &lt;em&gt;by writing and sharing more&lt;/em&gt;, traffic would necessarily grow organically. I’ll put my focus more on the writing than I did in 2022, and we’ll see the impact doing that will have.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>On Unit Testing in Temporal</title>
      <link>https://hugomartins.io/essays/2022/12/on-unit-testing-temporal/</link>
      <pubDate>Wed, 28 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2022/12/on-unit-testing-temporal/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been using &lt;a href=&#34;https://temporal.io/&#34;&gt;Temporal&lt;/a&gt;, &amp;ldquo;a developer-first, open source platform that ensures the successful execution of services and applications&amp;rdquo;, for troubleshooting purposes for a while now. We use it &lt;a href=&#34;https://www.youtube.com/watch?v=LxgkAoTSI8Q&#34;&gt;quite extensively at Datadog&lt;/a&gt;. Recently, I&amp;rsquo;ve started actually implementing something on top of Temporal and was amazed at the simplicity of its testing framework.&lt;/p&gt;
&lt;p&gt;At first I was a bit confused, as I&amp;rsquo;m interested in Go and could only find documentation focusing on Java. Eventually, I found &lt;a href=&#34;https://docs.temporal.io/go/how-to-test-workflow-definitions-in-go&#34;&gt;How to test Workflow Definitions in Go&lt;/a&gt;, a great introduction to the testing framework that Temporal offers with &lt;a href=&#34;https://pkg.go.dev/go.temporal.io/sdk@v1.17.0/testsuite&#34;&gt;testsuite&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It all starts with a &lt;code&gt;WorkflowTestSuite&lt;/code&gt;, in which we can initialize a &lt;code&gt;TestWorkflowEnvironment&lt;/code&gt;. This &lt;code&gt;TestWorkflowEnvironment&lt;/code&gt; is powerful and we immediately get access to a few important functions, such as &lt;code&gt;AssertExpectations&lt;/code&gt; or &lt;code&gt;ExecuteWorkflow&lt;/code&gt;. These allow you to do things as diverse as checking that all expected calls (to mocks) have been made and to execute a workflow inside a test environment. We can use &lt;code&gt;RegisterActivity&lt;/code&gt; or &lt;code&gt;RegisterWorkflow&lt;/code&gt; as well, to ensure our Activities and Workflows are available in the environment we&amp;rsquo;ll execute our tests in.&lt;/p&gt;
&lt;p&gt;Unfortunately, as pointed out in Temporal&amp;rsquo;s documentation, &lt;em&gt;&amp;ldquo;unless the Activity invocations are mocked(&amp;hellip;) the test environment will execute the actual Activity code including any calls to outside services.&amp;rdquo;&lt;/em&gt; This is particularly harmful if the Activities being invoked execute code that makes calls to endpoints on a network because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it makes the tests unable to execute without connecting to the network;&lt;/li&gt;
&lt;li&gt;it makes for unreliable and inconsistent behaviour of the tests;&lt;/li&gt;
&lt;li&gt;and it doesn&amp;rsquo;t allow us to test multiple failure modes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this reason, Temporal&amp;rsquo;s testing framework offers methods to mock Activities in a &lt;code&gt;TestWorkflowEnvironment&lt;/code&gt; such as &lt;code&gt;OnActivity&lt;/code&gt;. This works well when the Activities are implemented internally but I couldn&amp;rsquo;t get it to work when the Activities are implemented in a third-party package.&lt;/p&gt;
&lt;p&gt;I read a bit of the &lt;a href=&#34;https://github.com/temporalio/samples-go/blob/main/expense/workflow_test.go&#34;&gt;temporalio/samples-go&lt;/a&gt; repository, which houses a collection of samples and accompanying tests, to understand what needs to be done. It is &lt;em&gt;seems&lt;/em&gt; simple enough:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-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;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; UnitTestSuite &lt;span style=&#34;color:#268bd2&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    suite.Suite
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    testsuite.WorkflowTestSuite
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;func&lt;/span&gt; (s &lt;span style=&#34;color:#719e07&#34;&gt;*&lt;/span&gt;UnitTestSuite) &lt;span style=&#34;color:#268bd2&#34;&gt;TestSampleWorkflow&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#586e75&#34;&gt;// Initialize test environment for UnitTestSuite.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;	env = s.&lt;span style=&#34;color:#268bd2&#34;&gt;NewTestWorkflowEnvironment&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#586e75&#34;&gt;// Register needed Activities.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;	env.&lt;span style=&#34;color:#268bd2&#34;&gt;RegisterActivity&lt;/span&gt;(externalpackage.ExternalActivity)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#586e75&#34;&gt;// Mock Activities.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;	env.&lt;span style=&#34;color:#268bd2&#34;&gt;OnActivity&lt;/span&gt;(externalpackage.ExternalActivity, mock.Anything, mock.Anything).&lt;span style=&#34;color:#268bd2&#34;&gt;Return&lt;/span&gt;(&lt;span style=&#34;color:#cb4b16&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#586e75&#34;&gt;// Execute Workflow and Assert.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;	env.&lt;span style=&#34;color:#268bd2&#34;&gt;ExecuteWorkflow&lt;/span&gt;(SampleWorkflow)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	(&lt;span style=&#34;color:#719e07&#34;&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I was surprised it was this easy. I confess I was expecting a little bit more complexity. That might be due to my lack of knowledge about the internals of Temporal, but I have to say I was quite excited about how easily I was able to make progress.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Traffic: January to June 2022</title>
      <link>https://hugomartins.io/essays/2022/07/traffic-january-june-2022/</link>
      <pubDate>Mon, 25 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2022/07/traffic-january-june-2022/</guid>
      <description>&lt;p&gt;Last year I started publishing short summaries about the traffic this website receives. You can see the initial reports for &lt;a href=&#34;https://hugomartins.io/essays/2021/09/traffic-january-june-2021/&#34;&gt;January to June 2021&lt;/a&gt; and &lt;a href=&#34;https://hugomartins.io/essays/2022/01/traffic-july-december-2021/&#34;&gt;July to December 2021&lt;/a&gt;. This year I&amp;rsquo;m trying to keep doing just that. Here&amp;rsquo;s the traffic this website received during the initial semester of 2022.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://hugomartins.io/images/Stats-January-June-2022.png&#34; alt=&#34;Stats&#34;&gt;&lt;/p&gt;
&lt;p&gt;In total, from January to June 2022, there were 13127 unique visitors and 15156 pageviews (84/day). Google was where most traffic came from, followed by Bing, DuckDuckGo and Yandex. Compared with the previous six months, pageviews per day were up 1.7x, which I attribute to the compounding effect of Google redirecting more traffic to the website since around October of last year.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve written five essays throughout the initial half of 2022, with one being a traffic summary and four of those being focused on Kubernetes and CKAD. Throughout this initial semester of 2022, the top essays have remained exactly the same:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/02/how-to-pass-multiple-values-to-http-query-parameter/&#34;&gt;How To Pass Multiple Parameters To Same Value in Query Strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/01/build-a-terraform-private-registry/&#34;&gt;Building a Private Terraform Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/03/understanding-differences-between-list-and-mutablelist-in-kotlin/&#34;&gt;Understanding Differences Between List and MutableList in Kotlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2019/12/access-host-resources-minikube/&#34;&gt;How to Access Host Resources in Minikube Pods?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/02/using-require-and-check-in-kotlin/&#34;&gt;Using require and check Functions in Kotlin&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;. I attribute this situation to three reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google has continuously been directing people to those articles, which will naturally make them stand out more.&lt;/li&gt;
&lt;li&gt;I haven&amp;rsquo;t published anything in April, May or June, and have published five pieces in January, February and March. This means that there isn&amp;rsquo;t a lot of fresh essays ready for people to read, so they will naturally gravitate to older essays.&lt;/li&gt;
&lt;li&gt;I haven&amp;rsquo;t made much of an effort to promote the website, which means that once the most recent essays are published they won&amp;rsquo;t get as much traffic in the longer term, at least not as much as the most established essays.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve started this website as a place where I could explore the practice of writing, where I could experiment and, in some cases, take notes. I&amp;rsquo;m not discouraged by the halt in growth because it &lt;em&gt;makes sense&lt;/em&gt;, given what I&amp;rsquo;ve produced recently.&lt;/p&gt;
&lt;p&gt;The website keeps receiving some traffic, which I&amp;rsquo;m happy about, even though I haven&amp;rsquo;t been as consistent with a publishing schedule, which is &lt;em&gt;really&lt;/em&gt; what I&amp;rsquo;m not so happy about and I will aim at improving that in the following six months.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Understanding &#39;kubectl explain&#39;</title>
      <link>https://hugomartins.io/essays/2022/03/understanding-kubectl-explain/</link>
      <pubDate>Tue, 29 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2022/03/understanding-kubectl-explain/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#explain&#34;&gt;kubectl explain&lt;/a&gt; can be used to get more information about which fields a given resource needs, as well as the meaning behind those fields. It can be used in mainly two ways: either for getting information about the fields of a resource (e.g. &lt;code&gt;kubectl explain &amp;lt;resource&amp;gt;&lt;/code&gt;) or by getting information about a specific field of a resource (e.g. &lt;code&gt;kubectl explain &amp;lt;resource&amp;gt;.&amp;lt;field/s&amp;gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Together with &lt;code&gt;api-versions&lt;/code&gt; and &lt;code&gt;api-resources&lt;/code&gt; it can quickly provide a lot of insight into Kubernetes and what needs to be written on a manifest to properly create or edit objects.&lt;/p&gt;
&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;
&lt;p&gt;Getting information about root fields of Pods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ kubectl explain pods
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;KIND:     Pod
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VERSION:  v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DESCRIPTION:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Pod is a collection of containers that can run on a host. This resource is
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     created by clients and scheduled onto hosts.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FIELDS:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   apiVersion   &amp;lt;string&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     APIVersion defines the versioned schema of this representation of an
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     object. Servers should convert recognized schemas to the latest internal
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     value, and may reject unrecognized values. More info:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   kind &amp;lt;string&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Kind is a string value representing the REST resource this object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     represents. Servers may infer this from the endpoint the client submits
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     requests to. Cannot be updated. In CamelCase. More info:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   metadata     &amp;lt;Object&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Standard object&amp;#39;s metadata. More info:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   spec &amp;lt;Object&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Specification of the desired behavior of the pod. More info:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   status       &amp;lt;Object&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Most recently observed status of the pod. This data may not be up to date.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Populated by the system. Read-only. More info:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Getting information about the &lt;code&gt;spec&lt;/code&gt; of Pods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl explain pods&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;spec
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;KIND:     Pod
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VERSION:  v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RESOURCE: spec &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#cb4b16&#34;&gt;Object&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DESCRIPTION:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Specification of the desired behavior of the pod&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; More info:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     https:&lt;span style=&#34;color:#719e07&#34;&gt;//&lt;/span&gt;git&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;k8s&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;io&lt;span style=&#34;color:#719e07&#34;&gt;/&lt;/span&gt;community&lt;span style=&#34;color:#719e07&#34;&gt;/&lt;/span&gt;contributors&lt;span style=&#34;color:#719e07&#34;&gt;/&lt;/span&gt;devel&lt;span style=&#34;color:#719e07&#34;&gt;/&lt;/span&gt;sig&lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt;architecture&lt;span style=&#34;color:#719e07&#34;&gt;/&lt;/span&gt;api&lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt;conventions&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;md&lt;span style=&#34;color:#586e75&#34;&gt;#spec-and-status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     PodSpec is a description of a pod&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FIELDS:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   activeDeadlineSeconds        &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt;integer&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Optional duration &lt;span style=&#34;color:#719e07&#34;&gt;in&lt;/span&gt; seconds the pod may be active on the node relative to
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     StartTime before the system will actively try to mark it failed &lt;span style=&#34;color:#719e07&#34;&gt;and&lt;/span&gt; kill
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     associated containers&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Value must be a positive integer&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   affinity     &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#cb4b16&#34;&gt;Object&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     If specified, the pod&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;s scheduling constraints&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   automountServiceAccountToken &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt;boolean&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     AutomountServiceAccountToken indicates whether a service account token
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     should be automatically mounted&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   containers   &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt;[]&lt;span style=&#34;color:#cb4b16&#34;&gt;Object&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt;required&lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     List of containers belonging to the pod&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Containers cannot currently be
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     added &lt;span style=&#34;color:#719e07&#34;&gt;or&lt;/span&gt; removed&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; There must be at least one container &lt;span style=&#34;color:#719e07&#34;&gt;in&lt;/span&gt; a Pod&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Cannot be
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     updated&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   dnsConfig    &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#cb4b16&#34;&gt;Object&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Specifies the DNS parameters of a pod&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Parameters specified here will be
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     merged to the generated DNS configuration based on DNSPolicy&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   dnsPolicy    &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt;string&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Set DNS policy &lt;span style=&#34;color:#719e07&#34;&gt;for&lt;/span&gt; the pod&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Defaults to &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;ClusterFirst&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Valid values are
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;ClusterFirstWithHostNet&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;ClusterFirst&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;Default&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;None&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; DNS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     parameters given &lt;span style=&#34;color:#719e07&#34;&gt;in&lt;/span&gt; DNSConfig will be merged with the policy selected with
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     DNSPolicy&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; To have DNS options set along with hostNetwork, you have to
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     specify DNS policy explicitly to &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;ClusterFirstWithHostNet&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#719e07&#34;&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It explains what this field represents, as well as all the fields that can be configured inside this specific field, and their meanings. It can be a powerful tool to understand Kubernetes. A sort of  &lt;code&gt;man&lt;/code&gt; for Kubernetes itself.&lt;/p&gt;
&lt;p&gt;It can be particularly interesting to use &lt;code&gt;kubectl explain&lt;/code&gt; to inspect, when you forget, &lt;a href=&#34;https://hugomartins.io/essays/2022/02/essential-fields-in-kubernetes-manifests/&#34;&gt;essential fields in Kubernetes manifests&lt;/a&gt;, or internal details.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What Can Be Done With &#39;kubectl run&#39; Command?</title>
      <link>https://hugomartins.io/essays/2022/03/what-can-be-done-with-kubectl-run/</link>
      <pubDate>Fri, 18 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2022/03/what-can-be-done-with-kubectl-run/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#run&#34;&gt;kubectl run&lt;/a&gt; is a command that can &lt;em&gt;&amp;ldquo;create and run a particular image in a pod&amp;rdquo;&lt;/em&gt;, which means that it will start a pod with a particular image. It can also create the pod with some particular details by using combinations of flags. We can see the code for it in &lt;a href=&#34;https://github.com/kubernetes/kubectl/blob/f48256c8eef5df2e3a9c621dd667839bdbe7c4cd/pkg/cmd/run/run.go&#34;&gt;pkg/cmd/run/run.go&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;interesting-flags&#34;&gt;Interesting Flags&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--image&lt;/code&gt; specifies the image to be executed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--command&lt;/code&gt; allows to overwrite the command field in the container with whatever arguments are sent after &lt;code&gt;--&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--env&lt;/code&gt; to set environment variables in the pods, in the form of &lt;code&gt;key:value&lt;/code&gt; and one variable per &lt;code&gt;--env&lt;/code&gt;  flag.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--expose&lt;/code&gt; and &lt;code&gt;--port&lt;/code&gt; to create a ClusterIP associated with the pod.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--labels&lt;/code&gt; which allows us to configure labels for the specific pod. Labels are accepted with only one flag, separated by a comma.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--dry-run&lt;/code&gt; for testing purposes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;
&lt;p&gt;From documentation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl run nginx --image=nginx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl run hazelcast --image=hazelcast/hazelcast --env=&amp;#34;DNS_DOMAIN=cluster&amp;#34; --env=&amp;#34;POD_NAMESPACE=default&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl run hazelcast --image=hazelcast/hazelcast --labels=&amp;#34;app=hazelcast,env=prod&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl run nginx --image=nginx --command -- &amp;lt;cmd&amp;gt; &amp;lt;arg1&amp;gt; ... &amp;lt;argN&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;use-case&#34;&gt;Use Case&lt;/h2&gt;
&lt;p&gt;While I don&amp;rsquo;t see much use in &lt;code&gt;kubectl run&lt;/code&gt; for dealing with production grade systems, it can be a great resource for testing out different configurations of pods and creating a bunch of pods if there&amp;rsquo;s a need for it. It can also be a great introductory command for when first starting to deal with Kubernetes because it eases the interaction with Kubernetes without having to deal with YAML right away.&lt;/p&gt;
&lt;p&gt;Due to its &lt;code&gt;--output&lt;/code&gt; flag, it can also be a great way to use &lt;code&gt;kubectl&lt;/code&gt; to create pods, in a stable way, from scripts because we can have stable and reproducible outputs from it. The fact that we can use a &lt;code&gt;--dry-run&lt;/code&gt; flag is also a big plus.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Essential Fields in Kubernetes Manifests</title>
      <link>https://hugomartins.io/essays/2022/02/essential-fields-in-kubernetes-manifests/</link>
      <pubDate>Tue, 15 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2022/02/essential-fields-in-kubernetes-manifests/</guid>
      <description>&lt;p&gt;I recently started a quest to &lt;a href=&#34;https://hugomartins.io/essays/2022/02/ckad-in-2022/&#34;&gt;complete CKAD&lt;/a&gt; in the next few months, by May 2022. As I&amp;rsquo;ve explained in that previous essay, &amp;ldquo;I have spent quite some €€€ enrolling in it and I feel that it can still teach me a lot of relevant concepts about Kubernetes that will be useful&amp;rdquo; on my day-to-day.&lt;/p&gt;
&lt;p&gt;While studying for CKAD, through &lt;a href=&#34;https://www.udemy.com/course/certified-kubernetes-application-developer/&#34;&gt;Kubernetes Certified Application Developer (CKAD) with Tests&lt;/a&gt; and &lt;a href=&#34;http://www.kodekloud.com/&#34;&gt;KodeKloud&lt;/a&gt;, I&amp;rsquo;ve come to realize the importance of understanding the syntax of manifests in Kubernetes. Subconsciously, I obviously already knew this - the same way I know how important it is to dominate the syntax of a given programming language - but it is too easy to fall into a pattern of copy-pasting-and-changing, or simply filling in the gaps in already existing manifests.&lt;/p&gt;
&lt;p&gt;Manifests in Kubernetes are the baseline of describing and defining resources, that we can then create and edit afterwards. Manifests represent the object specification describing &amp;ldquo;its desired state, as well as some basic information about the object (such as a name).&amp;rdquo; &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; These manifests are most often described in &lt;code&gt;.yaml&lt;/code&gt; files.&lt;/p&gt;
&lt;p&gt;In essence, there are four essential fields in Kubernetes manifests that must be present in all manifests. These are: &lt;code&gt;apiVersion&lt;/code&gt;, &lt;code&gt;kind&lt;/code&gt;, &lt;code&gt;metadata&lt;/code&gt; and &lt;code&gt;spec&lt;/code&gt;. Each of these might have widely varying values populating them.&lt;/p&gt;
&lt;p&gt;As an example, a starting point for a Kubernetes manifest would be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiVersion:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kind:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apiversion&#34;&gt;apiVersion&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;apiVersion&lt;/code&gt; allows us to define what version of the API a given resource is going to be using. It can be simply &lt;code&gt;v1&lt;/code&gt;, which means it will be part of the &lt;em&gt;core&lt;/em&gt; API specified at &lt;code&gt;/api/v1&lt;/code&gt;. It can also be &lt;code&gt;&amp;lt;name&amp;gt;/&amp;lt;version&amp;gt;&lt;/code&gt;, for example &lt;code&gt;batch/v1&lt;/code&gt;, specifying that at resource uses an API that is under &lt;code&gt;/api/&amp;lt;name&amp;gt;&lt;/code&gt;. &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;We can find more about what APIs and versions exist on a given cluster by executing &lt;code&gt;kubectl api-version&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ kubectl api-versions
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admissionregistration.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admissionregistration.k8s.io/v1beta1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiextensions.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiextensions.k8s.io/v1beta1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiregistration.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiregistration.k8s.io/v1beta1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apps/v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;authentication.k8s.io/v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;authentication.k8s.io/v1beta1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Results will differ from cluster to cluster, and between Kubernetes versions. We can have custom APIs, disabled APIs, or recent APIs could&amp;rsquo;ve been implemented in different Kubernetes versions.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ReplicationController&lt;/code&gt; and &lt;code&gt;ReplicaSet&lt;/code&gt; are two popular objects that clarify this and differ in the &lt;code&gt;apiVersion&lt;/code&gt;. &lt;code&gt;ReplicaController&lt;/code&gt; is a component of the &lt;em&gt;core&lt;/em&gt; API in &lt;code&gt;v1&lt;/code&gt; so we would write &lt;code&gt;apiVersion: v1&lt;/code&gt; in its spec. &lt;code&gt;ReplicaSet&lt;/code&gt;, which evolved from &lt;code&gt;ReplicaController&lt;/code&gt;, is a component of a more recent API served at &lt;code&gt;apps/v1&lt;/code&gt;. This sort of versioning is incredibly powerful and flexible, allowing Kubernetes to evolve while keeping a lot of backwards compatibility.&lt;/p&gt;
&lt;h2 id=&#34;kind&#34;&gt;kind&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;kind&lt;/code&gt; represents the kind of object that is specified via a manifest. Each kind of resource will be available on a particular API. This makes it essential that the specified &lt;code&gt;kind&lt;/code&gt; and &lt;code&gt;apiVersion&lt;/code&gt;  match on a specific manifest.&lt;/p&gt;
&lt;p&gt;We can inspect which &lt;code&gt;kind&lt;/code&gt; we can use for objects by executing &lt;code&gt;kubectl api-resources&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl api-resources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NAME                              SHORTNAMES   APIVERSION                        NAMESPACED   KIND
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bindings                                       v1                                true         Binding
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;componentstatuses                 cs           v1                                false        ComponentStatus
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;configmaps                        cm           v1                                true         ConfigMap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiservices                                    apiregistration.k8s.io/v1         false        APIService
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;controllerrevisions                            apps/v1                           true         ControllerRevision
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;daemonsets                        ds           apps/v1                           true         DaemonSet
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;deployments                       deploy       apps/v1                           true         Deployment
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;replicasets                       rs           apps/v1                           true         ReplicaSet
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;statefulsets                      sts          apps/v1                           true         StatefulSet
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With &lt;code&gt;kubectl api-resources&lt;/code&gt; we can quickly see as well which &lt;code&gt;apiVersion&lt;/code&gt; needs to be specified in order to specify a particular resource.&lt;/p&gt;
&lt;h2 id=&#34;metadata&#34;&gt;metadata&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;metadata&lt;/code&gt;  describes information of an object that allows for the unique identification of that object. When creating a manifest, this field should have &lt;em&gt;at least&lt;/em&gt; an associated name. Usually we will also see a field named &lt;code&gt;labels&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;spec&#34;&gt;spec&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;spec&lt;/code&gt; defines the desired state of the object in Kubernetes. It will vary widely between different resources and API versions, which means that it can be tricky to figure out - or memorize - all the needed fields.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve found that there&amp;rsquo;s one instance of a resource that can be created without a &lt;code&gt;spec&lt;/code&gt; field which is namespaces. If we create a namespace with only &lt;code&gt;apiVersion&lt;/code&gt;, &lt;code&gt;kind&lt;/code&gt; and &lt;code&gt;metadata&lt;/code&gt;, creating the namespace with &lt;code&gt;kubectl create&lt;/code&gt;, Kubernetes will accept that manifest &lt;em&gt;but&lt;/em&gt; it will create the namespace internally with an appropriate &lt;code&gt;spec&lt;/code&gt;. As an example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kind: Namespace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name: my-namespace
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running &lt;code&gt;kubectl create&lt;/code&gt; results in:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ kubectl create -f my-namespace.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;namespace/my-namespace created
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Executing &lt;code&gt;kubectl get&lt;/code&gt; will allows us to see the injected &lt;code&gt;spec&lt;/code&gt; field:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ kubectl ns my-namespace -o yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apiVersion: v1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kind: Namespace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;metadata:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name: my-namespace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (...)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  selfLink: /api/v1/namespaces/test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  uid: f1b901a6-31d6-457a-aaaf-0cb6d600d52c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;spec:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  finalizers:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - kubernetes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;status:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  phase: Active
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;All of this information can be confirmed in Kubernetes&amp;rsquo; own documentation by reading &lt;a href=&#34;https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields&#34;&gt;Required Fields&lt;/a&gt;. Although this isn&amp;rsquo;t a deep exploration of manifests, having solid bases can be extremely important to understand what has been built on top of this. Reasoning about this structure also provides a glimpse at the baseline that provides so much flexibility to Kubernetes, allowing it to have 50+ components &lt;em&gt;out-of-the-box&lt;/em&gt; and a lot of extensibility via custom resources.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#describing-a-kubernetes-object&#34;&gt;Describing a Kubernetes object&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://kubernetes.io/docs/reference/using-api/&#34;&gt;API Overview&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Certified Kubernetes Application Developer (CKAD) in 2022</title>
      <link>https://hugomartins.io/essays/2022/02/ckad-in-2022/</link>
      <pubDate>Sun, 06 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2022/02/ckad-in-2022/</guid>
      <description>&lt;p&gt;May 2021 in sunny Portugal. I &lt;em&gt;virtually&lt;/em&gt; attended &lt;a href=&#34;https://events.linuxfoundation.org/archive/2021/kubecon-cloudnativecon-europe/&#34;&gt;KubeCon + CloudNativeCon Europe 2021&lt;/a&gt;, writing a &lt;a href=&#34;https://hugomartins.io/essays/2021/05/kubecon-europe-2021-highlights-1/&#34;&gt;series&lt;/a&gt; &lt;a href=&#34;https://hugomartins.io/essays/2021/05/kubecon-europe-2021-highlights-2/&#34;&gt;of&lt;/a&gt; &lt;a href=&#34;https://hugomartins.io/essays/2021/05/kubecon-europe-2021-highlights-3/&#34;&gt;daily&lt;/a&gt; &lt;a href=&#34;https://hugomartins.io/essays/2021/05/kubecon-europe-2021-highlights-4/&#34;&gt;highlights&lt;/a&gt; about this experience. It focused on the talks I most enjoyed, what I learned and technologies I&amp;rsquo;d keep an eye on. I even took the time to write some tweets, even though I barely use Twitter.&lt;/p&gt;
&lt;p&gt;At the time, I was using Kubernetes extensively. I was working as an SRE, which was really more a Platform Engineer, working on tooling in the Software Development Life Cycle ™️ domain, following the hype of &lt;a href=&#34;https://humanitec.com/blog/internal-platform-teams-what-are-they-and-do-you-need-one&#34;&gt;Internal Platform Teams&lt;/a&gt;. Kubernetes was quickly becoming, if it wasn&amp;rsquo;t already, the &lt;em&gt;de facto&lt;/em&gt; standard framework to build these sorts of platforms on. Kubernetes serves as the underlying &amp;ldquo;OS&amp;rdquo; of sorts, while a lot of applications and customization are baked on top of it.&lt;/p&gt;
&lt;p&gt;Due to the type of work I had been doing, and because it is a domain that interests me and I want to keep working on it, I ended up making the decision to enroll in the &lt;a href=&#34;https://training.linuxfoundation.org/certification/certified-kubernetes-application-developer-ckad/&#34;&gt;Certified Kubernetes Application Developer (CKAD)&lt;/a&gt;. I racked in an hefty discount from attending &lt;a href=&#34;https://events.linuxfoundation.org/archive/2021/kubecon-cloudnativecon-europe/&#34;&gt;KubeCon + CloudNativeCon Europe 2021&lt;/a&gt; and had an entire year to study for, register and pass CKAD. What could go wrong?!&lt;/p&gt;
&lt;p&gt;It was all very promising and hopeful but I ended up not being able to study for CKAD and ended up not registering to take the exam after almost a year. To make matters worse, CKAD went through &lt;a href=&#34;https://training.linuxfoundation.org/ckad-program-change-2021/&#34;&gt;a series of program changes&lt;/a&gt; just four months after I enrolled. It now includes questions about Helm, more security-oriented aspects, deployment strategies and CRDs, among other changes.&lt;/p&gt;
&lt;p&gt;Although I no longer feel the same motivation and excitement towards passing the exam, mostly because I&amp;rsquo;m not working as closely with Kubernetes anymore, I have spent quite some €€€ enrolling in it and I feel that it can still teach me a lot of relevant concepts about Kubernetes that will be useful, as well as help me improve my &lt;code&gt;kubectl&lt;/code&gt; proficiency, which I still use everyday.&lt;/p&gt;
&lt;p&gt;Because of the reasons above, I&amp;rsquo;m going to try and complete &lt;a href=&#34;https://training.linuxfoundation.org/certification/certified-kubernetes-application-developer-ckad/&#34;&gt;Certified Kubernetes Application Developer (CKAD)&lt;/a&gt; in 2022, more specifically, in the last few months I have until May. This means that I&amp;rsquo;ll have to dive into Kubernetes concepts and tooling, while studying, and write more about it which I&amp;rsquo;m hoping I&amp;rsquo;ll share in the form of small snippets and notes.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t want it to become a reference guide to Kubernetes but I believe that sharing notes and small essays might help me get more motivated towards studying for CKAD. In this way, I believe, I&amp;rsquo;ll probably start a small series of notes on Kubernetes. I&amp;rsquo;m not yet sure on what this series will be in terms of structure, or its name, but I&amp;rsquo;m hopeful that it will give me the extra boost I need in order to successfully study and complete CKAD.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Traffic: July to December 2021</title>
      <link>https://hugomartins.io/essays/2022/01/traffic-july-december-2021/</link>
      <pubDate>Tue, 04 Jan 2022 00:00:00 +0000</pubDate>
      
      <guid>https://hugomartins.io/essays/2022/01/traffic-july-december-2021/</guid>
      <description>&lt;p&gt;Earlier this year I wrote &lt;a href=&#34;https://hugomartins.io/essays/2021/09/traffic-january-june-2021/&#34;&gt;Traffic: January to June 2021&lt;/a&gt; with a quick summary about the traffic this website received between January and June of 2021. As I stated when I wrote it, it &amp;ldquo;isn&amp;rsquo;t necessarily an immediate concern whether this website gets much traffic&amp;rdquo; but it is always interesting to analyze and I&amp;rsquo;m always curious about it. So, without further ado, here are a few notes about the traffic this website received between July and December 2021.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://hugomartins.io/images/Stats-July-December-2021.png&#34; alt=&#34;Stats&#34;&gt;&lt;/p&gt;
&lt;p&gt;In total, from July to December, there were 8091 unique visitors and 9283 pageviews (50/day). Google was where most traffic came from, followed by DuckDuckGo, Bing and LinkedIn. Comparing with the previous six months, pageviews per day were up 2.3x which I attribute to Google appreciating some essays and redirecting much more traffic to them than before.&lt;/p&gt;
&lt;p&gt;Top Essays:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/02/how-to-pass-multiple-values-to-http-query-parameter/&#34;&gt;How To Pass Multiple Parameters To Same Value in Query Strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/01/build-a-terraform-private-registry/&#34;&gt;Building a Private Terraform Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/03/understanding-differences-between-list-and-mutablelist-in-kotlin/&#34;&gt;Understanding Differences Between List and MutableList in Kotlin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2019/12/access-host-resources-minikube/&#34;&gt;How to Access Host Resources in Minikube Pods?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hugomartins.io/essays/2021/02/using-require-and-check-in-kotlin/&#34;&gt;Using require and check Functions in Kotlin&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All of the top essays were already the top essays in the previous 6 months, although &lt;a href=&#34;https://hugomartins.io/essays/2021/02/how-to-pass-multiple-values-to-http-query-parameter/&#34;&gt;How To Pass Multiple Parameters To Same Value in Query Strings&lt;/a&gt; jumped from fifth to first. This change seems to be motivated by Google appreciating this essay much more than the remaining ones.&lt;/p&gt;
&lt;p&gt;Although, during these six months, I&amp;rsquo;ve written much less than in the previous six months (5 essays), it seems that the content written in the beginning of the year has lived long and enjoyed a good amount of traffic from Google.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
