<?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: Serge Logvinov</title>
    <description>The latest articles on DEV Community by Serge Logvinov (@sergelogvinov).</description>
    <link>https://dev.to/sergelogvinov</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%2F2079373%2Fa1e9ae69-13d1-4473-b210-3b72f05e8193.jpg</url>
      <title>DEV Community: Serge Logvinov</title>
      <link>https://dev.to/sergelogvinov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sergelogvinov"/>
    <language>en</language>
    <item>
      <title>Proxmox Virtual Machine optimization - Deep Dive</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Sun, 22 Feb 2026 09:07:23 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/proxmox-virtual-machine-optimization-deep-dive-mn9</link>
      <guid>https://dev.to/sergelogvinov/proxmox-virtual-machine-optimization-deep-dive-mn9</guid>
      <description>&lt;p&gt;In the previous articles, I covered the basic VM settings you should configure by default in Proxmox VE.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/sergelogvinov/proxmox-hugepages-for-vms-1fh3"&gt;Proxmox hugepages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sergelogvinov/proxmox-cpu-affinity-for-vms-4dhb"&gt;Proxmox CPU affinity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, I’ll explain what actually happens under the hood and why proper CPU, NUMA, and interrupt configuration is critical for high-performance workloads - especially if you run latency-sensitive services or Kubernetes worker nodes.&lt;/p&gt;

&lt;h1&gt;
  
  
  CPU Affinity - is not enough
&lt;/h1&gt;

&lt;p&gt;When you configure a CPU affinity list in Proxmox:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The VM is restricted to a predefined set of physical CPU cores.&lt;/li&gt;
&lt;li&gt;All vCPUs are allowed to run on those cores.&lt;/li&gt;
&lt;li&gt;However, the hypervisor scheduler can still move individual vCPUs between the allowed cores.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you allow cores 0-7, then: vCPU-1 may run on core 0 now, then move to core 3, then to core 6.&lt;br&gt;
The VM expects predictable CPU behavior, especially for workloads like databases, networking services, or Kubernetes nodes, which have their own optimizations based on CPU cache and latency. Moving VM CPU cores around can cause unpredictable performance degradation.&lt;/p&gt;

&lt;p&gt;To achieve stable performance, you need to ensure that each vCPU of the VM is pinned to a specific physical CPU core.&lt;br&gt;
Proxmox does not automatically pin each vCPU one-by-one.&lt;/p&gt;

&lt;p&gt;You must configure this explicitly by scripts or automate it — see solution below.&lt;/p&gt;
&lt;h1&gt;
  
  
  Memory Numa nodes - avoid cross-node memory access
&lt;/h1&gt;

&lt;p&gt;Modern servers (CPUs) use NUMA architecture.&lt;/p&gt;

&lt;p&gt;If NUMA is not configured correctly: Proxmox allocate memory across multiple NUMA nodes, and the VM may have to access memory from different NUMA nodes. This results in increased latency and cross-node (socket) memory access, which can significantly degrade performance.&lt;/p&gt;

&lt;p&gt;To avoid this, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;identify which physical cores belong to each NUMA node.&lt;/li&gt;
&lt;li&gt;define VM CPU affinity within a single NUMA node.&lt;/li&gt;
&lt;li&gt;configure VM NUMA settings to match that node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why use only one NUMA node for a VM is the best strategy? Because qemu does not provide a cpu architecture of the host machine by default.&lt;br&gt;
You need to use qemu arguments to pass it.&lt;/p&gt;

&lt;p&gt;In case if you have CPU cores and threads from one numa node - this arguments is enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-cpu 'host,topoext=on,host-cache-info=on' -smp '4,sockets=1,cores=2,threads=2,maxcpus=4'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not forget to set cores and threads according to your VM CPU configuration.&lt;/p&gt;

&lt;h1&gt;
  
  
  SR-IOV devices
&lt;/h1&gt;

&lt;p&gt;Each hardware device uses interrupts to notify the Linux kernel that it has data to process.&lt;br&gt;
If the interrupt is handled by a different CPU core than the one running the VM’s vCPU, several problems may occur:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU cache misses&lt;/li&gt;
&lt;li&gt;cross-core synchronization overhead&lt;/li&gt;
&lt;li&gt;increased memory traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need to set hardware interrupt handling list the same as the CPU affinity list of the VM to solve this problem.&lt;/p&gt;
&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;To automate all of this, I created an open-source component as part of &lt;a href="https://github.com/sergelogvinov/karpenter-provider-proxmox" rel="noopener noreferrer"&gt;Karpenter for Proxmox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Proxmox Scheduler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;observes running VMs&lt;/li&gt;
&lt;li&gt;reads their CPU affinity configuration&lt;/li&gt;
&lt;li&gt;pins each vCPU to a specific host core&lt;/li&gt;
&lt;li&gt;sets correct interrupt affinity for SR-IOV devices&lt;/li&gt;
&lt;li&gt;optionally optimizes CPU frequency governor for power consumption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It distributes as a &lt;code&gt;deb&lt;/code&gt; package and can be installed on the Proxmox host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; https://github.com/sergelogvinov/karpenter-provider-proxmox/releases/download/v0.10.1/proxmox-scheduler_0.10.1_linux_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also optimize power usage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;set CPU governor to performance for cores used by VMs&lt;/li&gt;
&lt;li&gt;set CPU governor to powersave for unused cores&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sergelogvinov/karpenter-provider-proxmox/blob/main/docs/scheduler.md" rel="noopener noreferrer"&gt;https://github.com/sergelogvinov/karpenter-provider-proxmox/blob/main/docs/scheduler.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sergelogvinov/terraform-proxmox-template-nodegroup/blob/main/main.tf#L34" rel="noopener noreferrer"&gt;https://github.com/sergelogvinov/terraform-proxmox-template-nodegroup/blob/main/main.tf#L34&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.proxmox.com/threads/hey-proxmox-community-lets-talk-about-resources-isolation.124256/" rel="noopener noreferrer"&gt;https://forum.proxmox.com/threads/hey-proxmox-community-lets-talk-about-resources-isolation.124256/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>proxmox</category>
      <category>linux</category>
    </item>
    <item>
      <title>Do you need a free-tier to learn Kubernetes?</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Tue, 30 Dec 2025 02:40:59 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/do-you-need-a-free-tier-to-learn-kubernetes-54pg</link>
      <guid>https://dev.to/sergelogvinov/do-you-need-a-free-tier-to-learn-kubernetes-54pg</guid>
      <description>&lt;p&gt;&lt;em&gt;This is my opinion, based on my experience and on job interviews with candidates.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is very important to understand the core components of Kubernetes — what happens when you create a new cluster and what is happening behind the scenes.&lt;br&gt;
This knowledge will help you troubleshoot issues in the future. In such cases, I do not believe ChatGPT can fully help if you do not already understand the fundamentals.&lt;/p&gt;

&lt;p&gt;Pods, Deployments, Services, and other basic components are relatively easy to learn through video courses or ChatGPT explanations.&lt;/p&gt;

&lt;p&gt;Since most Kubernetes clusters run in the cloud, it’s important to understand how Kubernetes communicates with a cloud provider.&lt;br&gt;
Bootstrap your own simple cloud. Proxmox is a good alternative and a vendor lock-in-free solution.&lt;/p&gt;

&lt;p&gt;One Proxmox node is enough to get started, 4 CPUs and 16 GB of RAM are sufficient to run two virtual machines.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one Control-plane node&lt;/li&gt;
&lt;li&gt;one Worker node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will delete and recreate the worker nodes many times. This process will help you understand how the cluster works.&lt;/p&gt;

&lt;p&gt;Use well-known kubernetes distributions like Talos. It is easy to install, and GitHub provides many examples on how to set it up.&lt;br&gt;
Talos has a dedicated distribution for Proxmox, so you can use it without issues by following the official documentation.&lt;/p&gt;

&lt;p&gt;Most kubernetes clusters include components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CCM - cloud controller manager&lt;/li&gt;
&lt;li&gt;CNI - container network interface&lt;/li&gt;
&lt;li&gt;CSI - container storage interface&lt;/li&gt;
&lt;li&gt;Node automation - tools like Cluster Autoscaler or Karpenter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In well-known cloud providers, some components are configured for you by default, such as the CCM and CNI.&lt;br&gt;
All other components usually need to be installed manually.&lt;br&gt;
In a home lab, you need to install all components yourself.&lt;br&gt;
This helps you better understand how Kubernetes works in a cloud environment.&lt;/p&gt;

