<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Karan Sharma</title>
    <description>The latest articles on Forem by Karan Sharma (@mrkaran).</description>
    <link>https://forem.com/mrkaran</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F542%2F5689132.jpeg</url>
      <title>Forem: Karan Sharma</title>
      <link>https://forem.com/mrkaran</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mrkaran"/>
    <language>en</language>
    <item>
      <title>DNS Lookups in Kubernetes</title>
      <dc:creator>Karan Sharma</dc:creator>
      <pubDate>Mon, 03 Feb 2020 10:03:32 +0000</pubDate>
      <link>https://forem.com/mrkaran/dns-lookups-in-kubernetes-5cm1</link>
      <guid>https://forem.com/mrkaran/dns-lookups-in-kubernetes-5cm1</guid>
      <description>&lt;p&gt;Originally posted on my &lt;a href="https://mrkaran.dev/posts/ndots-kubernetes/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the primary advantages of deploying workloads in Kubernetes is seamless application discovery. Intra cluster communication becomes easy with the concept of &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="noopener noreferrer"&gt;Service&lt;/a&gt; which represents a Virtual IP backing a set of Pod IPs. For example, if &lt;code&gt;vanilla&lt;/code&gt; service needs to talk to a &lt;code&gt;chocolate&lt;/code&gt; service, it can directly use the Virtual IP for &lt;code&gt;chocolate&lt;/code&gt;. Now the question is who resolves the DNS query for &lt;code&gt;chocolate&lt;/code&gt; and how?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmr-karan%2Fblog%2Fmaster%2Fimages%2Fdns-k8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmr-karan%2Fblog%2Fmaster%2Fimages%2Fdns-k8s.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DNS resolution is configured in Kubernetes cluster through &lt;a href="https://coredns.io/" rel="noopener noreferrer"&gt;CoreDNS&lt;/a&gt;. The kubelet configures each Pod's &lt;code&gt;/etc/resolv.conf&lt;/code&gt; to use the coredns pod as the &lt;code&gt;nameserver&lt;/code&gt;. You can see the contents of &lt;code&gt;/etc/resolv.conf&lt;/code&gt; inside any pod, they'll look something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;search hello.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.152.183.10
options ndots:5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This config is used by DNS clients to forward the DNS queries to a DNS server. &lt;code&gt;resolv.conf&lt;/code&gt; is the resolver configuration file which has information about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;nameserver&lt;/strong&gt; : Where the DNS queries are forwarded to. In our case this is the address of &lt;code&gt;CoreDNS&lt;/code&gt; service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;search&lt;/strong&gt;: Represents the search path for a particular domain. Interestingly &lt;code&gt;google.com&lt;/code&gt; or &lt;code&gt;mrkaran.dev&lt;/code&gt; is not FQDN (fully qualified domain name). A standard convention that most DNS resolvers follow is that if a domain ends with &lt;code&gt;.&lt;/code&gt; (representing the root zone), the domain is considered to be FQDN. Some resolvers try to act smart and append the &lt;code&gt;.&lt;/code&gt; themselves. So &lt;code&gt;mrkaran.dev.&lt;/code&gt; is an FQDN but &lt;code&gt;mrkaran.dev&lt;/code&gt; is not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ndots&lt;/strong&gt;: This is the most interesting value and is the &lt;em&gt;highlight&lt;/em&gt; of this post. &lt;code&gt;ndots&lt;/code&gt; represents the threshold value of the number of dots in a query name to consider it as a "fully qualified" domain name. More on this later, as we discover the flow of DNS lookup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's check what happens when we query for &lt;code&gt;mrkaran.dev&lt;/code&gt; in a pod.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nslookup mrkaran.dev
Server: 10.152.183.10
Address: 10.152.183.10#53

