<?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>DEV Community: Jennifer Luther Thomas</title>
    <description>The latest articles on DEV Community by Jennifer Luther Thomas (@mapgirll).</description>
    <link>https://dev.to/mapgirll</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%2F1192300%2Fcdfd0758-aeff-4b28-93e7-954acb07561f.JPG</url>
      <title>DEV Community: Jennifer Luther Thomas</title>
      <link>https://dev.to/mapgirll</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mapgirll"/>
    <language>en</language>
    <item>
      <title>How purpose-built observability will speed up your Kubernetes troubleshooting</title>
      <dc:creator>Jennifer Luther Thomas</dc:creator>
      <pubDate>Tue, 28 Nov 2023 21:47:06 +0000</pubDate>
      <link>https://dev.to/mapgirll/how-purpose-built-observability-will-speed-up-your-kubernetes-troubleshooting-3m5l</link>
      <guid>https://dev.to/mapgirll/how-purpose-built-observability-will-speed-up-your-kubernetes-troubleshooting-3m5l</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xECZEx4B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AObfl4sRWLHyNT5QEKV0AOg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xECZEx4B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AObfl4sRWLHyNT5QEKV0AOg.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you remember from my &lt;a href="https://medium.com/@mapgirll/a-beginners-journey-to-kubernetes-security-0023ca9079ad"&gt;last post&lt;/a&gt;, in my previous job, I was battling a support case where a user had implemented network security policies for their FME Flow (Server) application and a part of the application wasn’t working. They were using &lt;a href="https://openservicemesh.io/"&gt;Open Service Mesh&lt;/a&gt; (a lightweight and extensible cloud-native service mesh), which had some mechanism for recommending Kubernetes security policies. However, in doing so it had missed one of the port ranges that FME Flow required. This took &lt;strong&gt;weeks&lt;/strong&gt; of troubleshooting with involvement from the customer, resellers/consultants with escalation to the software vendor (me).&lt;/p&gt;

&lt;p&gt;Knowing that FME Flow was working fine before the network security policies were applied, OSM seemed like the probable cause. But with no insights into network topology or flow logs to see how those policies had potentially impacted FME it was difficult to isolate the problem. I had also never used OSM before, which made it hard for me to know where to start. Eventually the customer figured out that a port range had been missed in the network security policies so I can’t take any credit for the resolution.&lt;/p&gt;

&lt;p&gt;If the customer or I had access to Kubernetes observability back then, it would have made it so much easier and faster to troubleshoot the issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what is observability?
&lt;/h3&gt;

&lt;p&gt;Observability refers to the ability to understand the internal state of a system by looking at the external outputs of the system. For me, the main benefit was being able to quickly view my intra-cluster traffic and identify where packets were being denied and why.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.tigera.io/tigera-products/calico-cloud/"&gt;Calico Cloud&lt;/a&gt; (which I’m using for this example) this can be found inside the &lt;a href="https://www.tigera.io/features/dynamic-service-graph/"&gt;Dynamic Service and Threat Graph&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Dynamic Service and Threat Graph provides a point-to-point, topographical representation of traffic within your cluster to observe Kubernetes environment behavior, troubleshoot connectivity issues, and identify performance hotspots.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;According to Splunk, in their “&lt;a href="https://www.splunk.com/en_us/form/state-of-observability.html?utm_campaign=google_amer_en_search_brand&amp;amp;utm_source=google&amp;amp;utm_medium=cpc&amp;amp;utm_content=StateofO11y23_EB&amp;amp;utm_term=splunk%20observability&amp;amp;_bk=splunk%20observability&amp;amp;_bt=658881201317&amp;amp;_bm=p&amp;amp;_bn=g&amp;amp;_bg=111780047679&amp;amp;device=c&amp;amp;gad_source=1&amp;amp;gclid=CjwKCAiAvJarBhA1EiwAGgZl0MYnXYqfaArlFS2ZEYlgC8OGOAbOaz8ck4E0EZXdv-9aPbX874UB5RoCZHsQAvD_BwE"&gt;The State of Observability 2023&lt;/a&gt;” report:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Observability has become foundational to modern enterprises, providing a way to see into the stunningly complex web of systems that characterizes today’s IT environments”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would agree with that.&lt;/p&gt;