&lt;p&gt;In a Proxmox installation, all required components already exist on the internet, mainly on GitHub.&lt;br&gt;
Today, self-hosted solutions based on Proxmox can give you almost the same experience as public clouds, while helping you build strong knowledge of core Kubernetes components.&lt;br&gt;
After that, switching to a public cloud will be much easier for you.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install Proxmox CCM, Proxmox CSI, and Karpenter. The CNI is already included in the Talos distribution.&lt;br&gt;
Do everything manually. Write down all the steps and save them in your GitHub repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Play with your cluster, break things and fix them again.&lt;br&gt;
Deploy simple applications, scale them up and down, and monitor resource usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try to automate the installation using Terraform.&lt;br&gt;
Save the code in your GitHub repository and create step-by-step instructions explaining how to deploy it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then use GitOps best practices to manage your cluster with Argo CD or Flux CD.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just remember, all these steps already exist on the internet. You can search for them on Google or ask ChatGPT.&lt;/p&gt;

&lt;p&gt;This experience will give you strong advantages in future job interviews, even if the company uses a different cloud provider.&lt;br&gt;
Do not forget to mention that you have your own home lab and share links to your GitHub repositories.&lt;/p&gt;

&lt;p&gt;The certificates show only that you know the right answers, but your home lab shows that you can more than that.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>proxmox</category>
      <category>devops</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud: Talos network</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Tue, 14 Jan 2025 12:08:29 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-talos-network-51lo</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-talos-network-51lo</guid>
      <description>&lt;p&gt;The network management is an important part of a Kubernetes cluster, especially in hybrid and multi-cloud environments. The stability and predictability of the network are very important for the applications running on the cluster. The network is usually more stable in one physical location than in a cross-cloud environment.&lt;/p&gt;

&lt;p&gt;The basic components can impact the stability of the application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS resolving&lt;/li&gt;
&lt;li&gt;Network stability&lt;/li&gt;
&lt;li&gt;Network latency&lt;/li&gt;
&lt;li&gt;Network bandwidth&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  DNS resolving
&lt;/h1&gt;

&lt;p&gt;The application needs to resolve DNS names to IP addresses. By default, a Kubernetes cluster uses CoreDNS as its DNS server. CoreDNS is deployed as a Kubernetes deployment and can be scaled up or down. However, if the CoreDNS pods are very far from the application pod, latency may increase, and DNS names might fail to resolve.&lt;/p&gt;

&lt;p&gt;To solve this issue, use a DaemonSet to deploy CoreDNS on each node. Additionally, set the TrafficPolicy for the CoreDNS service to Local &lt;a href="https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-service-traffic-topology-and-routing-3gle"&gt;Service traffic topology and routing&lt;/a&gt;. The DNS traffic will stay within the node, keeping the latency very low.&lt;/p&gt;

&lt;h1&gt;
  
  
  Network stability
&lt;/h1&gt;

&lt;p&gt;For kubelet and kube-proxy, network stability is crucial. These components communicate with the Kubernetes API server to configure the network and run the pods. The kubelet also updates the status of the pods and node. If the status is not updated regularly, the Kubernetes API can mark the node as unhealthy, and the pods may be rescheduled to another node.&lt;/p&gt;

&lt;p&gt;Imagine a situation where the pods and network are working fine, but the kubelet loses connection to the API server (for example, if the Kubernetes API load balancer goes down). Kubernetes will create new copies of the pods on another node, and the old pods will be terminated once the kubelet reconnects to the API server. For stateless applications, this behavior is usually not a problem. However, for stateful applications, like databases, it can cause significant issues.&lt;/p&gt;

&lt;p&gt;Talos solves this problem by using an embedded load balancer on each node. The kubelet and kube-proxy (or CNI plugins) connect to the local load balancer, which forwards traffic to the API server. This ensures consistent connectivity and helps avoid unnecessary disruptions caused by API server load balancer failures.&lt;/p&gt;

&lt;p&gt;You can switch it on by setting in machine configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;features&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubePrism&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7445&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this config, the Kubernetes API server becomes accessible on port 7445 on each node using the local host address.&lt;/p&gt;

&lt;h1&gt;
  
  
  Network latency and bandwidth
&lt;/h1&gt;

&lt;p&gt;The best way to reduce network latency is to use native network routing. However, in hybrid and multi-cloud environments, this is not possible. The CNI (Container Network Interface) provides network overlays to address this issue, using technologies like VXLAN, GRE, or WireGuard. In all these cases, the network overlay adds an additional header to the packets, increasing network latency and reducing network bandwidth.&lt;/p&gt;

&lt;p&gt;Talos includes an embedded network mesh based on WireGuard, a fast and secure VPN protocol that encrypts traffic between nodes. Regardless of where the nodes are located or whether they are behind NAT, the nodes can communicate with each other seamlessly.&lt;/p&gt;

&lt;p&gt;However, since this mesh is an additional component in the network stack, it can introduce latency and some instability. The recovery process in case of issues can be slow and may take a long time.&lt;/p&gt;

&lt;p&gt;The network mesh can be enabled in the machine configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubespan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;cluster&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;discovery&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To reduce the recovery time, you can set filters to limit the IP addresses that can be used to create the tunnels. By specifying these filters, you can ensure that the network mesh uses only specific IP in ranges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubespan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;::/0'&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;!192.168.0.0/16'&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;!172.16.0.0/12'&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;!10.0.0.0/8'&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;!fd00::/8'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or opposite case. If you have both public and private networks and want to use only the private network for the mesh (because the public network is slower and more expensive), you can configure the network mesh to exclusively use the private network.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kubespan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.0.0/16'&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;172.16.0.0/12'&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;10.0.0.0/8'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to establish a mesh network only between datacenters while using the native network for communication between nodes within each datacenter, consider using &lt;a href="https://kilo.squat.ai/" rel="noopener noreferrer"&gt;kilo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kilo can deploy as CNI plugin that creates a WireGuard-based mesh network across Kubernetes zones, region and datacenters. It allows efficient and secure connectivity between nodes in different datacenters while maintaining native networking within each datacenter. This hybrid approach can optimize performance by reducing latency and overhead for intra-datacenter traffic while ensuring secure and reliable communication between datacenters.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cloud</category>
      <category>hubridcloud</category>
      <category>network</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud: Bare-metal or Hypervisor</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Sun, 12 Jan 2025 08:22:31 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-bare-metal-or-hypervisor-a0p</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-bare-metal-or-hypervisor-a0p</guid>
      <description>&lt;p&gt;It is a very popular question: What is the best choice to deploy a Kubernetes node - directly on bare metal or by setting up a hypervisor first and then deploying the Kubernetes node on VMs? There is no single correct answer: it depends on your requirements and the power of your hardware.&lt;/p&gt;

&lt;p&gt;Let's compare both solutions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bare-metal installation
&lt;/h1&gt;

&lt;p&gt;If you have a small bare-metal server with 32 cores (or less) and 64-128 GB of RAM, the best choice is to install the Kubernetes node directly on the server. By default, the kubelet has a limitation of 110 pods on the node. If your workload requires a larger number of pods with small resource requirements, you need to think about adjusting the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allocate the subnet which has more then 256 IPs (by default subnet is /24 and it has 256 IPs)&lt;/li&gt;
&lt;li&gt;Reserving more resources for kubelet, each pod requires extra resources for kubelet&lt;/li&gt;
&lt;li&gt;Adjusting secrets/config maps sync period&lt;/li&gt;
&lt;li&gt;Check the NUMA and L3 cache architecture on the server&lt;/li&gt;
&lt;li&gt;Run special daemonsets to manage power, monitoring hardware, and other features&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Hypervisor installation
&lt;/h1&gt;

&lt;p&gt;Imagine you have a powerful server with 128 cores and 512 GB of RAM or more. You deploy a Kubernetes node on this server. During maintenance, you lose all the server's capacity. But if you use a hypervisor, you can create virtual machines (VMs) and maintain them one by one, and keep the rest of the VMs running. Also, the Linux kernel and applications are not designed to work efficiently with such a large amount of RAM and CPU cores. The kernel spends time managing TLB, NUMA, and other CPU features. Splitting the server into VMs can help solve many of these problems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each VM will use a separate NUMA node and Memory, L3 cache, see &lt;a href="https://dev.to/sergelogvinov/proxmox-cpu-affinity-for-vms-4dhb"&gt;CPU Affinity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You can maintain the VMs separately and do not lose the whole server capacity during maintenance, hypervisor kernel usually does nothing and work pritty stable. Restart whole server is not required so often&lt;/li&gt;
&lt;li&gt;You can use the hypervisor features like snapshots, dynamic disk attachment and resizing&lt;/li&gt;
&lt;li&gt;Kubernetes resources isolation, you can deploy different workloads on different VMs&lt;/li&gt;
&lt;li&gt;Simplified node management, add or remove the kubernetes node becomes easier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The very famous open-source hypervisors are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.proxmox.com/en/products/proxmox-virtual-environment/overview" rel="noopener noreferrer"&gt;Proxmox VE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cloud-hypervisor/cloud-hypervisor" rel="noopener noreferrer"&gt;Cloud-hypervisor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Proxmox as your hypervisor for Kubernetes can provide a cloud-like experience similar to well-known cloud providers, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic disk attachment, resizing (PV, PVC)&lt;/li&gt;
&lt;li&gt;Network load balancing, firewall, and other features&lt;/li&gt;
&lt;li&gt;Cluster bootstrapping by terraform&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>cloud</category>
      <category>hybridcloud</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud: Persistent storages</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Sat, 11 Jan 2025 07:07:24 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-persistent-storages-4c0o</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-persistent-storages-4c0o</guid>
      <description>&lt;p&gt;Persistent storage is a key component of any production-grade Kubernetes deployment.&lt;/p&gt;