Non-authoritative answer:
Name: mrkaran.dev
Address: 157.230.35.153
Name: mrkaran.dev
Address: 2400:6180:0:d1::519:6001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this experiment, I've also turned on CoreDNS logging level to &lt;code&gt;all&lt;/code&gt; which makes it highly verbose. Let's look at the logs of &lt;code&gt;coredns&lt;/code&gt; pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:35998 - 11131 &lt;span class="s2"&gt;"A IN mrkaran.dev.hello.svc.cluster.local. udp 53 false 512"&lt;/span&gt; NXDOMAIN qr,aa,rd 146 0.000263728s
&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:34040 - 36853 &lt;span class="s2"&gt;"A IN mrkaran.dev.svc.cluster.local. udp 47 false 512"&lt;/span&gt; NXDOMAIN qr,aa,rd 140 0.000214201s
&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:33468 - 29482 &lt;span class="s2"&gt;"A IN mrkaran.dev.cluster.local. udp 43 false 512"&lt;/span&gt; NXDOMAIN qr,aa,rd 136 0.000156107s
&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:58471 - 45814 &lt;span class="s2"&gt;"A IN mrkaran.dev. udp 29 false 512"&lt;/span&gt; NOERROR qr,rd,ra 56 0.110263459s
&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:54800 - 2463 &lt;span class="s2"&gt;"AAAA IN mrkaran.dev. udp 29 false 512"&lt;/span&gt; NOERROR qr,rd,ra 68 0.145091744s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whew. So 2 things piqued my interest here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The query iterates through all search paths until the answer contains a &lt;code&gt;NOERROR&lt;/code&gt; code (which the DNS clients understand and store it as the result). &lt;code&gt;NXDOMAIN&lt;/code&gt; simply indicates no record found for that domain name. Since &lt;code&gt;mrkaran.dev&lt;/code&gt; isn't an FQDN (according to &lt;code&gt;ndots=5&lt;/code&gt; setting), the resolver looks at search path and determines the order of query.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;A&lt;/code&gt; and &lt;code&gt;AAAA&lt;/code&gt; records are fired parallelly. This is because &lt;code&gt;single-request&lt;/code&gt; option in &lt;code&gt;/etc/resolv.conf&lt;/code&gt; has a default configuration to perform parallel IPv4 and IPv6 lookups. You can disable this using &lt;code&gt;single-request&lt;/code&gt; option.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: &lt;code&gt;glibc&lt;/code&gt; can be configured to send these requests sequentially but &lt;code&gt;musl&lt;/code&gt; cannot, so Alpine users must take note.&lt;/p&gt;

&lt;h3&gt;
  
  
  Playing around with ndots
&lt;/h3&gt;

&lt;p&gt;Let's play around with &lt;code&gt;ndots&lt;/code&gt; a bit more and see how it behaves. The idea is simple, for the DNS client to know whether a domain is an absolute one or not is through this &lt;code&gt;ndots&lt;/code&gt; setting. For example, if you query for &lt;code&gt;google&lt;/code&gt; simply, how will the DNS client know if this is an absolute domain. If you set &lt;code&gt;ndots&lt;/code&gt; as &lt;code&gt;1&lt;/code&gt;, the DNS client will say "oh, &lt;code&gt;google&lt;/code&gt; doesn't have even one 1 dot, let me try going through search list. However, if you query for &lt;code&gt;google.com&lt;/code&gt;, the search list will be completely ignored since the query name satisfies the &lt;code&gt;ndots&lt;/code&gt; threshold (At least one dot).&lt;/p&gt;

&lt;p&gt;We can see this by actually doing it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/resolv.conf
options ndots:1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nslookup mrkaran
Server: 10.152.183.10
Address: 10.152.183.10#53

