<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>dns on Digi Hunch</title><link>https://static.digihunch.com/tag/dns/</link><description>Recent content in dns on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Mon, 12 May 2025 23:28:25 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/dns/index.xml" rel="self" type="application/rss+xml"/><item><title>Service and Ingress -Traffic Management in Kubernetes</title><link>https://static.digihunch.com/2021/07/traffic-management-in-kubernetes-service-and-ingress/</link><pubDate>Sun, 04 Jul 2021 01:30:00 -0400</pubDate><guid>https://static.digihunch.com/2021/07/traffic-management-in-kubernetes-service-and-ingress/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-ingress-service.webp" alt="Featured image of post Service and Ingress -Traffic Management in Kubernetes" /&gt;&lt;p class="wp-block-paragraph"&gt;Update 2022-08 &amp;#8211; Read my latest article on &lt;a href="https://medium.com/slalom-build/managing-ingress-traffic-on-kubernetes-platforms-ebd537cdfb46"&gt;ingress traffic management&lt;/a&gt;. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this post we discuss the traffic management in Kubernetes, specifically on Service and Ingress objects. Let&amp;#8217;s start with a traditional architecture:&lt;/p&gt;&#10;&lt;p class="has-white-background-color has-background wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="463px" viewBox="-0.5 -0.5 463 251" style="max-width:100%;max-height:251px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="70" width="460" height="30" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 458px; height: 1px; padding-top: 85px; margin-left: 1px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Network Load Balancer&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="230" y="89" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Network Load Balancer&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="230" cy="20" rx="60" ry="20" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 171px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Client&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="230" y="24" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Client&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 230 63.63 L 230 46.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 230 68.88 L 226.5 61.88 L 230 63.63 L 233.5 61.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 230 41.12 L 233.5 48.12 L 230 46.37 L 226.5 48.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;rect x="321.43" y="110" width="140" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 247px; margin-left: 322px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;VM&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="391" y="247" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;VM&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="330" y="130" width="122.86" height="30" rx="4.5" ry="4.5" fill="#d5e8d4" stroke="#82b366" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 121px; height: 1px; padding-top: 145px; margin-left: 331px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;nginX&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="391" y="149" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;nginX&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="355" cy="205" rx="25" ry="25" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/ellipse&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 205px; margin-left: 331px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;App1&lt;br&gt;Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="355" y="209" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;App1&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="427.86" cy="205" rx="25" ry="25" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/ellipse&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 205px; margin-left: 404px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;App2&lt;br&gt;Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="428" y="209" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;App2&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 360.71 160 L 356.75 173.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 355.31 178.92 L 353.87 171.23 L 356.75 173.88 L 360.6 173.16 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 422.14 160 L 426.11 173.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 427.56 178.93 L 422.27 173.16 L 426.11 173.88 L 429 171.23 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;rect x="160" y="110" width="140" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 247px; margin-left: 161px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;VM&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="230" y="247" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;VM&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 231 100 L 231.34 123.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 231.41 128.88 L 227.81 121.93 L 231.34 123.63 L 234.81 121.83 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;rect x="170" y="130" width="122.86" height="30" rx="4.5" ry="4.5" fill="#d5e8d4" stroke="#82b366" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 121px; height: 1px; padding-top: 145px; margin-left: 171px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;nginX&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="231" y="149" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;nginX&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="195" cy="205" rx="25" ry="25" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/ellipse&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 205px; margin-left: 171px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;App1&lt;br&gt;Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="195" y="209" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;App1&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="267.86" cy="205" rx="25" ry="25" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/ellipse&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 205px; margin-left: 244px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;App2&lt;br&gt;Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="268" y="209" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;App2&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 200.71 160 L 196.75 173.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 195.31 178.92 L 193.87 171.23 L 196.75 173.88 L 200.6 173.16 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 262.14 160 L 266.11 173.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 267.56 178.93 L 262.27 173.16 L 266.11 173.88 L 269 171.23 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;rect x="0" y="110" width="140" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 247px; margin-left: 1px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;VM&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="70" y="247" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;VM&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="10" y="130" width="122.86" height="30" rx="4.5" ry="4.5" fill="#d5e8d4" stroke="#82b366" pointer-events="none"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 121px; height: 1px; padding-top: 145px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;nginX&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="71" y="149" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;nginX&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="35" cy="205" rx="25" ry="25" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/ellipse&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 205px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;App1&lt;br&gt;Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="35" y="209" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;App1&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="107.86" cy="205" rx="25" ry="25" fill="#ffffff" stroke="#000000" pointer-events="none"&gt;&lt;/ellipse&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 205px; margin-left: 84px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "&gt;App2&lt;br&gt;Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="108" y="209" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;App2&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 40.72 160 L 36.75 173.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 35.31 178.92 L 33.87 171.23 L 36.75 173.88 L 40.6 173.16 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 102.14 160 L 106.11 173.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 107.56 178.93 L 102.27 173.16 L 106.11 173.88 L 109 171.23 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 71 100 L 71.34 123.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 71.41 128.88 L 67.81 121.93 L 71.34 123.63 L 74.81 121.83 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 391 100 L 391.34 123.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;path d="M 391.41 128.88 L 387.81 121.93 L 391.34 123.63 L 394.81 121.83 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"&gt;&lt;/path&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;/g&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Viewer does not support full SVG 1.1&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this traditional architecture, we run application as processes on the operating system on each virtual machine. The application process is bound to a certain ports on the operating system, and is wrapped into services (e.g. systemd). On the same virtual machine, there is also a reverse proxy service (e.g. Nginx). There are several main functional areas as listed below, and how they are fulfilled in traditional architecture:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-regular"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Requirement&lt;/td&gt;&lt;td&gt;Detail&lt;/td&gt;&lt;td&gt;Typically fulfilled by&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;L4 Load balancing&lt;/td&gt;&lt;td&gt;TCP/UDP traffic routing, operating at L3 and L4&lt;/td&gt;&lt;td&gt;Network Load Balancer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TLS termination&lt;/td&gt;&lt;td&gt;Terminate TLS traffic, operating at L4&lt;/td&gt;&lt;td&gt;TLS termination is available in many products such as Load Balancer (L4/L7), Nginx, or the application itself.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Path-based routing&lt;/td&gt;&lt;td&gt;Route request based on URI path, operating at L7&lt;/td&gt;&lt;td&gt;Nginx, modern L7 Load Balancer.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Authentication&lt;/td&gt;&lt;td&gt;Integrate with external identity store, operating at L7&lt;/td&gt;&lt;td&gt;Nginx, modern L7 Load Balancer.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;These requirements are the problems that Kubernetes needs to solve in its own architecture. They are solved by different abstraction objects in Kubernetes. Before getting to traffic management, we first need to expose an application.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-service"&gt;Service&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;During traditional application deployment, we often need to organize a group of homogenous application instances as a single target for batch operation. The Pod object is an abstraction of a single application instance. The Deployment object is an abstraction of a group of homogenous Pods. The purpose of Deployment object is for Pod orchestration only. It is not designed to expose the application. To define how we want to expose an application, we use &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/"&gt;Service&lt;/a&gt; object.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The service object does not carry exactly the same functionalities as an operating system service. It connects to the frontend (client), as well as to the backend (server). There are two ways to connect to a backend:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;To connect to Pods as backend, use &lt;strong&gt;selector&lt;/strong&gt; and &lt;strong&gt;label&lt;/strong&gt;; the target port is Pod&amp;#8217;s port. This is the most common use case.&lt;/li&gt;&#10;&lt;li&gt;To connect to a custom backend (e.g. external database, services in different namespaces, during workload migration), define an &lt;strong&gt;Endpoints object&lt;/strong&gt; (including address and port), and target the port;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the frontend, there are several ways to expose service to client, as defined in ServiceType property. Each represents a level of exposure:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;ClusterIP (default)&lt;/strong&gt;: the service gets an internal IP address in the cluster. This is the lowest level of exposure. The service is only reachable from within the cluster. This is a good choice when the service is for internal assumption, such as database.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;NodePort&lt;/strong&gt;: the service is exposed at a static port on each node. The port must be in a range pre-specified during cluster provisioning (default 30000-32767). Each node proxies traffic to that port to the service. Without a load balancer, each node is a point of entry on its own. &lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;LoadBalancer&lt;/strong&gt;: this option works with external load balancer in cloud deployments. The actual creation of the &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer"&gt;load balancer&lt;/a&gt; happens asynchronously, and information about the provisioned balancer is published in the Service&amp;#8217;s&amp;nbsp;&lt;code&gt;.status.loadBalancer&lt;/code&gt;&amp;nbsp;field. Some cloud providers allow you to specify the&amp;nbsp;&lt;code&gt;loadBalancerIP&lt;/code&gt;. The benefit Load Balancer over NodePort, is it provides a single point of entry (for each service).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;ExternalName&lt;/strong&gt;: rare use case with custom endpoint object.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 class="wp-block-heading" id="h-headless-service"&gt;Headless service&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With service type ClusterIP, if you explicitly specify&amp;nbsp;&lt;code&gt;"None"&lt;/code&gt;&amp;nbsp;for the cluster IP (&lt;code&gt;.spec.clusterIP&lt;/code&gt;), the service is considered a headless service. With a headless service, a cluster IP is not allocated, kube-proxy does not handle these services, and there is no load balancing or proxying done by the platform for them. Each connection to the service is forwarded to one randomly selected backing pod. Hence the document points out that you can use a headless Service to interface with other service discovery mechanisms, without being tied to Kubernetes implementation. The behaviour differs slightly based on whether selectors are present, but both resembles DNS routing with multiple A record.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-virtual-ip"&gt;Virtual IP&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Kubernetes manages service traffic with virtual IP. When clients connect to virtual IP (VIP), the traffic is automatically transported to an appropriate endpoint. Virtual IP is implemented with kube-proxy. Kube-proxy can work in three modes: userspace, iptables and IPVS. I discussed these terms in &lt;a href="https://static.digihunch.com/2020/11/ipvs-iptables-and-kube-proxy/"&gt;this&lt;/a&gt; post last year. The takeaway is that IPVS is the recommended mode.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-ingress"&gt;Ingress&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Ingress in Kubernetes cannot match up with a counterpart in traditional architecture. It is mainly for path-based request routing. Also, do not confuse Ingress object with Ingress rule as a policy type in Network Policy object. Ingress is a high level abstraction and should be considered over Service object when the followings are involved in the routing.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Content-based or path-based L7 routing&lt;/li&gt;&#10;&lt;li&gt;Multiple protocols (e.g. gRPC, WebSockets)&lt;/li&gt;&#10;&lt;li&gt;Authentication&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Ingress usually work with service object (ClusterIP), as illustrated in Kubernetes documentation:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="661" height="321" src="https://static.digihunch.com/wp-content/uploads/2021/06/image-4.png" alt="" class="wp-image-2452"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Also note that if you have a service other than HTTP or HTTPS, that you need to expose to the Internet, it is recommended to use a service object of NodePort or LoadBalancer type.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We call Ingress a high-level abstraction. Ingress object (aka ingress resource) itself does not expose application. It simply defines a set of routing rules. The implementation is provided by another object (Ingress Controller), who enforces the routing rules by monitoring and manage traffic using its own Service and Pods. You must have an Ingress controller to satisfy an Ingress. Only creating an Ingress resource has no effect. There are a number of &lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/"&gt;Ingress Controllers&lt;/a&gt; to choose from. &lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-ingress-resource"&gt;Ingress Resource&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In an Ingress resource, annotations are used to configure some options, depending on the corresponding Ingress Controller. What annotation can be used depends on the the specific Ingress Controller. The backend can be either a service, or a resource. A common usage for a Resource backend is to ingress data to an object storage backend with static assets. You can define DefaultBackend for an Ingress.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Each Ingress should specify a class, a reference to an IngressClass resource that contains additional configuration including the name of the controller that should implement the class. Before the IngressClass resource and ingressClassname field were added in Kubernetes 1.8, Ingress classes were specified with a &lt;code&gt;kubernetes.io/ingress.class&lt;/code&gt;&amp;nbsp;annotation on the Ingress. This annotation was never formally defined, but was widely supported by Ingress controllers. For example, &lt;a href="https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/"&gt;here&lt;/a&gt; is the annotations supported by Nginx Controllers.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Below is the yaml output of the ingress from Kubernetes &lt;a href="https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/service/networking/minimal-ingress.yaml"&gt;documentation&lt;/a&gt;:&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-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;apiVersion&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;networking&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;k8s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;io&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Ingress&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;metadata&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;minimal&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ingress&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;annotations&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;nginx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ingress&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;kubernetes&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;io&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;rewrite&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;spec&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rules&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;paths&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;/testpath&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;pathType&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Prefix&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;backend&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;service&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;port&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;number&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 class="wp-block-heading" id="h-ingress-controller"&gt;Ingress Controller&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Ingress Controller exists in the form of Pods, usually as daemonSet, sometimes as a deployment. The Pods listens for requests to create or modify Ingress within the cluster, and converts the rules in the manifest into configuration directives for a load balancing components. Below is all the components related to Ingress Controller:&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-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; kubectl -n ingress-nginx get all&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME READY STATUS RESTARTS AGE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pod/ingress-nginx-admission-create-s7486 0/1 Completed &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pod/ingress-nginx-admission-patch-sjt2q 0/1 Completed &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pod/ingress-nginx-controller-5b74bc9868-6vmjc 1/1 Running &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span style="color:#f92672"&gt;(&lt;/span&gt;S&lt;span style="color:#f92672"&gt;)&lt;/span&gt; AGE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;service/ingress-nginx-controller LoadBalancer 10.106.25.194 localhost 80:31774/TCP,443:31576/TCP 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;service/ingress-nginx-controller-admission ClusterIP 10.102.38.191 &amp;lt;none&amp;gt; 443/TCP 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME READY UP-TO-DATE AVAILABLE AGE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deployment.apps/ingress-nginx-controller 1/1 &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME DESIRED CURRENT READY AGE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;replicaset.apps/ingress-nginx-controller-5b74bc9868 &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME COMPLETIONS DURATION AGE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;job.batch/ingress-nginx-admission-create 1/1 9s 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;job.batch/ingress-nginx-admission-patch 1/1 25s 11d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Ingress Controller can be implemented by load balancer resource from cloud platform, or Nginx. When you have one ingress resource and one controller, the matching is assumed. When you have multiple controllers, you need to use the &lt;a href="https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/"&gt;mechanism&lt;/a&gt; from the ingress controller to ensure correct matching.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Nginx is a popular controller and there are a couple of implementations as illustrated &lt;a href="https://www.nginx.com/blog/guide-to-choosing-ingress-controller-part-4-nginx-ingress-controller-options/#NGINX-vs.-Kubernetes-Community-Ingress-Controller"&gt;here&lt;/a&gt;. Let&amp;#8217;s take a look at Nginx Controller as an example. The troubleshooting &lt;a href="https://docs.nginx.com/nginx-ingress-controller/troubleshooting/"&gt;guide&lt;/a&gt; states that, For each Ingress/VirtualServer resource, the Ingress Controller generates a corresponding NGINX configuration file in the&amp;nbsp;&lt;code&gt;/etc/nginx/conf.d&lt;/code&gt;&amp;nbsp;folder. Additionally, the Ingress Controller generates the main configuration file&amp;nbsp;&lt;code&gt;/etc/nginx/nginx.conf&lt;/code&gt;, which includes all the configurations files from&amp;nbsp;&lt;code&gt;/etc/nginx/conf.d&lt;/code&gt;.&amp;nbsp;In the Rancher ingress example above, we can check the nginx &lt;a href="https://docs.nginx.com/nginx-ingress-controller/troubleshooting/#checking-the-generated-config"&gt;configuration&lt;/a&gt; with the commands below:&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-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl exec ingress-nginx-controller-5b74bc9868-6vmjc -n ingress-nginx -- cat /etc/nginx/nginx.conf | less&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;It is important to understand the difference between a load-balancer type service and an ingress. The &lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress"&gt;documentation&lt;/a&gt; for ingress states that: An Ingress does &lt;strong&gt;not&lt;/strong&gt; expose &lt;strong&gt;arbitrary ports or protocols&lt;/strong&gt;. Exposing services other than HTTP and HTTPS to the internet typically uses a service of type&amp;nbsp;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/#nodeport"&gt;Service.Type=NodePort&lt;/a&gt;&amp;nbsp;or&amp;nbsp;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer"&gt;Service.Type=LoadBalancer&lt;/a&gt;. This is because ingress operates at layer 7, so routes connections based on http host header or url path. Load balanced services operate at layer 4 so can load balance arbitrary tcp/udp/sctp services. Ingress should be backed by L7 load balancer, whereas load-balancer service should be backed by L4 load balancer.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-nginx-ingress-controller"&gt;Nginx Ingress Controller&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are several flavours of Nginx ingress controllers that cause much confusion. It is clarified on a blog &lt;a href="https://www.nginx.com/blog/guide-to-choosing-ingress-controller-part-4-nginx-ingress-controller-options/#NGINX-vs.-Kubernetes-Community-Ingress-Controller"&gt;post&lt;/a&gt; on Nginx website. To recap:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Community version: Found in the &lt;a href="https://github.com/kubernetes/ingress-nginx"&gt;kubernetes/ingress-nginx&lt;/a&gt; repo, the community Ingress controller is based on Nginx Open Source, with docs on &lt;a href="https://kubernetes.github.io/ingress-nginx/"&gt;Kuberentes.io&lt;/a&gt;. It is maintained by the Kubernetes community with &lt;a href="https://www.nginx.com/blog/nginx-sprint-2-0-clear-vision-fresh-code-new-commitments-to-open-source/#resources-for-kubernetes"&gt;assistance&lt;/a&gt; from the F5 Nginx team.&lt;/li&gt;&#10;&lt;li&gt;Nginx version: Found in the &lt;a href="https://github.com/nginxinc/kubernetes-ingress"&gt;nginxinc/kubernetes-ingress&lt;/a&gt; repo, the NGINX Ingress Controller is developed and maintained directly by F5 NGINX team, with docs on &lt;a href="https://docs.nginx.com/nginx-ingress-controller/"&gt;docs.nginx.com&lt;/a&gt;. It is available in two editions:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;NGINX Open Source-based&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://www.nginx.com/products/nginx-ingress-controller/"&gt;NGINX Plus&lt;/a&gt;-based&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are also a number of other Ingress controller based on NGINX, such as Kong, but their names are easily distinguished. If you&amp;#8217;re not sure which version you&amp;#8217;re using, check the container image, then compare the image name with the repos listed above.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-load-balancer"&gt;Load Balancer&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Kubernetes by itself does not have an object for Load Balancer. The function of traditional Load Balancer is implemented through Service and Ingress objects in Kubernetes, both of which can be satisfied by a load balancer object from the cloud platform (service-managed load balancer and ingress-managed load balancer). Alternatively, you may stand up a standalone load balancer independent of the Kubernetes cluster, which is not recommended.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If your architecture is complex and you have a lot of services (e.g. using microservice), then the overhead of managing everything with Service and Ingress in Kubernetes can be significant. In that case, consider delegating these tasks to a &lt;a href="https://en.wikipedia.org/wiki/Service_mesh"&gt;service mesh&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-troubleshooting"&gt;Troubleshooting&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There isn&amp;#8217;t a single recipe for troubleshooting service and ingress on Kubernetes. There are some good general guide lines &lt;a href="https://itnext.io/kubernetes-troubleshooting-saga-part-1-pods-deployments-and-cluster-52df5017df93"&gt;here&lt;/a&gt; and &lt;a href="https://itnext.io/kubernetes-troubleshooting-saga-part-2-networking-and-dns-connectivity-7f11013f6148"&gt;here&lt;/a&gt;, in addition to the guides (&lt;a href="https://kubernetes.io/docs/tasks/debug-application-cluster/debug-cluster/"&gt;here&lt;/a&gt; and &lt;a href="https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/"&gt;here&lt;/a&gt;) from official documentation. To run networking command from within the Pod network, you can launch a Pod using nicolaka &lt;a href="https://github.com/nicolaka/netshoot"&gt;netshoot&lt;/a&gt; image.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Bottom line&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We compared service and ingress in Kubernetes. In real life, we use both, and oftentimes along with CRDs of service mesh.&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/2021/06/kubernetes-networking-solutions-overview/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Kubernetes Networking Solutions Overview&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/07/helm-configuration-management-for-kubernetes-resources/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Helm – Configuration Management for Kubernetes Resources&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Kubernetes Networking Solutions Overview</title><link>https://static.digihunch.com/2021/06/kubernetes-networking-solutions-overview/</link><pubDate>Tue, 22 Jun 2021 12:14:26 -0400</pubDate><guid>https://static.digihunch.com/2021/06/kubernetes-networking-solutions-overview/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-k8s-networking.webp" alt="Featured image of post Kubernetes Networking Solutions Overview" /&gt;&lt;p class="wp-block-paragraph"&gt;Kubernetes networking involves a lot of details. We discuss some CNI plugins in this post. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The most basic mode is &lt;a href="https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#kubenet"&gt;kubenet&lt;/a&gt;. We use &amp;#8211;network-plugin=kubenet with kubelet process to use it. Kubenet is not a CNI plugin, but it works with bridge, lo and host-local (CNI-compliant implementations). We can directly specify MTU with &amp;#8211;network-plugin-mtu. Kubenet is a basic network plugin, based on bridge plugin, with the addition of port mapping and traffic shaping. It does not offer cross-node networking itself. Today it is typically used with managed clusters by cloud providers, where the cloud provider set up routing rules themselves for inter-node communication.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When a cluster goes multi-node, the main challenge is communication between Pods across different nodes. Pods come and go. The size of cluster could increase or decrease as well. The network solutions come in two network types: overlay network based on encapsulation, or non-overlay networks, most likely using routing techniques. Common backends for for multi-host container networking solutions include VXLAN encapsulation, IPIP encapsulation, host-gw, IPSec. In addition, there are some backends that only used by certain plugins.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-common-backends"&gt;Common Backends&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;VXLAN&lt;/strong&gt;: use in-kernel VXLAN to encapsulate the packets. VXLAN is a &lt;a href="https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking#"&gt;virtual networking capability&lt;/a&gt; in Linux which is also used in &lt;a href="https://static.digihunch.com/2020/08/virtualization-4-of-4-networking/"&gt;virtualization&lt;/a&gt; technology. VXLAN is an overlay technology requiring encapsulation of overlay network&amp;#8217;s layer-2 frame into UDP packet at layer 4 of underlay network. When configured, the VxLAN backend creates a Flannel interface on every host. When a container on one node wishes to send traffic to a different node, the packet goes from the container to the bridge interface in the host&amp;#8217;s network namespace. From there the bridge forwards it to the Flannel inteface because the kernel route table designates that this interface is the target for the non-local portion of the overlay network. The Flannel network drive wraps the packet in a UDP packet and sends it to the target host. Once it arrives at its destination, the process flows in reverse, with the Flannel driver on the destination host unwrapping the packet, sending it to the bridge interface, and from there the packet find its way into the overlay network and to the destination Pod.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;host-gw&lt;/strong&gt;: the host-gw is a non-overlay solution that maintains route tables on Linux Host to allow Pods to communicate across Nodes. It is only used in Flannel plugin. Suppose we have two hosts, each with two containers as connected below. Initially, container0 is not able to reach container2 because eth0 on node0 does not have an entry that matches container2&amp;#8217;s IP address. The packet is there sent to default route, which isn&amp;#8217;t destined to container2. &lt;/p&gt;&#10;&lt;figure class="wp-block-image is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://gblobscdn.gitbook.com/assets%2F-LOuzrzA9qdsjWfu2rC9%2F-LUPoGQ1ihiJFofTaO7A%2F-LUPoH4I_mQkNKdfkxU1%2Fhost-gw.png?alt=media" alt="" style="width:840px;height:366px" width="840" height="366"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;However, if we build rules to match container IP address, on the route table of each node. The issue would be solved. This is essentially how host-gw works. Specifically, on node 0, we add &amp;#8220;ip route add 192.168.1.0/24 via 10.20.0.2 dev eth0&amp;#8221;, on node 1, we add &amp;#8220;ip route add 192.168.0.0/24 via 10.20.0.1 dev eth0). The host-gw in Flannel will manage rule addition to us. Note that the two hosts must have direct layer 2 connectivity. In other words, there must not be a router between the two nodes. Otherwise, the routing table on the router is out of reach. In fact, all nodes in a Flannel network must have layer 2 connectivity with each other. In other words, all nodes must be in a single LAN. Host-gw provides better performance than VxLAN.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;IPSec&lt;/strong&gt; uses in-kernel IPSec to encapsulate and encrypt the packets. IPsec is a group of protocols to ensure authentication and encryption per packet between devices. Since it secures traffic at layer 3 and now it has become a major backend technology for VPN. IPsec adds several headers and trailers to datagram containing authentication and encryption information. The two major protocols working in IPSec are AH (Authentication Header) and ESP (Encapsulating Security Payload). AH serves up authentication services only; ESP provides both authentication and encryption abilities. It also uses IKE protocol for key exchange.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;IPSec works in two modes: transport and tunnelling mode. &lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Transport mode creates a secure tunnel between two devices end to end. The payload of each datagram is encrypted, but the original IP header is not. Intermediary routers are thus able to view the final destination of each datagram, unless a separate tunnelling protocol (e.g. GRE) is used.&lt;/li&gt;&#10;&lt;li&gt;Tunnel mode works between two endpoints, such as two routers, protecting all traffic that goes through the tunnel. The original IP header containing the final destination of the datagram is encrypted, in addition to the payload. To tell intermediary routers where to forward the datagrams, IPsec adds a new IP header. At each end of the tunnel, the routers decrypt the IP headers to deliver the datagram to their destinations. The intermediary routers does not know the final destination, or what transport protocol is used.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;IPIP&lt;/strong&gt; (IP over IP) tunnel is typically used to connect two internal IPv4 subnets through public IPv4 internete. It has the lowest overhead but can only transmit IPv4 unicast traffic.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-cni-plugins"&gt;CNI Plugins&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Originally, the network functions were developed in-tree. Then the CNI specification came up to allow plugin development out-of-tree to implement cluster networking functions. The Container Network Interface seeks to completely decoupled network management from container runtime. Kubernetes picked CNI over CNM in 2016, as discussed in my &lt;a href="https://static.digihunch.com/2020/08/virtualization-4-of-4-networking/"&gt;virtualization&lt;/a&gt; discussion. CNI clearly defines the specification for following activities:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;When a Pod comes up, give it a network interface&lt;/li&gt;&#10;&lt;li&gt;Assign IP to the network interface&lt;/li&gt;&#10;&lt;li&gt;When a Pod is deleted, delete the associated network interface&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When we configure a Kubernetes cluster, we must specify &amp;#8211;network-plugin switch, so that the cluster is operational. If we use CNI as network-plugin, we also need to install the plugin, optionally with the help of Rancher.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the worker node, we use &amp;#8211;network-plugin=cni with kubelet process to use CNI plugins. A plugin may consist one or more binaries. The binaries are located in /opt/cni/bin (or otherwise specified by &amp;#8211;cni-bin-dir). The configurations are located in /etc/cni/net.d (or otherwise specified in &amp;#8211;cni-conf-dir). Note that the configuration file may reference different plugin implementations for different network management purpose (e.g. interface creating, address allocation, etc). The &lt;a href="https://github.com/containernetworking/plugins"&gt;container networking repo&lt;/a&gt; provided some reference implementations and some of them are used by other plugins. These reference implementations include:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Main (interface creating): bridge, ipvlan, loopback, ptp, macvlan, etc&lt;/li&gt;&#10;&lt;li&gt;IPAM (IP address management): host-local, dhcp, static&lt;/li&gt;&#10;&lt;li&gt;Meta (other plugins): portmap, bandwidth&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;So, a CNI plugin consists of a networking solution for backend, and binaries to cover the aspects outlined above. I discussed some common backends above. Below I will introduce some common plugins and backends only available to each plugin&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-flannel"&gt;Flannel&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Flannel by CoreOS: supports a range of backends. The advantage of Flannel is it reduces the complexity of doing port mapping. &lt;a href="https://blog.laputa.io/kubernetes-flannel-networking-6a1cb1f8ec7c"&gt;This&lt;/a&gt; is a great post that covers the mechanism.&lt;/p&gt;&#10;&lt;figure class="wp-block-image is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://miro.medium.com/max/983/1*EFr8ohzABfStS7o9gGMYKw.png" alt="" style="width:737px;height:217px" width="737" height="217"/&gt;&lt;figcaption class="wp-element-caption"&gt;Flannel with overlay (e.g. VxLAN on UDP encapsulation)&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It supports VXLAN, host-gw, IPSec, IPIP as well as the followings:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;Amazon VPC&lt;/strong&gt;: recommended with Amazon VPC. AWS VPC creates IP routes in an AWS route table. The number of records in this table is limited by 50 so you can&amp;#8217;t have more than 50 machines in a cluster.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;GCE&lt;/strong&gt;: recommended with Google Compute Engine Network. Instead of using encapsulation, GCE also manipulates IP route to achieve maximum performance. Because of this, a separate flannel interface is not created.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;UDP&lt;/strong&gt;: debugging only for old kernels that don&amp;#8217;t support VXLAN&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-calico"&gt;Calico&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://en.wikipedia.org/wiki/Border_Gateway_Protocol"&gt;Border Gateway Protocol &lt;/a&gt;(BGP) is a standardized exterior gateway protocol designed to exchange routing and reachability information among autonomous systems (AS) on the Internet.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Calico operates at layer 3. It prefers BGP without an overlay network for the highest speed and efficiency, but in scenarios where hosts cannot directly communicate with one another, it can utilize an overlay solution (e.g. VxLAN or IP-in-IP). Calico also supports network policies for protecting workloads and nodes from malicious activity or aberrant applications.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Calico networking Pod contains a CNI container to keep track of Pod deployment, and register addresses and routes. It also contains a daemon that announces the IP and route information to the network via the Border Gateway Protocol (BGP). The BGP daemon build a map of the network that enables cross-host communication.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Calico requires a distributed and fault-tolerant key/value store, and deployments often choose etcd to deliver this component. Calico uses it to store metadata about routes, virtual interfaces, and entwork policy objects. Calico can either use a separate HA deployment of etcd, or the same etcd datastore with the Kubernetes cluster.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When we are unable to use BGP (e.g. with cloud provider, or in an environment where we have no permission to configure router peers. Calico&amp;#8217;s IP-in-IP mode encapsulates packets before sending them to other nodes.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Once IP-in-IP is configured, Calico wraps inter-Pod packets in a new packet with headers that indicate the source of the packet is the host with the originating Pod, and the target of the packet is the host with the destination Pod. The Linux kernel performs this encapsulation, and then forwards the packet to the destination host where it is unwrapped and delivered to the destination Pod.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-canal"&gt;Canal&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The followings is quoted from Rancher &lt;a href="https://rancher.com/blog/2019/2019-03-21-comparing-kubernetes-cni-providers-flannel-calico-canal-and-weave/"&gt;website&lt;/a&gt;:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Canal seeks to integrate the networking layer provided by Flannel with the networking policy capabilities of Calico. As the contributors worked through the details however, it became apparent that a full integration was not necessarily needed if work was done on both projects to ensure standardization and flexibility. As a result, the official project became somewhat defunct, but the intended ability to deploy the two technology together was achieved. For this reason, it&amp;#8217;s still sometimes easiest to refer to the combination as &amp;#8220;Canal&amp;#8221; even if the project no longer exists. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Because Canal is a combination of Flannel and Calico, its benefits are also at the intersection of these two technologies. The networking layer is the simple overlay provided by Flannel that works across many different deployment environments without much additional configuration. The network policy capabilities layered on top supplement the base network with Calico’s powerful networking rule evaluation to provide additional security and control.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-weave-net"&gt;Weave Net&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Weave Net by Weaveworks offers a different paradigm. Weave creates a mesh overlay network between each of the nodes in the cluster, allowing for flexible routing between participants. Applications use the network just as if the containers were all plugged into the same network switch, with no need to configure port mappings and links.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For more good references to determine networking options, check out these posts:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Calico &lt;a href="https://projectcalico.docs.tigera.io/networking/determine-best-networking"&gt;blog&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Rancher &lt;a href="https://www.suse.com/c/rancher_blog/comparing-kubernetes-cni-providers-flannel-calico-canal-and-weave/"&gt;blog&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Kubevious &lt;a href="https://kubevious.io/blog/post/comparing-kubernetes-container-network-interface-cni-providers"&gt;blog&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&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/2021/06/kubernetes-storage-explained/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Kubernetes Storage Explained – from in-tree plugin to CSI&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/07/traffic-management-in-kubernetes-service-and-ingress/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Service and Ingress -Traffic Management in Kubernetes&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Secure web application deployment</title><link>https://static.digihunch.com/2021/05/secure-web-application-deployment/</link><pubDate>Sun, 16 May 2021 15:19:41 -0400</pubDate><guid>https://static.digihunch.com/2021/05/secure-web-application-deployment/</guid><description>&lt;p class="wp-block-paragraph"&gt;In Nov 2020, I created &lt;a href="https://github.com/digihunch/orthweb/tree/2181001e29b0da5fd55f51a6dc2a522d3f83aee6" class="rank-math-link"&gt;OrthWeb&lt;/a&gt; project, a deployment of Orthanc&amp;#8217;s server. Orthanc is a DICOM viewer and repo shipped in Docker container. In the &lt;a href="https://static.digihunch.com/2020/11/medical-imaging-web-server-deployment-pipeline/" class="rank-math-link"&gt;deployment project&lt;/a&gt;, I use Terraform to provision infrastructure, including a managed PostgreSQL instance, an EC2 instance for docker runtime, and the init script to bring up the web service. I whipped up the project for a demo, and skipped some security configurations. For example, the password was stored in clear text in Terraform configuration. The web certificate is stored in the repository. I recently had some time to fix that. My effort leads up to the conclusion that this requires a better platform (i.e. managed Kubernetes cluster). So I wanted to note down how I got there.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Secret store&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In AWS, both parameter store and secret manager can act as secret store. Secrets manager comes at higher cost but some additional features, such as built-in password generator, secret rotation, and cross-account access. We use Secret Manager but we generate password within Terraform because we need to specify password during database provisioning. Secret store requires certain special characters to be eliminated. Terraform can specify the special characters allowed. For EC2 instance to pull from secret manager, the following entities are needed:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;A secret store&lt;/li&gt;&#10;&lt;li&gt;A VPC endpoint to expose secret store to subnet via private route. &lt;/li&gt;&#10;&lt;li&gt;The VPC endpoint needs its own security group&lt;/li&gt;&#10;&lt;li&gt;The instance profile of the EC2 instance must contain an IAM role to get secret value&lt;/li&gt;&#10;&lt;li&gt;The security group of EC2 instance needs to allow traffic to secret store&lt;/li&gt;&#10;&lt;li&gt;The script from EC2 instance uses VPC endpoint&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This is a common pattern for interaction between computing object and VPC endpoint. The details are in compute.tf, network.tf, secgrp.tf and secret.tf. The secret name needs to be partially randomized to avoid naming conflict with deactivated secrets.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="623" height="323" src="https://static.digihunch.com/wp-content/uploads/2021/05/secmgr.png" alt="" class="wp-image-2250"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Passing Secret to container&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here is an example CLI command to pull secret:&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-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ aws secretsmanager get-secret-value --secret-id DatabaseCreds51c1db4172ae9c54 --query SecretString --output text --endpoint-url https://vpce-0897b168cf1c60df2-khx32o7f.secretsmanager.us-east-1.vpce.amazonaws.com | jq -r .password&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The connection is made via private network route (whether the instance is in public or private subnet). Traffic is encrypted in TLS. Once in the operating system, the secret is available as standard output and can be stored to file, or saved in environment variable. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;My first attempted approach is docker&amp;#8217;s secret store and config so that I do not have to store secret in plain text on the file system. I eventually give up this approach due to several hiccups. First, secret and config are part of Docker swarm service. So it requires initializing docker swarm before I could port in the secret, with the following command:&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-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker swarm init&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo mdbuser123 | docker secret create db_un -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo m1p@ssw0rd | docker secret create db_pw -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo 10.2.32.41 | docker config create db_ep -&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The content of the secret and config are presented as files to the container file system at different locations, as can be verified this way:&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-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker service create --name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;redis&amp;#34;&lt;/span&gt; --secret&lt;span style="color:#f92672"&gt;=&lt;/span&gt;db_un --secret&lt;span style="color:#f92672"&gt;=&lt;/span&gt;db_pw --config&lt;span style="color:#f92672"&gt;=&lt;/span&gt;db_ep redis:alpine&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker container ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker exec -it c8ed2a278ca8 sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cat /db_ep&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cat /run/secrets/db_un&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cat /run/secrets/db_pw&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This is a great way to pass secret and config to container applications. However, since the values are stored as content of file, the main application must be able to load file content as its own configuration value. In my specific scenario, the application expects explicit value in its &lt;a href="https://orthanc.uclouvain.be/book/users/configuration.html" class="rank-math-link"&gt;configuration file&lt;/a&gt;, or environment variable.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the other hand, Docker &lt;a href="https://techbeacon.com/devops/how-keep-your-container-secrets-secure" class="rank-math-link"&gt;document&lt;/a&gt; states that docker secrets do not set environment variables directly. this was a conscous decision, because env var can unintentionally be leaked between containers. In other word I could present secrets as files but the application cannot use it. There is potentially a workaround &lt;a href="https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab" class="rank-math-link"&gt;here&lt;/a&gt; which is great function wise but an additional layer of complexity.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Moreover, I later discovered that this isn&amp;#8217;t even a viable approach if I use docker compose. This is because I must declare those entries from secret store or config store as &lt;a href="https://docs.docker.com/compose/compose-file/compose-file-v3/#configs" class="rank-math-link"&gt;external&lt;/a&gt;, and external secrets are not even available to containers created by docker-compose. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With reluctance, I store the config and secret keys and values to a file, and use the &lt;a href="https://docs.docker.com/compose/environment-variables/#the-env-file" class="rank-math-link"&gt;env_file&lt;/a&gt; section in docker compose to import them as environment variables. The application can pick up environment variables as configuration values.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;X509 Certificate&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We use a self-signed X509 certificate, along with the private key. The &lt;a href="https://orthanc.uclouvain.be/book/faq/https.html#securing-orthanc-using-self-signed-certificate" class="rank-math-link"&gt;creation&lt;/a&gt; is straightforward. However, when I tested on Mac, the browser does not load the page for &lt;a href="https://support.apple.com/en-us/HT210176" class="rank-math-link"&gt;this&lt;/a&gt; reason. Since macOS 10.15, the certificate requires several extensions: ExtendedKeyUsage, Subject alternative names and DNS name. The native openssl from the operating system is outdated (v 1.0.2) and I had to install openssl11 package and create it as follows:&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-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl11 req -x509 -nodes -days &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; -newkey rsa:2048 -keyout /tmp/private.key -out /tmp/certificate.crt -subj /C&lt;span style="color:#f92672"&gt;=&lt;/span&gt;CA/ST&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Ontario/L&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Waterloo/O&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Digihunch/OU&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Imaging/CN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;digihunch.com/emailAddress&lt;span style="color:#f92672"&gt;=&lt;/span&gt;info@3.237.97.93 -addext extendedKeyUsage&lt;span style="color:#f92672"&gt;=&lt;/span&gt;serverAuth -addext subjectAltName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;DNS:orthweb.digihunch.com,DNS:digihunch.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The Mac uses libreSSL backed openSSL utility and can achieve the same with slightly different command line argument.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Next Step&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The limitation with passing secret concerns me and I&amp;#8217;m looking to move to managed Kubernetes platform where &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-environment-variables" class="rank-math-link"&gt;secrets&lt;/a&gt; can be ported to environment variable of Pods. We can also consider &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html" class="rank-math-link"&gt;ECS&lt;/a&gt; in AWS which allows to inject sensitive data from secret manager to container. &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/2021/04/preparing-certified-kubernetes-administrator-exam/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Certified Kubernetes Administrator (CKA) Exam&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/05/getting-started-with-github-actions/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Getting started with GitHub Actions&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Networking basics 2 of 3 – Layer 4 and common network configurations</title><link>https://static.digihunch.com/2019/12/tcp-ip-basics-2-of-3-layer-4-and-common-technologies/</link><pubDate>Sat, 07 Dec 2019 23:19:00 -0400</pubDate><guid>https://static.digihunch.com/2019/12/tcp-ip-basics-2-of-3-layer-4-and-common-technologies/</guid><description>&lt;h3 class="wp-block-heading" id="h-transport-layer"&gt;Transport Layer&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Transport Layer handles multiplexing &amp;amp; de-multiplexing through ports. Port is more or less a virtual concept. Source port is usually ephemeral. Two dominant protocols are TCP and UDP.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;TCP relies on acknowledgement. TCP control flags are SYN, ACK, FIN, URG, PSH, RST, ECE, CWR. TCP connection is established by 3-way handshake and torn down by 4-way termination.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1223" height="502" src="https://static.digihunch.com/wp-content/uploads/2019/12/image.png" alt="" class="wp-image-515"/&gt;&lt;figcaption class="wp-element-caption"&gt;TCP handshake and termination&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Socket &amp;#8211; the instantiation of an end-point in a potential TCP connection. A socket can be in one of the following states:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;LISTEN: a TCP socket is ready and listening for incoming connections;&lt;/li&gt;&#10;&lt;li&gt;SYN_SENT: a SYNC request has been sent but connection hasn&amp;#8217;t been established yet;&lt;/li&gt;&#10;&lt;li&gt;SYN_RECEIVED: a socket previously in a LISTEN state has received a SYNC request and sent a SYN/ACK back;&lt;/li&gt;&#10;&lt;li&gt;ESTABLISHED: connection is up;&lt;/li&gt;&#10;&lt;li&gt;FIN_WAIT: FIN sent, ACK hasn&amp;#8217;t been received yet;&lt;/li&gt;&#10;&lt;li&gt;CLOSE_WAIT: connection has been closed at the TCP layer but the application that opened the socket hasn&amp;#8217;t release the hold on the socket yet;&lt;/li&gt;&#10;&lt;li&gt;CLOSED: connection fully terminated;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="403" height="306" src="https://static.digihunch.com/wp-content/uploads/2023/01/tcp-format.gif" alt="" class="wp-image-7811"/&gt;&lt;figcaption class="wp-element-caption"&gt;TCP packet format&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;TCP is a connection-oriented protocol&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Transport layer is responsible for re-sending data if data is lost&lt;/li&gt;&#10;&lt;li&gt;Sequence # is important because packet may arrive out of sync but receiver reassemble them in order&lt;/li&gt;&#10;&lt;li&gt;There is a lot of overhead (acknowledgement, establish connection first, tear down connection afterwards)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the other hand, UDP is connectionless. A good example is video streaming, where it is okay to lose a few packet along the way, in exchange of bandwidth saving.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Firewall may operate at different layers but it is most commonly used at transport layer, to block traffic based on port.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-application-layer"&gt;Application Layer&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There is no dominant protocol at this layer. IIS, Nginx and Apache are examples of applications operating at this layer.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-basic-network-configurations"&gt;Basic network configurations&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Standard modern network configuration involves: IP address, subnet mask, gateway and DNS server. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;DNS &lt;/strong&gt;&amp;#8211; global and highly distributed network service that resolves domain name into IP address. There are &lt;a href="https://www.golinuxhub.com/2014/01/how-does-dns-query-works-when-you-type.html"&gt;many steps in DNS resolution&lt;/a&gt;. DNS service listens on port 53. Two famous free public DNS servers are 8.8.8.8 and 8.4.4.4. DNS servers have five categories:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Caching name servers: store known domain name lookups in cache. TTL today can be a few hours, much shorter than what it used to be in early days;&lt;/li&gt;&#10;&lt;li&gt;Recursive name servers: perform full DNS resolution request;&lt;/li&gt;&#10;&lt;li&gt;Root name servers;&lt;/li&gt;&#10;&lt;li&gt;TLD name servers;&lt;/li&gt;&#10;&lt;li&gt;Authoritative name servers;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter is-resized"&gt;&lt;img decoding="async" src="https://1.bp.blogspot.com/-JqjgddtqOiw/U6ESNhWETCI/AAAAAAAADXM/JpwsJeSpCg8/s1600/dnsquery.png" alt="" style="width:433px;height:357px"/&gt;&lt;figcaption class="wp-element-caption"&gt;DNS resolution steps&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;DNS uses UDP protocol and it can generate a lot of traffic (TCP is impractical. If implemented in TCP, it would have required 44 packet for a DNS query, which is very expensive considering DNS query is just a precursor of the real traffic)&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Anycast DNS&lt;/strong&gt; &amp;#8211; any one of a number of DNS servers can respond to DNS queries, and typically the one that is geographically closest will provide the response. This reduces latency, improves uptime for the DNS resolving service and provides protection against DNS flood DDoS attacks.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;DNS record types&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;A record: domain name to IP address. DNS service round robin across multiple A records&lt;/li&gt;&#10;&lt;li&gt;AAAA (quad A) record: domain name to IPv6 address&lt;/li&gt;&#10;&lt;li&gt;CNAME: redirect traffic from one domain to another (e.g. test.com to www.test.com so you can minimize IP references)&lt;/li&gt;&#10;&lt;li&gt;MX record&lt;/li&gt;&#10;&lt;li&gt;SRV record&lt;/li&gt;&#10;&lt;li&gt;TXT record: originally for human consumption, freeform text for configuration purpose.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A FQDN (fully qualified domain name) can have up to 127 domains, but only three in most cases. (i.e. subdomain.domain.topleveldomain)&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;DNS zones&lt;/strong&gt; &amp;#8211; allow for easier control over multiple levels of a domain. DNS zones are configured in zone files. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Domains vs zones&lt;/strong&gt; &amp;#8211; Domains are broken into zones for which individual DNS servers are responsible. A domain represents the entire set of names/machines that are contained under an organizational domain name. For example, all domain names ending with &amp;#8220;.com&amp;#8221; are part of the &amp;#8220;com&amp;#8221; domain. A &amp;#8220;zone&amp;#8221; is a domain less any sub-domains delegated to other DNS servers. A DNS server could be responsible (authoritative) for all records under the &amp;#8220;xyz.com&amp;#8221; domain, but by defining NS-records for &amp;#8220;abc.xyz.com&amp;#8221;, this part of the domain is delegated to other DNS servers &amp;#8211; and possibly a different company/entity. A zone contains exactly one SOA-record describing the general properties of the zone, and any number of other DNS records. Entire zones can transferred from a primary DNS server to secondary DNS servers through Zone Transfers. A domain administrator would be responsible for creating zones, and delegating responsibility for these zones to an administrator and DNS server.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="597" height="529" src="https://static.digihunch.com/wp-content/uploads/2024/07/DNS-Zones-Illustration.jpg" alt="" class="wp-image-11546" srcset="https://static.digihunch.com/wp-content/uploads/2024/07/DNS-Zones-Illustration.jpg 597w, https://static.digihunch.com/wp-content/uploads/2024/07/DNS-Zones-Illustration-300x266.jpg 300w" sizes="auto, (max-width: 597px) 100vw, 597px" /&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Reverse DNS lookup&lt;/strong&gt; &amp;#8211; query for FQDN by IP. This is commonly used by email servers where anti-spam mechanism on the receiver needs to validate that sender&amp;#8217;s IP is associated with a domain as claimed. This is also used in logging application to convert IP into human-readable domains in the log data. Reverse DNS lookups query DNS server for a PTR (pointer reserve record). If the server does not have a PTR record, it cannot resolve a reverse lookup.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;DHCP&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;DHCP operates at application layer and helps you to configure&amp;nbsp; IP automatically with a lease, through automatic allocation, or fixed allocation based on MAC, etc. DHCP process involves address allocation, renewal, and release. Address allocation takes four steps:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Client sends a broadcast to discover DHCP server;&lt;/li&gt;&#10;&lt;li&gt;DHCP server broadcast a DHCP offer;&lt;/li&gt;&#10;&lt;li&gt;Client requests IP address from the DHCP server;&lt;/li&gt;&#10;&lt;li&gt;Server acknowledged the DHCP request;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here is an illustration of DHCP address allocation.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="713" height="527" src="https://static.digihunch.com/wp-content/uploads/2024/07/DHCP-address-allocation.gif" alt="" class="wp-image-11548"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;DHCP can also be used to set NTP address.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;NAT&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Network Address Translation (NAT), can be implemented in many different ways in different OS. Essentially, it is a technology that allows a gateway, usually a router or firewall, to rewrite the source IP of an outgoing IP datagram while retaining the original IP in order to rewrite it into the response.&amp;nbsp; Two categories of NAT are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Basic NAT: provides a one-to-one translation of IP addresses, aka one-to-one NAT. Basic NATs can be used to interconnect two IP networks that have incompatible addressing.&lt;/li&gt;&#10;&lt;li&gt;One-to-many NAT: maps multiple private hosts to one publicly exposed IP address, aka IP masquerading. This can be a security measure so that no external host can establish to your computer without knowing your actual IP. Source port conflict can be managed in two ways:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;port preservation: When making outgoing connection, NAT preserves the ephemeral port number used by internal client that initiates the connection; if two clients happen to use the same ephemeral port, then NAT picks a random port to initiate outgoing TCP connection;&lt;/li&gt;&#10;&lt;li&gt;port forwarding (port mapping): Forward traffic to certain destination based on the port of incoming request that NAT receives. &lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter is-resized"&gt;&lt;img decoding="async" src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/50/Internet_port_forwarding.png/800px-Internet_port_forwarding.png" alt="File:Internet port forwarding.png" style="width:521px;height:293px"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Proxy&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Proxy refers to a concept rather than a specific implementation. It exists on almost every layer in the network model, and act on behalf of a client in order to access other service. For example, &lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Web proxy used to be used to cache web traffic data in slow Internet but it is not necessary any more because 1) there is not much speed benefit; 2) website today is much more dynamic. &lt;/li&gt;&#10;&lt;li&gt;Reverse proxy is a popular architecture of web server, such as Nginx, to act as a front end of web servers, as well as point of decryption so web servers are free to just serve the content.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;VPN&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;VPN &amp;#8211; allows for extension of a private or local network to host that might not be on that local private network by using encrypted tunnel. There are many flavours of implementation for many purposes. It is a general concept rather than a specific protocol (just like NAT). VPN client provisions the computer with a &lt;span style="text-decoration: underline;"&gt;virtual interface&lt;/span&gt; with an IP that matches the address space of the private network, and establish a VPN tunnel to it. Most VPNs work by using the payload section of transport layer to carry an encrypted payload that actually contains an entire second set of packets: the network, the transport and the application layers of a packet intended to traverse a network. Basically, this payload is carried to the VPN&amp;#8217;s endpoint where all the other layers are stripped away and discarded. Then, the payload is unencrypted, leaving the VPN server with the top three layers of a new packet. This gets encapsulated with the proper datalink layer information and sent across the network. This process is completed in the inverse in the opposite direction. VPN usually requires strict authentication procedures and encryption. VPN can also be used to establish site-to-site connection (aka point-to-point VPN) where individual user doesn&amp;#8217;t have to establish connections on their own. Both sites needs specialized hardware to achieve this. Site-to-site VPN is a good alternative to WAN when two site don&amp;#8217;t need to transfer large amount of data for very fast speed.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;WAN&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Wide Area Network &amp;#8211; act like a single network, but span across multiple physical locations, it requires that you contract the link across the internet with ISP. ISP handles data link from one site to another.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="586" height="160" src="https://static.digihunch.com/wp-content/uploads/2019/12/image-4.png" alt="" class="wp-image-533"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Wireless Network&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Wireless protocol (802.11 family) defines how Wifi operates at physical and data link layer. Wifi networks operates on 2.4GHz and 5GHz frequency bands. Wireless frame is fairly different from Ethernet frame due to the nature of wireless transmission.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="http://static1.squarespace.com/static/55e6d56ee4b0139f372acc16/t/57597dd259827ef6e49d01cf/1465482710010/?format=1500w" alt="Image result for wireless frame&amp;quot;"/&gt;&lt;figcaption class="wp-element-caption"&gt;Wireless frame&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Wireless access point is a device that bridges the wireless and wired portions of a network. A single wired network might have many wireless access points to cover a large area.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Wireless network can be configured in a few main ways:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Ad-hoc network &amp;#8211; nodes all directly speak to each other. No supporting infrastructure is needed but not most common. It can be powerful tool during disasters.&lt;/li&gt;&#10;&lt;li&gt;Wireless LAN (WLAN) &amp;#8211; one or more access points act as abridge between wireless and wired network. This is the most common type in business world where the wired LAN provides link to the Internet.&lt;/li&gt;&#10;&lt;li&gt;Mesh networks &amp;#8211; a hybrid of the two above&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Wireless Security&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Wireless transmission is across the air so encryption is more important. The number of bit in the encryption key corresponds to how secure the encryption is.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;WEP (encryption technology) provides low level of privacy (40-bit encryption) and it is not preferred today;&lt;/li&gt;&#10;&lt;li&gt;WPA provides 128-bit key encryption; &lt;/li&gt;&#10;&lt;li&gt;WPA2 provides 256-bit key encryption and is most common today.&lt;/li&gt;&#10;&lt;li&gt;MAC filtering also help security in wireless&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Basic networking troubleshooting&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;ICMP ping to test general quality of connection;&lt;/li&gt;&#10;&lt;li&gt;traceroute discovers the path between two nodes and give you the information along the way;&lt;/li&gt;&#10;&lt;li&gt;netcat checks port and host address (telnet is retiring);&lt;/li&gt;&#10;&lt;li&gt;nslookup: very powerful in interactive mode for resolution tools;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;IPv6 &lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;IPv4 address running out in November 2019 is a major crisis. IPv6 becomes more critical to implement for many organizations. IPv6 address is very long with numbers. Numbers represents a natural way that computer thinks and operates, but not for human. So IPv6 comes with two rules to shorten the address:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="289" height="159" src="https://static.digihunch.com/wp-content/uploads/2019/12/image-2.png" alt="" class="wp-image-520"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;You may remove any leading 0;&lt;/li&gt;&#10;&lt;li&gt;Any number of consecutive groups can be replaced with two colons;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;IPv6 header looks like below:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" width="742" height="458" src="https://static.digihunch.com/wp-content/uploads/2019/12/image-3.png" alt="" class="wp-image-521" style="width:523px;height:323px"/&gt;&lt;figcaption class="wp-element-caption"&gt;IPv6 header&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Coexistence &amp;#8211; the optimal approach for existing networks is to focus not on transition but on coexistence. Coexistence may live a long period with these phases: 1) Turn on IPv6 routing in their existing IPv4 networks and start using it; 2) Contract IPv6 service with their upstream, peer, and downstream neighbours; 3) Use the IPv6 protocol in addition to IPv4 in their applications and services both on server equipment and on their clients; 4) turn off IPv4 at some point when it is no longer a business requirement.&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/2019/11/storage-nitty-gritty-5-of-5-replication/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Storage Nitty-Gritty 5 of 5 – Replication&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/12/networking-basics-3-of-3-common-network-technologies/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Networking Basics 3 of 3 – common network protocols and technologies&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>