&lt;p&gt;It is very challenging to rely on just one storage solution for all Kubernetes nodes, especially in hybrid cloud environments. In such cases, we can group the nodes based on their cloud or hypervisor type and use the storage solution that works best for each group. For example, one group of nodes might use a cloud provider's managed storage, while another might rely on local or on-premises storage.&lt;/p&gt;

&lt;p&gt;However, many Kubernetes resources or operators are not designed to work seamlessly with multiple types of storage classes. For example, the StatefulSet resource requires a single type of PersistentVolumeClaim (PVC) template to create PVCs during the scale-up process. This means all PVCs created by the StatefulSet will use the same storage class as defined in the template. Once the PVC is created, changing the storage class is not straightforward (technically, it is possible, but it involves a complex process and risks downtime).&lt;/p&gt;

&lt;h1&gt;
  
  
  Statefulset and Persistent Volume Claim
&lt;/h1&gt;

&lt;p&gt;How to use different storage classes for one statefulset?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;StatefulSet&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;volumeClaimTemplates&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;storage&lt;/span&gt;
      &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;accessModes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReadWriteOnce"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&gt;
        &lt;span class="na"&gt;storageClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;storage-class-1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's assume we have two storage classes: &lt;code&gt;storage-class-1&lt;/code&gt; and &lt;code&gt;storage-class-2&lt;/code&gt;. We want to have the first pod to use &lt;code&gt;storage-class-1&lt;/code&gt; and the second pod to use &lt;code&gt;storage-class-2&lt;/code&gt; in one statefulSet deployment.&lt;/p&gt;

&lt;p&gt;By default, all PersistentVolumeClaims (PVCs) created by the StatefulSet will use &lt;code&gt;storage-class-1&lt;/code&gt; if it is specified in the PVC template. To assign &lt;code&gt;storage-class-2&lt;/code&gt; to the second pod, we need to manually create a PVC with &lt;code&gt;storage-class-2&lt;/code&gt; before scaling up the StatefulSet. After creating this PVC, we can scale up the StatefulSet, and the second pod will automatically use the pre-created PVC with &lt;code&gt;storage-class-2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, it is possible to permanently change the storage class of PVCs after the StatefulSet has been created. However, this process is not straightforward and typically involves detaching the workload, editing the PVCs, and carefully managing the transition to avoid downtime.&lt;/p&gt;

&lt;p&gt;How we can change the storage class of the statefulSet without downtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Delete the statefulSet resources without deleting the pods&lt;/span&gt;
kubectl delete statefulset &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--cascade&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orphan
&lt;span class="c"&gt;# Change the storage class in statefulset yaml, apply it and scale up the statefulSet&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; statefulset.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flag &lt;code&gt;--cascade=orphan&lt;/code&gt; is very important because it will not delete the pods, and workloads will not be interrupted. After applying the new statefulSet, the new pods will be created with the new storage class.&lt;/p&gt;

&lt;h1&gt;
  
  
  Operator and Persistent Volume Claim
&lt;/h1&gt;

&lt;p&gt;Using an operator, we can also configure different storage classes, similar to what we did with the StatefulSet. However, there is an additional step involved when working with operators. Before making any changes to the storage classes, we need to scale down the operator. This is because the operator continuously manages and reconciles the resources it controls, and it may revert any manual changes we make to align with its predefined configurations.&lt;/p&gt;

&lt;p&gt;Once the operator is scaled down, we can manually create or modify the PVCs to use different storage classes. After completing the changes, we can safely scale the operator back up to resume its management tasks.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dynamic Persistent Volume Claim
&lt;/h1&gt;

&lt;p&gt;All of the above solutions have a major drawback: they require us to know the exact name of the PVC that will be created by the StatefulSet or the operator. This can make the process hard and error-prone, especially in dynamic or large-scale environments.&lt;/p&gt;

&lt;p&gt;A better way to solve this problem is to use a universal, dynamic approach for PVC creation. One solution is to leverage a special StorageClass resource. With this method, Kubernetes can automatically create PVCs and PVs with the appropriate storage class based on the cloud environment or node type. This approach removes the need for manual intervention or pre-defining PVC names and simplifies storage management in hybrid or multi-cloud environments. It ensures that storage provisioning is both seamless and adaptable to the underlying infrastructure.&lt;/p&gt;

&lt;p&gt;This solution is already available with the &lt;a href="https://github.com/sergelogvinov/hybrid-csi-plugin" rel="noopener noreferrer"&gt;Hybrid CSI&lt;/a&gt;. The Hybrid CSI plugin acts as a proxy between Kubernetes and existing CSI plugins. It does not have its own storage implementation or any specific knowledge of cloud providers. Instead, it forwards PVC creation requests to the appropriate CSI plugin during the PVC creation process.&lt;/p&gt;

&lt;p&gt;With the Hybrid CSI plugin, you can configure priorities for different types of CSI plugins. During PVC provisioning, the Hybrid CSI plugin will select and use the first available plugin based on the defined priorities. This makes it an efficient and flexible solution for managing storage across diverse environments without needing to hard-code storage configurations or manage complex PVC naming schemes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;storage.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;StorageClass&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hybrid&lt;/span&gt;
&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;storageClasses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;proxmox,hcloud-volumes&lt;/span&gt;
&lt;span class="na"&gt;provisioner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;csi.hybrid.sinextra.dev&lt;/span&gt;
&lt;span class="na"&gt;allowVolumeExpansion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;reclaimPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Delete&lt;/span&gt;
&lt;span class="na"&gt;volumeBindingMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;WaitForFirstConsumer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have a StorageClass named hybrid, which combines two underlying storage classes: proxmox and hcloud-volumes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;proxmox&lt;/code&gt; storage class is used for the Proxmox hypervisor.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;hcloud-volumes&lt;/code&gt; storage class is designed for the Hetzner Cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a pod is deployed, the Hybrid CSI plugin determines the underlying environment where the pod is running. If the pod is running on a Proxmox hypervisor, the plugin forwards the PVC creation request to the proxmox storage plugin. Conversely, if the pod is running on Hetzner Cloud, the plugin uses the Hcloud CSI plugin to handle the PVC creation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Example
&lt;/h1&gt;

&lt;p&gt;So we've deployed the statefulSet with the &lt;code&gt;hybrid&lt;/code&gt; storage class with two replicas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; default get pods,pvc
NAME         READY   STATUS    RESTARTS   AGE
pod/test-0   1/1     Running   0          31s
pod/test-1   1/1     Running   0          31s

NAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/storage-test-0   Bound    pvc-64440564-75e9-4926-82ef-280f412b11ee   1Gi        RWO            hybrid         &amp;lt;&lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                 32s
persistentvolumeclaim/storage-test-1   Bound    pvc-811cc51e-9c9f-4476-92e1-37382b175e7f   10Gi       RWO            hybrid         &amp;lt;&lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                 32s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deploying the StatefulSet, we can see that the PersistentVolumes (PVs) were created using the &lt;code&gt;proxmox&lt;/code&gt; and &lt;code&gt;hcloud-volumes&lt;/code&gt; storage classes. They have different sizes, because the Hetzner Cloud has a minimum size of 10Gi, proxmox has a less than 1Gi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; default get pv pvc-64440564-75e9-4926-82ef-280f412b11ee pvc-811cc51e-9c9f-4476-92e1-37382b175e7f
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS     VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-64440564-75e9-4926-82ef-280f412b11ee   1Gi        RWO            Delete           Bound    default/storage-test-0   proxmox          &amp;lt;&lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                          84s
pvc-811cc51e-9c9f-4476-92e1-37382b175e7f   10Gi       RWO            Delete           Bound    default/storage-test-1   hcloud-volumes   &amp;lt;&lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                          81s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The Hybrid CSI plugin is an excellent solution for hybrid cloud environments. It enables you to use different storage classes for different nodes without needing to modify StatefulSet or operator resources. The plugin simplifies storage management by dynamically forwarding PVC creation requests to the appropriate storage class based on the underlying infrastructure.&lt;/p&gt;