&lt;span class="k"&gt;**&lt;/span&gt; server can&lt;span class="s1"&gt;'t find mrkaran: NXDOMAIN
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CoreDNS logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:52495 - 2606 &lt;span class="s2"&gt;"A IN mrkaran.hello.svc.cluster.local. udp 49 false 512"&lt;/span&gt; NXDOMAIN qr,aa,rd 142 0.000524939s
&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:59287 - 57522 &lt;span class="s2"&gt;"A IN mrkaran.svc.cluster.local. udp 43 false 512"&lt;/span&gt; NXDOMAIN qr,aa,rd 136 0.000368277s
&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:53086 - 4863 &lt;span class="s2"&gt;"A IN mrkaran.cluster.local. udp 39 false 512"&lt;/span&gt; NXDOMAIN qr,aa,rd 132 0.000355344s
&lt;span class="o"&gt;[&lt;/span&gt;INFO] 10.1.28.1:56863 - 41678 &lt;span class="s2"&gt;"A IN mrkaran. udp 25 false 512"&lt;/span&gt; NXDOMAIN qr,rd,ra 100 0.034629206s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;mrkaran&lt;/code&gt; didn't specify any &lt;code&gt;.&lt;/code&gt; so the search list was used to find the answer.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: &lt;code&gt;ndots&lt;/code&gt; value is silently capped to &lt;code&gt;15&lt;/code&gt; and is &lt;code&gt;5&lt;/code&gt; in Kubernetes as default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling this in Production
&lt;/h3&gt;

&lt;p&gt;If your application is of the nature that makes a lot of external network calls, the DNS can become a bottleneck in case of heavy traffic since a lot of extra queries are made before the real DNS query is even fired. It's quite uncommon to see applications appending the root zone in the domain names, but that can be considered as a hack. So instead of using &lt;code&gt;api.twitter.com&lt;/code&gt;, you can hardcode your application to include &lt;code&gt;api.twitter.com.&lt;/code&gt; which would force the DNS clients to do an authoritative lookup directly on the absolute domain.&lt;/p&gt;

&lt;p&gt;Alternatively, since K8s 1.14, the &lt;code&gt;dnsConfig&lt;/code&gt; and &lt;code&gt;dnsPolicy&lt;/code&gt; feature gates have become stable. So while deploying a pod you can specify &lt;code&gt;ndots&lt;/code&gt; setting to something lesser, say &lt;code&gt;3&lt;/code&gt; or if you want to be really aggressive you can turn it down to &lt;code&gt;1&lt;/code&gt;. The consequences of this will be that every intra-node communication now has to include the full domain. This is one of the classic tradeoffs where you have to choose between performance and portability. If the app doesn't demand super low latencies, I guess you need not worry about this at all since DNS results are cached internally too.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;I got to know about this peculiarity first, in a K8s &lt;a href="https://failuremodes.dev/" rel="noopener noreferrer"&gt;meetup&lt;/a&gt; which I went to, last weekend where the folks mentioned about having to deal with this.&lt;/p&gt;

&lt;p&gt;Here are some additional links you can read on the web:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/kubernetes/issues/33554#issuecomment-266251056" rel="noopener noreferrer"&gt;Explainer on why ndots=5 in kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pracucci.com/kubernetes-dns-resolution-ndots-options-and-why-it-may-affect-application-performances.html" rel="noopener noreferrer"&gt;Great read on how ndots affects application performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.openwall.com/lists/musl/2017/03/15/3" rel="noopener noreferrer"&gt;musl and glibc resolver inconsistencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: I'm particularly not using &lt;code&gt;dig&lt;/code&gt; in this post. &lt;code&gt;dig&lt;/code&gt; apparently automatically adds a &lt;code&gt;.&lt;/code&gt; (root zone identifier) to make the domain an FQDN one &lt;strong&gt;without&lt;/strong&gt; even first going through the search path. I've mentioned about this briefly in one of my &lt;a href="https://mrkaran.dev/posts/dig-overview/" rel="noopener noreferrer"&gt;older&lt;/a&gt; posts. Nonetheless, it's quite surprising to see that you need to give a flag to make it behave in what seems to be a standard way.&lt;/p&gt;

&lt;h4&gt;
  
  
  It's always DNS, isn't it ;)
&lt;/h4&gt;

&lt;p&gt;Fin!&lt;/p&gt;

&lt;p&gt;Originally posted on my &lt;a href="https://mrkaran.dev/posts/ndots-kubernetes/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>dns</category>
    </item>
    <item>
      <title>sshuttle - A better ssh tunnel</title>
      <dc:creator>Karan Sharma</dc:creator>
      <pubDate>Sun, 12 Jan 2020 07:50:37 +0000</pubDate>
      <link>https://forem.com/mrkaran/using-sshtunnel-2h24</link>
      <guid>https://forem.com/mrkaran/using-sshtunnel-2h24</guid>
      <description>&lt;h2&gt;
  
  
  The Motivation
