<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>kubernetes Archives - Tailored Cloud</title>
	<atom:link href="https://tailored.cloud/category/kubernetes/feed/" rel="self" type="application/rss+xml" />
	<link>https://tailored.cloud/category/kubernetes/</link>
	<description>Kubernetes, devops and everything cloud</description>
	<lastBuildDate>Fri, 05 Jun 2020 15:41:40 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6</generator>
	<item>
		<title>Building applications for the cloud-native stack &#8211; continuation.</title>
		<link>https://tailored.cloud/dev/building-applications-for-the-cloud-native-stack-continuation/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=building-applications-for-the-cloud-native-stack-continuation</link>
					<comments>https://tailored.cloud/dev/building-applications-for-the-cloud-native-stack-continuation/#respond</comments>
		
		<dc:creator><![CDATA[tc-admin]]></dc:creator>
		<pubDate>Fri, 05 Jun 2020 15:41:38 +0000</pubDate>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[cloud-native]]></category>
		<guid isPermaLink="false">http://localhost:8080/?p=444</guid>

					<description><![CDATA[<p>The next parts of my blog series I wrote for the company blog are available. Here&#8217;s part 2 and part <a class="more-link" href="https://tailored.cloud/dev/building-applications-for-the-cloud-native-stack-continuation/">Continue Reading</a></p>
<p>The post <a href="https://tailored.cloud/dev/building-applications-for-the-cloud-native-stack-continuation/">Building applications for the cloud-native stack &#8211; continuation.</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>The next parts of my blog series I wrote for the company blog are available. Here&#8217;s <a rel="noreferrer noopener" href="https://www.giantswarm.io/blog/a-few-dozen-lines-of-code-part-2-creating-the-application" target="_blank">part 2</a> and <a rel="noreferrer noopener" href="https://www.giantswarm.io/blog/part-3-deploying-the-application-with-helm" target="_blank">part 3</a>. I posted about starting the series and <a href="http://localhost:8080/kubernetes/schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series/">part 1</a> before.</p>



<p>In part 2, I&#8217;m discussing how to build a simple micro services app that will be used as a &#8216;lab rat&#8217; for our experiments with the cloud-native stack later.</p>



<p>In part 3, I&#8217;m describing how you can deploy your application (just a binary) as a full fledged Kubernetes concept, up to the point where we can pack everything into a Helm chart.</p>



<p>Enjoy!</p>
<p>The post <a href="https://tailored.cloud/dev/building-applications-for-the-cloud-native-stack-continuation/">Building applications for the cloud-native stack &#8211; continuation.</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tailored.cloud/dev/building-applications-for-the-cloud-native-stack-continuation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Schrödinger&#8217;s come back to blogging: using the cloud-native stack series.</title>
		<link>https://tailored.cloud/kubernetes/schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series</link>
					<comments>https://tailored.cloud/kubernetes/schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series/#respond</comments>
		
		<dc:creator><![CDATA[tc-admin]]></dc:creator>
		<pubDate>Sat, 04 Apr 2020 12:13:32 +0000</pubDate>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[cloud-native]]></category>
		<guid isPermaLink="false">http://localhost:8080/?p=439</guid>

					<description><![CDATA[<p>It is a year since a wrote a blog post here. A lot has changed over this year in my <a class="more-link" href="https://tailored.cloud/kubernetes/schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series/">Continue Reading</a></p>
<p>The post <a href="https://tailored.cloud/kubernetes/schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series/">Schrödinger&#8217;s come back to blogging: using the cloud-native stack series.</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="682" src="https://localhost:8080/wp-content/uploads/2020/04/code-820275_1280-1024x682.jpg" alt="" class="wp-image-440" srcset="https://tailored.cloud/wp-content/uploads/2020/04/code-820275_1280-1024x682.jpg 1024w, https://tailored.cloud/wp-content/uploads/2020/04/code-820275_1280-300x200.jpg 300w, https://tailored.cloud/wp-content/uploads/2020/04/code-820275_1280-768x512.jpg 768w, https://tailored.cloud/wp-content/uploads/2020/04/code-820275_1280.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>A Few Dozen Lines of Code&#8230; just don&#8217;t count YAML as code <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></figcaption></figure>



<p>It is a year since a <a href="http://localhost:8080/kubernetes/smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services/">wrote a blog post here</a>. A lot has changed over this year in my professional life. After quitting my previous job, I was looking for new opportunities and eventually decided to join the cool team at <a href="https://www.giantswarm.io/">Giant Swarm</a> as a platform architect. I have to say this was a great choice! My focus is now on enabling our customers to run applications on top of Kubernetes clusters.</p>



<p>Still, I didn&#8217;t want to stop blogging. Fortunately, I can now connect everything as part of my new job! So, I&#8217;m switching my focus slightly to cloud-native applications running on Kubernetes than just Kubernetes. This is also the topic of a blog series called &#8220;A Few Dozen Lines of Code&#8221;, the first part of which was <a href="https://blog.giantswarm.io/a-few-dozen-lines-of-code/">just published</a> on our company blog!</p>



<p>This series is meant to show you how using an opinionated cloud-native stack of tools installed on your Kubernetes cluster can make your dev and operations team happier than ever <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Stay tuned for next parts, they should come shortly.</p>



<p>So, this entry is kind of &#8220;Schrödinger&#8217;s entry&#8221;. It is a new entry and it is not &#8211; as I&#8217;m just pointing you to <a href="https://blog.giantswarm.io/a-few-dozen-lines-of-code/">my article on the company blog</a>. Still, I will inform you if anything written by me is published there. Meanwhile, you can check other engineering articles published there, it&#8217;s good content.</p>
<p>The post <a href="https://tailored.cloud/kubernetes/schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series/">Schrödinger&#8217;s come back to blogging: using the cloud-native stack series.</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tailored.cloud/kubernetes/schrodingers-come-back-to-blogging-using-the-cloud-native-stack-series/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SmartNat &#8211; dirt cheap Kubernetes ingress controller for TCP/UDP services</title>
		<link>https://tailored.cloud/kubernetes/smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services</link>
					<comments>https://tailored.cloud/kubernetes/smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services/#comments</comments>
		
		<dc:creator><![CDATA[tc-admin]]></dc:creator>
		<pubDate>Wed, 03 Apr 2019 19:20:09 +0000</pubDate>
				<category><![CDATA[devops]]></category>
		<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[controllers]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[operators]]></category>
		<guid isPermaLink="false">http://localhost:8080/?p=420</guid>

					<description><![CDATA[<p>TL;DR SmartNat is a Kubernetes ingress controller for exposing a massive number of TCP/UDP services to the outside world using <a class="more-link" href="https://tailored.cloud/kubernetes/smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services/">Continue Reading</a></p>
<p>The post <a href="https://tailored.cloud/kubernetes/smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services/">SmartNat &#8211; dirt cheap Kubernetes ingress controller for TCP/UDP services</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">TL;DR</h2>



<ul class="wp-block-list"><li>SmartNat is a Kubernetes ingress controller for exposing a massive number of TCP/UDP services to the outside world using just 1 server</li><li>available on GitHub: <a href="https://github.com/DevFactory/smartnat">https://github.com/DevFactory/smartnat</a></li></ul>



<h2 class="wp-block-heading">SmartNat &#8211; Kubernetes ingress controller for TCP/UDP services</h2>



<p>Some time ago I wrote posts about <a href="http://localhost:8080/kubernetes/simple-custom-kubernetes-controller/">writing a very simple Kubernetes controller</a> and <a href="http://localhost:8080/kubernetes/write-a-kubernetes-controller-operator-sdk/">using operator framework</a> to create a more complete one. Well, at the same time, I was starting to work on one at the company I&#8217;m working for. Meanwhile, I convinced management at the company to release the project as an OpenSource &#8211; and here it is!</p>



<p>The project is called SmartNat. It&#8217;s a Kubernetes ingress controller for TCP/UDP services that allows you to drive external traffic to your Services. It&#8217;s kind of Service with NodePort, but on strong steroids. It runs on a separate instance (well, you can run however you like, but this makes the most sense) and interconnects external (usually public) network with the subnet used by your Kubernetes cluster. SmartNat allows you to use multiple network interfaces, each one having multiple IP addresses to forward traffic from an external network to your services on a port-by-port basis. That way using just a single server or instance you can easily expose hundreds or even thousands of Services. The important property is that all of this is done using L3/L4 tools only, so SmartNat helps where HTTP based Ingresses can&#8217;t. Additionally, SmartNat supports simple traffic filtering of traffic coming from external subnet and also HA mode.</p>



<p>If you&#8217;re interested, check the project on github: <a href="https://github.com/DevFactory/smartnat">https://github.com/DevFactory/smartnat</a>.</p>
<p>The post <a href="https://tailored.cloud/kubernetes/smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services/">SmartNat &#8211; dirt cheap Kubernetes ingress controller for TCP/UDP services</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tailored.cloud/kubernetes/smartnat-dirt-cheap-kubernetes-ingress-controller-for-tcp-udp-services/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Write a Kubernetes controller (operator) with operator-sdk</title>
		<link>https://tailored.cloud/kubernetes/write-a-kubernetes-controller-operator-sdk/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=write-a-kubernetes-controller-operator-sdk</link>
					<comments>https://tailored.cloud/kubernetes/write-a-kubernetes-controller-operator-sdk/#respond</comments>
		
		<dc:creator><![CDATA[tc-admin]]></dc:creator>
		<pubDate>Sat, 15 Sep 2018 19:25:25 +0000</pubDate>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[controllers]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[longer entry]]></category>
		<category><![CDATA[operators]]></category>
		<guid isPermaLink="false">http://localhost:8080/?p=377</guid>

					<description><![CDATA[<p>TL;DR: unless you need a really low-level control or are writing a specialized controller, do use one of the helper <a class="more-link" href="https://tailored.cloud/kubernetes/write-a-kubernetes-controller-operator-sdk/">Continue Reading</a></p>
<p>The post <a href="https://tailored.cloud/kubernetes/write-a-kubernetes-controller-operator-sdk/">Write a Kubernetes controller (operator) with operator-sdk</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>TL;DR:</h2>
<ul>
<li>unless you need a really low-level control or are writing a specialized controller, do use one of the helper libraries like  the <a href="https://github.com/operator-framework/operator-sdk">operator-sdk</a> or <a href="https://github.com/kubernetes-sigs/kubebuilder">kubebuilder</a> to avoid writing a lot of boilerplate code,</li>
<li>handling events and objects in the controller is about synchronizing the state between API object and the system, not about reacting to events,</li>
<li>try to be stateless, as keeping state is your problem,</li>
<li>when you write a Kubernetes controller, be sure you know what your state is and how to make it durable,</li>
<li>remember your controller can be restarted any time,</li>
<li>use <a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/">Custom Resource Definition</a> to create any API object you need,</li>
<li><a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/apis/app/v1alpha1/zz_generated.deepcopy.go#L22">DeepCopy()</a> API objects if you&#8217;re changing them,</li>
<li>if you&#8217;re creating new API objects, always set their <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L164">OwnerReference</a>.</li>
</ul>
<h2>Introduction</h2>
<p>Some time ago <a href="http://localhost:8080/kubernetes/simple-custom-kubernetes-controller/">I posted an entry</a> about how to write a Kubernetes controller. It was a very minimalistic example of a controller, which aimed only at putting the main pieces in place. Still, I wanted to explore the topic further and write something more realistic and useful. As you can learn in the previous blog entry, despite the simple idea of how a controller operates, writing one requires a lot of boilerplate code. Fortunately, there are already libraries/frameworks that are trying to remove this boilerplate stuff and get you on track much faster. I had a look at two of them: the <a href="https://github.com/operator-framework/operator-sdk">operator-sdk</a> and <a href="https://github.com/kubernetes-sigs/kubebuilder">kubebuilder</a>. As I found the operator-sdk first, I started with it. In this blog entry, I want to show you how to write a Kubernetes controller with operator-sdk.</p>
<p>My idea was pretty simple. I wanted to write an operator, which is useful, but still very simple, so it can serve as a tutorial material, showing how to build operators. This turned into a Netperf Operator, a kubernetes tool that allows you to run the good old network performance benchmarking tool called <a href="https://hewlettpackard.github.io/netperf/">netperf</a> (yes, click this URL and admire pure HTML at its best!). I wanted to be able to run netperf, a client-server application, between 2 kubernetes pods, preferably running on different cluster nodes. Such tests are pretty valuable as they are the only way you can check your real pod-to-pod network performance, including the impact of all the networking layers, like overlay networks and such. Normally, running netperf requires you to start a server at one place and a netperf client at the other end of the tested connection. I wanted to make this a one-step process, managed by an operator. And of course, learn and how you how to write a Kubernetes controller. You can check the resulting project on my github page: <a href="https://github.com/piontec/netperf-operator">netperf-operator</a>.</p>
<p>Oh, but why do I call it &#8220;operator&#8221;, not &#8220;controller&#8221;? These concepts are very close: people tend to name Kubernetes controllers specialized in running and configuring a single application  &#8220;an operator&#8221;. There are already many awesome operators. <a href="https://github.com/coreos/prometheus-operator">Prometheus-operator</a> is just one of them, but it really shows the power of an idea of running an application integrated with your kubernetes cluster and managed &#8220;the cluster way&#8221;. You can find other operators on the <a href="https://github.com/operator-framework/awesome-operators">awesome-operators</a> github page &#8211; be sure to check them.</p>
<h2>How does kubernetes controller/operator work and run?</h2>
<p>Well, this is mainly a reminder, but still a crucial one, so let&#8217;s say it once again. A very simplified controller&#8217;s life looks like this:</p>
<pre class="brush: plain; title: ; notranslate">
while true {
  receiveInfoAboutAPIObjects()
  synchronizeRealStateToMatchFetchedInfo()
}
</pre>
<p>There are a few consequences coming from the simple pseudocode above. The first one is that you need to receive notifications about the state and its changes of kubernetes objects that you&#8217;re interested in. Thankfully, the operator-sdk comes to the rescue here. It takes care of the synchronization with kubernetes API server and the notification loop. It also allows you to decide what type of API objects you want to observe.</p>
<p>Another important property is that the synchronization loop is not really event-driven, but state-driven. It means that your controller won&#8217;t receive events only when something changes, for example, a Pod dies or is created. You will get them then, but moreover, you will also get periodic refreshers: updates that show you the complete required state of the Kubernetes object, no matter if it changed or not since the last update. This is a very important property and you have to get it right. It took me some time to stick to it, so let me rephrase it. The notification loop doesn&#8217;t tell what change you need to perform in a system, but how the system should look like. It declares and describes the desired state, not the change that&#8217;s needed to produce it. Figuring out how to get to the desired state is a task for the controller.</p>
<p>Let me give you an example here. Let&#8217;s suppose we&#8217;re writing ReplicaSet controller. The ReplicaSet controller takes a pod configuration template and a desired number of pods to create. Its task is to ensure that the declared number of the pods are always running in the system. Let&#8217;s now assume we have created a ReplicaSet object with a Pod template and we set the pod count to 5 and also already 5 pods are running in the cluster. Now, if any of the pods die, the ReplicaSet controller gets a pod status update. But its reaction is not just &#8220;create a new pod&#8221;. Remember, a controller doesn&#8217;t react directly to the event, but checks for a difference between the configured and the real state. So, the controller checks that there are currently 4 pods running in the system, the required count is 5, so the solution is to start 1 new pod. But the same synchronization logic is also run periodically, even if there are no pod events in the system. Imagine now, that a whole node dies in the cluster and this node was running 2 out of 5 of our pods. Now, the cluster is not solving the problem of &#8220;how to notify the controller that 2 pods have died&#8221;. Instead, the controller will run the synchronization loop and check that there are now only 3 pods in the system and 5 are required, so the solution to reconcile the state is to start 2 new pods. So, we&#8217;re checking for the desired state and make it a reality, not simply react to events like.</p>
<p>One more important thing is that you should expect your controller/operator process to be terminated at any time. Most probably your controller will be run just as a pod in the cluster, and pods are mortal and should be easy to restart and recreate. This means, that if you need to keep a state, you basically have to keep it outside of your controller so that after a controller pod restart you can resume controller&#8217;s operations.</p>
<h2>How to write a Kubernetes controller with operator-sdk &#8211; bootstrapping</h2>
<p>After the general concepts presented above, we&#8217;re ready to write a Kubernetes controller and bootstrap a new operator project. This topic is nicely covered on the <a href="https://github.com/operator-framework/operator-sdk/blob/master/doc/user-guide.md">project&#8217;s github page</a>. Definitely, have a look there for a reference. I bootstrapped my project with</p>
<pre class="brush: bash; title: ; notranslate">
operator-sdk new netperf-operator --api-version=app.example.com/v1alpha1 --kind=Netperf
</pre>
<h2>Custom Resources and Custom Resource Definitions</h2>
<p>OK, but let&#8217;s pause for a second. You might be wondering how the controller pattern is really useful, except for controllers that are already in the Kubernetes, like Deployment or StatefulSet controller. After all, not everything is about pods and services, that are native objects in Kubernetes. But can you write a controller that handles some other objects? The great thing is that Kubernetes API and objects system is easily extensible. The same way the cluster gets information for standard controllers from your description of Pods, Deployments or Services, it can also handle any <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">Custom Resource</a>. It just needs to be configured using a <a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/">Custom Resource Definition</a>. Using this mechanism, you can introduce any object you need into your cluster and configure it using YAML files and &#8220;kubectl&#8221; or API calls. You can find the CRD for netperf-operator <a href="https://github.com/piontec/netperf-operator/blob/master/deploy/crd.yaml">here</a>. <a href="https://github.com/piontec/netperf-operator/blob/master/deploy/crd.yaml">The whole declaration</a> is really in these few lines:</p>
<pre class="brush: yaml; title: ; notranslate">
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: netperfs.app.example.com
spec:
  group: app.example.com
  names:
    kind: Netperf
    listKind: NetperfList
    plural: netperfs
    singular: netperf
  scope: Namespaced
  version: v1alpha1
</pre>
<p>It just defines the name of your Custom Resource (singular and plural), API object kind (Netperf) and that your CRD is scoped to a single namespace. And that&#8217;s it, you&#8217;re ready to create your own new &#8220;Netperf&#8221; objects. As you can see, we&#8217;re not giving here any data schema that we expect from the Custom Resource object. We handle that in the controller code; for CRD definition the object schema is irrelevant. Still, there&#8217;s a new feature in kubernetes 1.11 that allows for validating a Custom Resource by embedding <a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#validation">Custom Resource validation schema</a> in CRD definition, but it&#8217;s a new thing and just beta in 1.11.</p>
<p>So, the next step is to define your Custom Resource schema in code. Basic stuff is already generated by the &#8220;operator-sdk new&#8221; command used to bootstrap the project (<a href="https://github.com/piontec/netperf-operator/tree/master/pkg/apis/app/v1alpha1">check this directory</a>). The important part is that we have to add the Spec and Status parts of the Custom Resource (CR) object. Spec is the specification, so basically, an input describing the object. Status shows, well, the status of the object. Here&#8217;s how the <a href="https://github.com/piontec/netperf-operator/blob/master/pkg/apis/app/v1alpha1/types.go">full definition looks like</a>, but the most important part is:</p>
<pre class="brush: golang; title: ; notranslate">
type Netperf struct {
	metav1.TypeMeta   `json:&quot;,inline&quot;`
	metav1.ObjectMeta `json:&quot;metadata&quot;`
	Spec              NetperfSpec   `json:&quot;spec&quot;`
	Status            NetperfStatus `json:&quot;status,omitempty&quot;`
}

type NetperfSpec struct {
	ServerNode string `json:&quot;serverNode&quot;`
	ClientNode string `json:&quot;clientNode&quot;`
}

type NetperfStatus struct {
	Status          string  `json:&quot;status&quot;`
	ServerPod       string  `json:&quot;serverPod&quot;`
	ClientPod       string  `json:&quot;clientPod&quot;`
	SpeedBitsPerSec float64 `json:&quot;speedBitsPerSec&quot;`
}
</pre>
<p>Lines 1-6 were already generated. We&#8217;re just providing the NetperfSpec and NetperfStatus definition. In Spec, I&#8217;m expecting just 2 input variables: names of kubernetes nodes where the controller should run the netperf server and client pods. With Spec like that, we can define a netperf test between any 2 cluster nodes we want. The Status is responsible for showing what are the names of ServerPod and ClientPod, the overall Status of the current CR (a single netperf test) and the final test result in bps.</p>
<p>When your definition is done, you have to run the command:</p>
<pre class="brush: bash; title: ; notranslate">
operator-sdk generate k8s
</pre>
<p>This will generate some helper functions for your CR, like deep copying the object instances. Now your definition of the Custom Resource is done and you can already use it!</p>
<h2>The controller loop &#8211; checking what needs to be done</h2>
<p>Do you remember how much code it took to <a href="http://localhost:8080/kubernetes/simple-custom-kubernetes-controller/">start a control loop without any controller library</a>? You might be surprised when you check the <a href="https://github.com/piontec/netperf-operator/blob/master/cmd/netperf-operator/main.go">main.go</a> file. Basically, the bootstrap code is this:</p>
<pre class="brush: golang; title: ; notranslate">
resource := &quot;app.example.com/v1alpha1&quot;
kind := &quot;Netperf&quot;
namespace, err := k8sutil.GetWatchNamespace()
if err != nil {
	logrus.Fatalf(&quot;Failed to get watch namespace: %v&quot;, err)
}
resyncPeriod := 5
sdk.Watch(resource, kind, namespace, resyncPeriod)
sdk.Watch(&quot;v1&quot;, &quot;Pod&quot;, namespace, resyncPeriod)
sdk.Handle(stub.NewHandler(operator.NewNetperf(realkube.NewRealProvider())))
sdk.Run(context.TODO())
</pre>
<p>We&#8217;re declaring API resource type and kind, how frequently we want to get object status update from the API server and then in lines 8 and 9 we just start to watch changes on our &#8220;Netperf&#8221; and &#8220;Pod&#8221; objects. Why &#8220;Pod&#8221;? Because our Netperf Operator creates new pods with netperf client and server and it needs to react to changes and control their lifetime. After that, we register the Handler (line 10, the stub was generated during the bootstrap step as well) and then you Run the whole thing in line 11. The generated handler stub is just a generic handler of any type of objects. These generic objects are switched into domain-specific object types as soon as possible and handled accordingly with (<a href="https://github.com/piontec/netperf-operator/blob/master/pkg/stub/handler.go">full source</a>):</p>
<pre class="brush: golang; title: ; notranslate">
func (h *Handler) Handle(ctx context.Context, event sdk.Event) error {
	switch event.Object.(type) {
	case *v1alpha1.Netperf:
		netperf := event.Object.(*v1alpha1.Netperf)
		return h.operator.HandleNetperf(netperf, event.Deleted)
	case *v1.Pod:
		pod := event.Object.(*v1.Pod)
		return h.operator.HandlePod(pod, event.Deleted)
	default:
		logrus.Warnf(&quot;unknown event received: %s&quot;, event)
	}
	return nil
}
</pre>
<p>OK, now we have everything needed to write a custom Kubernetes controller in place: Custom Resource Definition (CRD), Netperf Custom Resource (CR) and the control loop, where we can easily react to the incoming information about the system state we have to create. Now the &#8220;only&#8221; thing left is to add our business logic that does that.</p>
<h2>Business logic, a.k.a. how to run Netperf on Kubernetes using API calls</h2>
<p>I won&#8217;t describe the whole code line by line here, you can check the <a href="https://github.com/piontec/netperf-operator/blob/master/pkg/netperf-operator/operator.go">source here</a>. But I want to give an overview that will hopefully make the code easier to understand.</p>
<h3>Handling state</h3>
<p>The main concept is that we need to react to events in a different way, depending on what we have already completed and the state Netperf object is in. It&#8217;s basically a <a href="https://en.wikipedia.org/wiki/Finite-state_machine">finite state machine</a>: our action depends on the state we&#8217;re in and the event we receive. We assume a single Netperf object can be in one of the following states:</p>
<ul>
<li>NetperfPhaseInitial: resource was created, but no actions were taken yet;</li>
<li>NetperfPhaseServer: server pod is being created, but the client is not yet started;</li>
<li>NetperfPhaseTest: the client pod is created as well and the test should be in progress;</li>
<li>NetperfPhaseDone: the client pod has stopped, we collect the result and stop both server and client pods; the test is complete;</li>
<li>NetperfPhaseError: something bad happened and the controller was not able to complete the test; we can&#8217;t proceed and finish with an error.</li>
</ul>
<p>Check the following image for visualization of states (circles), events (black font) and actions (violet font) we have to handle.</p>
<p><figure id="attachment_393" aria-describedby="caption-attachment-393" style="width: 628px" class="wp-caption aligncenter"><img decoding="async" class="wp-image-393 size-large" title="How to write a Kubernetes controller - state diagram of Netperf object" src="https://localhost:8080/wp-content/uploads/2018/09/netperf-operator-state-diagram-1024x605.png" alt="How to write a Kubernetes controller - state diagram of Netperf object" width="628" height="371" srcset="https://tailored.cloud/wp-content/uploads/2018/09/netperf-operator-state-diagram-1024x605.png 1024w, https://tailored.cloud/wp-content/uploads/2018/09/netperf-operator-state-diagram-300x177.png 300w, https://tailored.cloud/wp-content/uploads/2018/09/netperf-operator-state-diagram-768x454.png 768w, https://tailored.cloud/wp-content/uploads/2018/09/netperf-operator-state-diagram.png 1650w" sizes="(max-width: 628px) 100vw, 628px" /><figcaption id="caption-attachment-393" class="wp-caption-text">The state diagram of a Netperf object</figcaption></figure></p>
<p>As you can see, to make everything work, we have to keep state &#8211; our current action depends on what previously already was applied to a Netperf object. That&#8217;s a major issue. We can&#8217;t just keep the state as the object&#8217;s state in the RAM memory, as we have to deal with failures. No matter if we want to run our controller on Kubernetes itself, as a Pod, or outside the cluster, as a standalone process &#8211; we have to handle restarts. So, the solution is to offload the problem of keeping state to some external durable storage. If our state is big, we could use some external key-value storage, like Redis or Etcd. Fortunately, our whole state is just a single variable with the state&#8217;s name. In this case, we can just keep the state within the Netperf object itself &#8211; the kubernetes API server will be our durable storage. And in the same go, we provide a better feedback to our users, who can check what&#8217;s the state of a Netperf test. When you write a Kubernetes controller, make sure you know what your state is and how to make it durable.</p>
<p>Still, the bottom line is: your process can terminate at any moment. Write a kubernetes controller assuming it can be terminated and restarted at any time.</p>
<p>Oh, one more thing: in your code, you should never change the object that you received in the control loop. Always make a copy of the object first &#8211; that&#8217;s why you have this generated <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/apis/app/v1alpha1/zz_generated.deepcopy.go#L22">DeepCopy()</a> function. Then, save the copy with API server call.</p>
<h3>Control flow overview</h3>
<p>Let&#8217;s briefly go over what Netperf operator does for events in particular states:</p>
<ul>
<li>We start with <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L41">HandleNetperf()</a> method, which just checks if the event is about a Netperf object being deleted or created/updated (since we synchronize the state to match the API object, there&#8217;s actually no need to tell a create from an update event),
<ul>
<li>If it was a create/update, we go to <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L65:19">handleNetperfUpdateEvent()</a>, where we make sure that the Server pod is started and existing. Remember, we can receive this event multiple times, not just once or only when a new Netperf object is created! So, we check for the current Netperf object state. If it is &#8220;Initial&#8221; or &#8220;Server&#8221;, we run <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L78">startServerPod()</a>, which makes sure the pod either already exists or is created (but not blindly creates the pod). In other states, we ignore the update request, as to get to these states the server pod must have been already created.</li>
<li>If the delete flag was set,  we call <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L60">deleteNetperfPods()</a>, which basically does&#8230; nothing! Our netperf pods will be automatically deleted by the API server when the Netperf object that created them is deleted. This is possible because we correctly set the <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L164">OwnerReference</a> for our pods.</li>
</ul>
</li>
<li>The second entry point into our business logic controller is with <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L49">HandlePod()</a> method. Keep in mind that with this approach that method is called for every pod in the same namespace. So, we start with checking if the owner of the pod is an existing Netperf object. If not, our controller has nothing to care for it. If it is a related pod event, in <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L212:19">handlePodUpdateEvent()</a> we check if it is about a Server or a Client pod. Then, we call the event handler function for the specific kind of pod.
<ul>
<li>in <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L329:19">handleServerPodEvent()</a> we&#8217;re checking if the Server pod is already up and running. If not, we&#8217;re waiting. If it&#8217;s ready, we check if the client pod is already created for this Netperf object. Again, we&#8217;re not blindly creating a client pod, as it might have been already created. Instead, we check the current state and create the Client pod only if it doesn&#8217;t yet exist.</li>
<li>in <a href="https://github.com/piontec/netperf-operator/blob/436c7c101ddf98a7a23a4402693eb9d4f027ec58/pkg/netperf-operator/operator.go#L244">handleClientPodEvent()</a> we&#8217;re checking for the Client pod status. If it has already completed, we can get the output log from it, parse it and get the netperf speed result value. We&#8217;re also cleaning up both the Client and Server pod. Finally, we do the one last update of the Nerperf object, to include the test result in the Status part of the object definition.</li>
</ul>
</li>
</ul>
<h2>Building and running the project</h2>
<p>When you wrote a Kubernetes controller you naturally want to build and run it. Project building is described with a fairly complex workflow on the operator-sdk github page. This workflow includes building a docker image, then pushing it to the registry and after that deploying to a test cluster. This is nice when you want to test the full deployment cycle, but it&#8217;s terrible for development, as it takes a long time to build and deploy. On the github page of <a href="https://github.com/piontec/netperf-operator">Netperf Operator</a>, I described another approach for the development cycle, where you can just build and debug a local go binary, without even touching docker and deploying to cluster. Be sure to <a href="https://github.com/piontec/netperf-operator#-developers-guide">check it out</a>. You can also find information about how to run the Netperf Operator there.</p>
<h2>How to write a Kubernetes controller &#8211; a short summary</h2>
<p>OK, this entry is a lengthy one, not mentioning the linked code. Still, I really think that using a library like operator-sdk makes the whole thing much easier and faster. And creating a custom controller using a Custom Resource Definition really opens up plenty of possibilities for your needs. After all, Kubernetes is &#8220;just a new operating system&#8221; &#8211; at some point you have to write your own application&#8230; or rather write a Kubernets controller!</p>
<p>&nbsp;</p>
<p>The post <a href="https://tailored.cloud/kubernetes/write-a-kubernetes-controller-operator-sdk/">Write a Kubernetes controller (operator) with operator-sdk</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tailored.cloud/kubernetes/write-a-kubernetes-controller-operator-sdk/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>KubeCon and CloudNativeCon 2018 EU &#8211; short and delayed summary</title>
		<link>https://tailored.cloud/conferences/kubecon-2018-eu-summary/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=kubecon-2018-eu-summary</link>
					<comments>https://tailored.cloud/conferences/kubecon-2018-eu-summary/#respond</comments>
		
		<dc:creator><![CDATA[tc-admin]]></dc:creator>
		<pubDate>Sun, 03 Jun 2018 19:09:17 +0000</pubDate>
				<category><![CDATA[conferences]]></category>
		<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[KubeCon]]></category>
		<guid isPermaLink="false">http://localhost:8080/?p=340</guid>

					<description><![CDATA[<p>TL;DR: really good conference hot topics: security service mesh custom controllers and operators cool afterparty! watch all videos on this youtube <a class="more-link" href="https://tailored.cloud/conferences/kubecon-2018-eu-summary/">Continue Reading</a></p>
<p>The post <a href="https://tailored.cloud/conferences/kubecon-2018-eu-summary/">KubeCon and CloudNativeCon 2018 EU &#8211; short and delayed summary</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>TL;DR:</h2>
<ul>
<li>really good conference</li>
<li>hot topics:
<ul>
<li>security</li>
<li>service mesh</li>
<li>custom controllers and operators</li>
</ul>
</li>
<li>cool afterparty!</li>
<li>watch all videos on this <a href="https://www.youtube.com/watch?v=OUYTNywPk-s&amp;list=PLj6h78yzYM2N8GdbjmhVU65KYm_68qBmo">youtube channel</a></li>
</ul>
<h1>KubeCon 2018</h1>
<p>Yes, I should have written this post 3 weeks ago, but because of the conference itself, I was busy doing some learn&amp;code in my &#8220;free&#8221; time. So, because there are already multiple good summaries of KubeCon EU 2018 on the Internet, let me just give you a summary of my personal opinions, notes, and learnings from the conference.</p>
<p><figure id="attachment_344" aria-describedby="caption-attachment-344" style="width: 628px" class="wp-caption aligncenter"><img decoding="async" class="wp-image-344 size-large" src="https://localhost:8080/wp-content/uploads/2018/06/resized000-1024x683.jpg" alt="KubeCon 2018 - crowd in the hallway" width="628" height="419" srcset="https://tailored.cloud/wp-content/uploads/2018/06/resized000-1024x683.jpg 1024w, https://tailored.cloud/wp-content/uploads/2018/06/resized000-300x200.jpg 300w, https://tailored.cloud/wp-content/uploads/2018/06/resized000-768x512.jpg 768w, https://tailored.cloud/wp-content/uploads/2018/06/resized000.jpg 1600w" sizes="(max-width: 628px) 100vw, 628px" /><figcaption id="caption-attachment-344" class="wp-caption-text">KubeCon 2018 &#8211; crowd in the hallway</figcaption></figure></p>
<h1>General impressions</h1>
<p>In short: it was totally worth going there. This conference was really all about tech. In general, all sessions that I attended, including keynotes, were strictly technical and well prepared. Also, the &#8220;hallway track&#8221; is really great: you can learn a lot talking with other people and learning from their experience. Also, you can talk &#8211; and learn from &#8211; some of the community &#8220;stars&#8221;. I myself had an opportunity to talk to <a href="https://github.com/kelseyhightower">Kelsy Hightower</a> and <a href="https://github.com/thockin">Tim Hockin</a>.</p>
<p><figure id="attachment_346" aria-describedby="caption-attachment-346" style="width: 628px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-346 size-large" src="https://localhost:8080/wp-content/uploads/2018/06/resized002-1024x683.jpg" alt="KubeCon - keynotes session" width="628" height="419" srcset="https://tailored.cloud/wp-content/uploads/2018/06/resized002-1024x683.jpg 1024w, https://tailored.cloud/wp-content/uploads/2018/06/resized002-300x200.jpg 300w, https://tailored.cloud/wp-content/uploads/2018/06/resized002-768x512.jpg 768w, https://tailored.cloud/wp-content/uploads/2018/06/resized002.jpg 1600w" sizes="(max-width: 628px) 100vw, 628px" /><figcaption id="caption-attachment-346" class="wp-caption-text">KubeCon &#8211; keynotes session</figcaption></figure></p>
<p>The conference was also kind of crazy. There were over 4000 people and sometimes there were as many as 8 parallel tracks during breakout sessions. I highly recommend to just check the <a href="https://www.youtube.com/watch?v=OUYTNywPk-s&amp;list=PLj6h78yzYM2N8GdbjmhVU65KYm_68qBmo">youtube channel</a>, where all the videos &#8211; over 350 of them! &#8211; are available. One last thing: the afterparty was really cool! It was held in Tivoli Gardens, an amusement park in the center of Copenhagen. There was plenty of space, time and food to have a good time and talk with different people.</p>
<p><figure id="attachment_345" aria-describedby="caption-attachment-345" style="width: 628px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-345 size-large" src="https://localhost:8080/wp-content/uploads/2018/06/resized001-1024x683.jpg" alt="KubeCon - Tivoli park after dark" width="628" height="419" srcset="https://tailored.cloud/wp-content/uploads/2018/06/resized001-1024x683.jpg 1024w, https://tailored.cloud/wp-content/uploads/2018/06/resized001-300x200.jpg 300w, https://tailored.cloud/wp-content/uploads/2018/06/resized001-768x512.jpg 768w, https://tailored.cloud/wp-content/uploads/2018/06/resized001.jpg 1600w" sizes="(max-width: 628px) 100vw, 628px" /><figcaption id="caption-attachment-345" class="wp-caption-text">KubeCon &#8211; Tivoli park after dark</figcaption></figure></p>
<h1>Hot Kubernetes topics</h1>
<p>Some of the main topics were really recurring during the conference and it was easy to spot that there is a lot of work going in these areas. Here are the &#8220;hottest&#8221; ones:</p>
<h2>Service mesh</h2>
<p>Yes, service mesh is the &#8220;next big thing&#8221; and <a href="https://istio.io">Istio</a> project is really hot now.  In general, you could have an impression that Istio is the new Kubernetes: everyone has it, everyone runs it and it&#8217;s time to move past that, bring integration with other tools and see how you can exploit further the concept. But it&#8217;s not that fast. A few companies already admitted to run Istio in production, but the majority is only testing and evaluating it. I think this matches a common sense. The idea of service mesh is to have a separate layer built on top of the &#8220;normal&#8221; network stack, which is dedicated to managing traffic between different services running in your cluster and/or for your application. This management can include things like:</p>
<ul>
<li>request routing (canary deployments: please route 5% of my traffic to pods with label v2 and the rest to the stable deployment that has label v1)</li>
<li>monitoring and visibility (gather traffic and request detail with per-service granularity; like <a href="https://istio.io/docs/tasks/telemetry/using-istio-dashboard">Istio and Grafana</a>)</li>
<li>improved security (only services A and B are allowed to direct traffic to service C )</li>
<li>automated dependency discovery (like <a style="background-color: #ffffff; color: #b37800; outline: 0px;" href="https://istio.io/docs/tasks/telemetry/servicegraph/">Istio and Servicegraph</a>)</li>
<li>request tracing (<a href="https://istio.io/docs/tasks/telemetry/distributed-tracing/">like Istio and Jaeger</a>)</li>
</ul>
<p>All these possibilities are great, for me especially the area of monitoring and tracing, which can almost instantly improve your understanding of how services are behaving on their own and in relation to others. Still, let&#8217;s remember the idea is pretty fresh. It is wise to check and evaluate it on your own but later you have to decide if the increased complexity of your tech stack is worth the benefits you&#8217;re expecting. I highly recommend going through Istio&#8217;s <a href="https://istio.io/docs/guides/bookinfo/">getting started tutorial</a>. Also, keep in mind that Istio is now the leading implementation of the service mesh idea, but it&#8217;s not the only one. There are already new projects like <a href="https://conduit.io/">Conduit</a>.</p>
<h2>Security</h2>
<p>Another hot topic: a lot of effort is going into the security area.  A lot is going in the area of better containers isolation and providing cloud-native identification for services. Projects worth mentioning that I&#8217;ve heard about during the conference are:</p>
<ul>
<li><a href="https://spiffe.io/spiffe/">SPIFFY</a>/<a href="https://spiffe.io/spire/">SPIRE</a>: a specification and its implementation for providing strong identities to microservices</li>
<li><a href="https://github.com/google/gvisor">gVisor</a>: this sounded somehow incredible to me: a team from Google implemented a lightweight microkernel in userspace using golang. This microkernel is compatible (to some extent) with normal Linux kernel, but offers isolation layer for system calls, that exists between a container and operating system&#8217;s kernel. This has its own drawbacks (compatibility, performance cost), but sounds like a great way to improve container security.</li>
<li><a href="https://katacontainers.io/">kata containers</a>, which just released version 1.0. It&#8217;s another approach to strong container isolation, this time by implementing very lightweight virtual machines and a runtime to run them. Every container is running in a single lightweight virtual machine and the whole runtime is OCI compatible, so the isolation is transparent for a user.</li>
</ul>
<p><span style="color: #454545; font-family: Oswald, sans-serif; font-size: 30px;">Custom controllers and operators</span></p>
<p>This topic caught my personal attention. I thought that Kubernetes&#8217; controller mechanisms are somewhat monolithic and highly integrated parts if the orchestrator. I was wrong. Basically, every object you can create through Kubernetes API has its own controller, that is responsible for handling this particular type of resource and making sure that the state of resources in the cluster matches what is configured. As an example, think about ReplicaSet controller. ReplicaSet defines a number of pods that are required to run in the cluster and a label selector that allows checking how many of them are running in the cluster right now. The whole point of ReplicaSet controller is to check how many pods matching a selector are now available in the system and compare it to the value defined in the ReplicaSet object. If there are too many pods, some of them are stopped; if there&#8217;s not enough, new ones are created using Pod Template from the ReplicaSet definition.</p>
<p>The idea is, that you can easily provide your own controllers. They are just a process, that needs access to Kubernetes API and monitors the state of some API objects. They can either control some already defined API objects (like Pods or Deployments) or you can define your own resource types, called <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">Custom Resource Definitions</a>. This second approach leads to a new pattern in creating controllers called <a href="https://coreos.com/operators/">operators</a>. This idea was mainly started by the CoreOS team. The operator is an application specific controller, which can create and manage an application in a way, that is tuned for that particular operation. This can include functions like being able to define a backup policy in the same way as any other object in the cluster, like Pod. Be sure to check etcd, Prometheus or Vault operators as examples of this approach. The cool thing is that CoreOS created a library called <a href="https://github.com/operator-framework/operator-sdk">Operator SDK</a>, which makes implementing Operators easier.</p>
<p>After getting back from KubeCon, I really wanted to check how it works in practice. I started with trying to understand what are the basic elements and control logic of a controller. You can read about my findings in <a href="http://localhost:8080/kubernetes/simple-custom-kubernetes-controller/">this previous article</a>. But recently I also spent some time trying to implement Netperf Operator using the Operator SDK. My aim is to create an operator, that runs pod-to-pod network performance test for you. I&#8217;m really close to completing that, so stay tuned, a new blog entry about what I learned in the process is on the way.</p>
<h2>Other interesting stuff</h2>
<ul>
<li>I had no idea how much useful and interesting open source projects related to Kubernetes the team from Zalando has! Be sure to check <a href="https://opensource.zalando.com/">them</a> out! On the conference, they showed how they manage over 160 kubernetes clusters with their tools.</li>
<li>If you want to learn about all projects currently under CNCF and what maturity level they are, check this <a href="https://landscape.cncf.io/">CNCF Landscape page</a>.</li>
</ul>
<p>The post <a href="https://tailored.cloud/conferences/kubecon-2018-eu-summary/">KubeCon and CloudNativeCon 2018 EU &#8211; short and delayed summary</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tailored.cloud/conferences/kubecon-2018-eu-summary/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>A very simple custom Kubernetes controller</title>
		<link>https://tailored.cloud/kubernetes/simple-custom-kubernetes-controller/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=simple-custom-kubernetes-controller</link>
					<comments>https://tailored.cloud/kubernetes/simple-custom-kubernetes-controller/#respond</comments>
		
		<dc:creator><![CDATA[tc-admin]]></dc:creator>
		<pubDate>Thu, 17 May 2018 14:13:38 +0000</pubDate>
				<category><![CDATA[kubernetes]]></category>
		<guid isPermaLink="false">http://localhost:8080/?p=324</guid>

					<description><![CDATA[<p>TL;DR to learn how to build a custom Kubernetes controller, go to https://github.com/piontec/k8s-demo-controller, read, clone, learn and enjoy! Learning to write custom <a class="more-link" href="https://tailored.cloud/kubernetes/simple-custom-kubernetes-controller/">Continue Reading</a></p>
<p>The post <a href="https://tailored.cloud/kubernetes/simple-custom-kubernetes-controller/">A very simple custom Kubernetes controller</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>TL;DR</h2>
<ul>
<li>to learn how to build a custom Kubernetes controller, go to <a href="https://github.com/piontec/k8s-demo-controller">https://github.com/piontec/k8s-demo-controller</a>, read, clone, learn and enjoy!</li>
</ul>
<h2>Learning to write custom Kubernetes controller</h2>
<p><img loading="lazy" decoding="async" class="alignleft wp-image-327 size-thumbnail" src="https://localhost:8080/wp-content/uploads/2018/05/k8s-logo-150x150.png" alt="simple Kubernetes controller" width="150" height="150" srcset="https://tailored.cloud/wp-content/uploads/2018/05/k8s-logo-150x150.png 150w, https://tailored.cloud/wp-content/uploads/2018/05/k8s-logo-300x300.png 300w, https://tailored.cloud/wp-content/uploads/2018/05/k8s-logo.png 400w" sizes="(max-width: 150px) 100vw, 150px" /></p>
<p>Recently, after the KubeCon and CloudNativeCon 2018 in Copenhagen (short summary coming up soon), I decided to give a go to the more and more popular topic of custom kubernetes controllers. The problem is, it was not that easy to get started. I found some examples on the Internet, but none of them was really a bare minimum, that makes learning and understanding the code easier. So, I took <a href="https://github.com/bitnami-labs/kubewatch">kubewatch</a> and turned it into something that &#8211; I hope &#8211; is close to &#8220;the minimal kubernetes controller&#8221;.</p>
<p>The rest of this blog entry is actually the project on github itself: <a href="https://github.com/piontec/k8s-demo-controller">https://github.com/piontec/k8s-demo-controller</a>.  Go there, read my comments, read the code and you should be good to get started and explore further topics like <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">Custom Resource Definitions</a> or <a href="https://github.com/operator-framework/getting-started">Operator Framework</a>.</p>
<p>&nbsp;</p>
<p>The post <a href="https://tailored.cloud/kubernetes/simple-custom-kubernetes-controller/">A very simple custom Kubernetes controller</a> appeared first on <a href="https://tailored.cloud">Tailored Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tailored.cloud/kubernetes/simple-custom-kubernetes-controller/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