&lt;p&gt;This plugin is easy to use and requires no additional configuration once set up. You can even configure it as the default storage class for all your deployments, allowing you to manage storage seamlessly without worrying about specifying or switching between storage classes. This makes it a powerful and flexible tool for modern hybrid cloud Kubernetes deployments.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sergelogvinov/hybrid-csi-plugin" rel="noopener noreferrer"&gt;Hybrid CSI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/" rel="noopener noreferrer"&gt;StatefulSet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/storage/storage-classes/" rel="noopener noreferrer"&gt;StorageClass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" rel="noopener noreferrer"&gt;Persistent Volume Claim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>hybridcloud</category>
      <category>multicloud</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud: Network design</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Mon, 30 Dec 2024 11:35:58 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-network-design-3m9f</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-network-design-3m9f</guid>
      <description>&lt;p&gt;In hybrid cloud environments, network design is one of the most important and fundamental parts. It is a basic requirement for any type of Kubernetes cluster, whether it is a single-zone cluster or a multi-regional cluster. In this article, we will explain how to design a network for a hybrid cloud Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;Key Considerations for Network Design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure reliable and secure connections between on-premises and cloud data centers.&lt;/li&gt;
&lt;li&gt;Optimize network latency&lt;/li&gt;
&lt;li&gt;Plan IP address ranges to avoid conflicts between data centers&lt;/li&gt;
&lt;li&gt;Use firewalls to control traffic between networks&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Communication inside the cluster
&lt;/h1&gt;

&lt;p&gt;Node-to-node:&lt;/p&gt;

&lt;p&gt;All nodes in the cluster must have connectivity to each other. Control plane nodes must have access to the kubelet on each node. Nodes must have access to the control plane nodes. If you going to use Kubernetes Admission Controllers, the control plane need access to the pods too.&lt;/p&gt;

&lt;p&gt;Pod-to-pod:&lt;/p&gt;

&lt;p&gt;Pods must have access to the control plane nodes to reach the Kubernetes API. Monitoring systems must have access to all nodes to collect metrics and logs. Pods must be able to communicate with other pods within the same cluster. In many cases, pods also need access to the internet and cloud provider services. The latency between nodes, zones, and regions is a crucial factor. Application deployments should be aware of the network topology to optimize performance.  Furthermore, when regions are located in different cloud providers, communication can become unstable and slower. Proper planning and optimization are required to address these challenges.&lt;/p&gt;

&lt;p&gt;In summary, all pods and nodes must have connectivity with each other. A hybrid Kubernetes cluster has multiple zones and regions, adding more complexity to network design.&lt;/p&gt;

&lt;h1&gt;
  
  
  Network design
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Hardware or Saas VPN
&lt;/h2&gt;

&lt;p&gt;The well-known cloud providers offer VPN services. VPN links can be established between zones and regions, enabling secure and stable connections across different geographical locations. VPN connections can be hardware-based or software-based, depending on the infrastructure requirements. VPN helps in maintaining data security and encryption during transmission.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fxsyz9wges9d15kwx4r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fxsyz9wges9d15kwx4r.png" alt="Image description" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The red line represents the VPN connection between cloud providers. The VPN connection is encrypted and secure. However, this link uses public internet connections, which can sometimes be less reliable and have unstable bandwidth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Direct Connect
&lt;/h2&gt;

&lt;p&gt;Direct Connect is a dedicated network connection service provided by major cloud providers (e.g., AWS Direct Connect, Azure ExpressRoute, Google Cloud Interconnect). It allows organizations to establish a private, high-bandwidth connection between their the cloud provider's infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flchd1chj73acng9ukl38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flchd1chj73acng9ukl38.png" alt="Image description" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The latency between cloud providers is very low, and bandwidth is predictable. This link uses dedicated fiber optic cables, which are more reliable than the public internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mesh network
&lt;/h2&gt;

&lt;p&gt;A mesh network is a network topology where each node establishes a connection with every other node. Unlike traditional hierarchical networks, mesh networks are decentralized, allowing every node to cooperate in data distribution and routing. All connections are encrypted and secure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foh8su3zabt0ld4ix8auo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foh8su3zabt0ld4ix8auo.png" alt="Image description" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Known mesh solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://talos.dev" rel="noopener noreferrer"&gt;Talos Kubespan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cilium/cilium" rel="noopener noreferrer"&gt;Cilium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/istio" rel="noopener noreferrer"&gt;Istio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/linkerd/linkerd2" rel="noopener noreferrer"&gt;Linkerd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/squat/kilo" rel="noopener noreferrer"&gt;Kilo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tailscale/tailscale" rel="noopener noreferrer"&gt;TailScale&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Public IPv6 for Pods and Services
&lt;/h1&gt;

&lt;p&gt;A Kubernetes cluster supports IPv6 for both Pods and Services, allowing seamless communication across regions without requiring any special configuration for cross-region traffic. This native IPv6 support simplifies networking and ensures scalability for modern cloud-native workloads.&lt;/p&gt;

&lt;p&gt;However, enabling IPv6 alone is not enough to guarantee a secure communication environment. Ensure that your applications uses mutual TLS (mTLS) or other security mechanisms to protect data in transit.&lt;/p&gt;

&lt;p&gt;See more details &lt;a href="https://dev.to/sergelogvinov/kubernetes-pods-with-global-ipv6-1aaj"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that not all cloud providers fully support IPv6 for Kubernetes Pods and Services. Check with your cloud provider for the latest information on IPv6 support.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>hybridcloud</category>
    </item>
    <item>
      <title>Talos on GCP with Spot Instances</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Sat, 28 Dec 2024 12:35:37 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/talos-on-gcp-with-spot-instances-4iln</link>
      <guid>https://dev.to/sergelogvinov/talos-on-gcp-with-spot-instances-4iln</guid>
      <description>&lt;p&gt;Using Spot Instances on Google Cloud Platform (GCP) is an excellent way to reduce infrastructure costs. This guide explains how to run Talos on GCP with Spot Instances effectively.&lt;/p&gt;

&lt;p&gt;One unique behavior of GCP Spot Instances is that they lose their IP address when they are preempted (stopped by Google). Most Container Network Interfaces (CNI) can handle this and update the node's IP address. However, if you're using IPv6 for your Pods, the CNI cannot update the CIDR (IP range) resources assigned to the node. This means that after preemption, you cannot run Pods on that node with proper IPv6 addresses.&lt;/p&gt;

&lt;p&gt;This guide explains how to work around this issue and run Talos on GCP with Spot Instances effectively.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configurations
&lt;/h1&gt;

&lt;p&gt;Talos Cloud Controller Manager (CCM) is designed to work across different environments, including Google Cloud Platform (GCP). It can handle IP address changes when a node is preempted. To enable this functionality, you need to activate the &lt;code&gt;cloud-node-lifecycle&lt;/code&gt; controller in your Talos configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Helm values for Talos CCM&lt;/span&gt;
&lt;span class="na"&gt;enabledControllers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cloud-node&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cloud-node-lifecycle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How It Works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Talos CCM watches for node eviction events.&lt;/li&gt;
&lt;li&gt;When a node is preempted, Talos CCM removes the node's resources from the cluster.&lt;/li&gt;
&lt;li&gt;When the node starts again, Talos CCM adds the updated node resources back to the cluster.&lt;/li&gt;
&lt;li&gt;For the CNI plugin, it will appear as if the node was replaced with a new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, Talos CCM marks Spot Instances with the label:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;node.cloudprovider.kubernetes.io/lifecycle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;spot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use this label to schedule your Pods based on your specific requirements.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Running Talos on any cloud provider with Talos Cloud Controller Manager (CCM) is an excellent way to manage your Kubernetes cluster efficiently. Talos CCM can handle IP address changes when a node is preempted and helps you effectively manage Spot Instances for better resource optimization and cost savings.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://talos.dev" rel="noopener noreferrer"&gt;Talos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/siderolabs/talos-cloud-controller-manager" rel="noopener noreferrer"&gt;Talos CCM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sergelogvinov/kubernetes-pods-with-global-ipv6-1aaj"&gt;Public IPv6 for Pods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>cloud</category>
      <category>gcp</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud: Talos Cloud Controller Manager (CCM)</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Fri, 27 Dec 2024 12:34:40 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-talos-cloud-controller-manager-ccm-5bm7</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-talos-cloud-controller-manager-ccm-5bm7</guid>
      <description>&lt;p&gt;&lt;a href="https://talos.dev" rel="noopener noreferrer"&gt;Talos&lt;/a&gt; is a modern operating system designed specifically for Kubernetes. It supports various cloud providers, including AWS, Azure, Google Cloud, OpenStack, and on-premises environments. Talos focuses on security, simplicity, and ease of use. Because Talos nodes are aware of the cloud environment they are running in, the concept of Talos Cloud Controller Manager (CCM) was created&lt;/p&gt;

