<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>overlay network on Digi Hunch</title><link>https://static.digihunch.com/tag/overlay-network/</link><description>Recent content in overlay network on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Tue, 08 Apr 2025 14:51:44 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/overlay-network/index.xml" rel="self" type="application/rss+xml"/><item><title>Virtualization 4 of 4 – Networking</title><link>https://static.digihunch.com/2020/08/virtualization-4-of-4-networking/</link><pubDate>Fri, 21 Aug 2020 21:53:32 -0400</pubDate><guid>https://static.digihunch.com/2020/08/virtualization-4-of-4-networking/</guid><description>&lt;h3 class="wp-block-heading"&gt;Virtual LAN (VLAN)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Although VLAN emerged before virtualization and is technically not part of virtualization topic. I&amp;#8217;d just like to start from here as a refresher. Suppose we have computers from finance department and computers from sales department all connected to a single layer-2 switch. There are at least three problems: 1) too many devices on the same broadcast domain causes traffic congestion; 2) security can be compromised and 3) each department might have several physical locations. We introduce multi-layer switch to address these with two main features: 1) the VLAN feature can map ports to logical networks, so that all hosts are physically connected to a single switch, but logically to their own network (VLAN) 2) the SVI (switch virtual interface) feature allows inter-VLAN routing at layer 3. Such multi-layer switch is sometimes referred to as layer-3 switch. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;VLAN is local to a switch and a tag is required in ethernet frame in order to pass VLAN info across switches. This link between switches is called a &lt;strong&gt;trunk&lt;/strong&gt;. &lt;a href="https://en.wikipedia.org/wiki/IEEE_802.1Q"&gt;IEEE 802.1q&lt;/a&gt; (aka dot1q) is the networking standard for VLAN, which standardizes the tagging traffic between switches to tell which traffic belongs to which VLAN. The dot1q trunk (aka dot1q link) provides VLAN IDs fro frames traversing between switches. A trunk can be configured between two switches, or between a switch and a router. &lt;strong&gt;Trunking&lt;/strong&gt; is the process of traversing different VLAN traffic over the trunk. The ports on each switch need to be configured to enable trunking. While Cisco calls such ports &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;trunk port&lt;/strong&gt;&lt;/span&gt;, others call them &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;tagged port&lt;/strong&gt;&lt;/span&gt;. Their function is to add the VLAN tag to ethernet frame. In contrast, regular ports that send and receive frames without VLAN tag are called &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;access port&lt;/strong&gt;&lt;/span&gt; or &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;untagged port&lt;/strong&gt;&lt;/span&gt;. Trunk port carries traffic for multiple VLANS whereas access port carries traffic for a single VLAN. A network device connected to access port has no idea about its VLAN belonging. VLAN creation and management are the responsibility of the switch. Common trunking protocols include &lt;span style="text-decoration: underline;"&gt;VTP (VLAN trunking protocol) &lt;/span&gt;and &lt;span style="text-decoration: underline;"&gt;DTP (dynamic trunking protocol)&lt;/span&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This &lt;a href="https://www.youtube.com/watch?v=NmkFzDrZsXM"&gt;video&lt;/a&gt; and &lt;a href="https://www.professormesser.com/network-plus/n10-008/n10-008-video/vlans-and-trunking-n10-008/"&gt;this&lt;/a&gt; video have good explanations on VLAN.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Virtual Extensible LAN (VXLAN)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;VXLAN is an overlay protocol. Remember that in the standard TCP/IP stack, you normally encapsulate layer-3 IP datagram into a layer-2 ethernet frame. With the VXLAN encapsulation technique however, layer-2 frames can be encapsulated within layer-4 UDP packet.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;VXLAN allows you to stretch layer 2 connection over an intervening layer 3 network. VXLAN tunnel endpoints (VTEPs) are the endpoint device that terminate VXLAN tunnels and it can be either virtual or physical switch ports. It encapsulate VXLAN traffic and de-encapsulate the traffic when it leaves the VXLAN tunnel.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The VXLAN encapsulation includes the followings:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Outer Ethernet Header (source and dest MAC for underlay VTEPs)&lt;/li&gt;&#10;&lt;li&gt;Outer IP header (source and dest IP on underlay network)&lt;/li&gt;&#10;&lt;li&gt;Outer UDP header (including source and dest ports, 4789 default)&lt;/li&gt;&#10;&lt;li&gt;VXLAN Header (including VNI)&lt;/li&gt;&#10;&lt;li&gt;Inner Ethernet Frame (with source and dest MAC for overlay interfaces)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The VNI (VXLAN network identifier, aka VNID) included in the VXLAN header is 24-bit long. It is conceptually similiar to VLAN ID in VLAN but only with 12-bit length.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="http://chansblog.com/wp-content/uploads/2015/02/0.1-VXLAN-frame.jpg" alt=""/&gt;&lt;figcaption class="wp-element-caption"&gt;VXLAN Enapsulation&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The VXLAN protocol is documented in &lt;a href="https://tools.ietf.org/html/rfc7348"&gt;RFC7348&lt;/a&gt;. Its specification was originally created by VMware, Cisco and Arista. As it became more common in network virtualization (with data centre virtualization, and application containerization) several other players joined the list of contributors and they manufacture switches that support VXLAN. &lt;a href="https://support.huawei.com/enterprise/en/doc/EDOC1100086966#:~:text=VXLAN%20encapsulates%20a%20Layer%202,over%20a%20Layer%203%20network.&amp;amp;text=It%20establishes%20a%20logical%20tunnel,forward%20them%20through%20the%20tunnel."&gt;This&lt;/a&gt; is a section on VXLAN from the document of Huawei Cloud Engine 5800 switch.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.openvswitch.org/"&gt;Open vSwitch&lt;/a&gt; is an example of a software-based virtual network switch that supports VXLAN overlay networks.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In summary, the main benefits of VXLAN over VLAN are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;VXLAN scales up to 16 million logical networks, thanks to the 24-bit length of VNI&lt;/li&gt;&#10;&lt;li&gt;VXLAN supports layer 2 adjacency across IP networks. A VM belonging to existing layer 2 domain can be created in different data centre (where more computing resources are available), without being constrained by layer 2 boundaries, or being forced to create geographically stretched layer 2 domains (stretched VLAN).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Virtual Machine Networking&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For VM to connect to each other, within or across hosts, we need not only vNIC on VM, but also vSwitch to connect vNICs. A vSwitch (aka bridge) is a logically defined layer-2 device that passes frames between vNICs. On the same host, vNICs are directly connected to vSwitch, which is then connected to the physical NIC. Each vSwtich connects a broadcast domain. When we setup vNIC there are three modes:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Bridged networking:&lt;/strong&gt; VM connect to outside network using host&amp;#8217;s physical NIC, which acts as a bridge between vNIC and outside network. The VM is a full participant in the network as if it were a physical computer on the network. i.e. it obtain IP addressing information from a DHCP server on the outside (physical) network. The VM&amp;#8217;s IP address is also visible and directly accessible by other computers on the network. bridge networking is common for servers as VMs.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;NAT networking:&lt;/strong&gt; The VM relies on the host to act as NAT device to make outgoing network connection. The IP address of VM is assigned by virtual DHCP server on host. The guest VMs form a private network and computers on the outside network are external. The host translates private IP address into the host&amp;#8217;s IP address on the way out, and listens for returning traffic. Outside network sees traffic from VM guest as if it were from the host. This network mode is common when the VMs are mainly used as a client workstation.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Host-only networking: &lt;/strong&gt;creates a network that is completely contained within the host computer. The vSwtich is the hub of the private network and the physical NIC on the host is not involved. The VM will not have access to the outside network. This mode is useful when the VMs needs to be isolated from outside network, and only need to communicate with peers on the same host.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The difference between NAT networking and host-only networking is the exposure of VM guest to external network. All of these networking modes are &lt;a href="https://knowledge.broadcom.com/external/article/303393/understanding-networking-types-in-vmware.html"&gt;available&lt;/a&gt; on VMWare fusion, for example. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Advanced virtualization platform such as vSphere usually support multi-hosting. Multiple host can also be configured to form a distributed vSwitch, such as &lt;a href="https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.networking.doc/GUID-6E51D76A-DC9F-44E2-B673-7D92384AFDE4.html"&gt;vSphere Distributed Switch&lt;/a&gt;, in addition to standard switches.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Docker Networking&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I had a &lt;a href="https://static.digihunch.com/2020/07/dockersnetwork/"&gt;brief&lt;/a&gt; on Docker network covering three modes. Out of the three modes, single-host bridge network is the equivalent of host-only networking. MacVLAN driver is similar to bridged networking, in the sense that container may connect to external network, using host NIC as a bridge. However, the external network is still bound by physical location. This is when overlay network comes in handy.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;CNM and CNI&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the Docker networking, container needs to map its own port to host, of which the port resource is implemented by IP tables, which limits the scale and performance of the solution. Also, those networking modes do not address the problem of multi-host networking. As multi-host networking became a real need for containers, the industry started looking into different solutions. Container project favour a model where networking is decoupled from the container runtime. This also greatly improves application mobility. In this model, networking is handled by a &amp;#8216;plugin&amp;#8217; or &amp;#8216;driver&amp;#8217; that manages the network interface, and how the containers are connected to the network. The plugin also assigns the IP address to the container&amp;#8217;s network interfaces. In order for this model to succeed, there needs to be a well-defined interface or API between the container runtime and the network plugins.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker, the company behind the Docker container runtime, came up with the Container Network Model (CNM). Around the same time, CoreOS, the company responsible for creating the rkt container runtime, came up with the Container Network Interface (CNI). Kubernetes originally seeks to use CNM for its plugins, but they eventually decided to go with CNI. The primary reason was that CNM was still seen as something designed with Docker container runtime in mind and was hard to decouple from it. After this decision, several other open source project also turned to CNI for their container runtimes.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This &lt;a href="https://thenewstack.io/container-networking-landscape-cni-coreos-cnm-docker/"&gt;article&lt;/a&gt; expands further into the difference between CNM and CNI.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/08/virtualization-3-of-3-containers/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Virtualization 3 of 4 – Containers&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/08/zookeeper/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Zookeeper Summary&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Docker network in different modes</title><link>https://static.digihunch.com/2020/07/dockersnetwork/</link><pubDate>Wed, 01 Jul 2020 20:19:00 -0400</pubDate><guid>https://static.digihunch.com/2020/07/dockersnetwork/</guid><description>&lt;p class="wp-block-paragraph"&gt;Reading notes of &amp;#8220;Docker DeepDive&amp;#8221;. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker networking is backed by libnetwork, which is an implementation of &lt;a href="https://github.com/moby/libnetwork/blob/master/docs/design.md"&gt;Container Network Model&lt;/a&gt; (CNM), an open-source pluggable architecture designed to provide networking to containers. Libnetwork also provides native service discovery and basic container load balancing solution. Docker networking also involves some drivers that extend the CNM model with specific network topology implementation.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;Sandbox&lt;/strong&gt; &amp;#8211; an isolated network stack, including Ethernet interfaces, ports, routing tables, and DNS config, usually implemented through Linux namespace.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Endpoints&lt;/strong&gt; &amp;#8211; behave like regular network adapters, and can only be connected to a single network at a time. It connects sandbox to network. Endpoint is implemented in veth pair in Linux.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Networks&lt;/strong&gt; &amp;#8211; software implementation of an 802.1 bridge (aka switch). They group together, and isolate, a collection of endpoints that need to communicate.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://www.dclessons.com/uploads/2019/09/Docker-7.4.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker company separates network project out from its container project, as a plugin called libnetwork, which is developed in Golang and compliant to CNM. Libnetwork is the official implementation of CNM.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Libnetwork supports the following network modes:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;network mode&lt;/td&gt;&lt;td&gt;mechanism&lt;/td&gt;&lt;td&gt;use case&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;null&lt;/td&gt;&lt;td&gt;no network is provided to containers&lt;/td&gt;&lt;td&gt;quarantined environment for security&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;bridge&lt;/td&gt;&lt;td&gt;containers communicate with each other through bridge&lt;/td&gt;&lt;td&gt;containers needs to communicate with each other or with host service&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;host&lt;/td&gt;&lt;td&gt;process in container has access to host network stack and use host port&lt;/td&gt;&lt;td&gt;container needs to use host network stack (e.g. licence by mac address)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;container&lt;/td&gt;&lt;td&gt;place containers in a single net namespace so they can communicate with each other as localhost&lt;/td&gt;&lt;td&gt;proxy, kubernetes&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Linux veth comes in pairs to connect virtual network devices. For example, connect two net namespaces to allow intercommunication. Linux bridge is a virtual device, to connect two net namespaces.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://developers.redhat.com/blog/wp-content/uploads/2018/10/veth.png" alt="Introduction to Linux interfaces for virtual networking - Red Hat Developer"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Dockers ships with several built-in drivers, known as native drivers or local drivers, such as bridge, overlay and macvlan on Linux. There are also 3rd-party network drivers for docker (aka remote drivers).&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-host-network"&gt;Host network&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this mode libnetwork will not create network and net namespace for container. Container process shares the network configuration of the host, and therefore uses the ports on host. Other than network sharing, other aspects (e.g. process, file system, hostname, etc) are separated from host.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-bridge-networks"&gt;Bridge networks&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This type of network only exist on a single Docker host and can only connect containers that are on the same host. The word bridge refers to 802.1d bridge (layer 2 switch), which is used to connect multiple network interfaces.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Every Docker host gets a default single-host network, called &lt;span style="text-decoration: underline;"&gt;bridge&lt;/span&gt; on Linux. This is the network that all new containers will attach to by default.&lt;br&gt;Docker networks built with the bridge driver on Linux hosts are based on the linux bridge technology that has existed in the Linux kernel for a while. They&amp;#8217;re high performance and extremely stable. Linux &lt;em&gt;&lt;strong&gt;brctl&lt;/strong&gt;&lt;/em&gt; tool can inspect the linux bridge.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Bridge networks allows container on the same host to communicate with each other. Port mapping allows network connectivity between container and host. Traffic hitting host port will be redirected to container port.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-multi-host-overlays"&gt;Multi-host overlays&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Cross-host networking usually uses an overlay network, which builds a mesh between host and employs a large block of IP addresses within that mesh. A mesh network is a local network topology in which the infrastructure nodes connect directly, dynamically and non-hierarchically to as many other nodes as possible and cooperate with one another to efficiently route data from/to clients.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;You can attach a service to overlay network, which spans across multiple Docker hosts so that containers on different hosts can communicate &lt;span style="text-decoration: underline;"&gt;at layer 2&lt;/span&gt;. They are much better alternatives than bridge network for container-to-container communication. Overlay networking is very common due to its scalability. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The trick is basically the layer 2 frame of the overlay network is encapsulated into layer 3 datagram transmitted across underlay network, at layer 3. This is achieved through VXLAN tunnels, which allows you to create a virtual Layer 2 network on top of an existing Layer 3 infrastructure. VXLAN is an encapsulation technology that existing routers and network infrastructure just see as regular IP/UDP packets without issue.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To create the virtual Layer 2 overlay network, a VXLAN tunnel is created through the underlying Layer 3 IP infrastructure (aka underlay network). Each end of the VXLAN tunnel is terminated by a &lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;VXLAN Tunnel Endpoint (VTEP)&lt;/span&gt;&lt;/strong&gt;. It&amp;#8217;s this VTEP that performs the encapsulation/de-encapsulation.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-vxlan-networking"&gt;VXLAN networking&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To accomplish overlay network across multiple hosts, a new network sandbox was created on each host. A sandbox is like a container, but instead of running an application, it runs an isolated network stack &amp;#8211; one that&amp;#8217;s sandboxed from the network stack of the host itself.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;&lt;em&gt;virtual switch&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt; (aka virtual bridge) called Br0 is created inside the sandbox. A &lt;strong&gt;&lt;em&gt;VTEP&lt;/em&gt;&lt;/strong&gt; is also created with one end plumbed into the Br0 virtual switch, and the other end plumbed into the host network stack (VTEP). The end in the host network gets an IP address on the underlay network the host is connected to and is bound to a UDP socket on port 4789. The two VTEPs on each host create the overlay via a VXLAN tunnel.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Each container then gets its own virtual Ethernet (veth) adapter that is also plumbed into the local Br0 virtual switch.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Let&amp;#8217;s go over an example in the following diagram, where container C1 with an overlay IP needs to communicate to another container C2, with a different overlay IP, sitting on a different node (Docker host). Each node has its own underlay IP.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://img1.wsimg.com/isteam/ip/ada6c322-5e3c-4a32-af67-7ac2e8fbc7ba/8.jpg/:/cr=t:0%25,l:0%25,w:100%25,h:100%25/rs=w:1280" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;IP communication details:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;C1 creates the IP datagram with destination IP (C2) and sends it over its veth interface, which is connected to the Br0 virtual switch on the host node. &lt;/li&gt;&#10;&lt;li&gt;The virtual switch doesn&amp;#8217;t know where to send the datagram, as it doesn&amp;#8217;t have an entry in its ARP table that corresponds to the destination IP address. As a result, it floods the packet to all ports. The VTEP interface connected to Br0 knows how to forward the frame, so responds with its own MAC address. &lt;/li&gt;&#10;&lt;li&gt;This is a proxy APR reply and results in the Br0 switch learning how to forward the packet. So it updates its ARP mapping the destination IP address to the MAC address of the local VTEP.&lt;/li&gt;&#10;&lt;li&gt;The VTEP knows about C2 because all newly started containers have their network details propagated to the other nodes in the Swarm using the network&amp;#8217;s built-in gossip protocol. When the packet arrives at node2&lt;/li&gt;&#10;&lt;li&gt;The VTEP encapsulates the frame so it can be sent over the underlay transport infrastructure, by adding a VXLAN header to the Ethernet frame. The VXLAN header contains the VXLAN network ID (VNID) which is used to map frames from VLANs to VXLANs and vice versa.&lt;/li&gt;&#10;&lt;li&gt;Each VLAN gets mapped to VNID, so that the packet can be de-encapsulated on the receiving end and forwarded to the correct VLAN. This is how network isolation is maintained. The encapsulation also wraps the frame in a UDP packet with the IP address of the remote VTEP on node2 in the destination IP field, and the UDP port 4789 socket information. The underlying network does not know that it is transporting data frames for the overlay network.&lt;/li&gt;&#10;&lt;li&gt;When the packet arrives at node2, the kernel sees that it&amp;#8217;s addressed to UDP port 4789. The kernel also knows that it has a VTEP interface bound to this socket. As a result, it sends the packet to the VTEP, which reads the VNID, de-encapsulates the packet, and sends it on to its own local Br0 switch on the VLAN that corresponds the VNID. From there it is delivered to container C2&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker also supports Layer 3 routing within the same overlay network. For example, you can create an overlay network with two subnets, and Docker will take care of routing between them. Two subnets will require two virtual switches, Br0 and Br1, being created inside the sandbox, and routing happens by default.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-plugging-into-existing-vlans"&gt;Plugging into existing vLANs&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The built-in MACVLAN driver was created for onnect containerized apps to external physical network. A good example is partially containerized app, in which the containerized parts will need a way to communicate with the non-containerized parts still running on existing physical networks.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To connect the container interface through the host interface to an external network, the host NIC needs to be in promiscuous mode. For public cloud, this is most likely prohibited. For data centers, this depends on the network policy.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker MACVLAN driver is built on top of Linux kernel driver with the same name. As such, it supports VLAN trunking. This means we can create multiple MACVLAN networks and connect containers on the same Docker host to them.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" width="392" height="230" src="https://static.digihunch.com/wp-content/uploads/2020/07/image-2.png" alt="" class="wp-image-1169" style="width:540px;height:317px"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For connectivity issues between containers, it&amp;#8217;s worth checking both the daemon logs (on host) and container logs.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-service-discovery"&gt;Service discovery&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;allows all containers and Swarm services to locate each other by name, as long as they are on the same network. This leverages Docker&amp;#8217;s embedded DNS server as well as a DNS resolver in each container.&lt;br&gt;Each Swarm Service and standalone container started with the &amp;#8211;name flag will register its name and IP address with the Docker DNS service.&lt;br&gt;This name resolution, however, only works within the same network.&lt;br&gt;It is also possible to configure Swarm services and standalone containers with customized DNS options in case embedded Docker DNS server cannot resolve a query (/etc/resolv.conf)&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" width="381" height="103" src="https://static.digihunch.com/wp-content/uploads/2020/07/image-3.png" alt="" class="wp-image-1170" style="width:547px;height:148px"/&gt;&lt;/figure&gt;&#10;&lt;h3 class="wp-block-heading" id="h-ingress-load-balancing"&gt;Ingress load balancing&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Services published via ingress mode (by default, as opposed to host mode) can be accessed from any node in the Swarm, even nodes not running a service replica. Ingress mode uses a layer 4 routing mesh called the Service Mesh or the Swarm Mode Service Mesh.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" width="396" height="206" src="https://static.digihunch.com/wp-content/uploads/2020/07/image-4.png" alt="" class="wp-image-1171" style="width:557px;height:290px"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Updates:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The most common network modes that I use are host and bridge. With host network mode, container exposes ports on the interface of the host machine. Containers talk to each other via that interface. With bridge network, containers have their own namespace of networking separate from the one from the interface of the hosts, with a bridge getting the two networks connected.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-reference"&gt;Reference&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker Deep dive&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" width="830" height="1024" src="https://static.digihunch.com/wp-content/uploads/2023/01/docker-deep-dive-830x1024.jpeg" alt="" class="wp-image-7915" style="width:209px;height:258px" srcset="https://static.digihunch.com/wp-content/uploads/2023/01/docker-deep-dive-830x1024.jpeg 830w, https://static.digihunch.com/wp-content/uploads/2023/01/docker-deep-dive-243x300.jpeg 243w, https://static.digihunch.com/wp-content/uploads/2023/01/docker-deep-dive-768x947.jpeg 768w, https://static.digihunch.com/wp-content/uploads/2023/01/docker-deep-dive.jpeg 1000w" sizes="auto, (max-width: 830px) 100vw, 830px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/06/iterate-through-cassandra-table-with-datastax-python-driver/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;DataStax Python Driver&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/07/emc-productlines/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;EMC Isilon storage product&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Docker Compose, Docker Stack and Docker Swarm</title><link>https://static.digihunch.com/2020/05/docker-swarm-brief-notes/</link><pubDate>Sun, 24 May 2020 21:58:03 -0400</pubDate><guid>https://static.digihunch.com/2020/05/docker-swarm-brief-notes/</guid><description>&lt;p class="wp-block-paragraph"&gt;This posting covers some basic docker orchestration tools.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Docker Compose&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Docker Compose&amp;#8217;s predecessor is a tool called Fig developed by Orchard, which was acquired by Docker in 2014, with Fig renamed to Docker Compose. Docker Compose is the official container management tool. It is essentially a python script that parses yaml file, to make Docker API calls to manage containers dynamically. It is installed along with Docker on MacOS and Windows. On Linux, you will have to download package with curl command and install manually. Docker Compose has three versions so far and we should create new template with v3. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Docker compose yaml template consists of three parts:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;services&lt;/strong&gt;: similar to docker run&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;build: specify Dockerfile to build image&lt;/li&gt;&#10;&lt;li&gt;cap_add, cap_drop: specify kernel capabilities (e.g. NET_ADMIN, SYS_ADMIN)&lt;/li&gt;&#10;&lt;li&gt;command: override default startup command by container&lt;/li&gt;&#10;&lt;li&gt;container_name&lt;/li&gt;&#10;&lt;li&gt;depends_on&lt;/li&gt;&#10;&lt;li&gt;devices: map host device to container&lt;/li&gt;&#10;&lt;li&gt;dns&lt;/li&gt;&#10;&lt;li&gt;dns_search:&lt;/li&gt;&#10;&lt;li&gt;entryppoint: override entry point from image&lt;/li&gt;&#10;&lt;li&gt;env_file: specify file that stores environment variable&lt;/li&gt;&#10;&lt;li&gt;environment: specify environment variable&lt;/li&gt;&#10;&lt;li&gt;image: specify the location of image&lt;/li&gt;&#10;&lt;li&gt;pid: share the PID namespace with host&lt;/li&gt;&#10;&lt;li&gt;ports: expose network ports. HOST:CONTAINER&lt;/li&gt;&#10;&lt;li&gt;networks&lt;/li&gt;&#10;&lt;li&gt;volumes: mount host volume to container&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;networks&lt;/strong&gt;: similar to docker network create&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;volumes&lt;/strong&gt;: similar to docker volume create&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here is a typical structure of docker compose yaml template (wordpress):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;version: &amp;#34;3.8&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mysql:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image:mysql:5.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - mysql_data:/var/lib/mysql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_ROOT_PASSWORD:root&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_DATABASE:mywordpress&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_USER:digihunch&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_PASSWORD:hunchdigi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; wordpress:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - mysql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: wordpress:php7.4&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &amp;#34;8080:80&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart:always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WORDPRESS_DB_HOST:mysql:3306&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WORDPRESS_DB_USER:digihunch&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WORDPRESS_DB_PASSWORD: hunchdigi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WORDPRESS_DB_NAME: digihunch &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; frontend:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; backend:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;volumes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mysql-data: {}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In summary, Docker Compose is an orchestration tool for &lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;single host&lt;/span&gt;&lt;/strong&gt;, typically seen in development and test environment with dependencies between services.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Docker Stack&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A stack is a set of related services and infrastructure that gets deployed and managed as a unit. A docker stack file has the same format as Docker Compose file, with the only requirement that the version: key specify a value of 3.0. The other difference between Docker Stacks and Docker Compose, is that stacks do not support builds. All images have to be built prior to deploying the stack.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;From the stack file, Docker first executes the network section and create networks that do not exist. Then it goes through other elements. A service is a JSON collection(dictionary) that contains a bunch of keys. The image key is the only mandatory key in the service objects, which will be pulled from Docker Hub by default. Ports key maps the port of Swarm to the port of each service replica. By default, all ports are mapped using ingress mode. This means they&amp;#8217;ll be mapped and accesible from every node in the Swarm -even nodes not running a replica. The alternative is host mode, where ports are only mapped on Swarm nodes running replicas for the service.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The environment key lets you inject environment variables into services replica.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The secrets key defines two secrets &amp;#8211; revprox_cert and revprox_key. These must be defined in the top-level secrets key, and must exist on the system. Secrets get mounted into service replicas as a regular file. The secrets defined in this service will be mounted in each service replica as /run/secrets/revprox_cert and /run/secrets/revprox_key, unless otherwise specified.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The volumes key is used to mount pre-created volumes and host directories into a service replica.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The networks key ensures that all replicas for the service will be attached to the front-tier network. The network specified here must be defined in the networks top-level key, and if it doesn’t already exist, Docker will create it as an overlay.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The service also defines a placement constraint under the deploy key. This ensures that replicas for this service will always run on Swarm worker nodes. Placement constraints are a form of topology-aware scheduling, and can be a great way of influencing scheduling decisions.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When Docker stops a container, it issues a SIGTERM to the process with PID 1 inside the container. The container (its PID 1 process) then has a 10-second grace period to perform any clean-up operations. If it doesn’t handle the signal, it will be forcibly terminated after 10 seconds with a SIGKILL. The stop_grace_period property overrides this 10 second grace period.”&lt;br&gt;Although you may scale a docker service as part of a stack with scale command, it is not recommended. Instead, stack file should be used as the ultimate source of truth (declarative method vs imperative method). All changes to the stack should be made to the stack file, and the updated stack file used to redeploy the app.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Docker Swarm&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For multi-host cluster, Docker Swarm facilitates the deployment of micro-services. Docker Swarm is:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;a &lt;span style="text-decoration: underline;"&gt;cluster&lt;/span&gt; of Docker hosts: enterprise-grade, secure communication, PKI with automation, dynamic addition of nodes&lt;/li&gt;&#10;&lt;li&gt;an &lt;span style="text-decoration: underline;"&gt;orchestration engine&lt;/span&gt;, with deployment automation, deploying native swarm apps (using Docker API) and Kubernetes apps.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A Docker nodes can be physical servers, VMs, cloud instances, etc. Nodes are configured as managers or workers. Managers look after the control plane of the cluster, and dispatches tasks to workers. Managers forms a distributed management cluster on its own, and they use Raft protocol to ensure consistency. Workers accept tasks from managers and execute them. Swarm mandatorily uses TLS to encrypt communications, authenticate nodes, and authorize roles, with Automatic key rotation.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="388" src="https://static.digihunch.com/wp-content/uploads/2020/05/swarm-node-1024x388.webp" alt="" class="wp-image-13095" srcset="https://static.digihunch.com/wp-content/uploads/2020/05/swarm-node-1024x388.webp 1024w, https://static.digihunch.com/wp-content/uploads/2020/05/swarm-node-300x114.webp 300w, https://static.digihunch.com/wp-content/uploads/2020/05/swarm-node-768x291.webp 768w, https://static.digihunch.com/wp-content/uploads/2020/05/swarm-node-1536x582.webp 1536w, https://static.digihunch.com/wp-content/uploads/2020/05/swarm-node-2048x777.webp 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The atomic unit of scheduling on a swarm is the service. When a container is wrapped in a service, we call it a task or a replica, and the service construct adding things like scaling, rolling updates and simple rollbacks.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To initialize a swarm, we need to have the following ports open. Then we can initialize the first manager node, join additional manager nodes, and then join workers.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;2377/tcp: for secure client-to-swarm communication&lt;/li&gt;&#10;&lt;li&gt;7946/tcp &amp;amp; udp: for control plane gossip&lt;/li&gt;&#10;&lt;li&gt;4789/udp: for VXLAN-based overlay networks&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A Docker node can exist either in single-engine mode as stand alone, or in swarm mode as part of a swarm. Service only exist in swarm mode. Running docker swarm init on a Docker host in single-engine mode will switch that node into swarm mode, create a new swarm, and make the node the first manager of the swarm. Then additional nodes can be joined as managers or workers.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Swarm managers have native support for high availability, through an active-passive, multi-manager HA. Only one manager is considered active (the leader), which is the only one that will ever issue live commands against the swarm. If a passive manager receives commands for the swarm, it proxies them across to the leader.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Managers are either leaders or followers. This is Raft terminalogy because swarm uses an impelementation of the Raft consensus althorithm to power manager HA. As to HA, the following two best practices apply:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;deploy an odd number of managers&lt;/li&gt;&#10;&lt;li&gt;don&amp;#8217;t deploy too many managers (3 or 5 recommended, never more than 7)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Having an odd number of managers reduces the chances of split-brain conditions. Having less than 7 managers ensures that achieving consensus is quick.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With a service, we can specify name, port mappings, network to attach to, and images, as well as desired state for an application service. It is recommended in production environment to use docker-compose template to specify service. Services have replication mode, and the default is replicated. This will deploy a desired number of replicas and distribute them as evenly as possible across the cluster. The other mode is global, which runs a single replica on every node in the swarm.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Running &amp;#8220;docker service scale&amp;#8221; command can scale the number of service replicas from 5 to 10, which in the background updates the service&amp;#8217;s desired state to the newly specified number of replicas. Behind the scenes, Swarm also runs a scheduling algorithm that defaults to balancing replicas as evenly as possible across the node in the swarm. Docker makes it super easy to push updates to deployed applications. With rolling update, you may specify number of replicas to update at a time, and cool-off period per update.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a class="rank-math-link" href="https://upcloud.com/community/stories/docker-swarm-vs-kubernetes-comparison-of-the-two-giants-in-container-orchestration/"&gt;Here&lt;/a&gt; is a great article on the difference between Docker Swarm and Kubernetes.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/05/revamp-ansible-directory-for-scalability-1-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Ansible at scale 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/05/ansible-directory-for-scalability-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Ansible at scale 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>