&lt;/h2&gt;

&lt;p&gt;Sometime back I had to access a Kubernetes API server which was firewalled to a private VPC network. I didn't want to setup a separate bastion instance just to access this cluster, cause TBH bastions are kinda redundant in K8s as every task can be performed through the client-server APIs using &lt;code&gt;kubectl&lt;/code&gt;. So, all I needed was access to this API server from a trusted network in a secure way. Thanks to my friend &lt;a href="https://twitter.com/iamd3vil"&gt;@sarat&lt;/a&gt;, I got to know about &lt;a href="https://sshuttle.readthedocs.io/en/stable/"&gt;sshuttle&lt;/a&gt;. &lt;code&gt;sshuttle&lt;/code&gt; is quite unique in the sense that it's not really a VPN but acts like one (for most practical purposes). &lt;code&gt;sshuttle&lt;/code&gt; lets you access an internal network through a trusted node inside the VPC, without you having to deal with the mess of port forwarding or VPNs.&lt;/p&gt;

&lt;p&gt;The basic idea is pretty simple, &lt;code&gt;sshuttle&lt;/code&gt; starts a local &lt;code&gt;python&lt;/code&gt; server in your host machine and creates &lt;code&gt;iptables&lt;/code&gt; rules to route the destination packets of the specified CIDR blocks to this local server. At the server, the packets are multiplexed over an &lt;code&gt;ssh&lt;/code&gt; session and sent to the server. The server disassembles the multiplexed packet and the routes them to upstream. So, basically this is a clever hack to avoid TCP over TCP (which again is a mess on unreliable networks). Multiplexed streams on &lt;code&gt;ssh&lt;/code&gt; is just a single stateful TCP connection (as compared to VPN connections which are stateless). Now you must be wondering, how come the target server disassembles the packets. Yes, there needs to be some kind of &lt;code&gt;sshuttle&lt;/code&gt; daemon running which does that for you. This is where &lt;code&gt;sshuttle&lt;/code&gt; does some magic, it &lt;em&gt;automagically&lt;/em&gt; deploys a python script on your target host to perform this task. So yes, for &lt;code&gt;sshuttle&lt;/code&gt; to work, both the client and target need to have &lt;code&gt;python&lt;/code&gt; and &lt;code&gt;iptables&lt;/code&gt; installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;sshuttle -r user@port x.x.x.x&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All the packets routed to the CIDR block will now go through &lt;code&gt;sshuttle&lt;/code&gt; daemon, since it configured &lt;code&gt;iptables&lt;/code&gt; rules for them.&lt;br&gt;
Also, &lt;code&gt;sshuttle&lt;/code&gt; starts a local python server on your host machine. You can see it using &lt;code&gt;netstat&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;netstat &lt;span class="nt"&gt;-tunapl&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;python
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:12300         0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt;               LISTEN      27425/python         
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There's a &lt;code&gt;python&lt;/code&gt; server listening on port &lt;code&gt;12300&lt;/code&gt; in my host machine. To actually verify, this indeed is started by &lt;code&gt;sshuttle&lt;/code&gt;, you can use &lt;code&gt;pstree -p | less&lt;/code&gt; and search for &lt;code&gt;sshuttle&lt;/code&gt;. Here you can see &lt;code&gt;sshuttle&lt;/code&gt; did indeed start a &lt;code&gt;python&lt;/code&gt; server and the PID (&lt;code&gt;27425&lt;/code&gt;) matches with the one we saw in &lt;code&gt;netstat&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nt"&gt;-zsh&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;13201&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nt"&gt;---sshuttle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;27425&lt;span class="o"&gt;)&lt;/span&gt;-+-ssh&lt;span class="o"&gt;(&lt;/span&gt;27446&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nt"&gt;---ssh&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;27447&lt;span class="o"&gt;)&lt;/span&gt;
                                    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nt"&gt;-sudo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;27427&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nt"&gt;---python&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;27445&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can even forward DNS queries with the &lt;code&gt;--dns&lt;/code&gt; flag. This is super helpful if you have something like Route53 to host your DNS records on a private zone (for eg tld like &lt;code&gt;.internal&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Better than SSH tunnels?
&lt;/h3&gt;

&lt;p&gt;Yes, you can also port forward with ssh using:&lt;br&gt;
&lt;code&gt;ssh -nNT -L &amp;lt;local-port&amp;gt;:{upstream-host}:{upstream-port} user@remote&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The problem with &lt;code&gt;ssh&lt;/code&gt; tunnels is that they experience frequent packet loss on a normal WiFi connection and it's quite frustrating to deal with them. Moreover, sometimes you need access to multiple ports in your private network which requires you to explictly provide them with &lt;code&gt;-L&lt;/code&gt; flag which I find it as cumbersome. Also, you cannot forward DNS queries (over UDP) since &lt;code&gt;ssh&lt;/code&gt; can only do TCP.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sshuttle&lt;/code&gt; has made my life so simple!&lt;/p&gt;

&lt;p&gt;Fin!&lt;/p&gt;

&lt;p&gt;Originally posted at my &lt;a href="https://mrkaran.dev/posts/using-sshuttle/"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>Introducing kubekutr</title>
      <dc:creator>Karan Sharma</dc:creator>
      <pubDate>Tue, 07 Jan 2020 10:32:36 +0000</pubDate>
      <link>https://forem.com/mrkaran/introducing-kubekutr-3i0h</link>
      <guid>https://forem.com/mrkaran/introducing-kubekutr-3i0h</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SBlTUU2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/mr-karan/kubekutr/master/logo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SBlTUU2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/mr-karan/kubekutr/master/logo.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mr-karan/kubekutr/"&gt;kubekutr&lt;/a&gt; was born out of my frustration of organising K8s resource manifests files/directories. For the uninitiated, K8s lets you hold the state of your cluster &lt;a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/"&gt;declaratively&lt;/a&gt; as "manifest" files. K8s does so by a lot of asynchronous control loops to check whether the desired state matches the real world state and in case of drifts, it resets back to the user desired state (I oversimplified this, but hope you get the drift ;)). These files are predominantly &lt;code&gt;YAML&lt;/code&gt; but there's support for &lt;code&gt;JSON&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;Anyway, to create these manifest files for a production level project is quite a bit of manual labour. The API spec of every resource in Kubernetes is quite &lt;a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/"&gt;daunting&lt;/a&gt; and overwhelming. There are tools like Helm which abstract away the complexity of these YAML with it's own templating system. There are quite a lot of these charts available for 3rd party apps &lt;a href="https://github.com/helm/charts"&gt;here&lt;/a&gt;. The idea is you populate the Chart with just your own config "values" and you've a deployment ready in no time. Admittedly this works quite well for something you want to take out for a quick spin but personally I am not quite a fan of hiding away the complexity with a &lt;em&gt;magic&lt;/em&gt; layer. Also, the problem with Helm was the "Chart" (and templates) still had to be written by someone if you have a &lt;a href="https://github.com/kubernetes-sigs/kustomize/blob/master/docs/glossary.md#bespoke-configuration"&gt;bespoke&lt;/a&gt; application. Helm is more geared towards common off the shelf apps like DBs, Key Value stores, web proxies etc.&lt;/p&gt;

&lt;p&gt;I found out &lt;a href="//github.com/kubernetes-sigs/kustomize"&gt;kustomize&lt;/a&gt; few months back and quite happy with it's approach towards managing manifests. The basic idea behind &lt;code&gt;kustomize&lt;/code&gt; is that you create a &lt;em&gt;base&lt;/em&gt; and any kind of "customisations" must come as &lt;em&gt;overlays&lt;/em&gt;. This is such a powerful technique over wrangling templates. &lt;code&gt;kustomize&lt;/code&gt; A common approach is to name these &lt;em&gt;overlays&lt;/em&gt; based on the environment. For example, &lt;code&gt;dev&lt;/code&gt; deployment can have &lt;code&gt;replicas: 1&lt;/code&gt; for a pod, but &lt;code&gt;prod&lt;/code&gt; can apply a "patch" to update with &lt;code&gt;repliacs: 3&lt;/code&gt;. This way of separating two environments helps a lot when you follow &lt;a href="https://www.weave.works/technologies/gitops/"&gt;GitOps&lt;/a&gt; approach of deployment. All fine and good, until I realised I spent way too much time on copy-pasting the bases for different projects and manually editing these files for the new project config.&lt;/p&gt;

&lt;p&gt;Then I did what any other programmer would do, spend some more time to automate :P And that is how &lt;code&gt;kubekutr&lt;/code&gt; was born. (Quite an anticlimax I know!)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubekutr&lt;/code&gt; is a really simple tool to bootstrap a Kustomize &lt;code&gt;base&lt;/code&gt;. &lt;code&gt;kubekutr&lt;/code&gt; reads a config file, templates out different resources and produces them as YAML files. Now, I know a lot of you reading this would be going &lt;em&gt;Another damn templating solution&lt;/em&gt; in your mind and while that reaction is warranted, given that we have 200+ &lt;a href="https://docs.google.com/spreadsheets/d/1FCgqz1Ci7_VCz_wdh8vBitZ3giBtac_H8SBw4uxnrsE/edit#gid=0"&gt;tools&lt;/a&gt; in the community (everyone trying to solve similar problems in their own ways), I &lt;em&gt;legit&lt;/em&gt; could not find a simple enough tool which would let the boring part of scaffolding a base out of my way and let me focus on what's more important: the actual deployment. Hence I just decided to roll out my own solution which is the best one according to &lt;a href="https://en.wikipedia.org/wiki/IKEA_effect"&gt;IKEA effect&lt;/a&gt; (&lt;em&gt;just kidding&lt;/em&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow
&lt;/h3&gt;

&lt;p&gt;So, let's say you need to create a Nginx deployment, the &lt;code&gt;kubekutr&lt;/code&gt; &lt;code&gt;config.yml&lt;/code&gt; would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deployments:
  - name: nginx
    replicas: 1
    labels:
      - name: 'service: nginx'
    containers:
      - name: nginx
        image: 'nginx:latest'
        portInt: 80
        portName: nginx-port
services:
  - name: nginx
    type: ClusterIP
    port: 80
    targetPort: 80
    labels:
      - name: 'service: nginx'
    selectors:
      - name: 'service: nginx'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To create the &lt;code&gt;base&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubekutr -c config.yml scaffold -o nginx-deployment&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nginx-deployment&lt;/code&gt; folder is initialised and you can view &lt;code&gt;deployments/nginx.yml&lt;/code&gt; and &lt;code&gt;service/nginx.yml&lt;/code&gt; which &lt;code&gt;kubekutr&lt;/code&gt; created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ tree nginx-deployment

|-- base
|   |-- deployments
|   |   `-- nginx.yml
|   |-- ingresses
|   |-- services
|   |   `-- nginx.yml
|   `-- statefulsets
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat base/deployments/nginx.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    service: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      service: nginx
  template:
    metadata:
      labels:
        service: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
          - containerPort: 80
            name: nginx-port
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat base/services/nginx.yml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    service: nginx
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP
  selector:
    service: nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can now use the generated folder as a Kustomize &lt;code&gt;base&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non Goals
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;kubekutr&lt;/code&gt; isn't meant to replace the existing tools, it's just a real simple cookie cutter approach to &lt;code&gt;kustomize&lt;/code&gt; bases and that's pretty much it. &lt;code&gt;kustomize&lt;/code&gt; is native to Kubernetes and exposes the full API spec to end users. I feel that is much more better approach than templating solutions, the users must be exposed to the standard conventions rather than a random tool's own config fields. The benefits are the same conventions can then be used across a wide variety of tools (like &lt;code&gt;kubekutr&lt;/code&gt;) and users are in better control of the underlying resources. Adding a layer of magic also makes it harder to debug when shit goes down. Hence &lt;code&gt;kubekutr&lt;/code&gt; chose &lt;code&gt;kustomize&lt;/code&gt; to do all the heavy lifting of managing manifests.&lt;/p&gt;

&lt;p&gt;There's a lot of scope of improvements, but I wanted to just Ship It! and get some initial feedback. Let me know your thoughts on this :)&lt;/p&gt;

&lt;p&gt;Fin!&lt;/p&gt;

&lt;p&gt;Originally published at my &lt;a href="https://mrkaran.dev/posts/introducing-kubekutr/"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>go</category>
      <category>devops</category>
    </item>
    <item>
      <title>My Development Setup on a Macbook</title>
      <dc:creator>Karan Sharma</dc:creator>
      <pubDate>Fri, 04 Nov 2016 14:13:26 +0000</pubDate>
      <link>https://forem.com/mrkaran/my-development-setup-on-a-macbook</link>
      <guid>https://forem.com/mrkaran/my-development-setup-on-a-macbook</guid>
      <description>&lt;p&gt;I recently purchased a new 13" Macbook Pro 2015(after Apple's brilliant keynote) and quite like it so far. This is my first experience with macOS. After using strictly GNU/Linux distros for about 4 years(Fedora, Ubuntu, Mint, Arch, Elementary OS) I finally decided to take the plunge and use macOS. The battery life, excellent keyboard and trackpad, a beautiful display makes coding on it a really enjoyable experience. Something that I was surely missing on my bulky HP Pavilion G6.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A4cK7ZH4hBqLJvecS9e02EA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A4cK7ZH4hBqLJvecS9e02EA.png" alt="newmacbook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before starting off with my development setup, I would say there are a plenty of such blog-posts and guides available to make your machine the #ultimatedevmachine. The aim of this post is not that but just to share some of the tools I believe make your macOS experience more complete. I personally followed &lt;a href="https://github.com/nicolashery/mac-dev-setup" rel="noopener noreferrer"&gt;this&lt;/a&gt; as the holy grail but I'll break it down for you to include only the most relevant things that a generalist developer can install on her laptop and also not make it bloated.&lt;/p&gt;

&lt;h2&gt;
  
  
  iTerm2
&lt;/h2&gt;

&lt;p&gt;As developers spend most of the time tinkering with stuff on terminals, the first thing that you should do is to replace macOS default terminal with iTerm2. It has a lot of great features, about which you can read more &lt;a href="http://www.iterm2.com/features.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
I'm using Solarized Dark theme which can be easily downloaded over &lt;a href="http://ethanschoonover.com/solarized" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Apart from this, there are several other customisations which I simply took from this &lt;a href="https://github.com/nicolashery/mac-dev-setup#beautiful-terminal" rel="noopener noreferrer"&gt;guide&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Ae-vvoq1ZzKbsaV_nPaUNgA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Ae-vvoq1ZzKbsaV_nPaUNgA.png" alt="Beautiful terminal experience withÂ iTerm2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Homebrew
&lt;/h2&gt;

&lt;p&gt;It's the essential package manager every developer should be using. It makes installing other packages very convenient by downloading latest stable release, creating a symlink to &lt;code&gt;/usr/local&lt;/code&gt; and some really cool features like installing directly from a PR. You can read more about such features here. As a learning exercise for myself, I am going to try my hands on creating a formula for &lt;a href="https://coala.readthedocs.org/" rel="noopener noreferrer"&gt;coala&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  zsh
&lt;/h2&gt;

&lt;p&gt;No discussion of the terminal should ever be complete without mentioning zsh even once IMHO. I've been using zsh for 2 years and there's just no going back to old school bash. I've got so accustomed to zsh that it feels almost impossible to work on bash anymore. You can install zsh by&lt;br&gt;
&lt;code&gt;brew install zsh&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A0iHDpfIHgRK96x_hnb8vIw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A0iHDpfIHgRK96x_hnb8vIw.png" alt="zsh beingÂ brewed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also use &lt;code&gt;Prezto&lt;/code&gt; along with zsh rather than the popular &lt;code&gt;Oh My Zsh!&lt;/code&gt; because it's darn slow after a couple of plugins. You can follow the installation details present in the official documentation here.&lt;br&gt;
To change default theme you need to edit the following line in &lt;code&gt;~./zpreztorc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zstyle â€˜:prezto:module:prompt' theme â€˜powerline'&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;with the theme name. You can find out all theme names using&lt;/p&gt;

&lt;p&gt;&lt;code&gt;prompt -l&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;You can find a comprehensive list of all things zsh over &lt;a href="https://github.com/unixorn/awesome-zsh-plugins" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sublime Text
&lt;/h2&gt;

&lt;p&gt;As a developer you'll also spend a hefty time with editors as they are the place where magic happens. I have setup my Sublime Text to maximize my productivity while coding. I use the following plugins, but first in order to install any one of them you need to &lt;a href="https://packagecontrol.io/installation" rel="noopener noreferrer"&gt;install&lt;/a&gt; Package Control which is the package manager for Sublime Text.&lt;br&gt;
After you have setup Package Control, you can verify that it should look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AngOH3TNldmqJk418wsInMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AngOH3TNldmqJk418wsInMA.png" alt="âŒ˜+shift+ P"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some of the plugins I use: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/SideBarEnhancements-org/SideBarEnhancements/tree/st3" rel="noopener noreferrer"&gt;SideBarEnhancements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://emmet.io/" rel="noopener noreferrer"&gt;Emmet&lt;/a&gt; (A great time saver!)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sublimelinter.com/en/latest/" rel="noopener noreferrer"&gt;SublimeLinter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packagecontrol.io/packages/ColorPicker" rel="noopener noreferrer"&gt;ColorPicker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packagecontrol.io/packages/BracketHighlighter" rel="noopener noreferrer"&gt;BracketHighlighter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm using &lt;a href="https://github.com/equinusocio/material-theme" rel="noopener noreferrer"&gt;Material Theme&lt;/a&gt; which really prettifies it by a stretch.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Aw0Fbwfsrzba83RCNkWHXnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Aw0Fbwfsrzba83RCNkWHXnw.png" alt="Material Theme on SublimeÂ Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Vim
&lt;/h1&gt;

&lt;p&gt;I'm learning to use more and more Vim these days so I'll keep this section as a TBA and will update soon.&lt;/p&gt;

&lt;h1&gt;
  
  
  macOS Apps
&lt;/h1&gt;

&lt;p&gt;These are some of the apps that I believe should come preinstalled in any macOS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alfred&lt;/li&gt;
&lt;li&gt;InsomniaX&lt;/li&gt;
&lt;li&gt;CleanmyMac3&lt;/li&gt;
&lt;li&gt;Omnifocus&lt;/li&gt;
&lt;li&gt;Ulysses&lt;/li&gt;
&lt;li&gt;Android File Transfer&lt;/li&gt;
&lt;li&gt;Cheatsheetapp&lt;/li&gt;
&lt;li&gt;iStatMenus&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far I'm really happy with it but will keep adding tools or plugins that I find on the go. I am still in the honeymoon phase with my Mac so if you think I did an injustice to this post by not including your favourite tool, tweet it out to me and I'll definitely check it out.&lt;br&gt;
Till then, Happy Coding!&lt;/p&gt;

&lt;p&gt;This article was originally posted on my blog over &lt;a href="https://medium.com/@mrkaran/my-development-setup-7e767d33fc41#.epefeqil5" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Hi, I'm Karan Sharma</title>
      <dc:creator>Karan Sharma</dc:creator>
      <pubDate>Fri, 04 Nov 2016 13:54:51 +0000</pubDate>
      <link>https://forem.com/mrkaran/hi-im-karan-sharma</link>
      <guid>https://forem.com/mrkaran/hi-im-karan-sharma</guid>
      <description>&lt;p&gt;I have been coding for 2 years.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/mr-karan" rel="noopener noreferrer"&gt;@mr-karan&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in New Delhi, IN.&lt;/p&gt;

&lt;p&gt;I am a final year CS undergrad.&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Python, Javascript.&lt;/p&gt;

&lt;p&gt;I am currently learning more about ReactJs.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