&lt;p&gt;The Talos Cloud Controller Manager (CCM) is built to work effectively in hybrid cloud environments. It collects information from Talos nodes and provides an easy and secure way to manage the lifecycle of Kubernetes nodes in the cluster.&lt;/p&gt;

&lt;p&gt;The components of Talos CCM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cloud-node&lt;/code&gt;: is responsible for initializing and managing new nodes when they join a cluster.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cloud-node-lifecycle&lt;/code&gt;: Talos CCM does not have any credentials to make a call to the API of the cloud provider. What is why this component is not supported. You need to run native CCM from the cloud provider only with &lt;code&gt;cloud-node-lifecycle&lt;/code&gt; component, all other components should be disabled.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node-route-controller&lt;/code&gt;: Not supported.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;service-lb-controller&lt;/code&gt;: Not supported.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node-ipam-controller&lt;/code&gt;: Manages IP addresses for the Pods in the cluster.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node-csr-approval&lt;/code&gt;: Approves the certificate requests from the nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Controller cloud-node
&lt;/h1&gt;

&lt;p&gt;The cloud-node component is responsible for initializing and managing new nodes when they join a cluster. It performs tasks like: registering and attaching nodes to the Kubernetes cluster, adding important labels, and preparing the node for workloads.&lt;/p&gt;

&lt;p&gt;The important labels for hybrid environments are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;topology.kubernetes.io/region&lt;/code&gt; specifies the region of the node&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;topology.kubernetes.io/zone&lt;/code&gt; specifies the availability zone&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node.kubernetes.io/instance-type&lt;/code&gt; specifies the instance type of the node&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node.cloudprovider.kubernetes.io/platform&lt;/code&gt; specifies the cloud platform where the node is running&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These labels are essential for Kubernetes to place workloads (Pods) on the correct nodes based on regional and infrastructure requirements.&lt;/p&gt;

&lt;p&gt;In bare-metal environments or environments not recognized by Talos, you can predefine rules for the Cloud Controller Manager. These rules act as a configuration blueprint and are applied to nodes based on their metadata. &lt;a href="https://github.com/siderolabs/talos-cloud-controller-manager/blob/main/docs/config.md" rel="noopener noreferrer"&gt;Official documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;transformations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# All rules are applied in order, all matched rules are applied to the node&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nocloud-nodes&lt;/span&gt;
    &lt;span class="c1"&gt;# Match nodes by nodeSelector&lt;/span&gt;
    &lt;span class="na"&gt;nodeSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;matchExpressions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform           &amp;lt;- talos platform metadata variable case insensitive&lt;/span&gt;
            &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;In            &amp;lt;- In, NotIn, Exists, DoesNotExist, Gt, Lt, Regexp&lt;/span&gt;
            &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                 &lt;span class="s"&gt;&amp;lt;- array of string values&lt;/span&gt;
              &lt;span class="s"&gt;- nocloud&lt;/span&gt;
    &lt;span class="c1"&gt;# Set labels for matched nodes&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;pvc-storage-class/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-storage-class"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web-nodes                 &amp;lt;- transformation name, optional&lt;/span&gt;
    &lt;span class="na"&gt;nodeSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Or condition for nodeSelector&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;matchExpressions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# And condition for matchExpressions&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform           &amp;lt;- talos platform metadata variable case insensitive&lt;/span&gt;
            &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;In            &amp;lt;- In, NotIn, Exists, DoesNotExist, Gt, Lt, Regexp&lt;/span&gt;
            &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                 &lt;span class="s"&gt;&amp;lt;- array of string values&lt;/span&gt;
              &lt;span class="s"&gt;- metal&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hostname&lt;/span&gt;
            &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Regexp&lt;/span&gt;
            &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;^web-[\w]+$         &amp;lt;- go regexp pattern&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Add label to the node, in this case, we add well-known node role label&lt;/span&gt;
      &lt;span class="na"&gt;node-role.kubernetes.io/web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first rule applies to nodes on &lt;code&gt;nocloud&lt;/code&gt; platform environment, such as Proxmox or Oxide. It sets the &lt;code&gt;pvc-storage-class/name&lt;/code&gt; label to node.&lt;br&gt;
The second rule for &lt;code&gt;metal&lt;/code&gt; platform with hostnames starting with &lt;code&gt;web-&lt;/code&gt;. It sets the &lt;code&gt;node-role.kubernetes.io/web&lt;/code&gt; label, which means the node role.&lt;/p&gt;

&lt;h1&gt;
  
  
  Controller cloud-node-lifecycle
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;cloud-node-lifecycle&lt;/code&gt; component plays a crucial role in managing the lifecycle of Kubernetes nodes by interacting with the cloud provider's API. Its main responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying if a virtual machine (instance) is still running in the cloud provider's infrastructure.&lt;/li&gt;
&lt;li&gt;Ensuring the node is still registered and valid within the cloud environment.&lt;/li&gt;
&lt;li&gt;Monitoring the overall health and status of the node from the cloud provider's perspective.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, Talos CCM does not have credentials to access cloud provider APIs. To manage the &lt;code&gt;cloud-node-lifecycle&lt;/code&gt; functionality, you need to run the native CCM provided by your cloud provider. You can run as many CCMs as you have cloud environments in cloud-node-lifecycle mode with simple changes in the code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Controller node-route-controller
&lt;/h1&gt;

&lt;p&gt;Not supported.&lt;/p&gt;

&lt;h1&gt;
  
  
  Controller service-lb-controller
&lt;/h1&gt;

&lt;p&gt;Not supported.&lt;/p&gt;

&lt;h1&gt;
  
  
  Controller node-ipam-controller
&lt;/h1&gt;

&lt;p&gt;This controller makes sense only if you want to have global IPv6 addresses for your Pods. Kubernetes already supports IPv6 for Pods, but only within a single segment. Talos CCM can handle as many segments as you have nodes. The controller allocates an IPv6 segment from the node's range and assigns it to each Pod. See mode detailed example &lt;a href="https://dev.to/sergelogvinov/kubernetes-pods-with-global-ipv6-1aaj"&gt;Kubernetes PODs with global IPv6&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Controller node-csr-approval
&lt;/h1&gt;

&lt;p&gt;The Kubernetes API server must communicate with the Kubelet API to retrieve logs, metrics, and other node-level information. This communication happens over a secure channel, and the Kubelet API is protected by a TLS certificate. By default, when a Kubelet starts, it generates a self-signed certificate to enable TLS communication. However, the Kubernetes API server cannot inherently trust this self-signed certificate because there’s no verification from a Certificate Authority (CA).&lt;/p&gt;

&lt;p&gt;To address this issue, Kubernetes uses the &lt;code&gt;node-csr-approval&lt;/code&gt; controller, which is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a node starts, the Kubelet generates a Certificate Signing Request (CSR) and submits it to the Kubernetes API server.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;node-csr-approval&lt;/code&gt; controller validates the CSR to ensure it meets the security and policy requirements.&lt;/li&gt;
&lt;li&gt;If the CSR is valid, the controller approves it, and the Kubernetes Certificate Authority (CA) signs the certificate.&lt;/li&gt;
&lt;li&gt;The signed certificate is sent back to the Kubelet for use in secure communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Whether you're running Talos in a hybrid cloud environment or in an on-premises setup, Talos CCM is an essential tool for managing your Kubernetes cluster efficiently.&lt;/p&gt;

&lt;p&gt;Talos CCM simplifies and streamlines the lifecycle management of nodes, automating key processes such as node initialization, labeling, and certificate management. It ensures that every node in your cluster is properly registered, labeled, and ready to serve workloads in a secure and consistent way.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;hybrid cloud deployments&lt;/code&gt;, Talos CCM makes it easier to integrate nodes across different environments, ensuring smooth communication and consistent behavior across the cluster, regardless of where your nodes are hosted. By handling these tasks automatically, Talos CCM reduces operational complexity, minimizes human error, and saves time for administrators. In short:&lt;/p&gt;

&lt;p&gt;If you're using Talos, using Talos CCM isn't just an option—it's a best practice.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-cloud-controller-manager-ccm-jdn"&gt;What is CCM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://talos.dev" rel="noopener noreferrer"&gt;Talos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/siderolabs/talos-cloud-controller-manager" rel="noopener noreferrer"&gt;Talos Cloud Controller Manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sergelogvinov/gitops-examples" rel="noopener noreferrer"&gt;Deploy CCMs in one cluster example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>hybridcloud</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud: Cloud Controller Manager (CCM)</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Thu, 26 Dec 2024 08:47:38 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-cloud-controller-manager-ccm-jdn</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-cloud-controller-manager-ccm-jdn</guid>
      <description>&lt;p&gt;Almost all Kubernetes services have cloud integration. You might not even know you're using it. For example, when you create a LoadBalancer service, Kubernetes will automatically create a cloud load balancer on the cloud provider's side for you. This is a great feature because you don’t need to worry about the cloud provider's API or how to set up an external load balancer.&lt;/p&gt;