&lt;p&gt;Observability helps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;understand the communication patterns within Kubernetes&lt;/li&gt;
&lt;li&gt;visualize microservice communication&lt;/li&gt;
&lt;li&gt;quickly see dependencies and interactions&lt;/li&gt;
&lt;li&gt;identify external services&lt;/li&gt;
&lt;li&gt;analyze performance&lt;/li&gt;
&lt;li&gt;speed up troubleshooting&lt;/li&gt;
&lt;li&gt;increase resilience&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The situation
&lt;/h3&gt;

&lt;p&gt;In the FME Flow (an enterprise spatial ETL application) &lt;a href="https://github.com/safesoftware/helm-charts"&gt;helm chart&lt;/a&gt; you can add a value for the &lt;em&gt;fmeserver.portpool&lt;/em&gt;. This defines a range of ports that the FME Engines (the ‘worker’ that does all of the ETL processing) use when connecting to the FME Core, which is essentially the brains of the application.&lt;/p&gt;

&lt;p&gt;If you apply network security policies (without the port range exposed) after you’ve already launched FME you may not notice immediately. In fact, I think the issue mainly manifested itself when an FME Engine needed to communicate with the Core to retrieve database connection information (if an ETL job was reading/writing to a database) which was not the easiest to troubleshoot. This was the customer’s situation that was brought to me.&lt;/p&gt;

&lt;p&gt;If you don’t allow the port range within the cluster &lt;em&gt;before&lt;/em&gt; you install the application you may find that the FME Engines can’t register with the FME Core and the problem would be more obvious and critical. If the FME Engines aren’t registering, you’re not going to be processing any data.&lt;/p&gt;

&lt;p&gt;This is why I wanted to see how fast I could identify and fix this issue using observability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reproducing the scenario
&lt;/h3&gt;

&lt;p&gt;As I’ve been learning more about Calico Cloud and it’s capabilities, I realized the policies that I implemented previously could not only be used in Calico Cloud, but I could easily and quickly view how all of the components of my application communicate with each other and if the policies I’m putting in place are working.&lt;/p&gt;

&lt;p&gt;Connecting Calico Cloud to my cluster was a piece of cake. The UI generates a command that you can apply to your cluster. Then while you take an extended coffee or a snack break, it installs everything in your cluster and you’re ready to go!&lt;/p&gt;

&lt;p&gt;To reproduce the customer scenario, I had the Policy Board open on one screen.&lt;/p&gt;

&lt;p&gt;The Policy Board lets me see which policies I have enforced, either by applying them via CLI or creating in the Calico Cloud interface. It very quickly gives insights into which policies are evaluating traffic whether packets are being allowed or denied.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5LWdD6MQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AayL0f5XynwRf9w4aHJ_WPg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5LWdD6MQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AayL0f5XynwRf9w4aHJ_WPg.png" alt="" width="800" height="346"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Policies Board in Calico Cloud&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On my other screen I had the Dynamic Service and Threat Graph open, which allows you to click on any line and see what traffic is flowing between components.&lt;/p&gt;

&lt;p&gt;Based on the arrow direction we can easily see that traffic is flowing from NGINX (the ingress) to FME (the application). The arrow is green, which means that traffic is allowed. Inspecting the traffic shows the protocol, ports and any policies in place in the right hand sidebar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B_5YyNsi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/875/1%2AxCLB35OYizgFX1xVOeIFhA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B_5YyNsi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/875/1%2AxCLB35OYizgFX1xVOeIFhA.png" alt="" width="800" height="329"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An up-close view of the communication between two Kubernetes namespaces&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we look inside the fme namespace we can see traffic communicating between the different components. There is a red line between the engine deployment groups and the engine registration service (core).&lt;/p&gt;

&lt;p&gt;Inspecting that traffic flow shows the engine group is trying to communicate with the core on ports 7070 and 42001–42002 (the port range I specified in the helm chart is 42000–43000).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ydTcqKbm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/877/1%2Ac5dDXDlulDVTOzKufhpC-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ydTcqKbm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/877/1%2Ac5dDXDlulDVTOzKufhpC-Q.png" alt="" width="800" height="265"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A topological view of microservices communication within the fme namespace&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Looking at the right-hand panel we can see that traffic is being denied as it leaves the engine group.&lt;/p&gt;