&lt;p&gt;In a self-hosted Kubernetes cluster or a hybrid cloud environment, you need to deploy a Cloud Controller Manager (CCM) to enable cloud integration. The CCM is a Kubernetes component that communicates with the cloud provider's API to create and manage cloud resources. It serves as a bridge between Kubernetes and the cloud provider, allowing you to use features such as load balancers, block storage, and network routing.&lt;/p&gt;

&lt;p&gt;Here's what each key component of CCM does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cloud-node&lt;/strong&gt;: Initializes new nodes during the scale-up process. It ensures nodes are correctly registered in the cluster with the necessary cloud-specific metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cloud-node-lifecycle&lt;/strong&gt;: Removes nodes from the cluster during the scale-down process. It detects and handles unhealthy or deleted nodes based on information from the cloud provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;node-route-controller&lt;/strong&gt;: Creates and manages routes inside the cloud provider's network. It ensures nodes can communicate with each other across the cloud infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;service-lb-controller&lt;/strong&gt;: Creates and manages external load balancers for LoadBalancer type services in Kubernetes. It ensures external traffic can reach the appropriate pods through cloud-managed load balancers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Controllers cloud-node and cloud-node-lifecycle
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;cloud-node&lt;/code&gt; controller is responsible for initializing new nodes in the cluster. When a new node is added to the cluster, either by an auto-scaler or manually, the cloud-node controller communicates with the cloud provider's API to register and attach the node to the cluster. It also adds labels and taints to the node, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;topology.kubernetes.io/region&lt;/li&gt;
&lt;li&gt;topology.kubernetes.io/zone&lt;/li&gt;
&lt;li&gt;node.kubernetes.io/instance-type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These labels help the Kubernetes scheduler place pods on the correct nodes. For example, you can configure a pod to run only in a specific region, zone, or cloud provider environment.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cloud-node-lifecycle&lt;/code&gt; controller is responsible for removing nodes from the cluster. When a node is deleted—either manually, due to failure, or by an auto-scaler—the cloud-node-lifecycle controller ensures that the node is properly removed from the cluster's state. It also handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detaching cloud resources associated with the node.&lt;/li&gt;
&lt;li&gt;Ensuring all pods running on the removed node are rescheduled to other healthy nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These controllers work together to ensure node lifecycle management aligns with both the Kubernetes cluster state and the cloud provider's infrastructure.&lt;/p&gt;

&lt;h1&gt;
  
  
  Controller node-route-controller
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;node-route-controller&lt;/code&gt; is responsible for creating and managing network routes inside the cloud provider's network. When a new node is added to the cluster, the node-route-controller communicates with the cloud provider's API to create a route that directs traffic to the new node.&lt;/p&gt;

&lt;p&gt;How It Works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The controller ensures traffic can flow between nodes, even if they are spread across different availability zones.&lt;/li&gt;
&lt;li&gt;It is particularly useful when you want to route traffic from an external load balancer directly to the pods on the nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not all cloud providers support this feature. Support depends on the cloud provider's networking capabilities. It typically works best in one cloud-only environments where routing is fully managed by the cloud provider.&lt;/p&gt;

&lt;p&gt;In hybrid cloud environments, the node-route-controller introduces additional complexity because you need to manage pod-subnet routes between: on-premises infrastructure, different cloud environments.&lt;/p&gt;

&lt;p&gt;This means configuring consistent routing tables across both environments to ensure traffic flows correctly. Misconfigurations or lack of routing support can cause network connectivity issues between pods across on-premises and cloud nodes.&lt;/p&gt;