&lt;p&gt;In Calico Cloud at the bottom of the Dynamic Service and Threat Graph is a Flows table which lists every flow happening within the cluster. This includes source and destination, ports, policies, action, process ID, etc. To find out which policy is denying the traffic we can look at the policies that are evaluating the flow from engine to the engine registration service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c-GZAhq6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ay7KviTSChiSucrArTDqHYg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c-GZAhq6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Ay7KviTSChiSucrArTDqHYg.png" alt="" width="800" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default deny policy is in place to block any traffic that I haven’t explicitly allowed as part of my zero-trust security posture. I deliberately excluded my port range from any policy so that it would be denied by default to reproduce the customer’s scenario.&lt;/p&gt;

&lt;p&gt;To allow traffic to flow as intended the engine policy will need to be set up so that it can communicate with the other FME Flow components.&lt;/p&gt;

&lt;p&gt;To apply this policy to the engines, I used this policy label selector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;selector: safe.k8s.fmeserver.component == "engine"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the Create Policy UI where I’ve defined ingress and egress rules for the engines:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UTpXnOCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/774/1%2A7OdIrI7wSIMYx1W8uqX0nQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UTpXnOCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/774/1%2A7OdIrI7wSIMYx1W8uqX0nQ.png" alt="" width="774" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The ingress and egress rules for the fme engine deployment&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And if you’d rather look at the yaml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: application.engine-fmeserver
  namespace: fme
spec:
  tier: application
  order: 37.5
  selector: safe.k8s.fmeserver.component == "engine"
  serviceAccountSelector: ''
  ingress:
    - action: Allow
      protocol: TCP
      source:
        selector: safe.k8s.fmeserver.component == "core"
      destination:
        ports:
          - '7500'
  egress:
    - action: Allow
      protocol: TCP
      source: {}
      destination:
        selector: safe.k8s.fmeserver.component == "core"
        ports:
          - '7070'
          - '42000:43000'
    - action: Allow
      protocol: TCP
      source: {}
      destination:
        selector: app.kubernetes.io/name == "postgresql"
        ports:
          - '5432'
  types:
    - Ingress
    - Egress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And almost like magic, the Dynamic Service and Threat Graph turns green:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iTwS_3RF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AJag-homTrvURl2r7ocsEsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iTwS_3RF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AJag-homTrvURl2r7ocsEsw.png" alt="" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another snazzy feature that makes it easy to see which components are talking to which is to click on it in the Dynamic Service and Threat Graph. Clicking on the engine-standard-group deployment shows every inbound and outbound communication on the right-hand side.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flow Visualization
&lt;/h3&gt;

&lt;p&gt;Another observability feature of Calico Cloud that I’ve recently come to appreciate is Flow Visualization, or “FlowViz”.&lt;/p&gt;

&lt;p&gt;At first look, it’s a bit of a WTF moment. This doesn’t tell me anything?!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vyKB2caV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A9g6KCqmXbVF2E3gC3KCFMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vyKB2caV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A9g6KCqmXbVF2E3gC3KCFMA.png" alt="" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of the topological view that is easy to comprehend at first look, Flow Visualization gives a 360 degree view of your cluster, with network traffic represented volumetrically. Moving in from the outside it represents namespaces, endpoint names and flows. Colour-coded flows quickly lets you see if there’s any denied traffic, and next to this visualization is a table that shows allowed and denied traffic by namespace, with connections per second (CPS), packets per second (PPS) and bits per second (BPS), if network performance is your thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wp-5MqPU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/600/1%2AZdhvsTKW7FQQylQnyhobfw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wp-5MqPU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/600/1%2AZdhvsTKW7FQQylQnyhobfw.gif" alt="" width="600" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also ‘zoom in’ to your namespace and easily find denied traffic and which policies are denying (or allowing) traffic. Clicking on the denied traffic flow (as shown in the gif above) instantly shows which policy is responsible so that it can be fixed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;If the customer had the same visibility into their cluster it would have been &lt;strong&gt;very easy&lt;/strong&gt; to identify the denied traffic and correct the policies. But then I wouldn’t be here telling this story.&lt;/p&gt;

&lt;p&gt;Observability using Dynamic Service and Threat Graph, FlowViz and the Policy Board make it &lt;em&gt;incredibly&lt;/em&gt; easy and fast to apply the correct network security policies to protect your workloads, as well as see what’s actually going on inside your cluster! The massive overhead of writing policies in yaml and taking an iterative approach to testing connection by connection is &lt;em&gt;so last blog&lt;/em&gt;. Not only does observability make your cluster look cool, I’ve found it incredibly valuable.&lt;/p&gt;

&lt;p&gt;If you want to give it a go for yourself, &lt;a href="http://www.calicocloud.io/"&gt;sign up for a Calico Cloud trial&lt;/a&gt;. There is also a &lt;a href="https://play.instruqt.com/tigera/invite/npp8jkc5wmbi"&gt;hands-on tutorial to learn how to gain observability and optimize troubleshooting&lt;/a&gt; in under an hour.&lt;/p&gt;

&lt;p&gt;Stay connected with me on here, &lt;a href="https://twitter.com/mapgirll"&gt;X&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/jennifer-luther-thomas-59b79071/"&gt;LinkedIn&lt;/a&gt; to follow my journey and more introductory security content!&lt;/p&gt;

&lt;p&gt;If you want to see all of my policies for FME Flow reach out and I can share the yaml.&lt;/p&gt;

</description>
      <category>calico</category>
      <category>kubernetesobservabil</category>
      <category>kubernetes</category>
      <category>troubleshooting</category>
    </item>
    <item>
      <title>A beginner’s journey to Kubernetes security</title>
      <dc:creator>Jennifer Luther Thomas</dc:creator>
      <pubDate>Fri, 13 Oct 2023 03:31:28 +0000</pubDate>
      <link>https://dev.to/mapgirll/a-beginners-journey-to-kubernetes-security-25ol</link>
      <guid>https://dev.to/mapgirll/a-beginners-journey-to-kubernetes-security-25ol</guid>
      <description>&lt;p&gt;Come with me on my career journey as I learn all about Kubernetes security.&lt;/p&gt;

&lt;p&gt;If you’re reading this blog then I’m assuming you have some knowledge of Kubernetes. If not, and you’re interested in learning, I not only learnt a lot but also &lt;em&gt;enjoyed&lt;/em&gt;&lt;a href="https://www.udemy.com/course/docker-kubernetes-the-practical-guide/?couponCode=D_0923"&gt;this course&lt;/a&gt; on Udemy (not affiliated in any way — I just found this course extremely engaging and helpful!).&lt;/p&gt;

&lt;p&gt;I’d like to say I wasn’t a complete stranger to security prior to accepting a position at &lt;a href="https://www.tigera.io/"&gt;Tigera&lt;/a&gt;. I follow the &lt;a href="https://www.reddit.com/r/Scams/"&gt;r/scams&lt;/a&gt; subreddit and had read &lt;a href="https://www.goodreads.com/en/book/show/36560496"&gt;The Perfect Weapon&lt;/a&gt; but in hindsight I was totally ignorant of how Kubernetes clusters could be compromised, and what security measures can be put in place. After my technical interview task, I was surprised at how easy implementing some basic security is.&lt;/p&gt;

&lt;p&gt;With this blog I’m here to make Kubernetes and security a little more accessible. I wrote this with the intention to help users who are new to Kubernetes security. Perhaps, like me, you’ve never really considered Kubernetes security before. Perhaps you’ve been asked to secure your cluster and you’re not sure what the first steps that you need to take are. Or perhaps you’re already familiar with the concepts of zero-trust and microsegmentation and you want to know how to protect your cluster from malicious traffic.&lt;/p&gt;

&lt;p&gt;In this blog I’ll give you an introduction to Kubernetes networking and security policies, why they are used, policy examples (and what I did wrong/didn’t consider) and how you can easily (and for free) implement them in your own Kubernetes clusters!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I do work for Tigera so this content will be biased towards&lt;/em&gt; &lt;a href="https://www.tigera.io/project-calico/"&gt;&lt;em&gt;Calico&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, as that’s what I am using.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Scenario
&lt;/h3&gt;

&lt;p&gt;I was still working at Safe Software as a Technical Support Lead for Cloud and Containers when I was interviewing for Tigera. During this time, I coincidentally had my first security support case come in from a user who was using &lt;a href="https://openservicemesh.io/"&gt;Open Service Mesh&lt;/a&gt; (OSM) in their cluster, and &lt;a href="https://fme.safe.com/platform/"&gt;FME Flow&lt;/a&gt; (the product I was supporting) was not working correctly.&lt;/p&gt;