&lt;p&gt;You can check the pod-subnets and node IPs by commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Pod CIDR&lt;/span&gt;
kubectl get nodes &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{range .items[*].spec}{.podCIDRs}{"\n"}{end}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;span class="c"&gt;# Node IPs&lt;/span&gt;
kubectl get nodes &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{range .items[*].status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output should be like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Pod CIDR&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.32.7.0/24"&lt;/span&gt;,&lt;span class="s2"&gt;"fd00:10:32::7:0/112"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.32.10.0/24"&lt;/span&gt;,&lt;span class="s2"&gt;"fd00:10:32::a:0/112"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="c"&gt;# Node IPs&lt;/span&gt;
172.16.2.100
172.16.2.101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a Kubernetes cluster, node IPs usually come from the same subnet, meaning all nodes are part of one network range. However, the pods on each node get their IP addresses from different subnets (Pod CIDRs). The &lt;code&gt;node-route-controller&lt;/code&gt; solves this by creating routes in the cloud provider's network. These routes tell the cloud network how to reach each pod subnet through its corresponding node.&lt;/p&gt;

&lt;p&gt;From the cloud provider's side it will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip route add 10.32.7.0/24 gw 172.16.2.100
ip route add 10.32.10.0/24 gw 172.16.2.101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the node-route-controller sets up the routes in the cloud provider's network, cloud services like LoadBalancer will know how to route traffic to the pods.&lt;/p&gt;

&lt;h1&gt;
  
  
  Controller service-lb-controller
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;service-lb-controller&lt;/code&gt; is responsible for creating and managing load balancers in the cloud provider's network. When you create a LoadBalancer service in Kubernetes, the service-lb-controller will create a cloud load balancer in the cloud provider's API and route traffic to the service's pods through the node ports or directly to the pods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;loadBalancerClass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-cloud-provider&lt;/span&gt;
  &lt;span class="na"&gt;allocateLoadBalancerNodePorts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyApp&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;clusterIP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10.0.171.239&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LoadBalancer&lt;/span&gt;
&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;loadBalancer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;ip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.0.2.127&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;allocateLoadBalancerNodePorts&lt;/code&gt; option tells the service-lb-controller to create a node port for the service, in case if the cloud provider does not support direct routing to the pods. The cloud provider will create a load balancer and route traffic to the node port, which will then forward it to the service's pods. Default value is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;loadBalancerClass&lt;/code&gt; option specifies the cloud provider's load balancer class to use. This is useful in hybrid cloud environments, otherwise, the CCM with service-lb-controller could create a cloud load balancer in all cloud providers where the cluster is running. The default value is undefined.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;status.loadBalancer.ingress&lt;/code&gt; field shows the IP address of the cloud load balancer. You can use this IP address to access the service from outside the cluster. This IP from different subnets of you kubernetes cluster. It can be a public IP address or a private IP address, depending on the cloud provider's configuration.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hybrid Cloud Considerations
&lt;/h1&gt;

&lt;p&gt;When deploying a Cloud Controller Manager (CCM) in a hybrid cloud environment, there are several key points to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most CCMs are designed to work only in their respective cloud environments. They assume full control over nodes, routes, and load balancers within their cloud infrastructure.&lt;/li&gt;
&lt;li&gt;LoadBalancer services are tightly integrated with the cloud provider's network. In a hybrid cloud environment, LoadBalancer services may not work properly, or their setup may require manual configuration and custom routing rules.&lt;/li&gt;
&lt;li&gt;The cloud provider's network may not be able to route traffic directly to pod IPs located in a different cloud or on-premises environment. You may need to manually configure custom routes or use dedicated networking solutions (e.g., VPNs, interconnects, or SD-WAN) to ensure connectivity.&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;two CCMs&lt;/code&gt; in a single Kubernetes cluster is tricky and can cause conflicts. Both CCMs may attempt to manage the same nodes, routes, or load balancers. Without clear separation of responsibilities, you might encounter unexpected behavior or resource management issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recommendations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;node-route-controller&lt;/code&gt; and &lt;code&gt;service-lb-controller&lt;/code&gt; may not work as expected in a hybrid cloud environment. Just disable them.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;cloud-node-lifecycle&lt;/code&gt; can remove the nodes from another cloud provider's environment, because it doesn't know about this nodes on cloud provider's side.&lt;/li&gt;
&lt;li&gt;The nodes from one cloud provider may not initialize properly in another provider's environment. However, the CCM specific to each environment will usually handle node initialization correctly. So &lt;code&gt;cloud-node&lt;/code&gt; keeps working well.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cloud-node-lifecycle&lt;/code&gt; controller may remove nodes from another cloud provider because it doesn’t recognize them. Mismanagement can cause healthy nodes to be removed unintentionally. To prevent this we need to add changes to the code to avoid removing nodes from another cloud provider.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The Cloud Controller Manager (CCM) is a critical component for managing cloud resources, enabling dynamic scaling, and ensuring nodes are properly prepared in cloud environments. It acts as the bridge between Kubernetes and cloud infrastructure, automating resource management and simplifying cluster operations.&lt;/p&gt;

&lt;p&gt;However, in hybrid cloud environments, traditional CCMs face limitations due to provider-specific designs, network routing complexities, and conflicts between multiple CCMs. With a few key adjustments to the CCM code and configuration settings, you can use multiple cloud providers in a single Kubernetes cluster without compromising performance or reliability.&lt;/p&gt;

&lt;p&gt;You can find the CCM changes in my repositories. The core improvement involves adding a processing delay during node initialization in the CCM. One CCM gets sufficient time to fully initialize the node before another CCM takes any action. Once a node is properly initialized by its corresponding cloud provider's CCM, other CCMs will skip interfering with the node’s state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/sergelogvinov/cloud-provider/tree/nodelifecycle-1.31" rel="noopener noreferrer"&gt;cloud-provider&lt;/a&gt; the base package for the cloud provider implementation&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sergelogvinov/containers" rel="noopener noreferrer"&gt;images with changes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sergelogvinov/gitops-examples" rel="noopener noreferrer"&gt;fluxcd example to deploy them&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>hybridcloud</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud: Service traffic topology and routing</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Wed, 25 Dec 2024 10:28:27 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-service-traffic-topology-and-routing-3gle</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-service-traffic-topology-and-routing-3gle</guid>
      <description>&lt;p&gt;Kubernetes is a powerful tool for managing container workloads in data centers and cloud systems. However, using Kubernetes in a hybrid cloud (both on-premises and cloud) has challenges, especially with networking and traffic routing. By default, Kubernetes services use a &lt;code&gt;round-robin&lt;/code&gt; algorithm to share traffic between nodes. But this method is not always the best for hybrid clouds because nodes are spread across different locations.&lt;/p&gt;

&lt;p&gt;In this article, we will explain why traffic routing is important in a hybrid Kubernetes environment and share best practices for improving network traffic performance.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Traffic Topology and Routing Matter
&lt;/h1&gt;

&lt;p&gt;In a hybrid Kubernetes environment, workloads run both in on-premises data centers and cloud providers. This setup can cause poor network traffic routing, leading to higher latency and lower performance. If your cloud costs depend on data transfer, this can also make your bills higher.&lt;/p&gt;

&lt;p&gt;By optimizing traffic routing, you can make sure that network traffic moves efficiently between nodes. Sometimes, traffic might not even need to leave the physical server, saving time and costs. This helps to reduce latency, improve performance, and lower your monthly expenses.&lt;/p&gt;

&lt;h1&gt;
  
  
  Internal Traffic Policy
&lt;/h1&gt;

&lt;p&gt;Kubernetes has an internal traffic policy that lets you control how traffic moves inside the cluster. By default, Kubernetes services use the &lt;code&gt;Cluster&lt;/code&gt; traffic policy. This policy sends traffic to any available endpoint within the cluster, no matter where it is located.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyApp&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="na"&gt;internalTrafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;internalTrafficPolicy: Local&lt;/code&gt; setting makes sure that traffic only goes to endpoints on the same node. This is helpful for workloads needing low latency and high speed. However, it can also lead to dropped requests if the pods are not running on the same node.&lt;/p&gt;

&lt;p&gt;Production use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ingress controllers&lt;/code&gt; (e.g., Traefik or Nginx) often use this policy to handle traffic from an external load balancer. The load balancer checks the Ingress controller pod and sends traffic to a healthy one.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DaemonSets&lt;/code&gt; which run on every node in the cluster, can also use this policy to communicate with other pods on the same node. A good example is &lt;code&gt;CoreDNS&lt;/code&gt;. Since all pods need to resolve DNS names, it makes sense to run CoreDNS on every node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/" rel="noopener noreferrer"&gt;Official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Topology Aware Routing
&lt;/h1&gt;

&lt;p&gt;Kubernetes also supports topology-aware routing, which helps optimize network traffic based on the physical location of nodes. This feature lets you set rules for services to make sure traffic stays within the same region or availability zone whenever possible. This improves performance, reduces latency, and can help lower costs for cross-zone or cross-region traffic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;service.kubernetes.io/topology-mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auto&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyApp&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;Auto&lt;/code&gt; mode, topology-aware routing will automatically send traffic to the nearest endpoint in the current zone. This works only if each zone has at least one endpoint. If one or more zones have no endpoints, traffic will follow the default &lt;code&gt;round-robin&lt;/code&gt; routing instead.&lt;/p&gt;

&lt;p&gt;So, the number of endpoints should be equal to or greater than the number of zones to ensure proper routing. I do &lt;code&gt;not recommend&lt;/code&gt; using this method for hybrid clouds. In many cases, you might not have endpoints in every zone. This can cause traffic to fall back to round-robin routing, which may not be optimal for performance or cost in a hybrid setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/" rel="noopener noreferrer"&gt;Official documentation&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Traffic distribution
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyApp&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="na"&gt;trafficDistribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PreferClose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;trafficDistribution: PreferClose&lt;/code&gt; setting helps to send traffic to the closest endpoint in the zone. If there is no endpoint in the current zone, traffic will be sent to other zones using round-robin routing. This method does not require an endpoint in every zone, which makes it more suitable for hybrid cloud environments.&lt;/p&gt;

&lt;p&gt;Production use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ingress controllers&lt;/code&gt; To serve traffic to the closest endpoint in the same zone for better performance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cache services&lt;/code&gt; (e.g., Redis or Memcached) to ensure faster access by reaching the nearest endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Pod-to-service&lt;/code&gt; communication in microservices architecture, traffic between pods and services can use nearby endpoints to reduce latency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/#traffic-distribution" rel="noopener noreferrer"&gt;Official documentation&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In a hybrid Kubernetes environment, traffic routing is crucial for optimizing network performance and reducing costs. By using &lt;code&gt;internal traffic policies&lt;/code&gt; and &lt;code&gt;traffic distribution&lt;/code&gt; settings, you can make sure that traffic moves efficiently between nodes. This helps to reduce latency, improve performance, and lower your monthly expenses.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>hybridcloud</category>
    </item>
    <item>
      <title>Kubernetes on Hybrid Cloud dream or reality?</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Tue, 24 Dec 2024 13:03:11 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-dream-or-reality-59bg</link>
      <guid>https://dev.to/sergelogvinov/kubernetes-on-hybrid-cloud-dream-or-reality-59bg</guid>
      <description>&lt;p&gt;Many organizations are interested in running Kubernetes on a hybrid cloud setup. This usually becomes a priority after major outages in their data centers or receiving unexpectedly high bills from their cloud provider. The goal is to leverage the flexibility and scalability of Kubernetes while avoiding vendor lock-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Hybrid Cloud
&lt;/h2&gt;

&lt;p&gt;Running Kubernetes on a hybrid cloud means operating a single Kubernetes cluster across on-premises infrastructure and public cloud environments. Public clouds might include well-known providers such as AWS, Azure, or Google Cloud, while private clouds could involve platforms like OpenStack, Proxmox, or even bare-metal servers.&lt;/p&gt;

&lt;p&gt;Benefits of Hybrid Cloud Kubernetes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost Efficiency: Run baseline workloads on bare-metal servers and scale using public clouds when extra capacity is needed.&lt;/li&gt;
&lt;li&gt;Flexibility: Choose the best cloud provider for specific workloads based on cost or performance.&lt;/li&gt;
&lt;li&gt;Unified Management: Manage all workloads from a single Kubernetes cluster.&lt;/li&gt;
&lt;li&gt;Vendor Independence: Avoid being locked into a single cloud provider.&lt;/li&gt;
&lt;li&gt;Database Solutions: Run database operators directly on Kubernetes, similar to how managed databases work in the cloud.&lt;/li&gt;
&lt;li&gt;Disaster Recovery: Keep standby nodes in the cloud for quick failover during outages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Challenges of Running Kubernetes on Hybrid Cloud
&lt;/h2&gt;

&lt;p&gt;While the benefits are significant, running Kubernetes on a hybrid cloud is not without challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Integration: Native integration with cloud services is essential for smooth operation.&lt;/li&gt;
&lt;li&gt;Networking: Secure and reliable connections between on-premises and cloud environments are crucial.&lt;/li&gt;
&lt;li&gt;Latency: Minimize latency by optimizing traffic routing.&lt;/li&gt;
&lt;li&gt;Security: Implement robust measures to secure workloads and data across environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Existing Solutions for Hybrid Kubernetes
&lt;/h2&gt;

&lt;p&gt;Kubernetes already offers several tools and features for managing hybrid cloud clusters effectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://talos.dev/" rel="noopener noreferrer"&gt;Talos&lt;/a&gt;: A secure, immutable, and minimal operating system designed for Kubernetes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/concepts/architecture/cloud-controller/" rel="noopener noreferrer"&gt;Cloud Controller Manager&lt;/a&gt;: Helps manage Kubernetes nodes in cloud environments.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" rel="noopener noreferrer"&gt;Persistent Volumes&lt;/a&gt;: Support for multiple storage types, enabling on-premises and cloud storage usage within the same cluster.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/sergelogvinov/kubernetes-pods-with-global-ipv6-1aaj"&gt;IPv6 for Pods and Services&lt;/a&gt;: Allows seamless pod-to-pod communication without the need for NAT.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/" rel="noopener noreferrer"&gt;Internal Traffic Policy&lt;/a&gt;: Controls how traffic is routed within the cluster.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/" rel="noopener noreferrer"&gt;Topology Aware Routing&lt;/a&gt;: Optimizes network traffic routing based on the physical location of nodes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/#traffic-distribution" rel="noopener noreferrer"&gt;Traffic distribution&lt;/a&gt;: Distributes traffic across multiple zones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Networking Setup
&lt;/h2&gt;

&lt;p&gt;Networking is one of the most important aspects of a hybrid Kubernetes cluster. You must ensure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A secure VPN or direct connection between on-premises and cloud networks.&lt;/li&gt;
&lt;li&gt;Consistent IP addressing and DNS resolution.&lt;/li&gt;
&lt;li&gt;Proper network policies for traffic management.&lt;/li&gt;
&lt;li&gt;Load balancing across on-premises and cloud environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Network architecture is very important for hybrid cloud Kubernetes. It very hard to change after the cluster is up and running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cluster Configuration
&lt;/h2&gt;

&lt;p&gt;When setting up your cluster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define which workloads run on-premises and which in the cloud.&lt;/li&gt;
&lt;li&gt;Use node selector/affinity to control where specific pods run.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Control plane configuration
&lt;/h2&gt;

&lt;p&gt;Kubernetes uses etcd as its database to store cluster state. It is crucial to ensure etcd remains highly available and secure. Here are some best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use an odd number of etcd nodes: This ensures high availability and avoids split-brain scenarios.&lt;/li&gt;
&lt;li&gt;Run across multiple availability zones or cloud providers: Ensure low latency between nodes and select providers with minimal latency.&lt;/li&gt;
&lt;li&gt;Regularly back up etcd data: Prevent data loss with automated backups.&lt;/li&gt;
&lt;li&gt;Disaster Recovery Plans: Test and train disaster recovery plans for etcd failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cloud integration
&lt;/h2&gt;

&lt;p&gt;Most of the cloud providers offer addons to integrate with Kubernetes. These addons was disaigned to run on the cloud provider's Kubernetes service. However, you can run them on your hybrid cluster as well, with some modifications.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CCM (Cloud Controller Manager) requires the changes in the code, check my &lt;a href="https://github.com/sergelogvinov/containers" rel="noopener noreferrer"&gt;already modified version&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CSI (Container Storage Interface) is a standard for exposing storage systems to containerized workloads on Kubernetes. Most of them works well in hybrid cloud setup.&lt;/li&gt;
&lt;li&gt;Cluster Node Autoscaler also requires &lt;a href="https://github.com/sergelogvinov/containers/tree/main/cluster-autoscaler" rel="noopener noreferrer"&gt;some changes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monitor and Optimize
&lt;/h2&gt;

&lt;p&gt;Monitoring tools like Prometheus and Grafana can help track the health and performance of your hybrid cluster. Additionally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use autoscalers to manage resource usage efficiently.&lt;/li&gt;
&lt;li&gt;Set alerts for potential issues.&lt;/li&gt;
&lt;li&gt;Regularly review and optimize your cluster setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Running a Kubernetes cluster in a hybrid environment offers flexibility and scalability, but it requires careful planning and execution.&lt;br&gt;
To find out more about Kubernetes on hybrid cloud, check out the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/sergelogvinov/terraform-talos" rel="noopener noreferrer"&gt;Talos on Hybrid Cloud&lt;/a&gt; to deploy Talos on different cloud providers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sergelogvinov/gitops-examples" rel="noopener noreferrer"&gt;Fluxcd&lt;/a&gt; to install base addons in hybrid cluster&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sergelogvinov/containers" rel="noopener noreferrer"&gt;Container images&lt;/a&gt; with modified cloud addons&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sergelogvinov/helm-charts" rel="noopener noreferrer"&gt;Helm charts&lt;/a&gt; for deploying applications in hybrid cluster&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>cloud</category>
      <category>linux</category>
      <category>hybridcloud</category>
    </item>
    <item>
      <title>Proxmox Virtual Machine optimization</title>
      <dc:creator>Serge Logvinov</dc:creator>
      <pubDate>Mon, 23 Dec 2024 05:26:50 +0000</pubDate>
      <link>https://dev.to/sergelogvinov/proxmox-virtual-machine-optimization-7mn</link>
      <guid>https://dev.to/sergelogvinov/proxmox-virtual-machine-optimization-7mn</guid>
      <description>&lt;p&gt;Proxmox Virtual Environment (VE) is a powerful open-source virtualization platform used to manage virtual machines (VMs). To make your VMs run faster, you need to set them up correctly.&lt;/p&gt;

&lt;h1&gt;
  
  
  Common optimizations
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;CPU settings&lt;/li&gt;
&lt;li&gt;Memory settings&lt;/li&gt;
&lt;li&gt;Network configuration&lt;/li&gt;
&lt;li&gt;Disk storage type&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  CPU Settings
&lt;/h1&gt;

&lt;h3&gt;
  
  
  CPU Type
&lt;/h3&gt;

&lt;p&gt;If you do not want to use live migration, you need to set the CPU type to &lt;code&gt;host&lt;/code&gt;. This setting allows the VM to use all features of the physical CPU but disables live migration entirely, which might not be suitable for all environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  CPU Affinity
&lt;/h3&gt;

&lt;p&gt;Set dedicated CPU by setting CPU affinity for the VM. This setting will prevent the VM from using other CPUs.&lt;/p&gt;

&lt;p&gt;Turn on NUMA (Non-Uniform Memory Access) for better memory handling on large servers. Choose the right CPU cores in one NUMA node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/sergelogvinov/proxmox-cpu-affinity-for-vms-4dhb"&gt;More details&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Memory Settings
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Memory Huge Pages
&lt;/h3&gt;

&lt;p&gt;Consider using huge pages for better memory performance. Huge pages are larger than normal pages and can improve memory access speed. It allocates memory in 2MB or 1GB chunks, dyring the boot process. And this memory is reserved for the VM only, the hypervisor cannot use it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/sergelogvinov/proxmox-hugepages-for-vms-1fh3"&gt;More details&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Network Configuration
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Use VirtIO Network Driver
&lt;/h3&gt;

&lt;p&gt;Always use VirtIO drivers for network cards. VirtIO drivers are paravirtualized drivers for network and disk devices. They are faster than the default drivers. Enable Multiqueue queues the same as the number of CPU cores.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Jumbo Frames
&lt;/h3&gt;

&lt;p&gt;Allow Jumbo Frames for larger network packets. You can enable Jumbo Frames in Proxmox by setting the MTU (Maximum Transmission Unit) value to 9000 on the network interface configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  SR-IOV
&lt;/h3&gt;

&lt;p&gt;Use Single Root I/O Virtualization (SR-IOV) for better network performance. SR-IOV allows a single physical network card to appear as multiple virtual network cards. After enabling SR-IOV, you can assign a virtual function to the VM. VM will have direct access to the physical network card. The Hypervisor will not be involved in network processing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/sergelogvinov/network-performance-optimization-with-nvidia-connectx-on-proxmox-5f7j"&gt;More details&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Disk Storage Type
&lt;/h1&gt;

&lt;p&gt;The disk storage type is one of the most important factors for VM performance.&lt;br&gt;
Local storage is faster than network storage. SSD is faster than HDD.&lt;br&gt;
LVM (not a thin) is faster than ZFS. ZFS is faster than NFS.&lt;/p&gt;

&lt;p&gt;For the safety of your data, use the soft RAID 1 or 10 for the local storage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for 2 disks use RAID 1 with mdraid implementation&lt;/li&gt;
&lt;li&gt;for 4 disks or more try to use ZFS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LVM backend is faster than other backends for the local storage.&lt;br&gt;
ZFS backend works better with large storage, but it requires more memory and CPU.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use VirtIO/SCSI VirtIO drivers
&lt;/h3&gt;

&lt;p&gt;Always use VirtIO drivers for disk devices. VirtIO drivers are paravirtualized drivers for disk devices. They are faster than the default drivers.&lt;/p&gt;

&lt;h3&gt;
  
  
  SR-IOV
&lt;/h3&gt;

&lt;p&gt;For the huge storage performance, you can use SR-IOV for disk devices. You can assign NVME directly to the VM. The VM will have direct access to the physical disk, this performance will have performance as on the host machine.&lt;/p&gt;

</description>
      <category>proxmox</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