&lt;p&gt;For context, FME Flow is an enterprise tool that lets you automate ETL tasks. In 2019, the traditional installation was adapted for Docker and Kubernetes and the different components of FME Flow were containerized. OSM allows you to manage, secure, and get out-of-the box observability features for highly dynamic microservice environments.&lt;/p&gt;

&lt;p&gt;This was the first time I had to evaluate FME Flow’s pod to pod communication to troubleshoot and reproduce where the communication was breaking down (spoiler alert: OSM had missed a port pool). It was also my first security related question in about 3 years of supporting FME Flow on Kubernetes (excluding customer reported CVEs from image scanning). With my newfound exposure to network policies (thanks Calico), I undertook the challenge of writing policies to control and test communication between FME Flow pods. And while I say challenge, if you are already comfortable with YAML and can plan a sensible roll out of policies (so you can test iteratively) it is not that difficult.&lt;/p&gt;

&lt;p&gt;But first:&lt;/p&gt;

&lt;h3&gt;
  
  
  What are network and security policies for Kubernetes and containers?
&lt;/h3&gt;

&lt;p&gt;In Kubernetes all pods are allowed to communicate with each other by default — it’s a very flat network. If one application has vulnerabilities or has been compromised, then everything else in that cluster is at risk. Network policies can restrict traffic between pods, reducing the risk that if one application is compromised, a bad actor will not be able to travel to other pods within that cluster (also known as&lt;a href="https://www.tigera.io/learn/guides/zero-trust/microsegmentation/"&gt;microsegmentation&lt;/a&gt;). And if you’re thinking that it’s unlikely that &lt;em&gt;your&lt;/em&gt; application will be a target, the concept of&lt;a href="https://www.tigera.io/tigera-products/zero-trust/"&gt;zero trust&lt;/a&gt; can also protect from human error within an organization or social engineering.&lt;/p&gt;

&lt;p&gt;Kubernetes environments are designed to be dynamic and ephemeral. How can you write traditional rules to protect your pods or allow traffic when at any moment they may or may not exist? If a pod or node is scaled, terminated or recreated, can you guarantee your rules will always be targeting the correct pod(s) or node(s) if the IP address has changed?&lt;/p&gt;

&lt;p&gt;The Kubernetes Network Policy API solves that problem by supporting namespaces, label selectors, CIDRs, a few protocols and named port numbers. However, Kubernetes doesn’t enforce these policies itself, and instead delegates these to a Container Network Interface, or CNI (&lt;a href="https://github.com/containernetworking/cni#what-is-cni"&gt;What is CNI?&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Tigera is the creator and maintainer of&lt;a href="https://www.tigera.io/project-calico/"&gt;Calico Open Source&lt;/a&gt;, and because this is where I was interviewing (and now work) I chose this as my CNI.&lt;/p&gt;

&lt;p&gt;Each CNI can add functionality on top of what the Kubernetes default is. As an example, Calico Network Policy supports added features, such as applying policies to any kind of Kubernetes endpoint, ingress and/or egress rules, actions (allow, deny, log, pass) and source and destination match criteria.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating policies
&lt;/h3&gt;

&lt;p&gt;Knowing what ports to allow and between which components of FME Flow was the easy part. For traditional installations there was a list of services and the &lt;a href="https://docs.safe.com/fme/html/FME-Flow/ReferenceManual/FME-Flow-Ports.htm"&gt;ports FME communicates over&lt;/a&gt; so all I had to do was match them up with the right pod.&lt;/p&gt;

&lt;p&gt;Before I show you some of the network policies that I created I want to mention a couple of things.&lt;/p&gt;

&lt;p&gt;If you want to do this for yourself, know that when no network policies are applied to a pod then all traffic is allowed (&lt;a href="https://docs.tigera.io/calico-cloud/network-policy/beginners/kubernetes-default-deny#default-denyallow-behavior"&gt;default allow&lt;/a&gt;). If you apply a policy, then all traffic will be denied to that pod unless specifically allowed.&lt;/p&gt;

&lt;p&gt;This leads into my next point: have a plan for how to test and deploy your policies. If we take FME Flow as an example, which is made up of multiple pods/services that all communicate with each other, you don’t want to start by allowing traffic to your database first and not the UI that the clients will interact with, because you won’t be able to easily test and verify that your policies are working (more on that in a future blog).&lt;/p&gt;

&lt;h3&gt;
  
  
  FME Flow Example
&lt;/h3&gt;

&lt;p&gt;Having worked with FME for 10 years, I’m intimately familiar with how the FME Flow components work and communicate, so I’ll use it as my example here. This could translate to any Kubernetes application with multiple services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B1JnSkP4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AC3JjNdDHRo6Chd0AYyCXHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B1JnSkP4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AC3JjNdDHRo6Chd0AYyCXHg.png" alt="" width="800" height="313"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Kubernetes Architecture Diagram for FME Flow&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As mentioned above, as soon as any policy is applied to a pod then traffic is denied. Knowing that, I always check that my application works correctly before applying any kind of policy. To confirm that policies are being applied I started with a default-deny.yaml policy, denying any ingress or egress traffic to the fmeserver namespace. This stops any communication coming into or out of any pods or endpoints within the fmeserver namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: projectcalico.org/v3 
kind: NetworkPolicy 
metadata: 
  name: default-deny-fmeserver 
  namespace: fmeserver 
spec: 
  order: 100 
  selector: all() 
  types: 
 - Ingress 
 - Egress 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you apply the above policy in your own environment and try to access any component of FME Flow, you won’t be able to. You have to write policies to allow all of the necessary communication.&lt;/p&gt;

&lt;p&gt;I’ll show you the policy that was applied to the queue-fmeserver pod, which is basically a Redis container for the FME Flow job queues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: projectcalico.org/v3 
kind: NetworkPolicy 
metadata: 
  name: queue-fmeserver 
  namespace: fmeserver # NetworkPolicies are namespaced, this is the namespace where the policy will apply 
spec: 
  order: 0 
  selector: statefulset.kubernetes.io/pod-name contains 'queue' # What these rules apply to, in this case the Queue Pod 
  ingress: # inbound traffic
 - action: Allow 
   protocol: TCP 
   source: 
     selector: statefulset.kubernetes.io/pod-name contains 'core' # What source pod(s) are allowed, in this case any traffic from core pods
   destination:  
     ports: [6379] #inbound default Redis port 
  egress: # outbound traffic
 - action: Deny 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the benefits of YAML is that it’s easily readable, so it’s quite easy to see what’s going on here (plus I actually remembered to add comments to my policies).&lt;/p&gt;

&lt;h3&gt;
  
  
  How the policy is constructed:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico/latest/reference/resources/networkpolicy#metadata"&gt;&lt;em&gt;metadata&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.name:&lt;/em&gt; The policy name is crucial, and make sure it’s unique. I cannot confirm nor deny if I’ve accidentally forgotten to change the policy name when copying and pasting and spent too much time troubleshooting why my policies weren’t working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico/latest/reference/resources/networkpolicy#metadata"&gt;&lt;em&gt;metadata&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.namespace:&lt;/em&gt; Make sure the policy applies to the correct namespace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico/latest/reference/resources/networkpolicy#spec"&gt;&lt;em&gt;spec&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.selector:&lt;/em&gt; Make sure the policy is applied to the correct pods by using label selectors. By doing this, if the application scales this policy will apply to all of the correct pods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico/latest/reference/resources/networkpolicy#spec"&gt;&lt;em&gt;spec&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.ingress:&lt;/em&gt; Here you can see the rules allowing traffic into any queue pods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico/latest/reference/resources/networkpolicy#spec"&gt;&lt;em&gt;spec&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.egress:&lt;/em&gt; Here you can see the rules denying traffic out of any queue pods. In this case the queue/Redis pod shouldn’t be initiating communication with any other pod or service, hence egress is denied.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s talk about the FME Engine policy
&lt;/h3&gt;

&lt;p&gt;For another example, here you can see the policy I created for the FME Engine. This is the pod that does all of the data processing. One FME Engine can process one ETL job at a time. However, don’t just copy this policy for your own environment, and I’ll tell you why.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: projectcalico.org/v3 
kind: NetworkPolicy 
metadata: 
  name: engine-fmeserver 
  namespace: fmeserver # NetworkPolicies are namespaced, this is the namespace where the policy will apply 
spec: 
  order: 0 
  selector: safe.k8s.fmeserver.component contains 'engine' # What these rules apply to, in this case the engine pod (fme engine containers) 
  ingress: 
 - action: Allow 
   protocol: TCP 
   source: 
     selector: statefulset.kubernetes.io/pod-name contains 'core' 
   destination:  
     ports: [7500, 7501, '4500:4800'] #https://docs.safe.com/fme/html/FME-Flow/ReferenceManual/FME-Flow-Ports.htm  
  egress: 
 - action: Allow 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My selector for this policy is set to apply to all engine pods. However, in FME you can create multiple&lt;a href="https://docs.safe.com/fme/html/FME-Flow/AdminGuide/Kubernetes/Kubernetes-Defining-FME-Engines-Queue-Control-Properties.htm"&gt;engine deployments with different properties&lt;/a&gt; to enable queue control (so a specific number or subset of engines performs certain jobs). I’ve seen FME Flow users set up different engine deployments for different business processes and systems. If you’re security conscious and serious about zero trust you will want to create multiple engine policies.&lt;/p&gt;

&lt;p&gt;For example, one engine deployment may be configured to only process jobs that are reading/writing data to a file share and a PostGIS database. That engine should only have egress (outbound) access on ports 445 and 5432, and not just “Allow”. I know this _now — _but I didn’t realize the importance of egress two months ago. You can also specify destination IP addresses which may applicable if you’re connecting to resources or services with a static IP.&lt;/p&gt;

&lt;p&gt;Why? If you allow all egress traffic then a bad actor has the potential to exfiltrate your data, communicate with their command and control centre, or continue to traverse you cluster and network and look for more valuable targets. If (in this scenario) someone accesses your engine container they may be able to access your PostGIS instance or your file share, but they have no way of exfiltrating that data (from that pod) because you’ve denied egress traffic except to known and trusted destinations. They’ll have to find another weak link.&lt;/p&gt;

&lt;p&gt;When creating policies, you want to make sure you understand what your services will need to communicate with and create policies with the right&lt;a href="https://docs.tigera.io/calico-enterprise/latest/reference/resources/globalnetworkpolicy#selector"&gt;selectors&lt;/a&gt; and ingress/egress rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why are policies important?
&lt;/h3&gt;

&lt;p&gt;If you are deploying your applications on-premises or on VMs and using firewalls — why aren’t you protecting your Kubernetes applications?&lt;/p&gt;

&lt;p&gt;Securing the perimeter of your network or applications is a good first line of defense but you cannot rely on it alone. By combining security methods, you improve your security posture and reduce the damage if a container or cluster is compromised.&lt;/p&gt;

&lt;p&gt;If you’ve ever played Age of Empires, do you just build a wall around the outside of your base and call it a day? Probably not, unless you lose a lot. You’re likely building defensive units and structures inside your base, protecting valuable assets (monastry? market?), upgrading your castle/towers, and putting archers in them. If you keep getting breached, you’re going to lose resources and units fighting them off which would’ve been better spent on upgrades and attacking.&lt;/p&gt;

&lt;p&gt;However, losing at Age of Empires because your base got destroyed is not going to be as disastrous, expensive, or damaging as getting hacked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrap up
&lt;/h3&gt;

&lt;p&gt;If you’re newer to Kubernetes, container security, or both — I hope this was an informative, introductory read and you feel confident in how you can begin to secure your own Kubernetes workloads with policies and understand why that’s important.&lt;/p&gt;

&lt;p&gt;If you want to improve your security posture I encourage you to check out &lt;a href="https://www.tigera.io/project-calico/"&gt;Project Calico&lt;/a&gt; functionality, or explore our &lt;a href="https://www.tigera.io/tigera-products/compare-products/"&gt;commercial offerings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to try this for yourself, check out the&lt;a href="https://play.instruqt.com/tigera/invite/cgzdhiwnjrsy/tracks/calico-installation-and-best-practices"&gt;Calico installation and best practices lab&lt;/a&gt; (this is what I used before my interview).&lt;/p&gt;

&lt;p&gt;Stay connected with me on &lt;a href="https://medium.com/@mapgirll"&gt;here&lt;/a&gt;, &lt;a href="https://twitter.com/mapgirll"&gt;X&lt;/a&gt;or &lt;a href="https://www.linkedin.com/in/jennifer-luther-thomas-59b79071/"&gt;LinkedIn&lt;/a&gt; (or Steam for a game of AoE4?) for updates about Calico and more introductory security content!&lt;/p&gt;

</description>
      <category>fme</category>
      <category>kubernetes</category>
      <category>calico</category>
      <category>networkpolicy</category>
    </item>
  </channel>
</rss>
